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))