diff --git a/contrib/lisp/org-mac-link.el b/contrib/lisp/org-mac-link.el
index 3dfe43607..6bd6dc5c9 100644
--- a/contrib/lisp/org-mac-link.el
+++ b/contrib/lisp/org-mac-link.el
@@ -66,6 +66,7 @@
;; Vimperator/Firefox.app - Grab the url of the frontmost tab in the frontmost window
;; Safari.app - Grab the url of the frontmost tab in the frontmost window
;; Google Chrome.app - Grab the url of the frontmost tab in the frontmost window
+;; Brave.app - Grab the url of the frontmost tab in the frontmost window
;; Together.app - Grab links to the selected items in the library list
;; Skim.app - Grab a link to the selected page in the topmost pdf document
;; Microsoft Outlook.app - Grab a link to the selected message in the message list
@@ -164,6 +165,12 @@
:group 'org-mac-link
:type 'boolean)
+(defcustom org-mac-grab-Brave-app-p t
+ "Add menu option [b]rave to grab links from Brave.app."
+ :tag "Grab Brave.app links"
+ :group 'org-mac-link
+ :type 'boolean)
+
(defcustom org-mac-grab-Together-app-p nil
"Add menu option [t]ogether to grab links from Together.app."
:tag "Grab Together.app links"
@@ -249,6 +256,7 @@ When done, go grab the link, and insert it at point."
("f" "irefox" org-mac-firefox-insert-frontmost-url ,org-mac-grab-Firefox-app-p)
("v" "imperator" org-mac-vimperator-insert-frontmost-url ,org-mac-grab-Firefox+Vimperator-p)
("c" "hrome" org-mac-chrome-insert-frontmost-url ,org-mac-grab-Chrome-app-p)
+ ("b" "rave" org-mac-brave-insert-frontmost-url ,org-mac-grab-Brave-app-p)
("e" "evernote" org-mac-evernote-note-insert-selected ,org-mac-grab-Evernote-app-p)
("t" "ogether" org-mac-together-insert-selected ,org-mac-grab-Together-app-p)
("S" "kim" org-mac-skim-insert-page ,org-mac-grab-Skim-app-p)
@@ -424,6 +432,39 @@ The links are of the form ::split::."
(interactive)
(insert (org-mac-chrome-get-frontmost-url)))
+
+;; Handle links from Brave.app
+;; Grab the frontmost url from Brave. Same limitations as
+;; Firefox/Chrome because Brave doesn't publish an Applescript
+;; dictionary
+
+(defun org-as-mac-brave-get-frontmost-url ()
+ (let ((result
+ (do-applescript
+ (concat
+ "set frontmostApplication to path to frontmost application\n"
+ "tell application \"Brave\"\n"
+ " set theUrl to get URL of active tab of first window\n"
+ " set theResult to (get theUrl) & \"::split::\" & (get name of window 1)\n"
+ "end tell\n"
+ "activate application (frontmostApplication as text)\n"
+ "set links to {}\n"
+ "copy theResult to the end of links\n"
+ "return links as string\n"))))
+ (replace-regexp-in-string
+ "^\"\\|\"$" "" (car (split-string result "[\r\n]+" t)))))
+
+;;;###autoload
+(defun org-mac-brave-get-frontmost-url ()
+ (interactive)
+ (message "Applescript: Getting Brave url...")
+ (org-mac-paste-applescript-links (org-as-mac-brave-get-frontmost-url)))
+
+;;;###autoload
+(defun org-mac-brave-insert-frontmost-url ()
+ (interactive)
+ (insert (org-mac-brave-get-frontmost-url)))
+
;; Handle links from Safari.app
;; Grab the frontmost url from Safari.
diff --git a/lisp/org-element.el b/lisp/org-element.el
index cdb574e17..78b185197 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -3912,7 +3912,18 @@ element it has to parse."
((looking-at "%%(")
(org-element-diary-sexp-parser limit affiliated))
;; Table.
- ((looking-at "[ \t]*\\(|\\|\\+\\(-+\\+\\)+[ \t]*$\\)")
+ ((or (looking-at "[ \t]*|")
+ ;; There is no strict definition of a table.el
+ ;; table. Try to prevent false positive while being
+ ;; quick.
+ (let ((rule-regexp "[ \t]*\\+\\(-+\\+\\)+[ \t]*$")
+ (next (line-beginning-position 2)))
+ (and (looking-at rule-regexp)
+ (save-excursion
+ (forward-line)
+ (re-search-forward "^[ \t]*\\($\\|[^|]\\)" limit t)
+ (and (> (line-beginning-position) next)
+ (org-match-line rule-regexp))))))
(org-element-table-parser limit affiliated))
;; List.
((looking-at (org-item-re))
diff --git a/lisp/org-pcomplete.el b/lisp/org-pcomplete.el
index d245f6981..062f38a7c 100644
--- a/lisp/org-pcomplete.el
+++ b/lisp/org-pcomplete.el
@@ -104,10 +104,11 @@ The return value is a string naming the thing at point."
(char-before)))
(cons "tex" nil))
;; Tags on a headline.
- ((and (org-at-heading-p)
- (eq ?: (save-excursion
- (skip-chars-backward "[:alnum:]_@#%")
- (char-before))))
+ ((and (org-match-line
+ (format "\\*+ \\(?:.+? \\)?\\(:\\)\\(\\(?::\\|%s\\)+\\)?[ \t]*$"
+ org-tag-re))
+ (or (org-point-in-group (point) 2)
+ (= (point) (match-end 1))))
(cons "tag" nil))
;; TODO keywords on an empty headline.
((and (string-match "^\\*+ +\\S-*$" line-to-here)
@@ -372,7 +373,8 @@ This needs more work, to handle headings with lots of spaces in them."
(setq lst (delete tag lst)))
lst))
(and (string-match ".*:" pcomplete-stub)
- (substring pcomplete-stub (match-end 0))))))
+ (substring pcomplete-stub (match-end 0)))
+ t)))
(defun pcomplete/org-mode/drawer ()
"Complete a drawer name, including \"PROPERTIES\"."
diff --git a/lisp/org.el b/lisp/org.el
index b78243c2c..0da000738 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -10284,9 +10284,10 @@ a link."
(org-search-radio-target
(org-element-property :path context))
(org-link-search
- (if (member type '("custom-id" "coderef"))
- (org-element-property :raw-link context)
- path)
+ (pcase type
+ ("custom-id" (concat "#" path))
+ ("coderef" (format "(%s)" path))
+ (_ path))
;; Prevent fuzzy links from matching
;; themselves.
(and (equal type "fuzzy")
@@ -20442,7 +20443,8 @@ object (e.g., within a comment). In these case, you need to use
(cond
;; In a table, call `org-table-next-row'. However, before first
;; column or after last one, split the table.
- ((or (and (eq (org-element-type context) 'table)
+ ((or (and (eq 'table (org-element-type context))
+ (not (eq 'table.el (org-element-property :type context)))
(>= (point) (org-element-property :contents-begin context))
(< (point) (org-element-property :contents-end context)))
(org-element-lineage context '(table-row table-cell) t))
@@ -20468,9 +20470,8 @@ object (e.g., within a comment). In these case, you need to use
(call-interactively #'org-open-at-point))
;; Insert newline in heading, but preserve tags.
((and (not (bolp))
- (save-excursion (beginning-of-line)
- (let ((case-fold-search nil))
- (looking-at org-complex-heading-regexp))))
+ (let ((case-fold-search nil))
+ (org-match-line org-complex-heading-regexp)))
;; At headline. Split line. However, if point is on keyword,
;; priority cookie or tags, do not break any of them: add
;; a newline after the headline instead.
diff --git a/testing/lisp/test-org-pcomplete.el b/testing/lisp/test-org-pcomplete.el
index c9fa4c908..581eab549 100644
--- a/testing/lisp/test-org-pcomplete.el
+++ b/testing/lisp/test-org-pcomplete.el
@@ -125,6 +125,39 @@
(pcomplete)
(buffer-string)))))
+(ert-deftest test-org-pcomplete/tag ()
+ "Test tag completion."
+ ;; Complete at end of line, according to `org-current-tag-alist'.
+ (should
+ (equal "* H :foo:"
+ (org-test-with-temp-text "* H :"
+ (let ((org-current-tag-alist '(("foo")))) (pcomplete))
+ (buffer-string))))
+ (should
+ (equal "* H :foo:bar:"
+ (org-test-with-temp-text "* H :foo:b"
+ (let ((org-current-tag-alist '(("bar")))) (pcomplete))
+ (buffer-string))))
+ ;; If `org-current-tag-alist' is non-nil, complete against tags in
+ ;; buffer.
+ (should
+ (equal "* H1 :bar:\n* H2 :bar:"
+ (org-test-with-temp-text "* H1 :bar:\n* H2 :"
+ (let ((org-current-tag-alist nil)) (pcomplete))
+ (buffer-string))))
+ ;; Do not complete in the middle of a line.
+ (should
+ (equal "* H :notag: :real:tags:"
+ (org-test-with-temp-text "* H :notag: :real:tags:"
+ (let ((org-current-tag-alist '(("foo")))) (pcomplete))
+ (buffer-string))))
+ ;; Complete even when there's a match on the line.
+ (should
+ (equal "* foo: :foo:"
+ (org-test-with-temp-text "* foo: :"
+ (let ((org-current-tag-alist '(("foo")))) (pcomplete))
+ (buffer-string)))))
+
(ert-deftest test-org-pcomplete/todo ()
"Test TODO completion."
(should
diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el
index 669ad4377..6e1abc827 100644
--- a/testing/lisp/test-org.el
+++ b/testing/lisp/test-org.el
@@ -2338,6 +2338,12 @@ SCHEDULED: <2014-03-04 tue.>"
"* H1\n:PROPERTIES:\n:CUSTOM_ID: custom\n:END:\n* H2\n[[#custom]]"
(org-open-at-point)
(looking-at-p "\\* H1")))
+ ;; Handle escape characters.
+ (should
+ (org-test-with-temp-text
+ "* H1\n:PROPERTIES:\n:CUSTOM_ID: [%]\n:END:\n* H2\n[[#%5B%25%5D]]"
+ (org-open-at-point)
+ (looking-at-p "\\* H1")))
;; Throw an error on false positives.
(should-error
(org-test-with-temp-text