Merge branch 'maint'

This commit is contained in:
Nicolas Goaziou 2019-12-22 14:58:14 +01:00
commit 2eeafcaf34
8 changed files with 176 additions and 233 deletions

View File

@ -2940,23 +2940,21 @@ or alternatively
#+cindex: escape syntax, for links
#+cindex: backslashes, in links
Some =\= and =]= characters in the {{{var(LINK)}}} part need to be
"escaped", i.e., preceded by another =\= character. More
specifically, the following character categories, and only them, must
be escaped, in order:
Some =\=, =[= and =]= characters in the {{{var(LINK)}}} part need to
be "escaped", i.e., preceded by another =\= character. More
specifically, the following characters, and only them, must be
escaped:
1. all consecutive =\= characters at the end of the link,
2. any =]= character at the very end of the link,
3. all consecutive =\= characters preceding =][= or =]]= patterns,
4. any =]= character followed by either =[= or =]=.
1. all =[= and =]= characters,
2. every =\= character preceding either =]= or =[=,
3. every =\= character at the end of the link.
#+findex: org-link-escape
Org takes for granted that such links are correctly escaped.
Functions inserting links (see [[*Handling Links]]) take care of this.
You only need to bother about those rules when inserting directly, or
yanking, a URI within square brackets. When in doubt, you may use the
function ~org-link-escape~, which turns a link string into its
properly escaped form.
Functions inserting links (see [[*Handling Links]]) properly escape
ambiguous characters. You only need to bother about the rules above
when inserting directly, or yanking, a URI within square brackets.
When in doubt, you may use the function ~org-link-escape~, which turns
a link string into its escaped form.
Once a link in the buffer is complete, with all brackets present, Org
changes the display so that =DESCRIPTION= is displayed instead of

View File

@ -50,15 +50,11 @@ Org used to percent-encode sensitive characters in the URI part of the
bracket links.
Now, escaping mechanism uses the usual backslash character, according
to the following rules, applied in order:
to the following rules:
1. All consecutive =\= characters at the end of the link must be
escaped;
2. Any =]= character at the very end of the link must be escaped;
3. All consecutive =\= characters preceding =][= or =]]= patterns must
be escaped;
4. Any =]= character followed by either =[= or =]= must be escaped;
5. Others =]= and =\= characters need not be escaped.
1. All =[= and =]= characters in the URI must be escaped;
2. Every =\= character preceding either =[= or =]= must be escaped;
3. Every =\= character at the end of the URI must be escaped.
When in doubt, use the function ~org-link-escape~ in order to turn
a link string into its properly escaped form.

View File

