From 4ee066381cfe941f58040c117fec83a9712cc80a Mon Sep 17 00:00:00 2001 From: Boruch Baum Date: Fri, 22 Dec 2017 21:44:52 -0500 Subject: [PATCH] * lisp/mail/footnote.el: Misc changes in preparation for more (footnote-section-tag-regexp): Don't require the trailing space. (Footnote--point-in-body-p, Footnote--get-area-point-min) (Footnote--get-area-point-max): New functions. (Footnote-narrow-to-footnotes, Footnote-text-under-cursor): Use them. --- lisp/mail/footnote.el | 142 +++++++++++++++++++++++++++++++----------- 1 file changed, 106 insertions(+), 36 deletions(-) diff --git a/lisp/mail/footnote.el b/lisp/mail/footnote.el index 0c39f62f3ee..272672904bf 100644 --- a/lisp/mail/footnote.el +++ b/lisp/mail/footnote.el @@ -3,6 +3,7 @@ ;; Copyright (C) 1997, 2000-2017 Free Software Foundation, Inc. ;; Author: Steven L Baur +;; Boruch Baum ;; Keywords: mail, news ;; Version: 0.19 @@ -29,9 +30,36 @@ ;; [1] Footnotes look something like this. Along with some decorative ;; stuff. -;; TODO: -;; Reasonable Undo support. -;; more language styles. +;;;; TODO: +;; + Reasonable Undo support. +;; - could use an `apply' entry in the buffer-undo-list to be warned when +;; a footnote we inserted is removed via undo. +;; - should try to handle the more general problem of deleting/removing +;; footnotes via standard editing commands rather than via footnote +;; commands. +;; + more language styles. +;; + The key sequence 'C-c ! a C-y C-c ! b' should auto-fill the +;; footnote in adaptive fill mode. This does not seem to be a bug in +;; `adaptive-fill' because it behaves that way on all point movements +;; + Handle footmode mode elegantly in all modes, even if that means refuses to +;; accept the burden. For example, in a programming language mode, footnotes +;; should be commented. +;; + Manually autofilling the a first footnote should not cause it to +;; wrap into the footnote section tag +;; + Current solution adds a second newline after the section tag, so it is +;; clearly a separate paragraph. There may be stylistic objections to this. +;; + Footnotes with multiple paragraphs should not have their first +;; line out-dented. +;; + Upon leaving footnote area, perform an auto-fill on an entire +;; footnote (including multiple paragraphs), or on entire footnote area. +;; + fill-paragraph takes arg REGION, but seemingly only when called +;; interactively. +;; + At some point, it became necessary to change `footnote-section-tag-regexp' +;; to remove its trailing space. (Adaptive fill side-effect?) +;; + useful for lazy testing +;; (setq footnote-narrow-to-footnotes-when-editing t) +;; (setq footnote-section-tag "Footnotes: ") +;; (setq footnote-section-tag-regexp "Footnotes\\(\\[.\\]\\)?:") ;;; Code: @@ -101,11 +129,15 @@ footnotes." :type 'string :group 'footnote) -(defcustom footnote-section-tag-regexp "Footnotes\\(\\[.\\]\\)?: " +(defcustom footnote-section-tag-regexp + ;; Even if `footnote-section-tag' has a trailing space, let's not require it + ;; here, since it might be trimmed by various commands. + "Footnotes\\(\\[.\\]\\)?:" "Regexp which indicates the start of a footnote section. This variable is disregarded when `footnote-section-tag' is the empty string. Customizing this variable has no effect on buffers already displaying footnotes." + :version "27.1" :type 'regexp :group 'footnote) @@ -532,20 +564,15 @@ styles." footnote-end-tag) 'footnote-number to))))) -;; Not needed? +;; Not needed? <-- 2017-12 Boruch: Not my comment! BUT, when I +;; starting hacking the code, this function +;; `Footnote-narrow-to-footnotes' was never narrowing, and the result +;; wasn't breaking anything. (defun Footnote-narrow-to-footnotes () "Restrict text in buffer to show only text of footnotes." - (interactive) ; testing - (goto-char (point-max)) - (when (re-search-backward footnote-signature-separator nil t) - (let ((end (point))) - (cond - ((and (not (string-equal footnote-section-tag "")) - (re-search-backward - (concat "^" footnote-section-tag-regexp) nil t)) - (narrow-to-region (point) end)) - (footnote-text-marker-alist - (narrow-to-region (cdar footnote-text-marker-alist) end)))))) + (interactive) ; testing + (narrow-to-region (Footnote--get-area-point-min) + (Footnote--get-area-point-max))) (defun Footnote-goto-char-point-max () "Move to end of buffer or prior to start of .signature." @@ -625,28 +652,22 @@ styles." (< (car e1) (car e2))))) (defun Footnote-text-under-cursor () - "Return the number of footnote if in footnote text. + "Return the number of the current footnote if in footnote text. Return nil if the cursor is not positioned over the text of a footnote." - (when (and (let ((old-point (point))) - (save-excursion - (save-restriction - (Footnote-narrow-to-footnotes) - (and (>= old-point (point-min)) - (<= old-point (point-max)))))) - footnote-text-marker-alist - (>= (point) (cdar footnote-text-marker-alist))) - (let ((i 1) - alist-txt rc) + (when (and footnote-text-marker-alist + (<= (Footnote--get-area-point-min) + (point) + (Footnote--get-area-point-max))) + (let ((i 1) alist-txt result) (while (and (setq alist-txt (nth i footnote-text-marker-alist)) - (null rc)) - (when (< (point) (cdr alist-txt)) - (setq rc (car (nth (1- i) footnote-text-marker-alist)))) - (setq i (1+ i))) - (when (and (null rc) - (null alist-txt)) - (setq rc (car (nth (1- i) footnote-text-marker-alist)))) - rc))) + (null result)) + (when (< (point) (cdr alist-txt)) + (setq result (car (nth (1- i) footnote-text-marker-alist)))) + (setq i (1+ i))) + (when (and (null result) (null alist-txt)) + (setq result (car (nth (1- i) footnote-text-marker-alist)))) + result))) (defun Footnote-under-cursor () "Return the number of the footnote underneath the cursor. @@ -654,6 +675,53 @@ Return nil if the cursor is not over a footnote." (or (get-text-property (point) 'footnote-number) (Footnote-text-under-cursor))) +(defun Footnote--point-in-body-p () + "Return non-nil if point is in the buffer text area, +i.e. before the beginning of the footnote area." + (< (point) (Footnote--get-area-point-min))) + +(defun Footnote--get-area-point-min (&optional before-tag) + "Return start of the first footnote. +If there is no footnote area, returns `point-max'. +With optional arg BEFORE-TAG, return position of the `footnote-section-tag' +instead, if applicable." + (cond + ;; FIXME: Shouldn't we use `Footnote--get-area-point-max' instead? + ((not footnote-text-marker-alist) (point-max)) + ((not before-tag) (cdr (first footnote-text-marker-alist))) + ((string-equal footnote-section-tag "") + (cdr (first footnote-text-marker-alist))) + (t + (save-excursion + (goto-char (cdr (first footnote-text-marker-alist))) + (if (re-search-backward (concat "^" footnote-section-tag-regexp) nil t) + (match-beginning 0) + (message "Footnote section tag not found!") + ;; This `else' should never happen, and indicates an error, + ;; ie. footnotes already exist and a footnote-section-tag is defined, + ;; but the section tag hasn't been found. We choose to assume that the + ;; user deleted it intentionally and wants us to behave in this buffer + ;; as if the section tag was set "", so we do that, now. + ;;(setq footnote-section-tag "") + ;; + ;; HOWEVER: The rest of footnote mode does not currently honor or + ;; account for this. + ;; + ;; To illustrate the difference in behavior, create a few footnotes, + ;; delete the section tag, and create another footnote. Then undo, + ;; comment the above line (that sets the tag to ""), re-evaluate this + ;; function, and repeat. + ;; + ;; TODO: integrate sanity checks at reasonable operational points. + (cdr (first footnote-text-marker-alist))))))) + +(defun Footnote--get-area-point-max () + "Return the end of footnote area. +This is either `point-max' or the start of a `.signature' string, as +defined by variable `footnote-signature-separator'. If there is no +footnote area, returns `point-max'." + (save-excursion (Footnote-goto-char-point-max))) + ;;; User functions (defun Footnote-make-hole () @@ -739,7 +807,7 @@ delete the footnote with that number." (point) (if footnote-spaced-footnotes (search-forward "\n\n" nil t) - (save-restriction + (save-restriction ; <= 2017-12 Boruch: WHY?? I see no narrowing / widening here. (end-of-line) (next-single-char-property-change (point) 'footnote-number nil (Footnote-goto-char-point-max)))))) @@ -855,6 +923,8 @@ play around with the following keys: (make-local-variable 'footnote-start-tag) (make-local-variable 'footnote-end-tag) + ;; filladapt is an XEmacs package which AFAIK has never been ported + ;; to Emacs. (when (boundp 'filladapt-token-table) ;; add tokens to filladapt to match footnotes ;; 1] xxxxxxxxxxx x x x or [1] x x x x x x x -- 2.39.2