GNU bug report logs - #13989
Make Info support footnotes

Previous Next

Package: emacs;

Reported by: Xue Fuqiao <xfq.free <at> gmail.com>

Date: Mon, 18 Mar 2013 10:27:01 UTC

Severity: wishlist

Done: Juri Linkov <juri <at> jurta.org>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: Juri Linkov <juri <at> jurta.org>
To: Xue Fuqiao <xfq.free <at> gmail.com>
Cc: 13989 <at> debbugs.gnu.org
Subject: bug#13989: Make Info support footnotes
Date: Wed, 20 Mar 2013 00:30:21 +0200
> And it's pretty straightforward to implement:

But footnotes are still not navigable.  Typing `TAB' should navigate
to the next/previous footnote as it does for the cross-node references
and URLs.

Since adding a footnote regexp to `Info-next-reference' will create
false positives such as e.g. `TAB' will find plain text "(1)" and "(2)"
in the node (info "(emacs) Copying"), a better approach would be
to support text-property links like used in the *Help* buffers where
links have a special text property that `TAB' (`forward-button')
searches for to navigate to the next link.

These two approaches can co-exist in Info, so `TAB' will move point
to the closest position found either by `re-search-forward' or
`next-single-char-property-change'.

Later these text properties could be added to links in virtual nodes
because this approach is more efficient and reliable.

=== modified file 'lisp/info.el'
--- lisp/info.el	2013-02-21 06:55:19 +0000
+++ lisp/info.el	2013-03-19 22:28:00 +0000
@@ -3057,6 +3078,38 @@ (defun Info-mouse-scroll-down (e)
 	(select-window (posn-window (event-start e))))
     (Info-scroll-down)))
 
+(defun Info-next-reference-or-link (pat prop)
+  "Move point to the next pattern-based cross-reference or property-based link.
+The next cross-reference is searched using the regexp PAT, and the next link
+is searched using the text property PROP.  Move point to the closest found position
+of either a cross-reference found by `re-search-forward' or a link found by
+`next-single-char-property-change'.  Return the new position of point, or nil."
+  (let ((pcref (save-excursion (re-search-forward pat nil t)))
+	(plink (next-single-char-property-change (point) prop)))
+    (when (and (< plink (point-max)) (not (get-char-property plink prop)))
+      (setq plink (next-single-char-property-change plink prop)))
+    (if (< plink (point-max))
+	(if (and pcref (<= pcref plink))
+	    (goto-char (or (match-beginning 1) (match-beginning 0)))
+	  (goto-char plink))
+      (if pcref (goto-char (or (match-beginning 1) (match-beginning 0)))))))
+
+(defun Info-prev-reference-or-link (pat prop)
+  "Move point to the previous pattern-based cross-reference or property-based link.
+The previous cross-reference is searched using the regexp PAT, and the previous link
+is searched using the text property PROP.  Move point to the closest found position
+of either a cross-reference found by `re-search-backward' or a link found by
+`previous-single-char-property-change'.  Return the new position of point, or nil."
+  (let ((pcref (save-excursion (re-search-backward pat nil t)))
+	(plink (previous-single-char-property-change (point) prop)))
+    (when (and (> plink (point-min)) (not (get-char-property plink prop)))
+      (setq plink (previous-single-char-property-change plink prop)))
+    (if (> plink (point-min))
+	(if (and pcref (>= pcref plink))
+	    (goto-char (or (match-beginning 1) (match-beginning 0)))
+	  (goto-char plink))
+      (if pcref (goto-char (or (match-beginning 1) (match-beginning 0)))))))
+
 (defun Info-next-reference (&optional recur count)
   "Move cursor to the next cross-reference or menu item in the node.
 If COUNT is non-nil (interactively with a prefix arg), jump over
@@ -3071,14 +3124,13 @@ (defun Info-next-reference (&optional re
 	    (old-pt (point))
 	    (case-fold-search t))
 	(or (eobp) (forward-char 1))
-	(or (re-search-forward pat nil t)
+	(or (Info-next-reference-or-link pat 'link)
 	    (progn
 	      (goto-char (point-min))
-	      (or (re-search-forward pat nil t)
+	      (or (Info-next-reference-or-link pat 'link)
 		  (progn
 		    (goto-char old-pt)
 		    (user-error "No cross references in this node")))))
-	(goto-char (or (match-beginning 1) (match-beginning 0)))
 	(if (looking-at "\\* Menu:")
 	    (if recur
 		(user-error "No cross references in this node")
@@ -3099,14 +3151,13 @@ (defun Info-prev-reference (&optional re
       (let ((pat "\\*note[ \n\t]+\\([^:]+\\):\\|^\\* .*:\\|[hf]t?tps?://")
 	    (old-pt (point))
 	    (case-fold-search t))
-	(or (re-search-backward pat nil t)
+	(or (Info-prev-reference-or-link pat 'link)
 	    (progn
 	      (goto-char (point-max))
-	      (or (re-search-backward pat nil t)
+	      (or (Info-prev-reference-or-link pat 'link)
 		  (progn
 		    (goto-char old-pt)
 		    (user-error "No cross references in this node")))))
-	(goto-char (or (match-beginning 1) (match-beginning 0)))
 	(if (looking-at "\\* Menu:")
 	    (if recur
 		(user-error "No cross references in this node")
@@ -3840,7 +3892,25 @@ (defun Info-try-follow-nearest-node (&op
      ((setq node (Info-get-token (point) "File: " "File: \\([^,\n\t]*\\)"))
       (Info-goto-node "Top" fork))
      ((setq node (Info-get-token (point) "Prev: " "Prev: \\([^,\n\t]*\\)"))
-      (Info-goto-node node fork)))
+      (Info-goto-node node fork))
+     ;; footnote
+     ((setq node (Info-get-token (point) "(" "\\(([0-9]+)\\)"))
+      (let ((old-point (point)) new-point)
+	(save-excursion
+	  (goto-char (point-min))
+	  (when (re-search-forward "^[ \t]*-+ Footnotes -+$" nil t)
+	    (setq new-point (if (< old-point (point))
+				;; Go to footnote reference
+				(and (search-forward node nil t)
+				     ;; Put point at beginning of link
+				     (match-beginning 0))
+			      ;; Go to footnote definition
+			      (search-backward node nil t)))))
+	(if new-point
+	    (progn
+	      (goto-char new-point)
+	      (setq node t))
+	  (setq node nil)))))
     node))
 
 (defun Info-mouse-follow-link (click)
@@ -4896,6 +4966,21 @@ (defun Info-fontify-node ()
                                  mouse-face highlight
                                  help-echo "mouse-2: go to this URL"))))
 
+      ;; Fontify footnotes
+      (goto-char (point-min))
+      (when (and not-fontified-p (re-search-forward "^[ \t]*-+ Footnotes -+$" nil t))
+	(let ((limit (point)))
+	  (goto-char (point-min))
+	  (while (re-search-forward "\\(([0-9]+)\\)" nil t)
+	    (add-text-properties (match-beginning 0) (match-end 0)
+                                 `(font-lock-face info-xref
+                                   link t
+                                   mouse-face highlight
+                                   help-echo
+				   ,(if (< (point) limit)
+					"mouse-2: go to footnote definition"
+				      "mouse-2: go to footnote reference"))))))
+
       ;; Hide empty lines at the end of the node.
       (goto-char (point-max))
       (skip-chars-backward "\n")





This bug report was last modified 12 years and 124 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.