emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
blob 42aacea815444ee477f5cc6a2381244f32e54172 4986 bytes (raw)
name: lisp/ol-man.el 	 # note: path name is non-authoritative(*)

  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-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Maintainer: Bastien Guerry <bzg@gnu.org>
;; Keywords: outlines, hypermedia, calendar, wp
;; 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&section=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

debug log:

solving 42aacea81 ...
found 42aacea81 in https://git.savannah.gnu.org/cgit/emacs/org-mode.git

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).