|
@@ -30,6 +30,7 @@
|
|
|
|
|
|
|
|
;;; Code:
|
|
;;; Code:
|
|
|
|
|
|
|
|
|
|
+(require 'subr-x) ; `string-trim', `string-remove-prefix'
|
|
|
(require 'ol)
|
|
(require 'ol)
|
|
|
|
|
|
|
|
;; Declare external functions and variables
|
|
;; Declare external functions and variables
|
|
@@ -43,7 +44,8 @@
|
|
|
(org-link-set-parameters "info"
|
|
(org-link-set-parameters "info"
|
|
|
:follow #'org-info-open
|
|
:follow #'org-info-open
|
|
|
:export #'org-info-export
|
|
:export #'org-info-export
|
|
|
- :store #'org-info-store-link)
|
|
|
|
|
|
|
+ :store #'org-info-store-link
|
|
|
|
|
+ :insert-description #'org-info-description-as-command)
|
|
|
|
|
|
|
|
;; Implementation
|
|
;; Implementation
|
|
|
(defun org-info-store-link ()
|
|
(defun org-info-store-link ()
|
|
@@ -63,24 +65,65 @@
|
|
|
"Follow an Info file and node link specified by PATH."
|
|
"Follow an Info file and node link specified by PATH."
|
|
|
(org-info-follow-link path))
|
|
(org-info-follow-link path))
|
|
|
|
|
|
|
|
|
|
+(defun org-info--link-file-node (path)
|
|
|
|
|
+ "Extract file name and node from info link PATH.
|
|
|
|
|
+
|
|
|
|
|
+Return cons consisting of file name and node name or \"Top\" if node
|
|
|
|
|
+part is not specified. Components may be separated by \":\" or by \"#\".
|
|
|
|
|
+File may be a virtual one, see `Info-virtual-files'."
|
|
|
|
|
+ (if (not path)
|
|
|
|
|
+ '("dir" . "Top")
|
|
|
|
|
+ (string-match "\\`\\([^#:]*\\)\\(?:[#:]:?\\(.*\\)\\)?\\'" path)
|
|
|
|
|
+ (let* ((node (match-string 2 path))
|
|
|
|
|
+ ;; Do not reorder, `string-trim' modifies match.
|
|
|
|
|
+ (file (string-trim (match-string 1 path))))
|
|
|
|
|
+ (cons
|
|
|
|
|
+ (if (org-string-nw-p file) file "dir")
|
|
|
|
|
+ (if (org-string-nw-p node) (string-trim node) "Top")))))
|
|
|
|
|
+
|
|
|
|
|
+(defun org-info-description-as-command (link desc)
|
|
|
|
|
+ "Info link description that can be pasted as command.
|
|
|
|
|
+
|
|
|
|
|
+For the following LINK
|
|
|
|
|
+
|
|
|
|
|
+ \"info:elisp#Non-ASCII in Strings\"
|
|
|
|
|
+
|
|
|
|
|
+the result is
|
|
|
|
|
+
|
|
|
|
|
+ info \"(elisp) Non-ASCII in Strings\"
|
|
|
|
|
+
|
|
|
|
|
+that may be executed as shell command or evaluated by
|
|
|
|
|
+\\[eval-expression] (wrapped with parenthesis) to read the manual
|
|
|
|
|
+in Emacs.
|
|
|
|
|
+
|
|
|
|
|
+Calling convention is similar to `org-link-make-description-function'.
|
|
|
|
|
+DESC has higher priority and returned when it is not nil or empty string.
|
|
|
|
|
+If LINK is not an info link then DESC is returned."
|
|
|
|
|
+ (let* ((prefix "info:")
|
|
|
|
|
+ (need-file-node (and (not (org-string-nw-p desc))
|
|
|
|
|
+ (string-prefix-p prefix link))))
|
|
|
|
|
+ (pcase (and need-file-node
|
|
|
|
|
+ (org-info--link-file-node (string-remove-prefix prefix link)))
|
|
|
|
|
+ ;; Unlike (info "dir"), "info dir" shell command opens "(coreutils)dir invocation".
|
|
|
|
|
+ (`("dir" . "Top") "info \"(dir)\"")
|
|
|
|
|
+ (`(,file . "Top") (format "info %s" file))
|
|
|
|
|
+ (`(,file . ,node) (format "info \"(%s) %s\"" file node))
|
|
|
|
|
+ (_ desc))))
|
|
|
|
|
|
|
|
(defun org-info-follow-link (name)
|
|
(defun org-info-follow-link (name)
|
|
|
"Follow an Info file and node link specified by NAME."
|
|
"Follow an Info file and node link specified by NAME."
|
|
|
- (if (or (string-match "\\(.*\\)\\(?:#\\|::\\)\\(.*\\)" name)
|
|
|
|
|
- (string-match "\\(.*\\)" name))
|
|
|
|
|
- (let ((filename (match-string 1 name))
|
|
|
|
|
- (nodename-or-index (or (match-string 2 name) "Top")))
|
|
|
|
|
- (require 'info)
|
|
|
|
|
- ;; If nodename-or-index is invalid node name, then look it up
|
|
|
|
|
- ;; in the index.
|
|
|
|
|
- (condition-case nil
|
|
|
|
|
- (Info-find-node filename nodename-or-index)
|
|
|
|
|
- (user-error (Info-find-node filename "Top")
|
|
|
|
|
- (condition-case nil
|
|
|
|
|
- (Info-index nodename-or-index)
|
|
|
|
|
- (user-error "Could not find '%s' node or index entry"
|
|
|
|
|
- nodename-or-index)))))
|
|
|
|
|
- (user-error "Could not open: %s" name)))
|
|
|
|
|
|
|
+ (pcase-let ((`(,filename . ,nodename-or-index)
|
|
|
|
|
+ (org-info--link-file-node name)))
|
|
|
|
|
+ (require 'info)
|
|
|
|
|
+ ;; If nodename-or-index is invalid node name, then look it up
|
|
|
|
|
+ ;; in the index.
|
|
|
|
|
+ (condition-case nil
|
|
|
|
|
+ (Info-find-node filename nodename-or-index)
|
|
|
|
|
+ (user-error (Info-find-node filename "Top")
|
|
|
|
|
+ (condition-case nil
|
|
|
|
|
+ (Info-index nodename-or-index)
|
|
|
|
|
+ (user-error "Could not find '%s' node or index entry"
|
|
|
|
|
+ nodename-or-index))))))
|
|
|
|
|
|
|
|
(defconst org-info-emacs-documents
|
|
(defconst org-info-emacs-documents
|
|
|
'("ada-mode" "auth" "autotype" "bovine" "calc" "ccmode" "cl" "dbus" "dired-x"
|
|
'("ada-mode" "auth" "autotype" "bovine" "calc" "ccmode" "cl" "dbus" "dired-x"
|
|
@@ -95,7 +138,8 @@
|
|
|
Taken from <https://www.gnu.org/software/emacs/manual/html_mono/.>")
|
|
Taken from <https://www.gnu.org/software/emacs/manual/html_mono/.>")
|
|
|
|
|
|
|
|
(defconst org-info-other-documents
|
|
(defconst org-info-other-documents
|
|
|
- '(("libc" . "https://www.gnu.org/software/libc/manual/html_mono/libc.html")
|
|
|
|
|
|
|
+ '(("dir" . "https://www.gnu.org/manual/manual.html") ; index
|
|
|
|
|
+ ("libc" . "https://www.gnu.org/software/libc/manual/html_mono/libc.html")
|
|
|
("make" . "https://www.gnu.org/software/make/manual/make.html"))
|
|
("make" . "https://www.gnu.org/software/make/manual/make.html"))
|
|
|
"Alist of documents generated from Texinfo source.
|
|
"Alist of documents generated from Texinfo source.
|
|
|
When converting info links to HTML, links to any one of these manuals are
|
|
When converting info links to HTML, links to any one of these manuals are
|
|
@@ -129,9 +173,7 @@ See `org-info-emacs-documents' and `org-info-other-documents' for details."
|
|
|
(defun org-info-export (path desc format)
|
|
(defun org-info-export (path desc format)
|
|
|
"Export an info link.
|
|
"Export an info link.
|
|
|
See `org-link-parameters' for details about PATH, DESC and FORMAT."
|
|
See `org-link-parameters' for details about PATH, DESC and FORMAT."
|
|
|
- (let* ((parts (split-string path "#\\|::"))
|
|
|
|
|
- (manual (car parts))
|
|
|
|
|
- (node (or (nth 1 parts) "Top")))
|
|
|
|
|
|
|
+ (pcase-let ((`(,manual . ,node) (org-info--link-file-node path)))
|
|
|
(pcase format
|
|
(pcase format
|
|
|
(`html
|
|
(`html
|
|
|
(format "<a href=\"%s#%s\">%s</a>"
|
|
(format "<a href=\"%s#%s\">%s</a>"
|