Browse Source

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

Jan Böcker 15 years ago
parent
commit
55dee1d251
2 changed files with 82 additions and 5 deletions
  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>
 2010-04-09  Carsten Dominik  <carsten.dominik@gmail.com>
 
 
 	* org-mobile.el (org-mobile-check-setup): Make sure that there is
 	* 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")
 			(string :tag "Command")
 			(sexp :tag "Lisp form")))))
 			(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
 (defgroup org-refile nil
   "Options concerning refiling entries in Org-mode."
   "Options concerning refiling entries in Org-mode."
   :tag "Org Refile"
   :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.
 and to use an external application to visit the file.
 
 
 Optional LINE specifies a line to go to, optional SEARCH a string to
 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
+search for.  If LINE or SEARCH is given, the file will be
-opened in Emacs.
+opened in Emacs, unless one of the entries in org-file-apps-ex matches.
 If the file does not exist, an error is thrown."
 If the file does not exist, an error is thrown."
-  (setq in-emacs (or in-emacs line search))
   (let* ((file (if (equal path "")
   (let* ((file (if (equal path "")
 		   buffer-file-name
 		   buffer-file-name
 		 (substitute-in-file-name (expand-file-name path))))
 		 (substitute-in-file-name (expand-file-name path))))
@@ -9139,10 +9174,19 @@ If the file does not exist, an error is thrown."
 		 file))
 		 file))
 	 (a-m-a-p (assq 'auto-mode apps))
 	 (a-m-a-p (assq 'auto-mode apps))
 	 (dfile (downcase file))
 	 (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-buffer (current-buffer))
 	 (old-pos (point))
 	 (old-pos (point))
 	 (old-mode major-mode)
 	 (old-mode major-mode)
-	 ext cmd)
+	 ext cmd link-match-data)
     (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\.gz\\)$" dfile)
     (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\.gz\\)$" dfile)
 	(setq ext (match-string 1 dfile))
 	(setq ext (match-string 1 dfile))
       (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\)$" dfile)
       (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\)$" dfile)
@@ -9154,6 +9198,17 @@ If the file does not exist, an error is thrown."
      (t
      (t
       (setq cmd (or (and remp (cdr (assoc 'remote apps)))
       (setq cmd (or (and remp (cdr (assoc 'remote apps)))
 		    (and dirp (cdr (assoc 'directory 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)
 		    (assoc-default dfile (org-apps-regexp-alist apps a-m-a-p)
 				   'string-match)
 				   'string-match)
 		    (cdr (assoc ext apps))
 		    (cdr (assoc ext apps))
@@ -9185,6 +9240,19 @@ If the file does not exist, an error is thrown."
 		     (shell-quote-argument
 		     (shell-quote-argument
 		      (convert-standard-filename file)))
 		      (convert-standard-filename file)))
 		   t t cmd)))
 		   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
       (save-window-excursion
 	(start-process-shell-command cmd nil cmd)
 	(start-process-shell-command cmd nil cmd)
 	(and (boundp 'org-wait) (numberp org-wait) (sit-for org-wait))
 	(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))))
 	(if search (org-link-search search))))
      ((consp cmd)
      ((consp cmd)
       (let ((file (convert-standard-filename file)))
       (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)))
      (t (funcall (cdr (assq 'file org-link-frame-setup)) file)))
     (and (org-mode-p) (eq old-mode 'org-mode)
     (and (org-mode-p) (eq old-mode 'org-mode)
 	 (or (not (equal old-buffer (current-buffer)))
 	 (or (not (equal old-buffer (current-buffer)))