From 48af4166fde469aaced46d70f01c39d460bd0f86 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Wed, 17 Aug 2016 23:43:38 +0200 Subject: [PATCH] Consider edit buffers in `org-src-coderef-regexp' * lisp/org-src.el (org-src-coderef-format): New function (org-src-coderef-regexp): Change signature. * lisp/ob-core.el (org-babel--normalize-body): * lisp/ox.el (org-export-unravel-code): Use new functions. * testing/lisp/test-org-src.el (test-org-src/coderef-format): New test. --- lisp/ob-core.el | 3 +- lisp/org-src.el | 37 ++++++++++--- lisp/ox.el | 7 ++- testing/lisp/test-org-src.el | 104 +++++++++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 13 deletions(-) diff --git a/lisp/ob-core.el b/lisp/ob-core.el index 4b497d3f3..3a456d5a2 100644 --- a/lisp/ob-core.el +++ b/lisp/ob-core.el @@ -555,7 +555,8 @@ character and coderef labels when appropriate." ;; paragraph filling. Treat them as a white space. (replace-regexp-in-string "\n[ \t]*" " " body) (let ((body (replace-regexp-in-string - (org-src-coderef-regexp datum) "" body nil nil 1))) + (org-src-coderef-regexp (org-src-coderef-format datum)) "" + body nil nil 1))) (if (or org-src-preserve-indentation (org-element-property :preserve-indent datum)) body diff --git a/lisp/org-src.el b/lisp/org-src.el index 6dceabf1f..172c33b01 100644 --- a/lisp/org-src.el +++ b/lisp/org-src.el @@ -715,19 +715,38 @@ If BUFFER is non-nil, test it instead." org-src-window-setup) (pop-to-buffer-same-window buffer)))) -(defun org-src-coderef-regexp (element) - "Return regexp matching coderef for ELEMENT. +(defun org-src-coderef-format (&optional element) + "Return format string for block at point. -ELEMENT has a `src-block' or `example-block' type. +When optional argument ELEMENT is provided, use that block. +Otherwise, assume point is either at a source block, at an +example block. + +If point is in an edit buffer, retrieve format string associated +to the remote source block." + (cond + ((and element (org-element-property :label-fmt element))) + ((org-src-edit-buffer-p) (org-src-do-at-code-block (org-src-coderef-format))) + ((org-element-property :label-fmt (org-element-at-point))) + (t org-coderef-label-format))) + +(defun org-src-coderef-regexp (fmt &optional label) + "Return regexp matching a coderef format string FMT. + +When optional argument LABEL is non-nil, match coderef for that +label only. Match group 1 contains the full coderef string with surrounding white spaces. Match group 2 contains the same string without any -surrounding space. Match group 3 contains the label." - (let ((label (regexp-quote (or (org-element-property :label-fmt element) - org-coderef-label-format)))) - (format "\\S-\\([ \t]*\\(%s\\)[ \t]*\\)$" - (replace-regexp-in-string - "%s" "\\([-a-zA-Z0-9_ ]+\\)" label nil t)))) +surrounding space. Match group 3 contains the label. + +A coderef format regexp can only match at the end of a line." + (format "\\S-\\([ \t]*\\(%s\\)[ \t]*\\)$" + (replace-regexp-in-string + "%s" + (if label (regexp-quote label) "\\([-a-zA-Z0-9_ ]+\\)") + (regexp-quote fmt) + nil t))) (defun org-edit-footnote-reference () "Edit definition of footnote reference at point." diff --git a/lisp/ox.el b/lisp/ox.el index ed0a27da8..aeb5d4909 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -79,8 +79,9 @@ (declare-function org-publish "ox-publish" (project &optional force async)) (declare-function org-publish-all "ox-publish" (&optional force async)) (declare-function org-publish-current-file "ox-publish" (&optional force async)) -(declare-function org-publish-current-project "ox-publish" - (&optional force async)) +(declare-function org-publish-current-project "ox-publish" (&optional force async)) +(declare-function org-src-coderef-format "org-src" (&optional element)) +(declare-function org-src-coderef-regexp "org-src" (fmt &optional label)) (defvar org-publish-project-alist) (defvar org-table-number-fraction) @@ -4531,7 +4532,7 @@ reference on that line (string)." value (org-remove-indentation value))))) ;; Build a regexp matching a loc with a reference. - (ref-re (org-src-coderef-regexp element))) + (ref-re (org-src-coderef-regexp (org-src-coderef-format element)))) ;; Return value. (cons ;; Code with references removed. diff --git a/testing/lisp/test-org-src.el b/testing/lisp/test-org-src.el index bc6ef169d..656a5d73e 100644 --- a/testing/lisp/test-org-src.el +++ b/testing/lisp/test-org-src.el @@ -133,5 +133,109 @@ This is a tab:\t. (org-edit-src-exit) (buffer-string)))))) +(ert-deftest test-org-src/coderef-format () + "Test `org-src-coderef-format' specifications." + ;; Regular tests in a src block, an example block and an edit + ;; buffer. + (should + (equal "foo" + (let ((org-coderef-label-format "foo")) + (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp\n0\n#+END_SRC" + (org-src-coderef-format))))) + (should + (equal "foo" + (let ((org-coderef-label-format "foo")) + (org-test-with-temp-text "#+BEGIN_EXAMPLE\n0\n#+END_EXAMPLE" + (org-src-coderef-format))))) + (should + (equal "foo" + (let ((org-coderef-label-format "foo") result) + (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp\n0\n#+END_SRC" + (org-edit-special) + (setq result (org-src-coderef-format)) + (org-edit-src-exit) + result)))) + ;; When a local variable in the source buffer is available, use it. + (should + (equal "bar" + (let ((org-coderef-label-format "foo")) + (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp\n0\n#+END_SRC" + (setq-local org-coderef-label-format "bar") + (org-src-coderef-format))))) + (should + (equal "bar" + (let ((org-coderef-label-format "foo") result) + (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp\n0\n#+END_SRC" + (setq-local org-coderef-label-format "bar") + (org-edit-special) + (setq result (org-src-coderef-format)) + (org-edit-src-exit) + result)))) + ;; Use provided local format even if in an edit buffer. + (should + (equal "bar" + (let ((org-coderef-label-format "foo")) + (org-test-with-temp-text + "#+BEGIN_SRC emacs-lisp -l \"bar\"\n0\n#+END_SRC" + (org-src-coderef-format))))) + (should + (equal "bar" + (let ((org-coderef-label-format "foo") result) + (org-test-with-temp-text + "#+BEGIN_SRC emacs-lisp -l \"bar\"\n0\n#+END_SRC" + (org-edit-special) + (setq result (org-src-coderef-format)) + (org-edit-src-exit) + result)))) + ;; Local format has precedence over local variables. + (should + (equal "bar" + (let ((org-coderef-label-format "foo")) + (org-test-with-temp-text + "#+BEGIN_SRC emacs-lisp -l \"bar\"\n0\n#+END_SRC" + (setq-local org-coderef-label-format "foo") + (org-src-coderef-format))))) + (should + (equal "bar" + (let ((org-coderef-label-format "foo") result) + (org-test-with-temp-text + "#+BEGIN_SRC emacs-lisp -l \"bar\"\n0\n#+END_SRC" + (setq-local org-coderef-label-format "foo") + (org-edit-special) + (setq result (org-src-coderef-format)) + (org-edit-src-exit) + result)))) + ;; When optional argument provides a coderef format string, use it. + (should + (equal "bar" + (let ((org-coderef-label-format "foo") + (element (org-element-create 'src-block '(:label-fmt "bar")))) + (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp\n0\n#+END_SRC" + (org-src-coderef-format element))))) + (should + (equal "baz" + (let ((org-coderef-label-format "foo") + (element (org-element-create 'src-block '(:label-fmt "baz")))) + (org-test-with-temp-text + "#+BEGIN_SRC emacs-lisp -l \"bar\"\n0\n#+END_SRC" + (setq-local org-coderef-label-format "foo") + (org-src-coderef-format element))))) + ;; If it doesn't provide any label format string, fall back to + ;; regular checks. + (should + (equal "foo" + (let ((org-coderef-label-format "foo") + (element (org-element-create 'src-block))) + (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp\n0\n#+END_SRC" + (org-src-coderef-format element))))) + (should + (equal "bar" + (let ((org-coderef-label-format "foo") + (element (org-element-create 'src-block))) + (org-test-with-temp-text + "#+BEGIN_SRC emacs-lisp -l \"bar\"\n0\n#+END_SRC" + (setq-local org-coderef-label-format "foo") + (org-src-coderef-format element)))))) + (provide 'test-org-src) ;;; test-org-src.el ends here