all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Juri Linkov <juri@jurta.org>
To: Xue Fuqiao <xfq.free@gmail.com>
Cc: 13989@debbugs.gnu.org
Subject: bug#13989: Make Info support footnotes
Date: Wed, 20 Mar 2013 00:30:21 +0200	[thread overview]
Message-ID: <87obefdnuq.fsf@mail.jurta.org> (raw)
In-Reply-To: <87k3p4fig2.fsf@mail.jurta.org> (Juri Linkov's message of "Tue, 19 Mar 2013 00:35:57 +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")






  reply	other threads:[~2013-03-19 22:30 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-18 10:24 bug#13989: Make Info support footnotes Xue Fuqiao
2013-03-18 22:35 ` Juri Linkov
2013-03-19 22:30   ` Juri Linkov [this message]
2013-03-20  3:50     ` Eli Zaretskii
2013-03-20 23:05       ` Juri Linkov
2013-03-21  8:09         ` Xue Fuqiao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87obefdnuq.fsf@mail.jurta.org \
    --to=juri@jurta.org \
    --cc=13989@debbugs.gnu.org \
    --cc=xfq.free@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.