-(defalias 'help 'help-for-help)
-(make-help-screen help-for-help
- "a b c C f F C-f i I k C-k l L m n p s t v w C-c C-d C-n C-p C-w; ? for help:"
- "You have typed %THIS-KEY%, the help character. Type a Help option:
-\(Use SPC or DEL to scroll through this text. Type \\<help-map>\\[help-quit] to exit the Help command.)
-
-a command-apropos. Give a substring, and see a list of commands
- (functions interactively callable) that contain
- that substring. See also the apropos command.
-b describe-bindings. Display table of all key bindings.
-c describe-key-briefly. Type a command key sequence;
- it prints the function name that sequence runs.
-C describe-coding-system. This describes either a specific coding system
- (if you type its name) or the coding systems currently in use
- (if you type just RET).
-f describe-function. Type a function name and get documentation of it.
-C-f Info-goto-emacs-command-node. Type a function name;
- it takes you to the Info node for that command.
-i info. The info documentation reader.
-I describe-input-method. Describe a specific input method (if you type
- its name) or the current input method (if you type just RET).
-C-i info-lookup-symbol. Display the definition of a specific symbol
- as found in the manual for the language this buffer is written in.
-k describe-key. Type a command key sequence;
- it displays the full documentation.
-C-k Info-goto-emacs-key-command-node. Type a command key sequence;
- it takes you to the Info node for the command bound to that key.
-l view-lossage. Show last 100 characters you typed.
-L describe-language-environment. This describes either a
- specific language environment (if you type its name)
- or the current language environment (if you type just RET).
-m describe-mode. Print documentation of current minor modes,
- and the current major mode, including their special commands.
-n view-emacs-news. Display news of recent Emacs changes.
-p finder-by-keyword. Find packages matching a given topic keyword.
-s describe-syntax. Display contents of syntax table, plus explanations
-t help-with-tutorial. Select the Emacs learn-by-doing tutorial.
-v describe-variable. Type name of a variable;
- it displays the variable's documentation and value.
-w where-is. Type command name; it prints which keystrokes
- invoke that command.
-
-F Display the frequently asked questions file.
-h Display the HELLO file which illustrates various scripts.
-C-c Display Emacs copying permission (General Public License).
-C-d Display Emacs ordering information.
-C-n Display news of recent Emacs changes.
-C-p Display information about the GNU project.
-C-w Display information on absence of warranty for GNU Emacs."
- help-map)
-
-(defun function-called-at-point ()
- "Return a function around point or else called by the list containing point.
-If that doesn't give a function, return nil."
- (with-syntax-table emacs-lisp-mode-syntax-table
- (or (condition-case ()
- (save-excursion
- (or (not (zerop (skip-syntax-backward "_w")))
- (eq (char-syntax (following-char)) ?w)
- (eq (char-syntax (following-char)) ?_)
- (forward-sexp -1))
- (skip-chars-forward "'")
- (let ((obj (read (current-buffer))))
- (and (symbolp obj) (fboundp obj) obj)))
- (error nil))
- (condition-case ()
- (save-excursion
- (save-restriction
- (narrow-to-region (max (point-min)
- (- (point) 1000)) (point-max))
- ;; Move up to surrounding paren, then after the open.
- (backward-up-list 1)
- (forward-char 1)
- ;; If there is space here, this is probably something
- ;; other than a real Lisp function call, so ignore it.
- (if (looking-at "[ \t]")
- (error "Probably not a Lisp function call"))
- (let ((obj (read (current-buffer))))
- (and (symbolp obj) (fboundp obj) obj))))
- (error nil)))))
-
-(defvar symbol-file-load-history-loaded nil
- "Non-nil means we have loaded the file `fns-VERSION.el' in `exec-directory'.
-That file records the part of `load-history' for preloaded files,
-which is cleared out before dumping to make Emacs smaller.")
-
-(defun load-symbol-file-load-history ()
- "Load the file `fns-VERSION.el' in `exec-directory' if not already done.
-That file records the part of `load-history' for preloaded files,
-which is cleared out before dumping to make Emacs smaller."
- (unless symbol-file-load-history-loaded
- (load (expand-file-name
- ;; fns-XX.YY.ZZ.el does not work on DOS filesystem.
- (if (eq system-type 'ms-dos)
- "fns.el"
- (format "fns-%s.el" emacs-version))
- exec-directory)
- ;; The file name fns-%s.el already has a .el extension.
- nil nil t)
- (setq symbol-file-load-history-loaded t)))
-
-(defun symbol-file (function)
- "Return the input source from which FUNCTION was loaded.
-The value is normally a string that was passed to `load':
-either an absolute file name, or a library name
-\(with no directory name and no `.el' or `.elc' at the end).
-It can also be nil, if the definition is not associated with any file."
- (load-symbol-file-load-history)
- (let ((files load-history)
- file functions)
- (while files
- (if (memq function (cdr (car files)))
- (setq file (car (car files)) files nil))
- (setq files (cdr files)))
- file))
-
-(defun describe-function (function)
- "Display the full documentation of FUNCTION (a symbol)."
- (interactive
- (let ((fn (function-called-at-point))
- (enable-recursive-minibuffers t)
- val)
- (setq val (completing-read (if fn
- (format "Describe function (default %s): " fn)
- "Describe function: ")
- obarray 'fboundp t nil nil (symbol-name fn)))
- (list (if (equal val "")
- fn (intern val)))))
- (if function
- (with-output-to-temp-buffer "*Help*"
- (prin1 function)
- ;; Use " is " instead of a colon so that
- ;; it is easier to get out the function name using forward-sexp.
- (princ " is ")
- (describe-function-1 function nil (interactive-p))
- (print-help-return-message)
- (save-excursion
- (set-buffer standard-output)
- ;; Return the text we displayed.
- (buffer-string)))
- (message "You didn't specify a function")))
-
-(defun describe-function-1 (function parens interactive-p)
- (let* ((def (if (symbolp function)
- (symbol-function function)
- function))
- file-name string need-close
- (beg (if (commandp def) "an interactive " "a ")))
- (setq string
- (cond ((or (stringp def)
- (vectorp def))
- "a keyboard macro")
- ((subrp def)
- (if (eq 'unevalled (cdr (subr-arity def)))
- (concat beg "special form")
- (concat beg "built-in function")))
- ((byte-code-function-p def)
- (concat beg "compiled Lisp function"))
- ((symbolp def)
- (while (symbolp (symbol-function def))
- (setq def (symbol-function def)))
- (format "an alias for `%s'" def))
- ((eq (car-safe def) 'lambda)
- (concat beg "Lisp function"))
- ((eq (car-safe def) 'macro)
- "a Lisp macro")
- ((eq (car-safe def) 'mocklisp)
- "a mocklisp function")
- ((eq (car-safe def) 'autoload)
- (setq file-name (nth 1 def))
- (format "%s autoloaded %s"
- (if (commandp def) "an interactive" "an")
- (if (eq (nth 4 def) 'keymap) "keymap"
- (if (nth 4 def) "Lisp macro" "Lisp function"))
- ))
- ;; perhaps use keymapp here instead
- ((eq (car-safe def) 'keymap)
- (let ((is-full nil)
- (elts (cdr-safe def)))
- (while elts
- (if (char-table-p (car-safe elts))
- (setq is-full t
- elts nil))
- (setq elts (cdr-safe elts)))
- (if is-full
- "a full keymap"
- "a sparse keymap")))
- (t "")))
- (when (and parens (not (equal string "")))
- (setq need-close t)
- (princ "("))
- (princ string)
- (with-current-buffer "*Help*"
- (save-excursion
- (save-match-data
- (if (re-search-backward "alias for `\\([^`']+\\)'" nil t)
- (help-xref-button 1 #'describe-function def
- "mouse-2, RET: describe this function")))))
- (or file-name
- (setq file-name (symbol-file function)))
- (if file-name
- (progn
- (princ " in `")
- ;; We used to add .el to the file name,
- ;; but that's completely wrong when the user used load-file.
- (princ file-name)
- (princ "'")
- ;; Make a hyperlink to the library.
- (with-current-buffer "*Help*"
- (save-excursion
- (re-search-backward "`\\([^`']+\\)'" nil t)
- (help-xref-button 1 #'(lambda (arg)
- (let ((location
- (find-function-noselect arg)))
- (pop-to-buffer (car location))
- (goto-char (cdr location))))
- function
- "mouse-2, RET: find function's definition")))))
- (if need-close (princ ")"))
- (princ ".")
- (terpri)
- ;; Handle symbols aliased to other symbols.
- (setq def (indirect-function def))
- ;; If definition is a macro, find the function inside it.
- (if (eq (car-safe def) 'macro)
- (setq def (cdr def)))
- (let ((arglist (cond ((byte-code-function-p def)
- (car (append def nil)))
- ((eq (car-safe def) 'lambda)
- (nth 1 def))
- ((and (eq (car-safe def) 'autoload)
- (not (eq (nth 4 def) 'keymap)))
- (concat "[Arg list not available until "
- "function definition is loaded.]"))
- (t t))))
- (cond ((listp arglist)
- (princ (cons (if (symbolp function) function "anonymous")
- (mapcar (lambda (arg)
- (if (memq arg '(&optional &rest))
- arg
- (intern (upcase (symbol-name arg)))))
- arglist)))
- (terpri))
- ((stringp arglist)
- (princ arglist)
- (terpri))))
- (let ((doc (documentation function)))
- (if doc
- (progn (terpri)
- (princ doc)
- (if (subrp (symbol-function function))
- (with-current-buffer standard-output
- (beginning-of-line)
- ;; Builtins get the calling sequence at the end of
- ;; the doc string. Move it to the same place as
- ;; for other functions.
-
- ;; In cases where `function' has been fset to a
- ;; subr we can't search for function's name in
- ;; the doc string. Kluge round that using the
- ;; printed representation. The arg list then
- ;; shows the wrong function name, but that
- ;; might be a useful hint.
- (let* ((rep (prin1-to-string def))
- (name (progn
- (string-match " \\([^ ]+\\)>$" rep)
- (match-string 1 rep))))
- (if (looking-at (format "(%s[ )]" (regexp-quote name)))
- (let ((start (point-marker)))
- (goto-char (point-min))
- (forward-paragraph)
- (insert-buffer-substring (current-buffer) start)
- (insert ?\n)
- (delete-region (1- start) (point-max)))
- (goto-char (point-min))
- (forward-paragraph)
- (insert
- "[Missing arglist. Please make a bug report.]\n")))
- (goto-char (point-max))))
- (help-setup-xref (list #'describe-function function)
- interactive-p))
- (princ "not documented")))))
-
-(defun variable-at-point ()
- "Return the bound variable symbol found around point.
-Return 0 if there is no such symbol."
- (condition-case ()
- (with-syntax-table emacs-lisp-mode-syntax-table
- (save-excursion
- (or (not (zerop (skip-syntax-backward "_w")))
- (eq (char-syntax (following-char)) ?w)
- (eq (char-syntax (following-char)) ?_)
- (forward-sexp -1))
- (skip-chars-forward "'")
- (let ((obj (read (current-buffer))))
- (or (and (symbolp obj) (boundp obj) obj)
- 0))))
- (error 0)))
-
-(defun help-xref-on-pp (from to)
- "Add xrefs for symbols in `pp's output between FROM and TO."
- (let ((ost (syntax-table)))
- (unwind-protect
- (save-excursion
- (save-restriction
- (set-syntax-table emacs-lisp-mode-syntax-table)
- (narrow-to-region from to)
- (goto-char (point-min))
- (while (not (eobp))
- (cond
- ((looking-at "\"") (forward-sexp 1))
- ((looking-at "#<") (search-forward ">" nil 'move))
- ((looking-at "\\(\\(\\sw\\|\\s_\\)+\\)")
- (let* ((sym (intern-soft (match-string 1)))
- (fn (cond ((fboundp sym) #'describe-function)
- ((or (memq sym '(t nil))
- (keywordp sym))
- nil)
- ((and sym (boundp sym))
- #'describe-variable))))
- (when fn (help-xref-button 1 fn sym)))
- (goto-char (match-end 1)))
- (t (forward-char 1))))))
- (set-syntax-table ost))))
-
-(defun describe-variable (variable &optional buffer)
- "Display the full documentation of VARIABLE (a symbol).
-Returns the documentation as a string, also.
-If VARIABLE has a buffer-local value in BUFFER (default to the current buffer),
-it is displayed along with the global value."
- (interactive
- (let ((v (variable-at-point))
- (enable-recursive-minibuffers t)
- val)
- (setq val (completing-read (if (symbolp v)
- (format
- "Describe variable (default %s): " v)
- "Describe variable: ")
- obarray 'boundp t nil nil
- (if (symbolp v) (symbol-name v))))
- (list (if (equal val "")
- v (intern val)))))
- (unless (bufferp buffer) (setq buffer (current-buffer)))
- (if (not (symbolp variable))
- (message "You did not specify a variable")
- (let (valvoid)
- (with-current-buffer buffer
- (with-output-to-temp-buffer "*Help*"
- (prin1 variable)
- (if (not (boundp variable))
- (progn
- (princ " is void")
- (setq valvoid t))
- (let ((val (symbol-value variable)))
- (with-current-buffer standard-output
- (princ "'s value is ")
- (terpri)
- (let ((from (point)))
- (pp val)
- (help-xref-on-pp from (point))))))
- (terpri)
- (if (local-variable-p variable)
- (progn
- (princ (format "Local in buffer %s; " (buffer-name)))
- (if (not (default-boundp variable))
- (princ "globally void")
- (let ((val (default-value variable)))
- (with-current-buffer standard-output
- (princ "global value is ")
- (terpri)
- ;; Fixme: pp can take an age if you happen to
- ;; ask for a very large expression. We should
- ;; probably print it raw once and check it's a
- ;; sensible size before prettyprinting. -- fx
- (let ((from (point)))
- (pp val)
- (help-xref-on-pp from (point))))))
- (terpri)))
- (terpri)
- (with-current-buffer standard-output
- (if (> (count-lines (point-min) (point-max)) 10)
- (progn
- ;; Note that setting the syntax table like below
- ;; makes forward-sexp move over a `'s' at the end
- ;; of a symbol.
- (set-syntax-table emacs-lisp-mode-syntax-table)
- (goto-char (point-min))
- (if valvoid
- (forward-line 1)
- (forward-sexp 1)
- (delete-region (point) (progn (end-of-line) (point)))
- (insert " value is shown below.\n\n")
- (save-excursion
- (insert "\n\nValue:"))))))
- (princ "Documentation:")
- (terpri)
- (let ((doc (documentation-property variable 'variable-documentation)))
- (princ (or doc "not documented as a variable.")))
- (help-setup-xref (list #'describe-variable variable (current-buffer))
- (interactive-p))
-
- ;; Make a link to customize if this variable can be customized.
- ;; Note, it is not reliable to test only for a custom-type property
- ;; because those are only present after the var's definition
- ;; has been loaded.
- (if (or (get variable 'custom-type) ; after defcustom
- (get variable 'custom-loads) ; from loaddefs.el
- (get variable 'standard-value)) ; from cus-start.el
- (let ((customize-label "customize"))
- (terpri)
- (terpri)
- (princ (concat "You can " customize-label " this variable."))
- (with-current-buffer "*Help*"
- (save-excursion
- (re-search-backward
- (concat "\\(" customize-label "\\)") nil t)
- (help-xref-button 1 (lambda (v)
- (if help-xref-stack
- (pop help-xref-stack))
- (customize-variable v))
- variable
- "mouse-2, RET: customize variable")))))
- ;; Make a hyperlink to the library if appropriate. (Don't
- ;; change the format of the buffer's initial line in case
- ;; anything expects the current format.)
- (let ((file-name (symbol-file variable)))
- (when file-name
- (princ "\n\nDefined in `")
- (princ file-name)
- (princ "'.")
- (with-current-buffer "*Help*"
- (save-excursion
- (re-search-backward "`\\([^`']+\\)'" nil t)
- (help-xref-button
- 1 (lambda (arg)
- (let ((location
- (find-variable-noselect arg)))
- (pop-to-buffer (car location))
- (goto-char (cdr location))))
- variable "mouse-2, RET: find variable's definition")))))
-
- (print-help-return-message)
- (save-excursion
- (set-buffer standard-output)
- ;; Return the text we displayed.
- (buffer-string)))))))