Function: hpath:find

hpath:find is an interactive and byte-compiled function defined in hpath.el.

Signature

(hpath:find PATHNAME &optional DISPLAY-WHERE NOSELECT)

Documentation

Edit PATHNAME using user customizable settings of display program and location.

Return the current buffer iff file is read into a buffer (not displayed with an external program), else nil.

PATHNAME may contain references to Emacs Lisp variables or shell environment variables using the syntax, "${variable-name}".

PATHNAME may start with a special prefix character that is handled as follows:
  !pathname - execute as a non-windowed program within a shell;
  &pathname - execute as a windowed program;
  -pathname - load as an Emacs Lisp program.

If PATHNAME does not start with a prefix character:

  it may be followed by a hash-style link reference to Org, HTML, XML,
  SGML, shell script comment, Markdown or Emacs outline headings of the
  form, <file>#<anchor-name>, e.g. "~/.bashrc#Alias Section";

  it may end with a line number (starts from 1) and optional column number
  (starts from 0) to which to go, of the form,
  :<line-number>[:<column-number>], e.g. "~/.bashrc:20:5"; normally, this
  is an absolute line number (disabling buffer restriction), but if
  preceded by a hash-style link reference, it is relative to the location
  of the link anchor and in the case of Koutlines, relative to the indent
  of the cell;

  Line and column can also include a leading and optional character, L
  for line and C for column, e.g. "~/.bashrc:L20:C5".

  if it matches a regular expression in the alist returned by
  (hpath:get-external-display-alist), invoke the associated external
  display program;

  if not, consult hpath:internal-display-alist for a specialized internal
  display function to use;

  if no matches are found there, consult hpath:display-where-alist
  using the optional second argument, DISPLAY-WHERE (a symbol);

  if that is nil, consult the value of hpath:display-where, and use the
  matching display function.

Optional third argument, NOSELECT, means simply find the file and return its buffer but don't display it. Any modifier prefix is ignored in such cases but locational suffixes within the file are utilized.

Key Bindings

Source Code

