summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Dominik <carsten.dominik@gmail.com>2010-08-06 08:34:33 +0200
committerCarsten Dominik <carsten.dominik@gmail.com>2010-08-06 08:34:33 +0200
commita84c8a2cba8c510acfa0c14487f6c993f664a406 (patch)
tree0198190cedc4405691f82cf8004d210ed0b62d51
parent23a11da5dfdc3fe61bc7668693f8b4736d38ca6d (diff)
downloadorg-mode-a84c8a2cba8c510acfa0c14487f6c993f664a406.tar.gz
Make internal links in Org files search for an exact headline match
* lisp/org.el (org-link-search-must-match-exact-headline): New option. (org-link-search-inhibit-query): New variable. (org-link-search): Search for exact headline match in Org files * doc/org.texi (Internal links): Document the changes in internal links. Internal links used to do a fuzzy text search for the link text. This patch changes the behavior for Org files. Here a link [[My Target]] now searches for an exact headline match, i.e. for a headline that does look like "* My Target", optionally with TODO keyword, priority cookie and tags. The new option `org-link-search-must-match-exact-headline' is `query-to-create' by default. This means that a failed link search will offer to create the headline as a top-level headline at the end of the buffer. This corresponds to a wiki-like behavior where missing targets are automatically created. If you do not like this behavior, change the option to t.
-rw-r--r--doc/org.texi24
-rw-r--r--lisp/org-exp.el25
-rw-r--r--lisp/org.el44
3 files changed, 55 insertions, 38 deletions
diff --git a/doc/org.texi b/doc/org.texi
index 628978e..301d46a 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -2806,23 +2806,13 @@ text before the first headline is usually not exported, so the first such
target should be after the first headline, or in the line directly before the
first headline.}.
-If no dedicated target exists, Org will search for the words in the link. In
-the above example the search would be for @samp{my target}. Links starting
-with a star like @samp{*My Target} restrict the search to
-headlines@footnote{To insert a link targeting a headline, in-buffer
-completion can be used. Just type a star followed by a few optional letters
-into the buffer and press @kbd{M-@key{TAB}}. All headlines in the current
-buffer will be offered as completions. @xref{Handling links}, for more
-commands creating links.}. When searching, Org-mode will first try an
-exact match, but then move on to more and more lenient searches. For
-example, the link @samp{[[*My Targets]]} will find any of the following:
-
-@example
-** My targets
-** TODO my targets are bright
-** my 20 targets are
-@end example
-
+If no dedicated target exists, Org will search for a headline that is exactly
+the link text but may also include a TODO keyword and tags@footnote{To insert
+a link targeting a headline, in-buffer completion can be used. Just type a
+star followed by a few optional letters into the buffer and press
+@kbd{M-@key{TAB}}. All headlines in the current buffer will be offered as
+completions.}. In non-Org files, the search will look for the words in the
+link text, in the above example the search would be for @samp{my target}.
Following a link pushes a mark onto Org's own mark ring. You can
return to the previous position with @kbd{C-c &}. Using this command
diff --git a/lisp/org-exp.el b/lisp/org-exp.el
index 6fc5109..36f8202 100644
--- a/lisp/org-exp.el
+++ b/lisp/org-exp.el
@@ -1289,18 +1289,19 @@ the current file."
(string-match "^\\." link))
nil)
(t
- (save-excursion
- (setq found (condition-case nil (org-link-search link)
- (error nil)))
- (when (and found
- (or (org-on-heading-p)
- (not (eq found 'dedicated))))
- (or (get-text-property (point) 'target)
- (get-text-property
- (max (point-min)
- (1- (or (previous-single-property-change
- (point) 'target) 0)))
- 'target))))))))
+ (let ((org-link-search-inhibit-query t))
+ (save-excursion
+ (setq found (condition-case nil (org-link-search link)
+ (error nil)))
+ (when (and found
+ (or (org-on-heading-p)
+ (not (eq found 'dedicated))))
+ (or (get-text-property (point) 'target)
+ (get-text-property
+ (max (point-min)
+ (1- (or (previous-single-property-change
+ (point) 'target) 0)))
+ 'target)))))))))
(when target
(set-match-data md)
(goto-char (match-beginning 1))
diff --git a/lisp/org.el b/lisp/org.el
index d2c1fdf..09fa360 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -1439,6 +1439,17 @@ Changing this requires a restart of Emacs to work correctly."
:group 'org-link-follow
:type 'integer)
+(defcustom org-link-search-must-match-exact-headline 'query-to-create
+ "Non-nil means internal links in Org files must exactly match a headline.
+When nil, the link search tries to match a phrase will all words
+in the search text."
+ :group 'org-link-follow
+ :type '(choice
+ (const :tag "Use fuzy text search" nil)
+ (const :tag "Match only exact headline" t)
+ (const :tag "Match extact headline or query to create it"
+ query-to-create)))
+
(defcustom org-link-frame-setup
'((vm . vm-visit-folder-other-frame)
(gnus . org-gnus-no-new-news)
@@ -9300,6 +9311,7 @@ the window configuration before `org-open-at-point' was called using:
(set-window-configuration org-window-config-before-follow-link)")
+(defvar org-link-search-inhibit-query nil) ;; dynamically scoped
(defun org-link-search (s &optional type avoid-pos)
"Search for a link search option.
If S is surrounded by forward slashes, it is interpreted as a
@@ -9317,7 +9329,7 @@ in all files. If AVOID-POS is given, ignore matches near that position."
(pre nil) (post nil)
words re0 re1 re2 re3 re4_ re4 re5 re2a re2a_ reall)
(cond
- ;; First check if there are any special
+ ;; First check if there are any special search functions
((run-hook-with-args-until-success 'org-execute-file-search-functions s))
;; Now try the builtin stuff
((and (equal (string-to-char s0) ?#)
@@ -9362,8 +9374,28 @@ in all files. If AVOID-POS is given, ignore matches near that position."
;;((eq major-mode 'dired-mode)
;; (grep (concat "grep -n -e '" (match-string 1 s) "' *")))
(t (org-do-occur (match-string 1 s)))))
+ ((and (org-mode-p) org-link-search-must-match-exact-headline)
+ (and (equal (string-to-char s) ?*) (setq s (substring s 1)))
+ (goto-char (point-min))
+ (cond
+ ((let (case-fold-search)
+ (re-search-forward (format org-complex-heading-regexp-format
+ (regexp-quote s))
+ nil t))
+ ;; OK, found a match
+ (goto-char (match-beginning 0)))
+ ((and (not org-link-search-inhibit-query)
+ (eq org-link-search-must-match-exact-headline 'query-to-create)
+ (y-or-n-p "No match - create this as a new heading? "))
+ (goto-char (point-max))
+ (or (bolp) (newline))
+ (insert "* " s "\n")
+ (beginning-of-line 0))
+ (t
+ (goto-char pos)
+ (error "No match"))))
(t
- ;; A normal search strings
+ ;; A normal search string
(when (equal (string-to-char s) ?*)
;; Anchor on headlines, post may include tags.
(setq pre "^\\*+[ \t]+\\(?:\\sw+\\)?[ \t]*"
@@ -9408,13 +9440,7 @@ in all files. If AVOID-POS is given, ignore matches near that position."
)
(goto-char (match-beginning 1))
(goto-char pos)
- (error "No match")))))
- (t
- ;; Normal string-search
- (goto-char (point-min))
- (if (search-forward s nil t)
- (goto-char (match-beginning 0))
- (error "No match"))))
+ (error "No match"))))))
(and (org-mode-p) (org-show-context 'link-search))
type))