summaryrefslogtreecommitdiff
path: root/lisp/man.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/man.el')
-rw-r--r--lisp/man.el205
1 files changed, 151 insertions, 54 deletions
diff --git a/lisp/man.el b/lisp/man.el
index 25dbd83600f..d96396483d3 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -97,6 +97,21 @@
:group 'external
:group 'help)
+(defcustom Man-prefer-synchronous-call nil
+ "Whether to call the Un*x \"man\" program synchronously.
+When this is non-nil, call the \"man\" program synchronously
+(rather than asynchronously, which is the default behavior)."
+ :type 'boolean
+ :group 'man
+ :version "30.1")
+
+(defcustom Man-support-remote-systems nil
+ "Whether to call the Un*x \"man\" program on remote systems.
+When this is non-nil, call the \"man\" program on the remote
+system determined by `default-directory'."
+ :type 'boolean
+ :version "30.1")
+
(defcustom Man-filter-list nil
"Manpage cleaning filter command phrases.
This variable contains a list of the following form:
@@ -307,7 +322,7 @@ If this is nil, `man' will use `locale-coding-system'."
:type 'hook
:group 'man)
-(defvar Man-name-regexp "[-[:alnum:]_­+][-[:alnum:]_.:­+]*"
+(defvar Man-name-regexp "[-[:alnum:]_­+[@][-[:alnum:]_.:­+]*"
"Regular expression describing the name of a manpage (without section).")
(defvar Man-section-regexp "[0-9][a-zA-Z0-9+]*\\|[LNln]"
@@ -523,8 +538,9 @@ Otherwise, the value is whatever the function
(define-button-type 'Man-xref-normal-file
'action (lambda (button)
- (let ((f (substitute-in-file-name
- (button-get button 'Man-target-string))))
+ (let ((f (concat (file-remote-p default-directory)
+ (substitute-in-file-name
+ (button-get button 'Man-target-string)))))
(if (file-exists-p f)
(if (file-readable-p f)
(view-file f)
@@ -537,6 +553,65 @@ Otherwise, the value is whatever the function
;; ======================================================================
;; utilities
+(defun Man-default-directory ()
+ "Return a default directory according to `Man-support-remote-systems'."
+ ;; Ensure that `default-directory' exists and is readable.
+ ;; We assume, that this function is always called inside the `man'
+ ;; command, so that we can check `current-prefix-arg' for reverting
+ ;; `Man-support-remote-systems'.
+ (let ((result default-directory)
+ (remote (if current-prefix-arg
+ (not Man-support-remote-systems)
+ Man-support-remote-systems)))
+
+ ;; Use a local directory if remote isn't possible.
+ (when (and (file-remote-p default-directory)
+ (not (and remote
+ ;; TODO:: Test that remote processes are supported.
+ )))
+ (setq result (expand-file-name "~/")))
+
+ ;; Check, whether the directory is accessible.
+ (if (file-accessible-directory-p result)
+ result
+ (expand-file-name (concat (file-remote-p result) "~/")))))
+
+(defun Man-shell-file-name ()
+ "Return a proper shell file name, respecting remote directories."
+ (or ; This works also in the local case.
+ (connection-local-value shell-file-name)
+ "/bin/sh"))
+
+(defun Man-header-file-path ()
+ "Return the C header file search path that Man should use.
+Normally, this is the value of the user option `Man-header-file-path',
+but when the man page is formatted on a remote system (see
+`Man-support-remote-systems'), this function tries to figure out the
+list of directories where the remote system has the C header files."
+ (let ((remote-id (file-remote-p default-directory)))
+ (if (null remote-id)
+ ;; The local case.
+ Man-header-file-path
+ ;; The remote case. Use connection-local variables.
+ (mapcar
+ (lambda (elt) (concat remote-id elt))
+ (with-connection-local-variables
+ (or (and (local-variable-p 'Man-header-file-path (current-buffer))
+ Man-header-file-path)
+ (setq-connection-local
+ Man-header-file-path
+ (let ((arch (with-temp-buffer
+ (when (zerop (ignore-errors
+ (process-file "gcc" nil '(t nil) nil
+ "-print-multiarch")))
+ (goto-char (point-min))
+ (buffer-substring (point) (line-end-position)))))
+ (base '("/usr/include" "/usr/local/include")))
+ (if (zerop (length arch))
+ base
+ (append
+ base (list (expand-file-name arch "/usr/include"))))))))))))
+
(defun Man-init-defvars ()
"Used for initializing variables based on display's color support.
This is necessary if one wants to dump man.el with Emacs."
@@ -575,7 +650,9 @@ This is necessary if one wants to dump man.el with Emacs."
(if Man-sed-script
(concat "-e '" Man-sed-script "'")
"")
- "-e '/^[\001-\032][\001-\032]*$/d'"
+ ;; Use octal numbers. Otherwise, \032 (Ctrl-Z) would
+ ;; suspend remote connections.
+ "-e '/^[\\o001-\\o032][\\o001-\\o032]*$/d'"
"-e '/\e[789]/s///g'"
"-e '/Reformatting page. Wait/d'"
"-e '/Reformatting entry. Wait/d'"
@@ -684,7 +761,11 @@ and the `Man-section-translations-alist' variables)."
(setq name (match-string 2 ref)
section (match-string 1 ref))))
(if (string= name "")
- ref ; Return the reference as is
+ ;; see Bug#66390
+ (mapconcat 'identity
+ (mapcar #'shell-quote-argument
+ (split-string ref "\\s-+"))
+ " ") ; Return the reference as is
(if Man-downcase-section-letters-flag
(setq section (downcase section)))
(while slist
@@ -709,22 +790,23 @@ program has no such option, but interprets any name containing
a \"/\" as a local filename. The function returns either `man-db'
`man', or nil."
(if (eq Man-support-local-filenames 'auto-detect)
- (setq Man-support-local-filenames
- (with-temp-buffer
- (let ((default-directory
- ;; Ensure that `default-directory' exists and is readable.
- (if (file-accessible-directory-p default-directory)
- default-directory
- (expand-file-name "~/"))))
- (ignore-errors
- (call-process manual-program nil t nil "--help")))
- (cond ((search-backward "--local-file" nil 'move)
- 'man-db)
- ;; This feature seems to be present in at least ver 1.4f,
- ;; which is about 20 years old.
- ;; I don't know if this version has an official name?
- ((looking-at "^man, versione? [1-9]")
- 'man))))
+ (with-connection-local-variables
+ (or (and (local-variable-p 'Man-support-local-filenames (current-buffer))
+ Man-support-local-filenames)
+ (setq-connection-local
+ Man-support-local-filenames
+ (with-temp-buffer
+ (let ((default-directory (Man-default-directory)))
+ (ignore-errors
+ (process-file manual-program nil t nil "--help")))
+ (cond ((search-backward "--local-file" nil 'move)
+ 'man-db)
+ ;; This feature seems to be present in at least
+ ;; ver 1.4f, which is about 20 years old. I
+ ;; don't know if this version has an official
+ ;; name?
+ ((looking-at "^man, versione? [1-9]")
+ 'man))))))
Man-support-local-filenames))
@@ -910,7 +992,8 @@ foo(sec)[, bar(sec) [, ...]] [other stuff] - description"
(unless (and Man-completion-cache
(string-prefix-p (car Man-completion-cache) prefix))
(with-temp-buffer
- (setq default-directory "/") ;; in case inherited doesn't exist
+ ;; In case inherited doesn't exist.
+ (setq default-directory (Man-default-directory))
;; Actually for my `man' the arg is a regexp.
;; POSIX says it must be ERE and "man-db" seems to agree,
;; whereas under macOS it seems to be BRE-style and doesn't
@@ -924,12 +1007,21 @@ foo(sec)[, bar(sec) [, ...]] [other stuff] - description"
;; error later.
(when (eq 0
(ignore-errors
- (call-process
+ (process-file
manual-program nil '(t nil) nil
"-k" (concat (when (or Man-man-k-use-anchor
(string-equal prefix ""))
"^")
- prefix))))
+ (if (string-equal prefix "")
+ prefix
+ ;; FIXME: shell-quote-argument
+ ;; is not entirely
+ ;; appropriate: we actually
+ ;; need to quote ERE here.
+ ;; But we don't have that, and
+ ;; shell-quote-argument does
+ ;; the job...
+ (shell-quote-argument prefix))))))
(setq table (Man-parse-man-k)))))
;; Cache the table for later reuse.
(when table
@@ -999,7 +1091,12 @@ names or descriptions. The pattern argument is usually an
Note that in some cases you will need to use \\[quoted-insert] to quote the
SPC character in the above examples, because this command attempts
-to auto-complete your input based on the installed manual pages."
+to auto-complete your input based on the installed manual pages.
+
+If `default-directory' is remote, and `Man-support-remote-systems'
+is non-nil, this command formats the man page on the remote system.
+A prefix argument reverses the value of `Man-support-remote-systems'
+for the current invocation."
(interactive
(list (let* ((default-entry (Man-default-man-entry))
@@ -1065,12 +1162,7 @@ to auto-complete your input based on the installed manual pages."
Man-coding-system
locale-coding-system))
;; Avoid possible error by using a directory that always exists.
- (default-directory
- (if (and (file-directory-p default-directory)
- (not (find-file-name-handler default-directory
- 'file-directory-p)))
- default-directory
- "/")))
+ (default-directory (Man-default-directory)))
;; Prevent any attempt to use display terminal fanciness.
(setenv "TERM" "dumb")
;; In Debian Woody, at least, we get overlong lines under X
@@ -1099,9 +1191,13 @@ to auto-complete your input based on the installed manual pages."
(defun Man-getpage-in-background (topic)
"Use TOPIC to build and fire off the manpage and cleaning command.
Return the buffer in which the manpage will appear."
- (let* ((man-args topic)
- (bufname (concat "*Man " man-args "*"))
- (buffer (get-buffer bufname)))
+ (let* ((default-directory (Man-default-directory))
+ (man-args topic)
+ (bufname
+ (if (file-remote-p default-directory)
+ (format "*Man %s %s*" (file-remote-p default-directory) man-args)
+ (format "*Man %s*" man-args)))
+ (buffer (get-buffer bufname)))
(if buffer
(Man-notify-when-ready buffer)
(message "Invoking %s %s in the background" manual-program man-args)
@@ -1118,21 +1214,21 @@ Return the buffer in which the manpage will appear."
"[cleaning...]")
'face 'mode-line-emphasis)))
(Man-start-calling
- (if (fboundp 'make-process)
- (let ((proc (start-process
+ (if (and (fboundp 'make-process)
+ (not Man-prefer-synchronous-call))
+ (let ((proc (start-file-process
manual-program buffer
- (if (memq system-type '(cygwin windows-nt))
- shell-file-name
- "sh")
+ (Man-shell-file-name)
shell-command-switch
(format (Man-build-man-command) man-args))))
(set-process-sentinel proc 'Man-bgproc-sentinel)
(set-process-filter proc 'Man-bgproc-filter))
(let* ((inhibit-read-only t)
(exit-status
- (call-process shell-file-name nil (list buffer nil) nil
- shell-command-switch
- (format (Man-build-man-command) man-args)))
+ (process-file
+ (Man-shell-file-name) nil (list buffer nil) nil
+ shell-command-switch
+ (format (Man-build-man-command) man-args)))
(msg ""))
(or (and (numberp exit-status)
(= exit-status 0))
@@ -1160,9 +1256,10 @@ Return the buffer in which the manpage will appear."
(buffer-read-only nil))
(erase-buffer)
(Man-start-calling
- (call-process shell-file-name nil (list (current-buffer) nil) nil
- shell-command-switch
- (format (Man-build-man-command) Man-arguments)))
+ (process-file
+ (Man-shell-file-name) nil (list (current-buffer) nil) nil
+ shell-command-switch
+ (format (Man-build-man-command) Man-arguments)))
(if Man-fontify-manpage-flag
(Man-fontify-manpage)
(Man-cleanup-manpage))
@@ -1262,21 +1359,21 @@ Same for the ANSI bold and normal escape sequences."
(progn
(goto-char (point-min))
(while (and (search-forward "__\b\b" nil t) (not (eobp)))
- (backward-delete-char 4)
+ (delete-char -4)
(put-text-property (point) (1+ (point))
'font-lock-face 'Man-underline))
(goto-char (point-min))
(while (search-forward "\b\b__" nil t)
- (backward-delete-char 4)
+ (delete-char -4)
(put-text-property (1- (point)) (point)
'font-lock-face 'Man-underline))))
(goto-char (point-min))
(while (and (search-forward "_\b" nil t) (not (eobp)))
- (backward-delete-char 2)
+ (delete-char -2)
(put-text-property (point) (1+ (point)) 'font-lock-face 'Man-underline))
(goto-char (point-min))
(while (search-forward "\b_" nil t)
- (backward-delete-char 2)
+ (delete-char -2)
(put-text-property (1- (point)) (point) 'font-lock-face 'Man-underline))
(goto-char (point-min))
(while (re-search-forward "\\(.\\)\\(\b+\\1\\)+" nil t)
@@ -1294,7 +1391,7 @@ Same for the ANSI bold and normal escape sequences."
;; condense it to a shorter line interspersed with ^H. Remove ^H with
;; their preceding chars (but don't put Man-overstrike). (Bug#5566)
(goto-char (point-min))
- (while (re-search-forward ".\b" nil t) (backward-delete-char 2))
+ (while (re-search-forward ".\b" nil t) (delete-char -2))
(goto-char (point-min))
;; Try to recognize common forms of cross references.
(Man-highlight-references)
@@ -1375,9 +1472,9 @@ script would have done them."
(if (or interactive (not Man-sed-script))
(progn
(goto-char (point-min))
- (while (search-forward "_\b" nil t) (backward-delete-char 2))
+ (while (search-forward "_\b" nil t) (delete-char -2))
(goto-char (point-min))
- (while (search-forward "\b_" nil t) (backward-delete-char 2))
+ (while (search-forward "\b_" nil t) (delete-char -2))
(goto-char (point-min))
(while (re-search-forward "\\(.\\)\\(\b\\1\\)+" nil t)
(replace-match "\\1"))
@@ -1392,7 +1489,7 @@ script would have done them."
;; condense it to a shorter line interspersed with ^H. Remove ^H with
;; their preceding chars (but don't put Man-overstrike). (Bug#5566)
(goto-char (point-min))
- (while (re-search-forward ".\b" nil t) (backward-delete-char 2))
+ (while (re-search-forward ".\b" nil t) (delete-char -2))
(Man-softhyphen-to-minus))
(defun Man-bgproc-filter (process string)
@@ -1926,7 +2023,7 @@ Specify which REFERENCE to use; default is based on word at point."
;; Header file support
(defun Man-view-header-file (file)
"View a header file specified by FILE from `Man-header-file-path'."
- (let ((path Man-header-file-path)
+ (let ((path (Man-header-file-path))
complete-path)
(while path
(setq complete-path (expand-file-name file (car path))