branch: scratch/rfc-mode
commit 1ae16d2fb877f0b8542aa56e728bfc091b08a1fd
Author: Daniel Martín <mardan...@yahoo.es>
Commit: Daniel Martín <mardan...@yahoo.es>

    Implement a command to navigate to existing sections
    
    Pressing "g" will ask the user for a RFC document section to navigate
    to. The last section that was navigated to is suggested as a default
    in the prompt.
    
    * rfc-mode.el (rfc-mode--titles): Variable that keeps a list of
    section titles.
    (rfc-mode--last-title): Variable that keeps the last section title
    that was navigated to.
    (rfc-mode-map): Bind command to g.
    (rfc-mode-goto-section): New command to navigate to a RFC section.
    (rfc-mode-highlight): Generate the rfc-mode--titles info.
---
 rfc-mode.el | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/rfc-mode.el b/rfc-mode.el
index 67a5c9989a..2943485138 100644
--- a/rfc-mode.el
+++ b/rfc-mode.el
@@ -94,6 +94,13 @@ Assume RFC documents are named as e.g. rfc21.txt, 
rfc-index.txt."
 (defconst rfc-mode-title-regexp "^\\(?:[0-9]+\\.\\)+\\(?:[0-9]+\\)? .*$"
   "Regular expression to model section titles in RFC documents.")
 
+(defvar rfc-mode--titles nil
+  "Buffer-local variable that keeps a list of section titles in this RFC.")
+(make-variable-buffer-local 'rfc-mode--titles)
+
+(defvar rfc-mode--last-title nil
+  "Last section title that the user visited.")
+
 ;;; Keys:
 
 (defvar rfc-mode-map
@@ -104,6 +111,7 @@ Assume RFC documents are named as e.g. rfc21.txt, 
rfc-index.txt."
     (define-key map (kbd "S-<tab>") 'backward-button)
     (define-key map (kbd "<prior>") 'rfc-mode-backward-page)
     (define-key map (kbd "<next>") 'rfc-mode-forward-page)
+    (define-key map (kbd "g") 'rfc-mode-goto-section)
     (define-key map (kbd "n") 'rfc-mode-next-section)
     (define-key map (kbd "p") 'rfc-mode-previous-section)
     map)
@@ -137,6 +145,32 @@ Assume RFC documents are named as e.g. rfc21.txt, 
rfc-index.txt."
   (rfc-mode-previous-header)
   (recenter 0))
 
+(defun rfc-mode-goto-section (section)
+  "Move point to SECTION."
+  (interactive
+   (let* ((default (if (member rfc-mode--last-title rfc-mode--titles)
+                       rfc-mode--last-title
+                     (car rfc-mode--titles)))
+          (completion-ignore-case t)
+          (prompt (concat "Go to section (default " default "): "))
+          (chosen (completing-read prompt rfc-mode--titles
+                                   nil nil nil nil default)))
+     (list chosen)))
+  (setq rfc-mode--last-title section)
+  (unless (rfc-mode--goto-section section)
+    (error "Section %s not found" section)))
+
+(defun rfc-mode--goto-section (section)
+  "Move point to SECTION if it exists, otherwise don't move point.
+Returns t if section is found, nil otherwise."
+  (let ((curpos (point))
+       (case-fold-search nil))
+    (goto-char (point-min))
+    (if (re-search-forward (concat "^" section) (point-max) t)
+       (progn (beginning-of-line) t)
+      (goto-char curpos)
+      nil)))
+
 (defun rfc-mode-next-section (n)
   "Move point to Nth next section (default 1)."
   (interactive "p")
@@ -196,6 +230,7 @@ Assume RFC documents are named as e.g. rfc21.txt, 
rfc-index.txt."
 
 (defun rfc-mode-highlight ()
   "Highlight the current buffer."
+  (setq rfc-mode--titles nil)
   (with-silent-modifications
     (let ((inhibit-read-only t))
       ;; Headers
@@ -217,7 +252,10 @@ Assume RFC documents are named as e.g. rfc21.txt, 
rfc-index.txt."
                 (end (match-end 0)))
             (put-text-property start end
                                'face 'rfc-mode-document-section-title-face)
+            (push (match-string 0) rfc-mode--titles)
             (goto-char end))))
+      ;; Keep titles in expected top to bottom order.
+      (setq rfc-mode--titles (nreverse rfc-mode--titles))
       ;; RFC references
       (save-excursion
         (goto-char (point-min))

Reply via email to