Function: org-open-file
org-open-file is an autoloaded and byte-compiled function defined in
org.el.gz.
Signature
(org-open-file PATH &optional IN-EMACS LINE SEARCH)
Documentation
Open the file at PATH.
First, this expands any special file name abbreviations. Then the
configuration variable org-file-apps is checked if it contains an
entry for this file type, and if yes, the corresponding command is launched.
If no application is found, Emacs simply visits the file.
With optional prefix argument IN-EMACS, Emacs will visit the file.
With a double C-u (universal-argument) C-u (universal-argument) prefix arg, Org tries to avoid opening in Emacs
and to use an external application to visit the file.
Optional LINE specifies a line to go to, optional SEARCH a string
to search for. If LINE or SEARCH is given, the file will be
opened in Emacs, unless an entry from org-file-apps that makes
use of groups in a regexp matches.
If you want to change the way frames are used when following a
link, please customize org-link-frame-setup.
If the file does not exist, throw an error.
Source Code
;; Defined in /usr/src/emacs/lisp/org/org.el.gz
;;;###autoload
(defun org-open-file (path &optional in-emacs line search)
"Open the file at PATH.
First, this expands any special file name abbreviations. Then the
configuration variable `org-file-apps' is checked if it contains an
entry for this file type, and if yes, the corresponding command is launched.
If no application is found, Emacs simply visits the file.
With optional prefix argument IN-EMACS, Emacs will visit the file.
With a double \\[universal-argument] \\[universal-argument] \
prefix arg, Org tries to avoid opening in Emacs
and to use an external application to visit the file.
Optional LINE specifies a line to go to, optional SEARCH a string
to search for. If LINE or SEARCH is given, the file will be
opened in Emacs, unless an entry from `org-file-apps' that makes
use of groups in a regexp matches.
If you want to change the way frames are used when following a
link, please customize `org-link-frame-setup'.
If the file does not exist, throw an error."
(let* ((file (if (equal path "") buffer-file-name
(substitute-in-file-name (expand-file-name path))))
(file-apps (append org-file-apps (org--file-default-apps)))
(apps (cl-remove-if #'org--file-apps-entry-locator-p file-apps))
(apps-locator (cl-remove-if-not #'org--file-apps-entry-locator-p
file-apps))
(remp (and (assq 'remote apps) (file-remote-p file)))
(dirp (unless remp (file-directory-p file)))
(file (if (and dirp org-open-directory-means-index-dot-org)
(concat (file-name-as-directory file) "index.org")
file))
(a-m-a-p (assq 'auto-mode apps))
(dfile (downcase file))
;; Reconstruct the original link from the PATH, LINE and
;; SEARCH args.
(link (cond (line (concat file "::" (number-to-string line)))
(search (concat file "::" search))
(t file)))
(ext
(and (string-match "\\`.*?\\.\\([a-zA-Z0-9]+\\(\\.gz\\)?\\)\\'" dfile)
(match-string 1 dfile)))
(save-position-maybe
(let ((old-buffer (current-buffer))
(old-pos (point))
(old-mode major-mode))
(lambda ()
(and (derived-mode-p 'org-mode)
(eq old-mode 'org-mode)
(or (not (eq old-buffer (current-buffer)))
(not (eq old-pos (point))))
(org-mark-ring-push old-pos old-buffer)))))
cmd link-match-data)
(cond
((member in-emacs '((16) system))
(setq cmd (cdr (assq 'system apps))))
(in-emacs (setq cmd 'emacs))
(t
(setq cmd (or (and remp (cdr (assq 'remote apps)))
(and dirp (cdr (assq 'directory apps)))
;; First, try matching against apps-locator if we
;; get a match here, store the match data for
;; later.
(let* ((case-fold-search t)
(match (assoc-default link apps-locator
'string-match)))
(if match
(progn (setq link-match-data (match-data))
match)
(progn (setq in-emacs (or in-emacs line search))
nil))) ; if we have no match in apps-locator,
; always open the file in emacs if line or search
; is given (for backwards compatibility)
(assoc-default dfile
(org--file-apps-regexp-alist apps a-m-a-p)
'string-match)
(cdr (assoc ext apps))
(cdr (assq t apps))))))
(when (eq cmd 'system)
(setq cmd (cdr (assq 'system apps))))
(when (eq cmd 'default)
(setq cmd (cdr (assoc t apps))))
(when (eq cmd 'mailcap)
(require 'mailcap)
(mailcap-parse-mailcaps)
(let* ((mime-type (mailcap-extension-to-mime (or ext "")))
(command (mailcap-mime-info mime-type)))
(if (stringp command)
(setq cmd command)
(setq cmd 'emacs))))
(when (and (not (eq cmd 'emacs)) ; Emacs has no problems with non-ex files
(not (file-exists-p file))
(not org-open-non-existing-files))
(user-error "No such file: %s" file))
(cond
((org-string-nw-p cmd)
(setq cmd (org--open-file-format-command cmd file link link-match-data))
(save-window-excursion
(message "Running %s...done" cmd)
;; Handlers such as "gio open" and kde-open5 start viewer in background
;; and exit immediately. Use pipe connection type instead of pty to
;; avoid killing children processes with SIGHUP when temporary terminal
;; session is finished.
;;
;; TODO: Once minimum Emacs version is 25.1 or above, consider using
;; the `make-process' invocation from 5db61eb0f929 to get more helpful
;; error messages.
(let ((process-connection-type nil))
(start-process-shell-command cmd nil cmd))
(and (boundp 'org-wait) (numberp org-wait) (sit-for org-wait))))
((or (stringp cmd)
(eq cmd 'emacs))
(funcall (cdr (assq 'file org-link-frame-setup)) file)
(widen)
(cond (line (org-goto-line line)
(when (derived-mode-p 'org-mode) (org-fold-reveal)))
(search (condition-case err
(org-link-search search)
;; Save position before error-ing out so user
;; can easily move back to the original buffer.
(error (funcall save-position-maybe)
(error "%s" (error-message-string err)))))))
((functionp cmd)
(save-match-data
(set-match-data link-match-data)
(condition-case nil
(funcall cmd file link)
;; FIXME: Remove this check when most default installations
;; of Emacs have at least Org 9.0.
((debug wrong-number-of-arguments wrong-type-argument
invalid-function)
(user-error "Please see Org News for version 9.0 about \
`org-file-apps'--Lisp error: %S" cmd)))))
((consp cmd)
;; FIXME: Remove this check when most default installations of
;; Emacs have at least Org 9.0. Heads-up instead of silently
;; fall back to `org-link-frame-setup' for an old usage of
;; `org-file-apps' with sexp instead of a function for `cmd'.
(user-error "Please see Org News for version 9.0 about \
`org-file-apps'--Error: Deprecated usage of %S" cmd))
(t (funcall (cdr (assq 'file org-link-frame-setup)) file)))
(funcall save-position-maybe)))