Open unlaered opened 7 years ago
sorry to bump an old feature request but figure it's better than adding a new one. Is there anything I can do to help with this (I'm not competent at Lisp sadly)?
I'm not sure sort feature is like this ?
diff --git a/markdown-mode.el b/markdown-mode.el
index a04f11d..54ec655 100644
--- a/markdown-mode.el
+++ b/markdown-mode.el
@@ -4538,6 +4538,42 @@ footnote text is found, NIL is returned."
(skip-chars-forward "[ \t]")
(point))))
+(defun markdown-footnote-find-all-marks ()
+ "Collect all footnote mark."
+ (save-excursion
+ (goto-char (point-min))
+ (cl-loop while (re-search-forward "\\[\\([^]]+\\)\\]\\(?:[^:]\\|\\'\\)" nil t)
+ collect (match-string-no-properties 1))))
+
+(defun markdown-footnote-find-all-texts ()
+ "Collect all footnote text."
+ (save-excursion
+ (goto-char (point-min))
+ (cl-loop while (re-search-forward "^ \\{0,3\\}\\[\\([^]]+\\)\\]:" nil t)
+ collect
+ (let ((id (match-string-no-properties 1))
+ (line (line-number-at-pos))
+ (content (buffer-substring-no-properties
+ (line-beginning-position) (line-end-position))))
+ (cons id (list :line line :content content))))))
+
+(defun markdown-footnote-sort ()
+ "Sort footnote text order by appearance."
+ (interactive)
+ (let* ((marks (markdown-footnote-find-all-marks))
+ (texts (markdown-footnote-find-all-texts))
+ (new-lines (sort (mapcar (lambda (e) (plist-get (cdr e) :line)) texts) #'<)))
+ (save-excursion
+ (cl-loop for mark in marks
+ for new-line in new-lines
+ when (assoc-default mark texts)
+ do
+ (progn
+ (goto-char (point-min))
+ (forward-line (1- new-line))
+ (delete-region (line-beginning-position) (line-end-position))
+ (insert (plist-get it :content)))))))
+
(defun markdown-footnote-marker-positions ()
"Return the position and ID of the footnote marker point is on.
The return value is a list (ID START END). If point is not on a
Not really, although that's helpful too. Something similar to Brett Terpstra's unique ids for footnotes tool: https://brettterpstra.com/projects/markdown-service-tools/ would be ideal…
I think this function does the job :
(defun markdown-footnote-find-all-marks ()
"Collect all footnote mark."
(save-excursion
(goto-char (point-min))
(cl-loop while (re-search-forward "\\[\\([^]]+\\)\\]\\(?:[^:]\\|\\'\\)" nil t)
collect (match-string-no-properties 1))))
(defun markdown-footnote-find-all-texts ()
"Collect all footnote text."
(save-excursion
(goto-char (point-min))
(cl-loop while (re-search-forward "^ \\{0,3\\}\\[\\([^]]+\\)\\]:" nil t)
collect
(let ((id (match-string-no-properties 1))
(line (line-number-at-pos))
(content (buffer-substring-no-properties
(line-beginning-position) (line-end-position))))
(cons id (list :line line :content content))))))
(defun markdown-footnote-sort ()
"Sort footnote text order by appearance."
(let* ((marks (markdown-footnote-find-all-marks))
(texts (markdown-footnote-find-all-texts))
(new-lines (sort (mapcar (lambda (e) (plist-get (cdr e) :line)) texts) #'<)))
(save-excursion
(cl-loop for mark in marks
for new-line in new-lines
when (assoc-default mark texts)
do
(progn
(goto-char (point-min))
(forward-line (1- new-line))
(delete-region (line-beginning-position) (line-end-position))
(insert (plist-get it :content)))))))
(defun renumber-footnotes ()
"Renumber footnotes in a Markdown document."
(save-excursion
(goto-char (point-min))
(let ((footnote-counter 1))
(while (re-search-forward "\\[\\^\\([0-9]+\\)\\]" nil t)
(replace-match (concat "[^" (number-to-string footnote-counter) "]"))
(setq footnote-counter (1+ footnote-counter))))))
(defun renumber-footnote-references ()
"Renumber footnote references in a Markdown document."
(save-excursion
(goto-char (point-min))
(let ((footnote-counter 1))
(while (re-search-forward "\\[\\^\\([0-9]+\\)\\]:" nil t)
(replace-match (concat "[^" (number-to-string footnote-counter) "]:"))
(setq footnote-counter (1+ footnote-counter))))))
(defun nb/md-normalize-footnotes ()
"Align footnote references and definitions in a Markdown document."
(interactive)
(markdown-footnote-sort)
(renumber-footnotes)
(renumber-footnote-references))
Org has a useful setting and behavior that I am seeking to replicate when working with Markdown buffers. In org-footnote.el,
org-footnote-auto-adjust
is defined such thatThere's more relevant functions beginning here in org-footnote.el.
What would be the simplest way to renumber footnotes in Markdown buffers? Markdown-mode doesn't seem to provide for this behavior. I don't write code. Aside from asking for a feature request to adapt this code from Org, are there global Emacs sorting functions that, with some find-and-replace ingenuity, can keep my footnotes in Markdown buffers correctly numbered? I know that some Markdown parsers will do sorting and renumbering automatically; for instance, say my Markdown buffer looks like this:
Here I created footnotes 1 and 2 before 3 and 4, and markdown-mode numbers and sorts them (at the end of the buffer) in the order that they were created. Now if I open the file in a preview app like Marked, the footnotes are automatically renumbered and sorted so that they reflect their location in the buffer. And this is something Org can do with its own footnotes. How can I do it with markdown buffers?