Function: org-link-search

org-link-search is a byte-compiled function defined in ol.el.gz.

Signature

(org-link-search S &optional AVOID-POS STEALTH)

Documentation

Search for a search string S.

If S starts with "#", it triggers a custom ID search.

If S is enclosed within parenthesis, it initiates a coderef search.

If S is surrounded by forward slashes, it is interpreted as a regular expression. In Org mode files, this will create an org-occur sparse tree. In ordinary files, occur will be used to list matches. If the current buffer is in dired-mode, grep will be used to search in all files.

When AVOID-POS is given, ignore matches near that position.

When optional argument STEALTH is non-nil, do not modify visibility around point, thus ignoring org-show-context-detail variable.

Search is case-insensitive and ignores white spaces. Return type of matched result, which is either dedicated or fuzzy.

Source Code

;; Defined in /usr/src/emacs/lisp/org/ol.el.gz
(defun org-link-search (s &optional avoid-pos stealth)
  "Search for a search string S.

If S starts with \"#\", it triggers a custom ID search.

If S is enclosed within parenthesis, it initiates a coderef
search.

If S is surrounded by forward slashes, it is interpreted as
a regular expression.  In Org mode files, this will create an
`org-occur' sparse tree.  In ordinary files, `occur' will be used
to list matches.  If the current buffer is in `dired-mode', grep
will be used to search in all files.

When AVOID-POS is given, ignore matches near that position.

When optional argument STEALTH is non-nil, do not modify
visibility around point, thus ignoring `org-show-context-detail'
variable.

Search is case-insensitive and ignores white spaces.  Return type
of matched result, which is either `dedicated' or `fuzzy'."
  (unless (org-string-nw-p s) (error "Invalid search string \"%s\"" s))
  (let* ((case-fold-search t)
	 (origin (point))
	 (normalized (replace-regexp-in-string "\n[ \t]*" " " s))
	 (starred (eq (string-to-char normalized) ?*))
	 (words (split-string (if starred (substring s 1) s)))
	 (s-multi-re (mapconcat #'regexp-quote words "\\(?:[ \t\n]+\\)"))
	 (s-single-re (mapconcat #'regexp-quote words "[ \t]+"))
	 type)
    (cond
     ;; Check if there are any special search functions.
     ((run-hook-with-args-until-success 'org-execute-file-search-functions s))
     ((eq (string-to-char s) ?#)
      ;; Look for a custom ID S if S starts with "#".
      (let* ((id (substring normalized 1))
	     (match (org-find-property "CUSTOM_ID" id)))
	(if match (progn (goto-char match) (setf type 'dedicated))
	  (error "No match for custom ID: %s" id))))
     ((string-match "\\`(\\(.*\\))\\'" normalized)
      ;; Look for coderef targets if S is enclosed within parenthesis.
      (let ((coderef (match-string-no-properties 1 normalized))
	    (re (substring s-single-re 1 -1)))
	(goto-char (point-min))
	(catch :coderef-match
	  (while (re-search-forward re nil t)
	    (let ((element (org-element-at-point)))
	      (when (and (memq (org-element-type element)
			       '(example-block src-block))
			 (org-match-line
			  (concat ".*?" (org-src-coderef-regexp
					 (org-src-coderef-format element)
					 coderef))))
		(setq type 'dedicated)
		(goto-char (match-beginning 2))
		(throw :coderef-match nil))))
	  (goto-char origin)
	  (error "No match for coderef: %s" coderef))))
     ((string-match "\\`/\\(.*\\)/\\'" normalized)
      ;; Look for a regular expression.
      (funcall (if (derived-mode-p 'org-mode) #'org-occur #'org-do-occur)
	       (match-string 1 s)))
     ;; From here, we handle fuzzy links.
     ;;
     ;; Look for targets, only if not in a headline search.
     ((and (not starred)
	   (let ((target (format "<<%s>>" s-multi-re)))
	     (catch :target-match
	       (goto-char (point-min))
	       (while (re-search-forward target nil t)
		 (backward-char)
		 (let ((context (org-element-context)))
		   (when (eq (org-element-type context) 'target)
		     (setq type 'dedicated)
		     (goto-char (org-element-property :begin context))
		     (throw :target-match t))))
	       nil))))
     ;; Look for elements named after S, only if not in a headline
     ;; search.
     ((and (not starred)
	   (let ((name (format "^[ \t]*#\\+NAME: +%s[ \t]*$" s-single-re)))
	     (catch :name-match
	       (goto-char (point-min))
	       (while (re-search-forward name nil t)
		 (let* ((element (org-element-at-point))
			(name (org-element-property :name element)))
		   (when (and name (equal words (split-string name)))
		     (setq type 'dedicated)
		     (beginning-of-line)
		     (throw :name-match t))))
	       nil))))
     ;; Regular text search.  Prefer headlines in Org mode buffers.
     ;; Ignore COMMENT keyword, TODO keywords, priority cookies,
     ;; statistics cookies and tags.
     ((and (derived-mode-p 'org-mode)
	   (let ((title-re
		  (format "%s.*\\(?:%s[ \t]\\)?.*%s"
			  org-outline-regexp-bol
			  org-comment-string
			  (mapconcat #'regexp-quote words ".+"))))
	     (goto-char (point-min))
	     (catch :found
	       (while (re-search-forward title-re nil t)
		 (when (equal words
			      (split-string
			       (org-link--normalize-string
				(org-get-heading t t t t))))
		   (throw :found t)))
	       nil)))
      (beginning-of-line)
      (setq type 'dedicated))
     ;; Offer to create non-existent headline depending on
     ;; `org-link-search-must-match-exact-headline'.
     ((and (derived-mode-p 'org-mode)
	   (eq org-link-search-must-match-exact-headline 'query-to-create)
	   (yes-or-no-p "No match - create this as a new heading? "))
      (goto-char (point-max))
      (unless (bolp) (newline))
      (org-insert-heading nil t t)
      (insert s "\n")
      (beginning-of-line 0))
     ;; Only headlines are looked after.  No need to process
     ;; further: throw an error.
     ((and (derived-mode-p 'org-mode)
	   (or starred org-link-search-must-match-exact-headline))
      (goto-char origin)
      (error "No match for fuzzy expression: %s" normalized))
     ;; Regular text search.
     ((catch :fuzzy-match
	(goto-char (point-min))
	(while (re-search-forward s-multi-re nil t)
	  ;; Skip match if it contains AVOID-POS or it is included in
	  ;; a link with a description but outside the description.
	  (unless (or (and avoid-pos
			   (<= (match-beginning 0) avoid-pos)
			   (> (match-end 0) avoid-pos))
		      (and (save-match-data
			     (org-in-regexp org-link-bracket-re))
			   (match-beginning 3)
			   (or (> (match-beginning 3) (point))
			       (<= (match-end 3) (point)))
			   (org-element-lineage
			    (save-match-data (org-element-context))
			    '(link) t)))
	    (goto-char (match-beginning 0))
	    (setq type 'fuzzy)
	    (throw :fuzzy-match t)))
	nil))
     ;; All failed.  Throw an error.
     (t (goto-char origin)
	(error "No match for fuzzy expression: %s" normalized)))
    ;; Disclose surroundings of match, if appropriate.
    (when (and (derived-mode-p 'org-mode) (not stealth))
      (org-fold-show-context 'link-search))
    type))