@ -716,12 +716,10 @@ This should be called after the variable `org-link-parameters' has changed."
(rx (seq "[["
;; URI part: match group 1.
(group
;; Allow an even number of backslashes right
;; before the closing bracket.
(or (one-or-more "\\\\")
(and (*? anything)
(not (any "\\"))
(zero-or-more "\\\\"))))
(one-or-more
(or (not (any "[]\\"))
(and "\\" (zero-or-more "\\\\") (any "[]"))
(and (one-or-more "\\") (not (any "[]"))))))
"]"
;; Description (optional): match group 2.
(opt "[" (group (+? anything)) "]")
@ -838,30 +836,21 @@ E.g. \"%C3%B6\" becomes the german o-Umlaut."
(defun org-link-escape (link)
"Backslash-escape sensitive characters in string LINK."
;; Escape closing square brackets followed by another square bracket
;; or at the end of the link. Also escape final backslashes so that
;; we do not escape inadvertently URI's closing bracket.
(with-temp-buffer
(insert link)
(insert (make-string (- (skip-chars-backward "\\\\"))
?\\))
(while (search-backward "\]" nil t)
(when (looking-at-p "\\]\\(?:[][]\\|\\'\\)")
(insert (make-string (1+ (- (skip-chars-backward "\\\\")))
?\\))))
(buffer-string)))
(replace-regexp-in-string
(rx (seq (group (zero-or-more "\\")) (group (or string-end (any "[]")))))
(lambda (m)
(concat (match-string 1 m)
(match-string 1 m)
(and (/= (match-beginning 2) (match-end 2)) "\\")))
link nil t 1))
(defun org-link-unescape (link)
"Remove escaping backslash characters from string LINK."
(with-temp-buffer
(save-excursion (insert link))
(while (re-search-forward "\\(\\\\+\\)\\]\\(?:[][]\\|\\'\\)" nil t)
(replace-match (make-string (/ (- (match-end 1) (match-beginning 1)) 2)
?\\)
nil t nil 1))
(goto-char (point-max))
(delete-char (/ (- (skip-chars-backward "\\\\")) 2))
(buffer-string)))
(replace-regexp-in-string
(rx (group (one-or-more "\\")) (or string-end (any "[]")))
(lambda (_)
(concat (make-string (/ (- (match-end 1) (match-beginning 1)) 2) ?\\)))
link nil t 1))
(defun org-link-make-string (link &optional description)
"Make a bracket link, consisting of LINK and DESCRIPTION.

View File

@ -24,7 +24,9 @@
(signal 'missing-test-dependency "Support for Python code blocks"))
(ert-deftest test-ob-python/colnames-yes-header-argument ()
(org-test-with-temp-text "#+name: eg
(should
(equal '(("col") hline ("a") ("b"))
(org-test-with-temp-text "#+name: eg
| col |
|-----|
| a |
@ -32,30 +34,30 @@
#+header: :colnames yes
#+header: :var x = eg
#+begin_src python
<point>#+begin_src python
return x
#+end_src"
(org-babel-next-src-block)
(should (equal '(("col") hline ("a") ("b"))
(org-babel-execute-src-block)))))
(org-babel-execute-src-block)))))
(ert-deftest test-ob-python/colnames-yes-header-argument-again ()
(org-test-with-temp-text "#+name: less-cols
(should
(equal '(("a") hline ("b*") ("c*"))
(org-test-with-temp-text "#+name: less-cols
| a |
|---|
| b |
| c |
#+header: :colnames yes
#+begin_src python :var tab=less-cols
<point>#+begin_src python :var tab=less-cols
return [[val + '*' for val in row] for row in tab]
#+end_src"
(org-babel-next-src-block)
(should (equal '(("a") hline ("b*") ("c*"))
(org-babel-execute-src-block)))))
(org-babel-execute-src-block)))))
(ert-deftest test-ob-python/colnames-nil-header-argument ()
(org-test-with-temp-text "#+name: eg
(should
(equal '(("col") hline ("a") ("b"))
(org-test-with-temp-text "#+name: eg
| col |
|-----|
| a |
@ -63,30 +65,30 @@ return x
#+header: :colnames nil
#+header: :var x = eg
#+begin_src python
<point>#+begin_src python
return x
#+end_src"
(org-babel-next-src-block)
(should (equal '(("col") hline ("a") ("b"))
(org-babel-execute-src-block)))))
(org-babel-execute-src-block)))))
(ert-deftest test-ob-python/colnames-no-header-argument-again ()
(org-test-with-temp-text "#+name: less-cols
(should
(equal '(("a*") ("b*") ("c*"))
(org-test-with-temp-text "#+name: less-cols
| a |
|---|
| b |
| c |
#+header: :colnames no
#+begin_src python :var tab=less-cols
<point>#+begin_src python :var tab=less-cols
return [[val + '*' for val in row] for row in tab]
#+end_src"
(org-babel-next-src-block)
(should (equal '(("a*") ("b*") ("c*"))
(org-babel-execute-src-block)))))
(org-babel-execute-src-block)))))
(ert-deftest test-ob-python/colnames-no-header-argument ()
(org-test-with-temp-text "#+name: eg
(should
(equal '(("col") ("a") ("b"))
(org-test-with-temp-text "#+name: eg
| col |
|-----|
| a |
@ -94,19 +96,18 @@ return x
#+header: :colnames no
#+header: :var x = eg
#+begin_src python
<point>#+begin_src python
return x
#+end_src"
(org-babel-next-src-block)
(should (equal '(("col") ("a") ("b"))
(org-babel-execute-src-block)))))
(org-babel-execute-src-block)))))
(ert-deftest test-ob-python/session-multiline ()
;; FIXME workaround to prevent starting prompt leaking into output
(run-python)
(sleep-for 0 10)
(org-test-with-temp-text "
#+begin_src python :session :results output
(should
(equal "20"
(org-test-with-temp-text "#+begin_src python :session :results output
foo = 0
for _ in range(10):
foo += 1
@ -115,26 +116,28 @@ return x
print(foo)
#+end_src"
(org-babel-next-src-block)
(should (equal "20" (org-babel-execute-src-block)))))
(org-babel-execute-src-block)))))
(ert-deftest test-ob-python/insert-necessary-blank-line-when-sending-code-to-interpreter ()
(org-test-with-temp-text "#+begin_src python :session :results value
(should
(equal 2 (org-test-with-temp-text "#+begin_src python :session :results value
if True:
1
2
#+end_src"
;; Previously, while adding `:session' to a normal code block, also need to add extra blank lines
;; to end indent block or indicate logical sections. Now, the `org-babel-python-evaluate-session'
;; can do it automatically:
;; >>> if True:
;; >>> 1
;; >>> <insert_blank_line_here>
;; >>> 2
(org-babel-execute-maybe)
(should (equal 2 (org-babel-execute-src-block)))))
;; Previously, while adding `:session' to a normal code
;; block, also need to add extra blank lines to end
;; indent block or indicate logical sections. Now, the
;; `org-babel-python-evaluate-session' can do it
;; automatically:
;;
;; >>> if True:
;; >>> 1
;; >>> <insert_blank_line_here>
;; >>> 2
(org-babel-execute-maybe)
(org-babel-execute-src-block)))))
(provide 'test-ob-python)
;;; test-ob-python.el ends here

View File

@ -55,49 +55,48 @@
(ert-deftest test-ol/escape ()
"Test `org-link-escape' specifications."
;; No-op when there is no backslash or closing square bracket.
(should (string= "foo[" (org-link-escape "foo[")))
;; Escape closing square bracket at the end of the link.
(should (string= "[foo\\]" (org-link-escape "[foo]")))
;; Escape closing square brackets followed by another square
;; bracket.
(should (string= "foo\\][bar" (org-link-escape "foo][bar")))
(should (string= "foo\\]]bar" (org-link-escape "foo]]bar")))
;; However, escaping closing square bracket at the end of the link
;; has precedence over the previous rule.
(should (string= "foo]\\]" (org-link-escape "foo]]")))
;; No-op when there is no backslash or square bracket.
(should (string= "foo" (org-link-escape "foo")))
;; Escape square brackets at boundaries of the link.
(should (string= "\\[foo\\]" (org-link-escape "[foo]")))
;; Escape square brackets followed by another square bracket.
(should (string= "foo\\]\\[bar" (org-link-escape "foo][bar")))
(should (string= "foo\\]\\]bar" (org-link-escape "foo]]bar")))
(should (string= "foo\\[\\[bar" (org-link-escape "foo[[bar")))
(should (string= "foo\\[\\]bar" (org-link-escape "foo[]bar")))
;; Escape backslashes at the end of the link.
(should (string= "foo\\\\" (org-link-escape "foo\\")))
;; Escape backslashes that could be confused with escaping
;; characters.
(should (string= "foo\\\\\\]" (org-link-escape "foo\\]")))
(should (string= "foo\\\\\\][" (org-link-escape "foo\\][")))
(should (string= "foo\\\\\\]]bar" (org-link-escape "foo\\]]bar")))
(should (string= "foo\\\\\\]\\[" (org-link-escape "foo\\][")))
(should (string= "foo\\\\\\]\\]bar" (org-link-escape "foo\\]]bar")))
;; Do not escape backslash characters when unnecessary.
(should (string= "foo\\bar" (org-link-escape "foo\\bar")))
(should (string= "foo\\]bar" (org-link-escape "foo\\]bar")))
;; Pathological cases: consecutive closing square brackets.
(should (string= "[[[foo\\]]\\]" (org-link-escape "[[[foo]]]")))
(should (string= "[[[foo]\\]] bar" (org-link-escape "[[[foo]]] bar"))))
(should (string= "\\[\\[\\[foo\\]\\]\\]" (org-link-escape "[[[foo]]]")))
(should (string= "\\[\\[foo\\]\\] bar" (org-link-escape "[[foo]] bar"))))
(ert-deftest test-ol/unescape ()
"Test `org-link-unescape' specifications."
;; No-op if there is no backslash.
(should (string= "foo[" (org-link-unescape "foo[")))
(should (string= "foo" (org-link-unescape "foo")))
;; No-op if backslashes are not escaping backslashes.
(should (string= "foo\\bar" (org-link-unescape "foo\\bar")))
(should (string= "foo\\]bar" (org-link-unescape "foo\\]bar")))
;;
;; Unescape backslashes before square brackets.
(should (string= "foo]bar" (org-link-unescape "foo\\]bar")))
(should (string= "foo\\]" (org-link-unescape "foo\\\\\\]")))
(should (string= "foo\\][" (org-link-unescape "foo\\\\\\][")))
(should (string= "foo\\]]bar" (org-link-unescape "foo\\\\\\]]bar")))
(should (string= "foo\\]]bar" (org-link-unescape "foo\\\\\\]\\]bar")))
(should (string= "foo\\[[bar" (org-link-unescape "foo\\\\\\[\\[bar")))
(should (string= "foo\\[]bar" (org-link-unescape "foo\\\\\\[\\]bar")))
;; Unescape backslashes at the end of the link.
(should (string= "foo\\" (org-link-unescape "foo\\\\")))
;; Unescape closing square bracket at the end of the link.
(should (string= "[foo]" (org-link-unescape "[foo\\]")))
;; Unescape closing square bracket at boundaries of the link.
(should (string= "[foo]" (org-link-unescape "\\[foo\\]")))
;; Pathological cases: consecutive closing square brackets.
(should (string= "[[[foo]]]" (org-link-unescape "[[[foo\\]]\\]")))
(should (string= "[[[foo]]] bar" (org-link-unescape "[[[foo]\\]] bar"))))
(should (string= "[[[foo]]]" (org-link-unescape "\\[\\[\\[foo\\]\\]\\]")))
(should (string= "[[foo]] bar" (org-link-unescape "\\[\\[foo\\]\\] bar"))))
(ert-deftest test-ol/make-string ()
"Test `org-link-make-string' specifications."
@ -204,11 +203,11 @@
;; Store file link to non-Org buffer, with context.
(should
(let ((org-stored-links nil)
(org-context-in-file-links t))
(org-link-context-for-files t))
(org-test-with-temp-text-in-file "one\n<point>two"
(fundamental-mode)
(let ((file (buffer-file-name)))
(equal (format "[[file:%s::one]]" file)
(equal (format "[[file:%s::two]]" file)
(org-store-link nil))))))
;; Store file link to non-Org buffer, without context.
(should
@ -223,11 +222,11 @@
;; buffer.
(should
(let ((org-stored-links nil)
(org-context-in-file-links nil))
(org-link-context-for-files nil))
(org-test-with-temp-text-in-file "one\n<point>two"
(fundamental-mode)
(let ((file (buffer-file-name)))
(equal (format "[[file:%s::one]]" file)
(equal (format "[[file:%s::two]]" file)
(org-store-link '(4)))))))
;; A C-u C-u does *not* reverse `org-context-in-file-links' in
;; non-Org buffer.

View File

@ -576,129 +576,87 @@ CLOCK: [2016-12-28 Wed 13:09]--[2016-12-28 Wed 15:09] => 2:00"
"Test \":link\" parameter in Clock table."
;; If there is no file attached to the document, link directly to
;; the headline.
(let (org-link-descriptive)
(should
(equal
"| Headline | Time |
|--------------+---------|
| *Total time* | *26:00* |
|--------------+---------|
| [[Foo][Foo]] | 26:00 |"
(org-test-with-temp-text
"* Foo
(should
(string-match-p "| +\\[\\[Foo]\\[Foo]] +| 26:00 +|"
(org-test-with-temp-text
"* Foo
CLOCK: [2016-12-27 Wed 13:09]--[2016-12-28 Wed 15:09] => 26:00"
(test-org-clock-clocktable-contents ":link t"))))
;; Otherwise, link to the headline in the current file.
(should
(equal
"| Headline | Time |
|-----------------------------+---------|
| *Total time* | *26:00* |
|-----------------------------+---------|
| [[file:filename::Foo][Foo]] | 26:00 |"
(org-test-with-temp-text
(org-test-with-temp-text-in-file
"* Foo
(test-org-clock-clocktable-contents ":link t"))))
;; Otherwise, link to the headline in the current file.
(should
(string-match-p
"| \\[\\[file:filename::Foo]\\[Foo]] +| 26:00 +|"
(org-test-with-temp-text
(org-test-with-temp-text-in-file
"* Foo
CLOCK: [2016-12-27 Wed 13:09]--[2016-12-28 Wed 15:09] => 26:00"
(let ((file (buffer-file-name)))
(replace-regexp-in-string
(regexp-quote file) "filename"
(test-org-clock-clocktable-contents ":link t :lang en"))))
(org-table-align)
(buffer-substring-no-properties (point-min) (point-max)))))
;; Ignore TODO keyword, priority cookie, COMMENT and tags in
;; headline.
(should
(equal
"| Headline | Time |
|--------------+---------|
| *Total time* | *26:00* |
|--------------+---------|
| [[Foo][Foo]] | 26:00 |"
(org-test-with-temp-text
"* TODO Foo
(let ((file (buffer-file-name)))
(replace-regexp-in-string
(regexp-quote file) "filename"
(test-org-clock-clocktable-contents ":link t :lang en"))))
(org-table-align)
(buffer-substring-no-properties (point-min) (point-max)))))
;; Ignore TODO keyword, priority cookie, COMMENT and tags in
;; headline.
(should
(string-match-p
"| \\[\\[Foo]\\[Foo]] +| 26:00 +|"
(org-test-with-temp-text
"* TODO Foo
CLOCK: [2016-12-27 Wed 13:09]--[2016-12-28 Wed 15:09] => 26:00"
(test-org-clock-clocktable-contents ":link t :lang en"))))
(should
(equal
"| Headline | Time |
|--------------+---------|
| *Total time* | *26:00* |
|--------------+---------|
| [[Foo][Foo]] | 26:00 |"
(org-test-with-temp-text
"* [#A] Foo
(test-org-clock-clocktable-contents ":link t :lang en"))))
(should
(string-match-p
"| \\[\\[Foo]\\[Foo]] +| 26:00 +|"
(org-test-with-temp-text
"* [#A] Foo
CLOCK: [2016-12-27 Wed 13:09]--[2016-12-28 Wed 15:09] => 26:00"
(test-org-clock-clocktable-contents ":link t :lang en"))))
(should
(equal
"| Headline | Time |
|--------------+---------|
| *Total time* | *26:00* |
|--------------+---------|
| [[Foo][Foo]] | 26:00 |"
(org-test-with-temp-text
"* COMMENT Foo
(test-org-clock-clocktable-contents ":link t :lang en"))))
(should
(string-match-p
"| \\[\\[Foo]\\[Foo]] +| 26:00 +|"
(org-test-with-temp-text
"* COMMENT Foo
CLOCK: [2016-12-27 Wed 13:09]--[2016-12-28 Wed 15:09] => 26:00"
(test-org-clock-clocktable-contents ":link t"))))
(should
(equal
"| Headline | Time |
|--------------+---------|
| *Total time* | *26:00* |
|--------------+---------|
| [[Foo][Foo]] | 26:00 |"
(org-test-with-temp-text
"* Foo :tag:
(test-org-clock-clocktable-contents ":link t"))))
(should
(string-match-p
"| \\[\\[Foo]\\[Foo]] +| 26:00 +|"
(org-test-with-temp-text
"* Foo :tag:
CLOCK: [2016-12-27 Wed 13:09]--[2016-12-28 Wed 15:09] => 26:00"
(test-org-clock-clocktable-contents ":link t :lang en"))))
;; Remove statistics cookie from headline description.
(should
(equal
"| Headline | Time |
|--------------+---------|
| *Total time* | *26:00* |
|--------------+---------|
| [[Foo][Foo]] | 26:00 |"
(org-test-with-temp-text
"* Foo [50%]
(test-org-clock-clocktable-contents ":link t :lang en"))))
;; Remove statistics cookie from headline description.
(should
(string-match-p
"| \\[\\[Foo]\\[Foo]] +| 26:00 +|"
(org-test-with-temp-text
"* Foo [50%]
CLOCK: [2016-12-27 Wed 13:09]--[2016-12-28 Wed 15:09] => 26:00"
(test-org-clock-clocktable-contents ":link t :lang en"))))
(should
(equal
"| Headline | Time |
|--------------+---------|
| *Total time* | *26:00* |
|--------------+---------|
| [[Foo][Foo]] | 26:00 |"
(org-test-with-temp-text
"* Foo [1/2]
(test-org-clock-clocktable-contents ":link t :lang en"))))
(should
(string-match-p
"| \\[\\[Foo]\\[Foo]] +| 26:00 +|"
(org-test-with-temp-text
"* Foo [1/2]
CLOCK: [2016-12-27 Wed 13:09]--[2016-12-28 Wed 15:09] => 26:00"
(test-org-clock-clocktable-contents ":link t :lang en"))))
;; Replace links with their description, or turn them into plain
;; links if there is no description.
(should
(equal
"| Headline | Time |
|-----------------------------------------------------------+---------|
| *Total time* | *26:00* |
|-----------------------------------------------------------+---------|
| [[Foo [[https://orgmode.org\\][Org mode]\\]][Foo Org mode]] | 26:00 |"
(org-test-with-temp-text
"* Foo [[https://orgmode.org][Org mode]]
(test-org-clock-clocktable-contents ":link t :lang en"))))
;; Replace links with their description, or turn them into plain
;; links if there is no description.
(should
(string-match-p
"| \\[\\[Foo \\\\\\[\\\\\\[https://orgmode\\.org\\\\]\\\\\\[Org mode\\\\]\\\\]]\\[Foo Org mode]] +| 26:00 +|"
(org-test-with-temp-text
"* Foo [[https://orgmode.org][Org mode]]
CLOCK: [2016-12-27 Wed 13:09]--[2016-12-28 Wed 15:09] => 26:00"
(test-org-clock-clocktable-contents ":link t :lang en"))))
(should
(equal
"| Headline | Time |
|-----------------------------------------------------------+---------|
| *Total time* | *26:00* |
|-----------------------------------------------------------+---------|
| [[Foo [[https://orgmode.org]\\]][Foo https://orgmode.org]] | 26:00 |"
(org-test-with-temp-text
"* Foo [[https://orgmode.org]]
(test-org-clock-clocktable-contents ":link t :lang en"))))
(should
(string-match-p
"| \\[\\[Foo \\\\\\[\\\\\\[https://orgmode\\.org\\\\]\\\\]]\\[Foo https://orgmode\\.org]] +| 26:00 +|"
(org-test-with-temp-text
"* Foo [[https://orgmode.org]]
CLOCK: [2016-12-27 Wed 13:09]--[2016-12-28 Wed 15:09] => 26:00"
(test-org-clock-clocktable-contents ":link t :lang en"))))))
(test-org-clock-clocktable-contents ":link t :lang en")))))
(ert-deftest test-org-clock/clocktable/compact ()
"Test \":compact\" parameter in Clock table."

View File

@ -2439,7 +2439,7 @@ SCHEDULED: <2014-03-04 tue.>"
;; Handle escape characters.
(should
(org-test-with-temp-text
"* H1\n:PROPERTIES:\n:CUSTOM_ID: [%]\n:END:\n* H2\n[[#[%\\]<point>]]"
"* H1\n:PROPERTIES:\n:CUSTOM_ID: [%]\n:END:\n* H2\n[[#\\[%\\]<point>]]"
(org-open-at-point)
(looking-at-p "\\* H1")))
;; Throw an error on false positives.
@ -2535,7 +2535,7 @@ Foo Bar
(looking-at "\\* TODO COMMENT Test")))
;; Correctly un-escape fuzzy links.
(should
(org-test-with-temp-text "* [foo]\n[[*[foo\\]][With escaped characters]]"
(org-test-with-temp-text "* [foo]\n[[*\\[foo\\]][With escaped characters]]"
(org-open-at-point)
(bobp)))
;; Match search strings containing newline characters, including

View File

@ -3555,7 +3555,7 @@ Another text. (ref:text)
(org-element-map tree 'link 'identity info t) info)))))
;; Handle escaped fuzzy links.
(should
(org-test-with-parsed-data "* [foo]\n[[[foo\\]]]"
(org-test-with-parsed-data "* [foo]\n[[\\[foo\\]]]"
(org-export-resolve-fuzzy-link
(org-element-map tree 'link #'identity info t) info))))