1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
;;; ol-man.el --- Links to man pages -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2020-2025 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Maintainer: Bastien Guerry <bzg@gnu.org>
;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
;;
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Commentary:
;; This file implements links to man pages from within Org mode.
;;; Code:
(require 'org-macs)
(org-assert-version)
(require 'ol)
(org-link-set-parameters "man"
:complete #'org-man-complete
:follow #'org-man-open
:export #'org-man-export
:store #'org-man-store-link)
(defcustom org-man-command 'man
"The Emacs command to be used to display a man page."
:group 'org-link
:type '(choice (const man) (const :tag "WoMan (obsolete)" woman)))
(declare-function Man-translate-references "man" (ref))
(defun org-man-open (path _)
"Visit the manpage on PATH.
PATH should be a topic that can be thrown at the man command.
If PATH contains extra ::STRING which will use `occur' to search
matched strings in man buffer."
(require 'man) ; For `Man-translate-references'
(string-match "\\(.*?\\)\\(?:::\\(.*\\)\\)?$" path)
(let* ((command (match-string 1 path))
;; FIXME: Remove after we drop Emacs 29 support.
;; Working around security bug #66390.
(command (if (not (equal (Man-translate-references ";id") ";id"))
;; We are on Emacs that escapes man command args
;; (see Emacs commit 820f0793f0b).
command
;; Older Emacs without the fix - escape the
;; arguments ourselves.
(mapconcat 'identity
(mapcar #'shell-quote-argument
(split-string command "\\s-+"))
" ")))
(search (match-string 2 path))
(buffer (funcall org-man-command command)))
(when search
(with-current-buffer buffer
(goto-char (point-min))
(unless (search-forward search nil t)
(let ((process (get-buffer-process buffer)))
(while (process-live-p process)
(accept-process-output process)))
(goto-char (point-min))
(search-forward search))
(forward-line -1)
(let ((point (point)))
(let ((window (get-buffer-window buffer)))
(set-window-point window point)
(set-window-start window point)))))))
(defun org-man-store-link (&optional _interactive?)
"Store a link to a README file."
(when (memq major-mode '(Man-mode woman-mode))
;; This is a man page, we do make this link
(let* ((page (org-man-get-page-name))
(link (concat "man:" page))
(description (format "Manpage for %s" page)))
(org-link-store-props
:type "man"
:link link
:description description))))
(defun org-man-get-page-name ()
"Extract the page name from the buffer name."
;; This works for both `Man-mode' and `woman-mode'.
(if (string-match " \\(\\S-+\\)\\*" (buffer-name))
(match-string 1 (buffer-name))
(error "Cannot create link to this man page")))
(defun org-man-export (link description backend)
"Export a man page LINK with DESCRIPTION.
BACKEND is the current export backend."
(let ((path (format "http://man.he.net/?topic=%s§ion=all" link))
(desc (or description link)))
(cond
((eq backend 'html) (format "<a target=\"_blank\" href=\"%s\">%s</a>" path desc))
((eq backend 'latex) (format "\\href{%s}{%s}" path desc))
((eq backend 'texinfo) (format "@uref{%s,%s}" path desc))
((eq backend 'ascii) (format "[%s] (<%s>)" desc path))
((eq backend 'md) (format "[%s](%s)" desc path))
(t path))))
(defvar Man-completion-cache) ; Defined in `man'.
(defun org-man-complete (&optional _arg)
"Complete man pages for `org-insert-link'."
(require 'man)
(concat
"man:"
(let ((completion-ignore-case t) ; See `man' comments.
(Man-completion-cache)) ; See `man' implementation.
(completing-read
"Manual entry: "
'Man-completion-table))))
(provide 'ol-man)
;;; ol-man.el ends here
|