瀏覽代碼

Match regexps in the new variable org-file-apps-ex against the whole link.

Jan Böcker 15 年之前
父節點
當前提交
55dee1d251
共有 2 個文件被更改,包括 82 次插入5 次删除
  1. 7 0
      lisp/ChangeLog
  2. 75 5
      lisp/org.el

+ 7 - 0
lisp/ChangeLog

@@ -1,3 +1,10 @@
+2010-04-09  Jan Böcker  <jan.boecker@jboecker.de>
+
+	* org.el (org-file-apps-ex): new variable.
+	(org-open-file): Before considering org-file-apps, first match the
+	regexps from org-file-apps-ex against the whole link. See
+	docstring of org-file-apps-ex.
+
 2010-04-09  Carsten Dominik  <carsten.dominik@gmail.com>
 
 	* org-mobile.el (org-mobile-check-setup): Make sure that there is

+ 75 - 5
lisp/org.el

@@ -1518,6 +1518,42 @@ For more examples, see the system specific constants
 			(string :tag "Command")
 			(sexp :tag "Lisp form")))))
 
+
+
+(defcustom org-file-apps-ex
+  '()
+  "This variable is like org-file-apps, except that the regular
+expressions are matched against the whole link, and you can use
+subexpressions to capture parts of the matched link to use as
+command line arguments or in a custom lisp form.
+
+In a command string to be executed, access the subexpression
+matches with %1, %2, etc. In a custom lisp form, you can access
+them with (match-string n link).
+
+Example:
+To allow linking to page 5 in a PDF using the following syntax:
+
+file:document.pdf::5
+
+use the following entry:
+
+Regular Expression:      \.pdf::\([0-9]+\)\'
+Command:                 evince %s -p %1
+
+The first (and only) subexpression captures the page number,
+which is passed to evince as the -p argument."
+  :group 'org-link-follow
+  :type '(repeat
+	  (cons (choice :value ""
+			(string :tag "Regular Expression"))
+		(choice :value ""
+			(const :tag "Visit with Emacs" emacs)
+			(string :tag "Command")
+			(sexp :tag "Lisp form")))))
+
+
+
 (defgroup org-refile nil
   "Options concerning refiling entries in Org-mode."
   :tag "Org Refile"
@@ -9124,10 +9160,9 @@ With a double C-c C-u 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 always be
-opened in Emacs.
+search for.  If LINE or SEARCH is given, the file will be
+opened in Emacs, unless one of the entries in org-file-apps-ex matches.
 If the file does not exist, an error is thrown."
-  (setq in-emacs (or in-emacs line search))
   (let* ((file (if (equal path "")
 		   buffer-file-name
 		 (substitute-in-file-name (expand-file-name path))))
@@ -9139,10 +9174,19 @@ If the file does not exist, an error is thrown."
 		 file))
 	 (a-m-a-p (assq 'auto-mode apps))
 	 (dfile (downcase file))
+	 ;; reconstruct the original file: link from the PATH, LINE and SEARCH args
+	 (link (cond ((and (eq line nil)
+			    (eq search nil))
+		       file)
+		      (line
+		      (concat file "::" (number-to-string line)))
+		     (search
+		      (concat file "::" search))))
+	 (dlink (downcase link))
 	 (old-buffer (current-buffer))
 	 (old-pos (point))
 	 (old-mode major-mode)
-	 ext cmd)
+	 ext cmd link-match-data)
     (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\.gz\\)$" dfile)
 	(setq ext (match-string 1 dfile))
       (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\)$" dfile)
@@ -9154,6 +9198,17 @@ If the file does not exist, an error is thrown."
      (t
       (setq cmd (or (and remp (cdr (assoc 'remote apps)))
 		    (and dirp (cdr (assoc 'directory apps)))
+		    ; first, try matching against org-file-apps-ex
+		    ; if we get a match here, store the match data for later
+		    (let ((match (assoc-default dlink org-file-apps-ex
+						'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 org-file-apps-ex,
+		                     ; always open the file in emacs if line or search
+		                     ; is given (for backwards compatibility)
 		    (assoc-default dfile (org-apps-regexp-alist apps a-m-a-p)
 				   'string-match)
 		    (cdr (assoc ext apps))
@@ -9185,6 +9240,19 @@ If the file does not exist, an error is thrown."
 		     (shell-quote-argument
 		      (convert-standard-filename file)))
 		   t t cmd)))
+
+      ;; Replace "%1", "%2" etc. in command with group matches from regex
+      (save-match-data
+	(let ((match-index 1)
+	      (number-of-groups (- (/ (length link-match-data) 2) 1)))
+	  (set-match-data link-match-data)
+	  (while (<= match-index number-of-groups)
+	    (let ((regex (concat "%" (number-to-string match-index)))
+		  (replace-with (match-string match-index dlink)))
+	      (while (string-match regex cmd)
+		(setq cmd (replace-match replace-with t t cmd))))
+	    (setq match-index (+ match-index 1)))))
+      
       (save-window-excursion
 	(start-process-shell-command cmd nil cmd)
 	(and (boundp 'org-wait) (numberp org-wait) (sit-for org-wait))
@@ -9197,7 +9265,9 @@ If the file does not exist, an error is thrown."
 	(if search (org-link-search search))))
      ((consp cmd)
       (let ((file (convert-standard-filename file)))
-	(eval cmd)))
+	(save-match-data
+	  (set-match-data link-match-data)
+	  (eval cmd))))	
      (t (funcall (cdr (assq 'file org-link-frame-setup)) file)))
     (and (org-mode-p) (eq old-mode 'org-mode)
 	 (or (not (equal old-buffer (current-buffer)))