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