* [Footnote-mode]: alignment option [CODE included]
@ 2017-12-07 6:18 Boruch Baum
2017-12-08 16:50 ` Stefan Monnier
0 siblings, 1 reply; 3+ messages in thread
From: Boruch Baum @ 2017-12-07 6:18 UTC (permalink / raw)
To: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 798 bytes --]
Hi. I'm not a member of the list, but I wanted to share some code that I
think would be useful for emacs users...
The attached code allows one to left-justify footnote text from the
first column of text, instead of from the left margin. I find this
aesthetically preferable, especially when I have long footnotes.
Once the code is evaluated and one has footnote-mode enabled, `C-c ! q'
toggles the feature. Then, whenever one performs an auto-fill, `M-q'',
feature acts. Of course, if one has visual-line-mode enabled, the
auto-fill acts automatically.
The current code is set up as defadvice-s (that's how long I've ended up
sitting on it), but if emacs wants it integrated into the mode, there's
no need for that.
--
hkp://keys.gnupg.net
CA45 09B5 5351 7C11 A9D1 7286 0036 9E45 1595 8BC0
[-- Attachment #2: footnote-snippet.el --]
[-- Type: text/plain, Size: 2471 bytes --]
;━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
; Footnote behavior customization
; + left-align footnote text to first character of first paragraph,
; not to left margin.
; + Instructions:
; + toggle the feature using 'mode-map-prexic q' (usually 'C-c ! q')
; + whenever you run `auto-fill' (M-q), it will act
; + if you set visual-line-mode, it acts automatically
(require 'footnote)
(setq Footnote-align-to-fn-text t
body-auto-fill-prefix nil)
(defun Footnote-calc-fn-alignment-column()
(+ footnote-body-tag-spacing
(length
(concat footnote-start-tag footnote-end-tag
(Footnote-index-to-string
(caar (last footnote-text-marker-alist)))))))
(defun Footnote-align-to-fn()
(when Footnote-align-to-fn-text
(setq body-auto-fill-prefix fill-prefix
fill-prefix (make-string (Footnote-calc-fn-alignment-column) 32))))
(defun Footnote-align-to-body()
(when (not Footnote-align-to-fn-text)
(setq fill-prefix body-auto-fill-prefix)))
(defun Footnote-toggle-alignment()
(interactive)
(setq Footnote-align-to-fn-text (not Footnote-align-to-fn-text))
(when footnote-text-marker-alist
(if (>= (point) (cdr (first footnote-text-marker-alist)))
(if Footnote-align-to-fn-text
(Footnote-align-to-fn)
(Footnote-align-to-body))))
(if Footnote-align-to-fn-text
(message "Footnotes will left-align to footnote text")
(message "Footnotes will left-align to body text")))
(define-key footnote-mode-map
(kbd "q") 'Footnote-toggle-alignment)
(defadvice Footnote-add-footnote (after update-auto-fill-prefix activate)
(interactive)
(Footnote-align-to-fn))
(defadvice Footnote-back-to-message (after restore-auto-fill-prefix
activate)
(interactive)
(setq fill-prefix body-auto-fill-prefix))
(defadvice Footnote-add-footnote (around abort-when-in-fn-area activate)
(interactive)
(if (or
(not footnote-text-marker-alist)
(< (point) (cdr (first footnote-text-marker-alist))))
ad-do-it
(message "Add footnotes only while in text body")))
;━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Footnote-mode]: alignment option [CODE included]
2017-12-07 6:18 [Footnote-mode]: alignment option [CODE included] Boruch Baum
@ 2017-12-08 16:50 ` Stefan Monnier
[not found] ` <jwvbmiylnmn.fsf-monnier+gmane.emacs.devel@gnu.org>
0 siblings, 1 reply; 3+ messages in thread
From: Stefan Monnier @ 2017-12-08 16:50 UTC (permalink / raw)
To: emacs-devel
> The attached code allows one to left-justify footnote text from the
> first column of text, instead of from the left margin. I find this
> aesthetically preferable, especially when I have long footnotes.
Could you give some example of the difference?
> Of course, if one has visual-line-mode enabled, the
> auto-fill acts automatically.
Hmm... how does visual-line-mode pay attention to
Footnote-align-to-fn-text (and know if it's inside a footnote)?
> The current code is set up as defadvice-s (that's how long I've ended up
> sitting on it), but if emacs wants it integrated into the mode, there's
> no need for that.
Of course. Some comments about the code:
> (defun Footnote-align-to-fn()
> (when Footnote-align-to-fn-text
> (setq body-auto-fill-prefix fill-prefix
> fill-prefix (make-string (Footnote-calc-fn-alignment-column) 32))))
IIUC body-auto-fill-prefix is just a var into which we temporarily save
the normal fill-prefix. So this should be named with a "[Ff]ootnote-"
prefix (arguably with a "--" somewhere to make it clear it's an
internal variable), and it should be made buffer-local (so there's no
cross-buffer pollution).
The more serious problem is that `fill-prefix' is set with no guarantee
it will be reset to its proper value later. E.g. if the user returns to
the body "manually" rather than via Footnote-back-to-message.
> (defun Footnote-toggle-alignment()
> (interactive)
> (setq Footnote-align-to-fn-text (not Footnote-align-to-fn-text))
> (when footnote-text-marker-alist
> (if (>= (point) (cdr (first footnote-text-marker-alist)))
> (if Footnote-align-to-fn-text
> (Footnote-align-to-fn)
> (Footnote-align-to-body))))
> (if Footnote-align-to-fn-text
> (message "Footnotes will left-align to footnote text")
> (message "Footnotes will left-align to body text")))
I suggest you make this into a minor mode:
(define-minor-mode Footnote-align-to-text
"When enabled, align footnote to the text rather than to the margin."
:lighter nil
(when footnote-text-marker-alist
(if (>= (point) (cdr (first footnote-text-marker-alist)))
(if Footnote-align-to-text
(Footnote-align-to-fn)
(Footnote-align-to-body)))))
> (defadvice Footnote-add-footnote (around abort-when-in-fn-area activate)
> (interactive)
> (if (or
> (not footnote-text-marker-alist)
> (< (point) (cdr (first footnote-text-marker-alist))))
> ad-do-it
> (message "Add footnotes only while in text body")))
I don't see how this relates to this new alignment feature.
Stefan
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Footnote-mode]: alignment option [CODE included]
[not found] ` <jwvbmiylnmn.fsf-monnier+gmane.emacs.devel@gnu.org>
@ 2017-12-18 0:13 ` Boruch Baum
0 siblings, 0 replies; 3+ messages in thread
From: Boruch Baum @ 2017-12-18 0:13 UTC (permalink / raw)
To: Stefan Monnier, Emacs-Devel List
[-- Attachment #1: Type: text/plain, Size: 2434 bytes --]
On 2017-12-16 10:05, Stefan Monnier wrote:
> Have you seen my reply last week in emacs-devel?
No. Thanks for contacting me off-list about it.
>> The attached code allows one to left-justify footnote text from the
>> first column of text, instead of from the left margin. I find this
>> aesthetically preferable, especially when I have long footnotes.
> Could you give some example of the difference?
Sure. The current behavior is:
[1] Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec
hendrerit tempor tellus. Donec pretium posuere tellus. Proin quam nisl,
The proposed optional alternative is:
[1] Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec
hendrerit tempor tellus. Donec pretium posuere tellus. Proin quam
>> Of course, if one has visual-line-mode enabled, the auto-fill acts
>> automatically.
> Hmm... how does visual-line-mode pay attention to
> Footnote-align-to-fn-text (and know if it's inside a footnote)?
I double-checked, and I wrote incorrectly.
> Some comments about the code:
>
> body-auto-fill-prefix is just a var into which we temporarily save
> the normal fill-prefix. So this should be named with a "[Ff]ootnote-"
> prefix (arguably with a "--" somewhere to make it clear it's an
> internal variable), and it should be made buffer-local (so there's no
> cross-buffer pollution).
Done. Note that the file `footnote.el' currently has all its `Private
variables' labeled without the "--" convention.
> The more serious problem is that `fill-prefix' is set with no guarantee
> it will be reset to its proper value later. E.g. if the user returns to
> the body "manually" rather than via Footnote-back-to-message.
Yes. Corrected.
> I suggest you make this into a minor mode:
Why a minor mode just for a small option of another minor mode?
>> (defadvice Footnote-add-footnote (around abort-when-in-fn-area activate)
> I don't see how this relates to this new alignment feature.
You're correct. It was part of my personal configuration to address a
bug that I had neglected to report, now emacs-bug#29756.
UPDATE:
=======
The updated code is attached, in two forms: 1) As a patch to the 25.2
version of footnote.el (ie. fully integrated into footnote mode without
any need for advising, and; 2) As a snippet, with the feature's
functions advised around the mode's current functions.
--
hkp://keys.gnupg.net
CA45 09B5 5351 7C11 A9D1 7286 0036 9E45 1595 8BC0
[-- Attachment #2: footnote.patch --]
[-- Type: text/x-diff, Size: 5682 bytes --]
--- footnote.el 2017-12-17 18:40:22.940312994 -0500
+++ footnote.el_new 2017-12-17 19:00:27.713722813 -0500
@@ -131,6 +131,14 @@ has no effect on buffers already display
:type 'regexp
:group 'footnote)
+(defcustom Footnote-align-to-fn-text t
+"Nil if footnote text is to be aligned flush left with left side
+of the footnote number. Non-nil if footnote text is to be aligned
+left with the first character of footnote text."
+ :type 'boolean
+ :group 'footnote)
+(make-variable-buffer-local 'Footnote-align-to-fn-text)
+
;;; Private variables
(defvar footnote-style-number nil
@@ -148,6 +156,12 @@ has no effect on buffers already display
(defvar footnote-mouse-highlight 'highlight
"Text property name to enable mouse over highlight.")
+(defvar Footnote--body-auto-fill-prefix nil
+"When Footnmote mode modifies variable `fill-prefix', store the
+prior value here, so that it can be restored when leaving the
+footnote area.")
+(make-variable-buffer-local 'Footnote--body-auto-fill-prefix)
+
;;; Default styles
;;; NUMERIC
(defconst footnote-numeric-regexp "[0-9]+"
@@ -609,8 +623,72 @@ Return nil if the cursor is not over a f
(or (get-text-property (point) 'footnote-number)
(Footnote-text-under-cursor)))
+(defun Footnote--calc-fn-alignment-column()
+"Calculate the left alignment for footnote text."
+ (+ footnote-body-tag-spacing
+ (length
+ (concat footnote-start-tag footnote-end-tag
+ (Footnote-index-to-string
+ (caar (last footnote-text-marker-alist)))))))
+
+(defun Footnote--align-to-body()
+ (when (not Footnote-align-to-fn-text)
+ (setq fill-prefix Footnote--body-auto-fill-prefix)
+ (setq Footnote--body-auto-fill-prefix nil)))
+
+(defun Footnote--point-in-body-p()
+ "Return `t' if point is in the buffer text area, ie. before the beginning of
+the footnote area."
+ ; NOTE: This code is shared with a patch I've proposed for emacs-bug#29756
+ (let
+ ((p (point))
+ (q (if (not footnote-text-marker-alist) (point-max)
+ (if (string-equal footnote-section-tag "")
+ (cdr (first footnote-text-marker-alist))
+ (goto-char (cdr (first footnote-text-marker-alist)))
+ (if (re-search-backward
+ (concat "^" footnote-section-tag-regexp) nil t)
+ (match-beginning 0)
+ ; 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.
+ (cdr (first footnote-text-marker-alist))
+ )))))
+ (goto-char p) ; undo `re-search-backward' side-effect
+ (if (< p q) t nil)))
+
;;; User functions
+(defun Footnote-toggle-alignment()
+ "Change whether footnote text is aligned flush left with the
+left of a footnote's number, or flush left with the first
+character of footnote text on the footnote's first line."
+ (interactive)
+ (setq Footnote-align-to-fn-text (not Footnote-align-to-fn-text))
+ (when footnote-text-marker-alist
+ (if (>= (point) (cdr (first footnote-text-marker-alist)))
+ (if Footnote-align-to-fn-text
+ (Footnote--align-to-fn)
+ (Footnote--align-to-body))))
+ (if Footnote-align-to-fn-text
+ (message "Footnotes will left-align to footnote text")
+ (message "Footnotes will left-align to body text")))
+
+(defun Footnote-fill-paragraph(&optional justify region)
+ (when (and (Footnote--point-in-body-p) Footnote--body-auto-fill-prefix)
+ (setq fill-prefix Footnote--body-auto-fill-prefix)
+ (setq Footnote--body-auto-fill-prefix nil))
+ (fill-paragraph justify region))
+
(defun Footnote-make-hole ()
(save-excursion
(let ((i 0)
@@ -661,7 +739,10 @@ by using `Footnote-back-to-message'."
(Footnote-narrow-to-footnotes)))
;; Emacs/XEmacs bug? save-excursion doesn't restore point when using
;; insert-before-markers.
- (goto-char opoint))))
+ (goto-char opoint))
+ (when Footnote-align-to-fn-text
+ (setq Footnote--body-auto-fill-prefix (or fill-prefix ""))
+ (setq fill-prefix (make-string (Footnote--calc-fn-alignment-column) 32)))))
(defun Footnote-delete-footnote (&optional arg)
"Delete a numbered footnote.
@@ -767,7 +848,9 @@ being set it is automatically widened."
(when note
(when footnote-narrow-to-footnotes-when-editing
(widen))
- (goto-char (cadr (assq note footnote-pointer-marker-alist))))))
+ (goto-char (cadr (assq note footnote-pointer-marker-alist)))
+ (setq fill-prefix Footnote--body-auto-fill-prefix)
+ (setq Footnote--body-auto-fill-prefix nil))))
(defvar footnote-mode-map
(let ((map (make-sparse-keymap)))
@@ -778,6 +861,8 @@ being set it is automatically widened."
(define-key map "g" 'Footnote-goto-footnote)
(define-key map "r" 'Footnote-renumber-footnotes)
(define-key map "s" 'Footnote-set-style)
+ (define-key map (kbd "M-q") 'Footnote-toggle-alignment)
+ (define-key map [remap fill-paragraph] 'Footnote-fill-paragraph)
map))
(defvar footnote-minor-mode-map
[-- Attachment #3: footnote-snippet.el --]
[-- Type: text/plain, Size: 6030 bytes --]
l;━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
; Footnote behavior customization
; + left-align footnote text to first character of first paragraph,
; not to left margin.
; + Instructions:
; + toggle the feature using 'mode-map-prefix M-q' (usually 'C-c ! M-q')
; + whenever you run `auto-fill' (M-q), it will act
; + if you set visual-line-mode, it acts automatically
(require 'footnote)
(defcustom Footnote-align-to-fn-text t
"Nil if footnote text is to be aligned flush left with left side
of the footnote number. Non-nil if footnote text is to be aligned
left with the first character of footnote text."
:type 'boolean
:group 'footnote)
(make-variable-buffer-local 'Footnote-align-to-fn-text)
(defvar Footnote--body-auto-fill-prefix nil
"When Footnmote mode modifies variable `fill-prefix', store the
prior value here, so that it can be restored when leaving the
footnote area.")
(make-variable-buffer-local 'Footnote--body-auto-fill-prefix)
(defun Footnote--calc-fn-alignment-column()
"Calculate the left alignment for footnote text."
(+ footnote-body-tag-spacing
(length
(concat footnote-start-tag footnote-end-tag
(Footnote-index-to-string
(caar (last footnote-text-marker-alist)))))))
(defun Footnote--align-to-fn()
"For the purpose of this feature proposal (only), this function is an advice :after
function `Footnote-add-footnote'. For implementation within emacs, the code would
be included at the end of that function."
; TODO: If the length has changed, eg. when adding footnote [10] after having
; footnote [9], refresh all footnotes with new alignment.
(when Footnote-align-to-fn-text
(setq Footnote--body-auto-fill-prefix (or fill-prefix ""))
(setq fill-prefix (make-string (Footnote--calc-fn-alignment-column) 32))))
(defun Footnote--align-to-body()
(when (not Footnote-align-to-fn-text)
(setq fill-prefix Footnote--body-auto-fill-prefix)
(setq Footnote--body-auto-fill-prefix nil)))
(defun Footnote--return-to-body(arg)
"For the purpose of this feature proposal (only), this function is an advice :after
function `Footnote-back-to-message'. For implementation within emacs, the code would
be included at the end of that function."
(setq fill-prefix Footnote--body-auto-fill-prefix)
(setq Footnote--body-auto-fill-prefix nil))
(defun Footnote--point-in-body-p()
"Return `t' if point is in the buffer text area, ie. before the beginning of
the footnote area."
; NOTE: This code is shared with a patch I've proposed for emacs-bug#29756
(let
((p (point))
(q (if (not footnote-text-marker-alist) (point-max)
(if (string-equal footnote-section-tag "")
(cdr (first footnote-text-marker-alist))
(goto-char (cdr (first footnote-text-marker-alist)))
(if (re-search-backward
(concat "^" footnote-section-tag-regexp) nil t)
(match-beginning 0)
; 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.
(cdr (first footnote-text-marker-alist))
)))))
(goto-char p) ; undo `re-search-backward' side-effect
(if (< p q) t nil)))
(defun Footnote--fill-paragraph-in-body(orig-function &optional justify region)
"For the purpose of this feature proposal (only), this function is an advice :before
function `fill-paragraph' to ensure that variable `fill-prefix' is correctly restored
and maintained when dealing with footnotes potentially possessing a different
`fill-prefix' value. This is meant to cover cases of the user manually returning to
the buffer text from the footnote area instead of using the function
`Footnote-back-to-message'.
For the purpose of implementation within emacs, this function would be a remap of
`fill-paragraph', specific to the `Footnote-mode' minor mode."
(when (and footnote-mode (Footnote--point-in-body-p) Footnote--body-auto-fill-prefix)
(setq fill-prefix Footnote--body-auto-fill-prefix)
(setq Footnote--body-auto-fill-prefix nil)))
(defun Footnote-toggle-alignment()
"Change whether footnote text is aligned flush left with the
left of a footnote's number, or flush left with the first
character of footnote text on the footnote's first line."
(interactive)
(setq Footnote-align-to-fn-text (not Footnote-align-to-fn-text))
(when footnote-text-marker-alist
(if (>= (point) (cdr (first footnote-text-marker-alist)))
(if Footnote-align-to-fn-text
(Footnote--align-to-fn)
(Footnote--align-to-body))))
(if Footnote-align-to-fn-text
(message "Footnotes will left-align to footnote text")
(message "Footnotes will left-align to body text")))
(define-key footnote-mode-map
(kbd "M-q") 'Footnote-toggle-alignment)
(advice-add 'Footnote-add-footnote :after #'Footnote--align-to-fn)
(advice-add 'Footnote-back-to-message :after #'Footnote--return-to-body)
(advice-add 'fill-paragraph :before #'Footnote--fill-paragraph-in-body)
;━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-12-18 0:13 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-12-07 6:18 [Footnote-mode]: alignment option [CODE included] Boruch Baum
2017-12-08 16:50 ` Stefan Monnier
[not found] ` <jwvbmiylnmn.fsf-monnier+gmane.emacs.devel@gnu.org>
2017-12-18 0:13 ` Boruch Baum
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).