From 9f5c252f93f2e1bb187b57760523e08df662abac Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Thu, 8 Jun 2017 00:57:38 +0200 Subject: [PATCH] org-src: Fix footnote reference remote editing * lisp/org-src.el (org-edit-footnote-reference): Do not collapse footnote definitions after editing remotely one of them. * testing/lisp/test-org-src.el (test-org-src/footnote-references): New test. --- lisp/org-src.el | 69 +++++++++++++++++++++--------------------- testing/lisp/test-org-src.el | 71 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 34 deletions(-) diff --git a/lisp/org-src.el b/lisp/org-src.el index 062f3b553..0e04d4b5a 100644 --- a/lisp/org-src.el +++ b/lisp/org-src.el @@ -810,45 +810,46 @@ A coderef format regexp can only match at the end of a line." (org-footnote-goto-definition label) (backward-char) (org-element-context))) - (inline (eq (org-element-type definition) 'footnote-reference)) + (inline? (eq 'footnote-reference (org-element-type definition))) (contents - (let ((c (org-with-wide-buffer - (org-trim (buffer-substring-no-properties - (org-element-property :begin definition) - (org-element-property :end definition)))))) - (add-text-properties - 0 - (progn (string-match (if inline "\\`\\[fn:.*?:" "\\`.*?\\]") c) - (match-end 0)) - '(read-only "Cannot edit footnote label" front-sticky t - rear-nonsticky t) - c) - (when inline - (let ((l (length c))) - (add-text-properties - (1- l) l - '(read-only "Cannot edit past footnote reference" - front-sticky nil rear-nonsticky nil) - c))) - c))) + (org-with-wide-buffer + (buffer-substring-no-properties + (or (org-element-property :post-affiliated definition) + (org-element-property :begin definition)) + (cond + (inline? (1+ (org-element-property :contents-end definition))) + ((org-element-property :contents-end definition)) + (t (goto-char (org-element-property :post-affiliated definition)) + (line-end-position))))))) + (add-text-properties + 0 + (progn (string-match (if inline? "\\`\\[fn:.*?:" "\\`.*?\\]") contents) + (match-end 0)) + '(read-only "Cannot edit footnote label" front-sticky t rear-nonsticky t) + contents) + (when inline? + (let ((l (length contents))) + (add-text-properties + (1- l) l + '(read-only "Cannot edit past footnote reference" + front-sticky nil rear-nonsticky nil) + contents))) (org-src--edit-element definition (format "*Edit footnote [%s]*" label) #'org-mode - `(lambda () - (if ,(not inline) (delete-region (point) (search-forward "]")) - (delete-region (point) (search-forward ":" nil t 2)) - (delete-region (1- (point-max)) (point-max)) - (when (re-search-forward "\n[ \t]*\n" nil t) - (user-error "Inline definitions cannot contain blank lines")) - ;; If footnote reference belongs to a table, make sure to - ;; remove any newline characters in order to preserve - ;; table's structure. - (when ,(org-element-lineage definition '(table-cell)) - (while (search-forward "\n" nil t) (delete-char -1))))) - (concat contents - (and (not (org-element-property :contents-begin definition)) - " ")) + (lambda () + (if (not inline?) (delete-region (point) (search-forward "]")) + (delete-region (point) (search-forward ":" nil t 2)) + (delete-region (1- (point-max)) (point-max)) + (when (re-search-forward "\n[ \t]*\n" nil t) + (user-error "Inline definitions cannot contain blank lines")) + ;; If footnote reference belongs to a table, make sure to + ;; remove any newline characters in order to preserve + ;; table's structure. + (when (org-element-lineage definition '(table-cell)) + (while (search-forward "\n" nil t) (replace-match ""))))) + contents 'remote)) ;; Report success. t)) diff --git a/testing/lisp/test-org-src.el b/testing/lisp/test-org-src.el index 853e15b45..9bf6644ad 100644 --- a/testing/lisp/test-org-src.el +++ b/testing/lisp/test-org-src.el @@ -365,5 +365,76 @@ This is a tab:\t. (org-edit-src-exit) (buffer-string)))))) +(ert-deftest test-org-src/footnote-references () + "Test editing footnote references." + ;; Error when there is no definition to edit. + (should-error + (org-test-with-temp-text "A footnote[fn:1]" + (org-edit-special))) + ;; Error when trying to edit an anonymous footnote. + (should-error + (org-test-with-temp-text "A footnote[fn::edit me!]" + (org-edit-special))) + ;; Edit a regular definition. + (should + (equal "[fn:1] Definition" + (org-test-with-temp-text "A footnote[fn:1]\n[fn:1] Definition" + (org-edit-special) + (prog1 (buffer-string) (org-edit-src-exit))))) + ;; Label should be protected against editing. + (should + (org-test-with-temp-text "A footnote[fn:1]\n[fn:1] Definition" + (org-edit-special) + (prog1 (get-text-property 0 'read-only (buffer-string)) + (org-edit-src-exit)))) + (should + (org-test-with-temp-text "A footnote[fn:1]\n[fn:1] Definition" + (org-edit-special) + (prog1 (get-text-property 5 'read-only (buffer-string)) + (org-edit-src-exit)))) + ;; Edit a regular definition. + (should + (equal + "A footnote[fn:1][fn:2]\n[fn:1] D1\n\n[fn:2] D2" + (org-test-with-temp-text + "A footnote[fn:1][fn:2]\n[fn:1] D1\n\n[fn:2] D2" + (org-edit-special) + (org-edit-src-exit) + (buffer-string)))) + ;; Edit an inline definition. + (should + (equal + "[fn:1:definition]" + (org-test-with-temp-text + "An inline[fn:1] footnote[fn:1:definition]" + (org-edit-special) + (prog1 (buffer-string) (org-edit-src-exit))))) + ;; Label and closing square bracket should be protected against + ;; editing. + (should + (org-test-with-temp-text "An inline[fn:1] footnote[fn:1:definition]" + (org-edit-special) + (prog1 (get-text-property 0 'read-only (buffer-string)) + (org-edit-src-exit)))) + (should + (org-test-with-temp-text "An inline[fn:1] footnote[fn:1:definition]" + (org-edit-special) + (prog1 (get-text-property 5 'read-only (buffer-string)) + (org-edit-src-exit)))) + (should + (org-test-with-temp-text "An inline[fn:1] footnote[fn:1:definition]" + (org-edit-special) + (prog1 (get-text-property 16 'read-only (buffer-string)) + (org-edit-src-exit)))) + ;; Do not include trailing white spaces when displaying the inline + ;; footnote definition. + (should + (equal + "[fn:1:definition]" + (org-test-with-temp-text + "An inline[fn:1] footnote[fn:1:definition] and some text" + (org-edit-special) + (prog1 (buffer-string) (org-edit-src-exit)))))) + (provide 'test-org-src) ;;; test-org-src.el ends here -- 2.11.4.GIT