;; Defined in ~/.emacs.d/elpa/hyperbole-20260414.325/hpath.el
(defun hpath:find (pathname &optional display-where noselect)
  "Edit PATHNAME using user customizable settings of display program and location.
Return the current buffer iff file is read into a buffer (not displayed with
an external program), else nil.

PATHNAME may contain references to Emacs Lisp variables or shell
environment variables using the syntax, \"${variable-name}\".

PATHNAME may start with a special prefix character that is handled as follows:
  !pathname  - execute as a non-windowed program within a shell;
  &pathname  - execute as a windowed program;
  -pathname  - load as an Emacs Lisp program.

If PATHNAME does not start with a prefix character:

  it may be followed by a hash-style link reference to Org, HTML, XML,
  SGML, shell script comment, Markdown or Emacs outline headings of the
  form, <file>#<anchor-name>, e.g. \"~/.bashrc#Alias Section\";

  it may end with a line number (starts from 1) and optional column number
  (starts from 0) to which to go, of the form,
  :<line-number>[:<column-number>], e.g. \"~/.bashrc:20:5\"; normally, this
  is an absolute line number (disabling buffer restriction), but if
  preceded by a hash-style link reference, it is relative to the location
  of the link anchor and in the case of Koutlines, relative to the indent
  of the cell;

  Line and column can also include a leading and optional character, L
  for line and C for column, e.g. \"~/.bashrc:L20:C5\".

  if it matches a regular expression in the alist returned by
  (hpath:get-external-display-alist), invoke the associated external
  display program;

  if not, consult `hpath:internal-display-alist' for a specialized internal
  display function to use;

  if no matches are found there, consult `hpath:display-where-alist'
  using the optional second argument, DISPLAY-WHERE (a symbol);

  if that is nil, consult the value of `hpath:display-where', and use the
  matching display function.

Optional third argument, NOSELECT, means simply find the file and return its
buffer but don't display it.  Any modifier prefix is ignored in such cases
but locational suffixes within the file are utilized."
  (interactive "FFind file: ")
  (unless (stringp pathname)
    ;; (debug) ;; Enable debugging if nil is ever sent to `hpath:find'
    (error "(hpath:find): pathname arg must be a string, not, %S" pathname))
  ;; `pathname' ends as the whole argument sent in except for any
  ;; initial modifier character.
  ;; `path' has extra location info (section, line num, col num)
  ;; stripped off, so it is just a findable path.
  (let ((case-fold-search t)
	(default-directory default-directory)
	modifier loc anchor anchor-start-pos hash
	kotl-flag path path-with-anchor line-num col-num instance-num)
    (setq loc (hattr:get 'hbut:current 'loc)
	  default-directory (or (hattr:get 'hbut:current 'dir)
				;; Loc may be a buffer without a file
				(if (stringp loc)
				    (file-name-directory loc)
				  default-directory)))
    ;; Parse Hyperbole action prefix char
    (when (string-match hpath:prefix-regexp pathname)
      (setq modifier (aref pathname 0)
	    pathname (substring pathname (match-end 0))))
    ;; Remove http file:// url prefix and decode the url
    (when (string-match "\\`file://" pathname)
      (setq pathname (hypb:decode-url (substring pathname (match-end 0)))))
    (setq path pathname) ;; default
    (cond ((string-match hpath:instance-line-column-regexp path)
	   (setq instance-num (string-to-number (match-string 1 path))
		 line-num (when (match-string 3 path)
			    (string-to-number (match-string 3 path)))
		 col-num (when (match-string 5 path)
			   (string-to-number (match-string 5 path)))
		 path (substring path 0 (match-beginning 0))))
	  ((string-match hpath:line-and-column-regexp path)
	   (setq line-num (string-to-number (match-string 1 path))
		 col-num (when (match-string 3 path)
			   (string-to-number (match-string 3 path)))
		 path (substring path 0 (match-beginning 0)))))
    (unless (file-exists-p path) ;; might be #autosave-file#
      (when (and (string-match hpath:markup-link-anchor-regexp path)
                 (not (string-empty-p (match-string 3 path))))
	(setq hash t
	      anchor (match-string 3 path)
	      anchor-start-pos (match-beginning 3)
	      path-with-anchor path
	      path (if (match-end 1)
		       (substring path 0 (match-end 1))
		     (or (hypb:buffer-file-name) "")))
	;; 'anchor' may improperly include trailing punctuation;
	;; remove it if so.
	(when (string-match "\\s.+\\'" anchor)
	  (setq anchor (substring anchor 0 (match-beginning 0))))))
    (if (string-empty-p path)
	(setq path ""
	      pathname "")
      ;; Never expand pathnames with modifier prepended
      (let ((referent (hywiki-get-referent path)))
        (when (eq (car referent) 'page)
          ;; This replaces the page name with name.org, so can be expanded
          ;; down below.
          (setq path (cdr referent))))
      (cond (modifier
	     (setq path (hpath:resolve path)))
	    (t (setq path (hpath:expand path)
                     pathname (hpath:absolute-to path default-directory))
	       ;; Remove http file:// url prefix that`hpath:absolute-to' may have
	       ;; added and decode the url
	       (when (string-match "\\`file://" pathname)
                 (setq pathname (hypb:decode-url (substring pathname (match-end 0))))))))
    (let ((remote-pathname (hpath:remote-p path)))
      (or modifier remote-pathname
	  (file-exists-p pathname)
	  (error "(hpath:find): \"%s\" does not exist"
		 (concat modifier pathname (when hash "#") anchor)))
      (or modifier remote-pathname
	  (file-readable-p pathname)
	  (error "(hpath:find): \"%s\" is not readable"
		 (concat modifier pathname (when hash "#") anchor)))
      (unless noselect
	;; If pathname is a remote file (not a directory), we have to copy it to
	;; a temporary local file and then display that.
	(when (and remote-pathname (not (file-directory-p remote-pathname)))
	  (copy-file remote-pathname
		     (setq path (concat hpath:tmp-prefix
					(file-name-nondirectory remote-pathname)))
		     t t)
	  (setq pathname (cond (anchor (concat remote-pathname "#" anchor))
			       (hash   (concat remote-pathname "#"))
			       (t path))))))
    (cond ((and modifier (not noselect))
	   (cond ((= modifier ?!)
		  (hact 'exec-shell-cmd pathname))
		 ((= modifier ?&)
		  (hact 'exec-window-cmd pathname))
		 ((= modifier ?-)
		  (hact 'load pathname)))
	   nil)

	  ;; Display paths either internally or externally.
	  (t (let ((display-executables (unless (or noselect (string-empty-p path))
					  (hpath:find-program path)))
		   executable)
	       (cond ((stringp display-executables)
		      (hact 'exec-window-cmd
			    (hpath:command-string display-executables pathname))
		      nil)
		     ((functionp display-executables)
		      (funcall display-executables pathname)
		      (current-buffer))
		     ((and (listp display-executables) display-executables)
		      (setq executable (hpath:find-executable display-executables))
		      (if executable
			  (hact 'exec-window-cmd
				(hpath:command-string executable pathname))
			(error "(hpath:find): No available executable from: %s"
			       display-executables)))
		     (t (setq path (hpath:validate path) ;; signals error when invalid
			      kotl-flag (string-match "\\.kotl?\\'" path))
			(let ((buf (cond
				    ;; If no path, e.g. just an anchor link in a non-file buffer,
				    ;; then must display within Emacs, ignoring any external programs.
				    ((string-empty-p path)
				     (unless noselect
				       (hpath:display-buffer (current-buffer) display-where))
                                     (current-buffer))
				    (noselect
				     (find-file-noselect path))
				    (t (funcall (hpath:display-path-function display-where) path)))))
			  (with-current-buffer buf
			    ;; Perform a loose test that the current buffer
			    ;; file name matches the path file name since exact
			    ;; matching of path is likely to be wrong in
			    ;; certain cases, e.g. with mount point or os path
			    ;; alterations.
			    (when (or (null (hypb:buffer-file-name))
				      (equal (file-name-nondirectory path)
					     (file-name-nondirectory (hypb:buffer-file-name))))
			      (cond ((and anchor kotl-flag)
				     (klink:act path-with-anchor anchor-start-pos))
				    ((or hash anchor)
				     (hpath:to-markup-anchor hash anchor instance-num)))
			      (when line-num
				;; With an anchor or instance number,
				;; goto line relative to anchor location,
				;; otherwise use absolute line number
				;; within the visible buffer portion.
				(if (or hash anchor)
				    (forward-line (1- line-num))
				  (hpath:to-line line-num)))
			      (when col-num
				(move-to-column
				 (if kotl-flag
				     (+ (kcell-view:indent) col-num)
				   col-num)))
			      (when kotl-flag
				(kotl-mode:to-valid-position))
			      (current-buffer)))))))))))