emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* Org mode links: Open a PDF file at a given page and highlight a given string
@ 2021-03-02 20:07 Rodrigo Morales
  2021-03-02 22:36 ` Kyle Meyer
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Rodrigo Morales @ 2021-03-02 20:07 UTC (permalink / raw)
  To: emacs-orgmode


I want to be able to

+ create a Org link to specific pages of a PDF. I've managed to
  accomplish this by setting the following value.

#+begin_src emacs-lisp :results silent
(setq org-file-apps
      '(("\\.pdf::\\([0-9]+\\)\\'" . "zathura -P %1 %s")))
#+end_src

The following links open the PDF at the given page.

[[file:~/Downloads/grub.pdf::10]]

[[file:~/Downloads/grub.pdf::20]]

[[file:~/Downloads/grub.pdf::30]]

+ create a Org link to specific pages of a PDF and highlight a given
  string.

#+begin_src emacs-lisp :results silent
(setq org-file-apps
      '(("\\.pdf::\\([0-9]+\\)::\\([^:]+\\)\\'" . "zathura -P %1 -f %2 %s")))
#+end_src

The following link must open the PDF at a given page and highlight the
given string. However, I'm getting the following error (see the
=#+begin_example= block below.)

[[file:~/Downloads/grub.pdf::95::do]]

#+begin_example
Debugger entered--Lisp error: (wrong-type-argument stringp nil)
  replace-match(nil t t "zathura -P 95 -f %2 /home/username/Downloads/grub....")
  org-open-file("~/Downloads/grub.pdf" nil nil "95::do")
  apply(org-open-file "~/Downloads/grub.pdf" nil (nil "95::do"))
  org-link-open((link (:type "file" :path "~/Downloads/grub.pdf" :format bracket :raw-link "file:~/Downloads/grub.pdf::95::do" :application nil :search-option "95::do" :begin 821 :end 858 :contents-begin nil :contents-end nil :post-blank 0 :parent (paragraph (:begin 821 :end 860 :contents-begin 821 :contents-end 859 :post-blank 1 :post-affiliated 821 :parent nil)))) nil)
  org-open-at-point(nil)
  funcall-interactively(org-open-at-point nil)
  call-interactively(org-open-at-point nil nil)
  command-execute(org-open-at-point)
#+end_example

Note that the following accomplishes what I'm looking for

#+begin_src bash
zathura -P 95 -f do ~/Downloads/grub.pdf
#+end_src

My question is: How can I get rid of that error so that the PDF is
opened at a given page and the string is highlighted?

PS: If you want a PDF to test the link presented in this message, you
can download the following PDF (564K). It was the smallest PDF in
gnu.org I was able to find.

#+begin_src bash :dir ~/Downloads :results silent
wget 'https://www.gnu.org/software/grub/manual/grub/grub.pdf'
#+end_src

-- 
Greetings,
Rodrigo Morales.

IRC: rdrg109 (freenode)


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Org mode links: Open a PDF file at a given page and highlight a given string
  2021-03-02 20:07 Org mode links: Open a PDF file at a given page and highlight a given string Rodrigo Morales
@ 2021-03-02 22:36 ` Kyle Meyer
  2021-03-03 12:37   ` Maxim Nikulin
  2021-09-27 16:39   ` Max Nikulin
  2021-03-03  2:31 ` Juan Manuel Macías
  2022-09-03 13:00 ` Max Nikulin
  2 siblings, 2 replies; 13+ messages in thread
From: Kyle Meyer @ 2021-03-02 22:36 UTC (permalink / raw)
  To: Rodrigo Morales; +Cc: emacs-orgmode

Rodrigo Morales writes:

[...]
> + create a Org link to specific pages of a PDF and highlight a given
>   string.
>
> #+begin_src emacs-lisp :results silent
> (setq org-file-apps
>       '(("\\.pdf::\\([0-9]+\\)::\\([^:]+\\)\\'" . "zathura -P %1 -f %2 %s")))
> #+end_src
>
> The following link must open the PDF at a given page and highlight the
> given string. However, I'm getting the following error (see the
> =#+begin_example= block below.)
>
> [[file:~/Downloads/grub.pdf::95::do]]
>
> #+begin_example
> Debugger entered--Lisp error: (wrong-type-argument stringp nil)
>   replace-match(nil t t "zathura -P 95 -f %2 /home/username/Downloads/grub....")

I haven't looked at this closely or tried to trigger the error, but an
in-flight patch is touching this area
(<https://orgmode.org/list/87mtw8fupl.fsf@kyleam.com>).  I've yet to
revisit it to address Maxim's helpful feedback, but I hope to soon and
will look at this error then too.

Thanks for reporting.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Org mode links: Open a PDF file at a given page and highlight a given string
  2021-03-02 20:07 Org mode links: Open a PDF file at a given page and highlight a given string Rodrigo Morales
  2021-03-02 22:36 ` Kyle Meyer
@ 2021-03-03  2:31 ` Juan Manuel Macías
  2021-03-03 14:51   ` Maxim Nikulin
  2022-09-03 13:00 ` Max Nikulin
  2 siblings, 1 reply; 13+ messages in thread
From: Juan Manuel Macías @ 2021-03-03  2:31 UTC (permalink / raw)
  To: Rodrigo Morales; +Cc: orgmode

Hi Rodrigo,

Rodrigo Morales <moralesrodrigo1100@gmail.com> writes:

> I want to be able to
>
> + create a Org link to specific pages of a PDF. I've managed to
>   accomplish this by setting the following value.
> [ ... ]
> + create a Org link to specific pages of a PDF and highlight a given
>   string.

A possible alternative, which gives you more control over the link, is
`org-link-set-parameters'. For example:

#+begin_src emacs-lisp
  (org-link-set-parameters
   "pdf-pag"
   :follow (lambda (path)
	     (let ((pag (if (string-match "::\\([1-9]+\\):*:*\\(.*\\)" path)
			    (match-string 1 path)
			  (error "no pages")))
		   (clean-path (expand-file-name (replace-regexp-in-string "::.+" "" path)))
		   (str (when (string-match "::\\([1-9]+\\)::\\(.+\\)" path)
			  (match-string 2 path))))
	       (start-process-shell-command "zathura" nil (concat "zathura "
								  clean-path
								  " -P "
								  pag
								  (when str
								    (format " -f '%s' " str)))))))
#+end_src

And then:

#+begin_src org
  [[pdf-pag:~/Downloads/grub.pdf::95::do]]
#+end_src

Best regards,

Juan Manuel 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Org mode links: Open a PDF file at a given page and highlight a given string
  2021-03-02 22:36 ` Kyle Meyer
@ 2021-03-03 12:37   ` Maxim Nikulin
  2021-09-27 16:39   ` Max Nikulin
  1 sibling, 0 replies; 13+ messages in thread
From: Maxim Nikulin @ 2021-03-03 12:37 UTC (permalink / raw)
  To: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 1993 bytes --]

On 03/03/2021 05:36, Kyle Meyer wrote:
> Rodrigo Morales writes:
> 
> [...]
>> + create a Org link to specific pages of a PDF and highlight a given
>>    string.
>>
>> #+begin_src emacs-lisp :results silent
>> (setq org-file-apps
>>        '(("\\.pdf::\\([0-9]+\\)::\\([^:]+\\)\\'" . "zathura -P %1 -f %2 %s")))
>> #+end_src
>>
>> The following link must open the PDF at a given page and highlight the
>> given string. However, I'm getting the following error (see the
>> =#+begin_example= block below.)
>>
>> [[file:~/Downloads/grub.pdf::95::do]]

Correct link should be [[info:grub#true]] (a joke, at least a kind of).

Actually I never considered search string for highlighting of particular 
text, so thank you for the hint. Browsers could generate (mutually 
incompatible) link to particular rectangle. With xpopple (fork of old 
xpdf) it is possible to send command to select region.

However I think it is better to use logical links instead of page numbers:

    okular --find do ~/Downloads/grub.pdf'#true'
    xpdf ~/Downloads/grub.pdf +true

Unfortunately firefox replaces "#" to percent-encoded sequence in 
command line argument and could not find the file. It requires editing 
in address bar.

>> #+begin_example
>> Debugger entered--Lisp error: (wrong-type-argument stringp nil)
>>    replace-match(nil t t "zathura -P 95 -f %2 /home/username/Downloads/grub....")
> 
> I haven't looked at this closely or tried to trigger the error, but an
> in-flight patch is touching this area
> (<https://orgmode.org/list/87mtw8fupl.fsf@kyleam.com>).  I've yet to
> revisit it to address Maxim's helpful feedback, but I hope to soon and
> will look at this error then too.

Kyle, your patch works for such handlers. This case is another argument 
to replace all substitutions in a single pass. Global state (match data) 
is the source of the problem.

I am attaching informal single-line patch for quick plumbing. 
Alternative is to use save-match-data around string-match inside the loop.

[-- Attachment #2: org-open-file-multi-subst.patch --]
[-- Type: text/x-patch, Size: 568 bytes --]

diff --git a/lisp/org.el b/lisp/org.el
index fd6226702..f45adb308 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -8757,8 +8757,8 @@ If the file does not exist, throw an error."
       (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)
+	    (set-match-data link-match-data)
 	    (let ((regex (concat "%" (number-to-string match-index)))
 		  (replace-with (match-string match-index dlink)))
 	      (while (string-match regex cmd)

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: Org mode links: Open a PDF file at a given page and highlight a given string
  2021-03-03  2:31 ` Juan Manuel Macías
@ 2021-03-03 14:51   ` Maxim Nikulin
  2021-03-03 16:11     ` Juan Manuel Macías
  0 siblings, 1 reply; 13+ messages in thread
From: Maxim Nikulin @ 2021-03-03 14:51 UTC (permalink / raw)
  To: emacs-orgmode

On 03/03/2021 09:31, Juan Manuel Macías wrote:
> 	       (start-process-shell-command "zathura" nil (concat "zathura "
> 								  clean-path
> 								  " -P "
> 								  pag
> 								  (when str
> 								    (format " -f '%s' " str)))))))

Please, do not forget to pass stings coming from user input through 
shell-quote-argument. There is combine-and-quote-strings function but 
its docstring tells that it is not safe enough. Ideally shell should be 
completely avoided in such cases and arguments should be passed as a 
list directly to exec. https://xkcd.com/327/



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Org mode links: Open a PDF file at a given page and highlight a given string
  2021-03-03 14:51   ` Maxim Nikulin
@ 2021-03-03 16:11     ` Juan Manuel Macías
  2021-03-05 13:02       ` Maxim Nikulin
  0 siblings, 1 reply; 13+ messages in thread
From: Juan Manuel Macías @ 2021-03-03 16:11 UTC (permalink / raw)
  To: Maxim Nikulin; +Cc: orgmode

Hi Maxim

Thanks for your advice, which I appreciate very much.

Maxim Nikulin <manikulin@gmail.com> writes:

> On 03/03/2021 09:31, Juan Manuel Macías wrote:
>> 	       (start-process-shell-command "zathura" nil (concat "zathura "
>> 								  clean-path
>> 								  " -P "
>> 								  pag
>> 								  (when str
>> 								    (format " -f '%s' " str)))))))
>
> Please, do not forget to pass stings coming from user input through
> shell-quote-argument. There is combine-and-quote-strings function but 
> its docstring tells that it is not safe enough. Ideally shell should
> be completely avoided in such cases and arguments should be passed as
> a list directly to exec. https://xkcd.com/327/

So, maybe it would look better like this (`start-process' instead of
`start-process-shell-command')?:

#+begin_src emacs-lisp
(org-link-set-parameters
 "pdf-pag"
 :follow (lambda (path)
	   (let ((pag (if (string-match "::\\([1-9]+\\):*:*\\(.*\\)" path)
			  (format "--page=%s" (match-string 1 path))
			(error "no pages")))
		 (clean-path (expand-file-name (replace-regexp-in-string "::.+" "" path)))
		 (str (when (string-match "::\\([1-9]+\\)::\\(.+\\)" path)
			(format "--find=%s" (match-string 2 path)))))
	     (if str
		 (start-process "zathura" nil "/usr/bin/zathura"
				clean-path
				pag
				str)
	       (start-process "zathura" nil "/usr/bin/zathura"
			      clean-path
			      pag)))))
#+end_src

Best reagards,

Juan Manuel 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Org mode links: Open a PDF file at a given page and highlight a given string
  2021-03-03 16:11     ` Juan Manuel Macías
@ 2021-03-05 13:02       ` Maxim Nikulin
  0 siblings, 0 replies; 13+ messages in thread
From: Maxim Nikulin @ 2021-03-05 13:02 UTC (permalink / raw)
  To: emacs-orgmode

On 03/03/2021 23:11, Juan Manuel Macías wrote:
> Maxim Nikulin writes:
>>
>> Please, do not forget to pass stings coming from user input through
>> shell-quote-argument.
> 
> So, maybe it would look better like this (`start-process' instead of
> `start-process-shell-command')?:

My intention was just to warn you against of opening a door
to shell injections.

Personally, as a workaround I would add an org-file-apps entry with
a single argument combining page and search string and would write
a tiny script that splits such argument and invokes the viewer.
I consider it as a better option in the sense of forward compatibility
since it allows to avoid custom link types. I expect that the bug
will be fixed soon.

I still suppose that it is serious limitation that such link format
does not support named link targets inside PDF files. Maybe the part
before second "::" could be considered as a named target
if it does not look like a number. I am unsure concerning search
strings containing "::", they may require more accurate regexp
or using e.g. percent encoding as in URLs.

> #+begin_src emacs-lisp
> (org-link-set-parameters
>   "pdf-pag"
>   :follow (lambda (path)
> 	   (let ((pag (if (string-match "::\\([1-9]+\\):*:*\\(.*\\)" path)
> 			  (format "--page=%s" (match-string 1 path))
> 			(error "no pages")))
> 		 (clean-path (expand-file-name (replace-regexp-in-string "::.+" "" path)))
> 		 (str (when (string-match "::\\([1-9]+\\)::\\(.+\\)" path)
> 			(format "--find=%s" (match-string 2 path)))))
> 	     (if str
> 		 (start-process "zathura" nil "/usr/bin/zathura"
> 				clean-path
> 				pag
> 				str)
> 	       (start-process "zathura" nil "/usr/bin/zathura"
> 			      clean-path
> 			      pag)))))
> #+end_src

If your are asking my opinion on your function, I think that the
variant with start-process is a better one. There is a low level
alternative make-process but it requires more code, so it is less
convenient. As to the style of lisp code, I am not a proper
person to make suggestions.

I suspect that your function has a problem with page numbers like 10.

I do not like repetition of the regexp and tend to think that minor
variations are unintended. On the other hand a variant I could offer
is not shorter despite just one regexp and just one call of a
match function.

#+begin_src elisp
   (defun wa-pdf-destination-zathura-args (target)
     (let ((suffix (string-match 
"::\\(?:\\([0-9]+\\)?\\(?:::\\(.+\\)\\)?\\|\\(.*\\)\\)$"
				target)))
       (if (not suffix)
	  (list (expand-file-name target))
	(let* ((invalid (match-string 3 target))
	       (file (cond
		      ((zerop suffix) (error "No file path in '%s'" target))
		      (invalid (error "Invalid destination within file: '%s'"
				      invalid))
		      (t (substring target 0 suffix))))
	       (page (match-string 1 target))
	       (search (match-string 2 target)))
	  (seq-remove #'null
		      (list (and page "--page") page
			    (and search "--find") search
			    (expand-file-name file)))))))

   (defun wa-launch-pdf-viewer (target)
     (let ((viewer "zathura")
	  (command (wa-pdf-destination-zathura-args target))
	  ;; Do not allocate a pty. Really required only if the application
	  ;; spawns background children and exits (xdg-open, gio open,
	  ;; kde-open5), see Emacs Bug #44824.
	  (process-connection-type nil))
       (apply #'start-process viewer "*Messages*" viewer command)))
#+end_src

#+begin_src elisp :results value list
   (mapcar #'wa-pdf-destination-zathura-args
	  '(
	    "~/Download/grub.pdf::95::do"
	    "file.pdf::95"
	    "file.pdf::::do"
	    "file.pdf"
	    ;; "::"
	    ;; "::95"
	    ;; "file.pdf::a"
	    ;; "file.pdf::95:do"
	    ))
#+end_src



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Org mode links: Open a PDF file at a given page and highlight a given string
  2021-03-02 22:36 ` Kyle Meyer
  2021-03-03 12:37   ` Maxim Nikulin
@ 2021-09-27 16:39   ` Max Nikulin
  1 sibling, 0 replies; 13+ messages in thread
From: Max Nikulin @ 2021-09-27 16:39 UTC (permalink / raw)
  To: orgmode; +Cc: Kyle Meyer

On 03/03/2021 05:36, Kyle Meyer wrote:
> Rodrigo Morales writes:
> 
> [...]
>> + create a Org link to specific pages of a PDF and highlight a given
>>    string.
>>
>> #+begin_src emacs-lisp :results silent
>> (setq org-file-apps
>>        '(("\\.pdf::\\([0-9]+\\)::\\([^:]+\\)\\'" . "zathura -P %1 -f %2 %s")))
>> #+end_src
>>
>> The following link must open the PDF at a given page and highlight the
>> given string. However, I'm getting the following error (see the
>> =#+begin_example= block below.)
>>
>> [[file:~/Downloads/grub.pdf::95::do]]
>>
>> #+begin_example
>> Debugger entered--Lisp error: (wrong-type-argument stringp nil)
>>    replace-match(nil t t "zathura -P 95 -f %2 /home/username/Downloads/grub....")
> 
> I haven't looked at this closely or tried to trigger the error, but an
> in-flight patch is touching this area
> (<https://orgmode.org/list/87mtw8fupl.fsf@kyleam.com>).  I've yet to
> revisit it to address Maxim's helpful feedback, but I hope to soon and
> will look at this error then too.

I suppose, it deserves to be tracked on updates.orgmode.org 
("org-open-file & org-file-apps multiple substitution bug")


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Org mode links: Open a PDF file at a given page and highlight a given string
  2021-03-02 20:07 Org mode links: Open a PDF file at a given page and highlight a given string Rodrigo Morales
  2021-03-02 22:36 ` Kyle Meyer
  2021-03-03  2:31 ` Juan Manuel Macías
@ 2022-09-03 13:00 ` Max Nikulin
  2022-09-20 11:54   ` Ihor Radchenko
  2 siblings, 1 reply; 13+ messages in thread
From: Max Nikulin @ 2022-09-03 13:00 UTC (permalink / raw)
  To: emacs-orgmode

On 03/03/2021 03:07, Rodrigo Morales wrote:
> 
> #+begin_src emacs-lisp :results silent
> (setq org-file-apps
>        '(("\\.pdf::\\([0-9]+\\)::\\([^:]+\\)\\'" . "zathura -P %1 -f %2 %s")))
> #+end_src

I am going to respond to a message from another thread containing 
discussion of a patch, but I suppose the following considerations are 
more appropriate in the thread discussing combined specifier for 
location withing a PDF document. For me it is more convenient to test 
ideas using okular, I hope, changing code for zathura or other PDF 
viewer is trivial.

Ihor Radchenko. Re: [PATCH] org.el: Fix percent substitutions in 
`org-open-file' Fri, 02 Sep 2022 20:08:17 +0800. 
https://list.orgmode.org/87tu5qm11q.fsf@localhost
>> +    ;; Page and search string,
>> +    ;; e.g. <file:///usr/share/doc/bash/bashref.pdf::34::order of redirections>.
>> +    (\"\\\\.pdf::\\\\([0-9]+\\\\)::\\\\(.+\\\\)\\\\\\='\"
>> +        . \"okular --page %1 --find %2 %s\")
>> +    ;; Internal anchor and search string,
>> +    ;; e.g. <file:///usr/share/doc/bash/bashref.pdf::Redirections::allocate a file>.
>> +    (\"\\\\.pdf::\\\\(.+\\\\)::\\\\(.+\\\\)\\\\\\='\"
>> +        . \"okular --find %2 file://%s\\\\\\\\#%1\")
>> +    ;; Page number, e.g. <file:///usr/share/doc/bash/bashref.pdf::34>.
>> +    (\"\\\\.pdf::\\\\([0-9]+\\\\)\\\\\\='\" . \"okular --page %1 %s\")
>> +    ;; Internal reference, e.g. <file:///usr/share/doc/bash/bashref.pdf::Redirections>.
>> +    (\"\\\\.pdf::\\\\(.+\\\\)\\\\\\='\" . \"okular file://%s\\\\\\\\#%1\")
>> +    ;; No location within the file, optionally followed by \"::\",
>> +    ;; e.g. <file:///usr/share/doc/bash/bashref.pdf>.
>> +    (\"\\\\.pdf\\\\(?:::\\\\)?\\\\\\='\" . \"okular %s\")
> 
> This is a nice set of examples, but it probably does not belong to this
> docstring. I'd rather see this in `org-file-apps' docstring or even in
> the manual.

It is a part of docstring, so number of slashes is doubled.

First of all, I overlooked possibility to distinguish text search 
"file:text.pdf::patttern" and cross reference target within the document 
"file:text.pdf::#anchor". Secondly, I forgot that PDF viewers may 
support compressed files.

Currently I believe that instead of injecting up to 6 entries into 
`org-file-apps' for various combinations of page, anchor, and search 
pattern, it is better to add single record with function handler. Notice 
that the approach presented above is not affected by the bug with 
multiple regexp group. Its additional advantage is that shell is not 
involved, so peculiar file names can not cause execution of some code 
when quoting and escaping are messed up.

I think a set of functions for popular PDF viewers (evince, zathura, 
okular, xpdf, xpopple, firefox, chromium & Co., etc.) should be defined 
in some package, but I am in doubts if it suitable for Org core.

Proof of concept implementation.

Configuration:

(add-to-list
  'org-file-apps
  `(("\\.pdf\\(?:\\.gz\\|\\.bz2\\|\\.xz\\)?\\(?:::.*\\)?\\'"
     . ,#'my-open-file-pdf-okular)))

Helper functions:

(defun my--parse-file-link-search (suffix-re link)
   "Parse PDF file LINK for page number, cross reference anchor, search 
string.

Return nil if it is not a link to some PDF file. Any element may be nil."
   (let ((case-fold-search t)) ; Handle files having .PDF suffix as well
     (and (string-match
	  (concat suffix-re
		  (rx
		   (optional "::"
			     (or (group (+ digit))
				 (group "#" (+ (not (any ?:))))
				 (optional "#")))
		   (optional "::"
			     (optional (group (+ anything))))
		   string-end))
	  link)
	 (mapcar (lambda (i) (match-string i link)) '(1 2 3)))))

(defun my-launch-viewer (command arguments)
   "Launch external application COMMAND with ARGUMENTS.

The function allows to avoid intermediate shell and so escaping
of arguments that otherwise might be considered as shell
specialls and run arbitrary commands.  The function launches
viewer process using shoot ant forget method like `browse-url-xdg-open',
so the application may run even after quit from Emacs."
   (apply #'call-process command nil 0 nil args))

(defun my-open-file-pdf-okular (file link)
   "PDF files handler for usage as a command in `org-file-apps' alist.

Customize `org-file-apps' to add the following entry:

 
\\='(\"\\\\.pdf\\\\(?:\\\\.gz\\\\|\\\\.bz2\\\\|\\\\.xz\\\\)?\\\\(?:::.*\\\\)?\\\\\\='\"
       . #\\='my-open-file-pdf-okular)

Open FILE at the location specified by LINK (page, internal
reference, search string).  Supported link search options (side
note: in the particular case of bash manual
<info:bash#Redirections> link may be used instead):

- Page number <file:///usr/share/doc/bash/bashref.pdf::34>.
- Page number and search text
   <file:///usr/share/doc/bash/bashref.pdf::34::order of redirections>.
- Cross reference anchor
   <file:///usr/share/doc/bash/bashref.pdf::#Redirections>.
- Cross reference anchor and search text
   <file:///usr/share/doc/bash/bashref.pdf::#Redirections::allocate a file>.
- Search text <file:///usr/share/doc/bash/bashref.pdf::allocate a file>.

Optionally the FILE may be compressed by gzip, bzip2, or xz."
   (pcase-let* ((pdf-re (rx ".pdf"
			   ;; .Z and .zip are not supported by okular
			   (optional (or ".gz" ".bz2" ".xz"))))
	       (`(,page ,ref ,find)
		(or (my--parse-file-link-search pdf-re link)
		    (error "Not a PDF file link: %S" link)))
	       (args (list "--"
		    (if (org-string-nw-p ref)
			(concat file ref)
		      file))))
       ;; Protect against file names starting from a dash that might be
       ;; considered as an option despite `org-open-file' passes absolute
       ;; file name and it is not strictly necessary.
       (when find
	(push find args)
	(push "--find" args))
       (when page
	(push page args)
	(push "--page" args))
       (my-launch-viewer "okular" args)))


And some tests

(ert-deftest test-my/parse-file-link-search ()
   (let ((pdf-re (rx ".pdf"
		    ;; .Z and .zip are not supported by okular
		    (optional (or ".gz" ".bz2" ".xz")))))
     (should-not (my--parse-file-link-search pdf-re "/no-match.doc"))
     (should-not (my--parse-file-link-search pdf-re "/no-match.doc::#ref"))
     (should (equal
	     '(nil nil nil)
	     (my--parse-file-link-search pdf-re "/just-file.pdf")))
     (should (equal
	     '(nil nil nil)
	     (my--parse-file-link-search pdf-re "/just-file-upper-case.PDF")))
     (should (equal
	     '("21" nil nil)
	     (my--parse-file-link-search pdf-re "/page.pdf::21")))
     (should (equal
	     '(nil "#ref" nil)
	     (my--parse-file-link-search pdf-re "/anchor.pdf::#ref")))
     (should (equal
	     '(nil nil "some text")
	     (my--parse-file-link-search pdf-re "/search-string.pdf::some text")))
     (should (equal
	     '(nil nil "in gzipped file")
	     (my--parse-file-link-search
	      pdf-re
	      "/compressed-search-string.pdf.GZ::in gzipped file")))
     (should (equal
	     '("32" nil "page text")
	     (my--parse-file-link-search
	      pdf-re
	      "/page-search.pdf::32::page text")))
     (should (equal
	     '(nil "#ref" "anchor text")
	     (my--parse-file-link-search
	      pdf-re
	      "/anchor-search.pdf::#ref::anchor text")))
     (should (equal
	     '(nil nil "::")
	     (my--parse-file-link-search pdf-re "/search-quad.pdf::::::")))
     (should (equal
	     '(nil nil nil)
	     (my--parse-file-link-search pdf-re "/nothing-1.pdf::")))
     (should (equal
	     '(nil nil nil)
	     (my--parse-file-link-search pdf-re "/nothing-2.PDF::::")))
     (should (equal
	     '(nil nil nil)
	     (my--parse-file-link-search pdf-re "/empty-anchor-1.pdf::#")))
     (should (equal
	     '(nil nil nil)
	     (my--parse-file-link-search pdf-re "/empty-anchor-2.pdf::#::")))
     (should (equal
	     '(nil nil "empty anchor text")
	     (my--parse-file-link-search
	      pdf-re
	      "/empty-anchor-1.pdf::#::empty anchor text")))))




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Org mode links: Open a PDF file at a given page and highlight a given string
  2022-09-03 13:00 ` Max Nikulin
@ 2022-09-20 11:54   ` Ihor Radchenko
  2022-09-20 17:03     ` Max Nikulin
  0 siblings, 1 reply; 13+ messages in thread
From: Ihor Radchenko @ 2022-09-20 11:54 UTC (permalink / raw)
  To: Max Nikulin; +Cc: emacs-orgmode

Max Nikulin <manikulin@gmail.com> writes:

> Currently I believe that instead of injecting up to 6 entries into 
> `org-file-apps' for various combinations of page, anchor, and search 
> pattern, it is better to add single record with function handler. Notice 
> that the approach presented above is not affected by the bug with 
> multiple regexp group. Its additional advantage is that shell is not 
> involved, so peculiar file names can not cause execution of some code 
> when quoting and escaping are messed up.
>
> I think a set of functions for popular PDF viewers (evince, zathura, 
> okular, xpdf, xpopple, firefox, chromium & Co., etc.) should be defined 
> in some package, but I am in doubts if it suitable for Org core.
>
> Proof of concept implementation.

Thanks for taking time to implement this proof of concept!

I think that it is a very good idea for Org core to support search terms
in file links that are handled by Free Software.

Moreover, I think that we should, by default, auto-detect and use Free
Software to open file links, when such software is installed on user
machine (unless the user explicitly instruct otherwise).

I see Free Software support as dedicated files like ol-evince,
ol-okular, etc. The file functionality and common function may probably
be factored out into ol-file library.

-- 
Ihor Radchenko,
Org mode contributor,
Learn more about Org mode at https://orgmode.org/.
Support Org development at https://liberapay.com/org-mode,
or support my work at https://liberapay.com/yantar92


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Org mode links: Open a PDF file at a given page and highlight a given string
  2022-09-20 11:54   ` Ihor Radchenko
@ 2022-09-20 17:03     ` Max Nikulin
  2022-09-21  8:17       ` Ihor Radchenko
  2022-09-21  8:18       ` Ihor Radchenko
  0 siblings, 2 replies; 13+ messages in thread
From: Max Nikulin @ 2022-09-20 17:03 UTC (permalink / raw)
  To: emacs-orgmode

On 20/09/2022 18:54, Ihor Radchenko wrote:
> Max Nikulin writes:
> 
>> Currently I believe that instead of injecting up to 6 entries into
>> `org-file-apps' for various combinations of page, anchor, and search
>> pattern, it is better to add single record with function handler. Notice
>> that the approach presented above is not affected by the bug with
>> multiple regexp group. Its additional advantage is that shell is not
>> involved, so peculiar file names can not cause execution of some code
>> when quoting and escaping are messed up.
>>
>> I think a set of functions for popular PDF viewers (evince, zathura,
>> okular, xpdf, xpopple, firefox, chromium & Co., etc.) should be defined
>> in some package, but I am in doubts if it suitable for Org core.
>>
>> Proof of concept implementation.
> 
> Thanks for taking time to implement this proof of concept!

I have realized that it misses customization of application binary 
(exact name or full path to non-standard location).

> I think that it is a very good idea for Org core to support search terms
> in file links that are handled by Free Software.

Maybe I misunderstand something, but your stress on Free Software here 
surprised me. I did not mention explicitly any proprietary application 
such as Adobe Reader. On the other hand support of Chromium (that is 
free) unavoidably assumes Google Chrome and likely MS Edge with other 
derived products with same customization as chromium vs. 
chromium-browser command name discrepancy in Linux distros.

> Moreover, I think that we should, by default, auto-detect and use Free
> Software to open file links, when such software is installed on user
> machine (unless the user explicitly instruct otherwise).

Could you, please, elaborate? E.g. for PDF file default is docview mode. 
Unless a user has an override in `org-file-apps', likely it should be 
used. Perhaps system-wide handler may be considered as a candidate, but 
on linux it means XDG MIME handlers that is not supported by Emacs, so 
only mailcap remains. Both XDG database and mailcap have no notion of 
location within the file to open.

> I see Free Software support as dedicated files like ol-evince,
> ol-okular, etc. The file functionality and common function may probably
> be factored out into ol-file library.

I am considering a single package, something like org-pdfviewer, that 
has definitions for all popular viewers: evince, okular, firefox, 
chromium, etc. I believed that user should explicitly configure 
preferred viewer by either adding an entry with supplied function to 
`org-file-apps' or this package has its own defcustoms and the entry 
injected to some variable as you suggested in
Ihor Radchenko. Re: [PATCH v2] org.el: Fix percent substitutions in 
`org-open-file' Mon, 05 Sep 2022 13:46:41 +0800. 
https://list.orgmode.org/875yi2xtj2.fsf@localhost

The point of defcustoms in the package instead of (or in addition to) 
`org-file-apps' is that evince and okular support more formats than PDF.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Org mode links: Open a PDF file at a given page and highlight a given string
  2022-09-20 17:03     ` Max Nikulin
@ 2022-09-21  8:17       ` Ihor Radchenko
  2022-09-21  8:18       ` Ihor Radchenko
  1 sibling, 0 replies; 13+ messages in thread
From: Ihor Radchenko @ 2022-09-21  8:17 UTC (permalink / raw)
  To: Max Nikulin; +Cc: emacs-orgmode

Max Nikulin <manikulin@gmail.com> writes:

>> I think that it is a very good idea for Org core to support search terms
>> in file links that are handled by Free Software.
>
> Maybe I misunderstand something, but your stress on Free Software here 
> surprised me. I did not mention explicitly any proprietary application 
> such as Adobe Reader. On the other hand support of Chromium (that is 
> free) unavoidably assumes Google Chrome and likely MS Edge with other 
> derived products with same customization as chromium vs. 
> chromium-browser command name discrepancy in Linux distros.

I was referring to GPL-compatible software.
If we have better integration with Libre/Free Software, it is suitable
for Org core. IMHO.

>> Moreover, I think that we should, by default, auto-detect and use Free
>> Software to open file links, when such software is installed on user
>> machine (unless the user explicitly instruct otherwise).
>
> Could you, please, elaborate? E.g. for PDF file default is docview mode. 
> Unless a user has an override in `org-file-apps', likely it should be 
> used. Perhaps system-wide handler may be considered as a candidate, but 
> on linux it means XDG MIME handlers that is not supported by Emacs, so 
> only mailcap remains. Both XDG database and mailcap have no notion of 
> location within the file to open.

I am referring to cdr of the org-file-apps entries.
docview will correspond to `emacs' command. XDG will correspond to
`system'. And we have `default', which could detect Libre Software, if
installed.

>> I see Free Software support as dedicated files like ol-evince,
>> ol-okular, etc. The file functionality and common function may probably
>> be factored out into ol-file library.
>
> I am considering a single package, something like org-pdfviewer, that 
> has definitions for all popular viewers: evince, okular, firefox, 
> chromium, etc. I believed that user should explicitly configure 
> preferred viewer by either adding an entry with supplied function to 
> `org-file-apps' or this package has its own defcustoms and the entry 
> injected to some variable as you suggested in
> Ihor Radchenko. Re: [PATCH v2] org.el: Fix percent substitutions in 
> `org-open-file' Mon, 05 Sep 2022 13:46:41 +0800. 
> https://list.orgmode.org/875yi2xtj2.fsf@localhost
>
> The point of defcustoms in the package instead of (or in addition to) 
> `org-file-apps' is that evince and okular support more formats than PDF.

I understand your idea. What I am suggesting is to implement support for
a subset of popular viewers (the Libre ones) and add it to Org core.
Support for non-Libre viewers could be added ad third-party packages
based on the Org core implementation.

The default viewer may be customized by user according to, say,
org-file-apps-default-pdf-viewer defaulting to 'auto (detect).
This customization will only take effect when the PDF file entry in
org-file-apps sets the command to `default'.

Hope I made my idea more clear.

-- 
Ihor Radchenko,
Org mode contributor,
Learn more about Org mode at https://orgmode.org/.
Support Org development at https://liberapay.com/org-mode,
or support my work at https://liberapay.com/yantar92


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Org mode links: Open a PDF file at a given page and highlight a given string
  2022-09-20 17:03     ` Max Nikulin
  2022-09-21  8:17       ` Ihor Radchenko
@ 2022-09-21  8:18       ` Ihor Radchenko
  1 sibling, 0 replies; 13+ messages in thread
From: Ihor Radchenko @ 2022-09-21  8:18 UTC (permalink / raw)
  To: Max Nikulin; +Cc: emacs-orgmode

Max Nikulin <manikulin@gmail.com> writes:

>> I think that it is a very good idea for Org core to support search terms
>> in file links that are handled by Free Software.
>
> Maybe I misunderstand something, but your stress on Free Software here 
> surprised me. I did not mention explicitly any proprietary application 
> such as Adobe Reader. On the other hand support of Chromium (that is 
> free) unavoidably assumes Google Chrome and likely MS Edge with other 
> derived products with same customization as chromium vs. 
> chromium-browser command name discrepancy in Linux distros.

I was referring to GPL-compatible software.
If we have better integration with Libre/Free Software, it is suitable
for Org core. IMHO.

>> Moreover, I think that we should, by default, auto-detect and use Free
>> Software to open file links, when such software is installed on user
>> machine (unless the user explicitly instruct otherwise).
>
> Could you, please, elaborate? E.g. for PDF file default is docview mode. 
> Unless a user has an override in `org-file-apps', likely it should be 
> used. Perhaps system-wide handler may be considered as a candidate, but 
> on linux it means XDG MIME handlers that is not supported by Emacs, so 
> only mailcap remains. Both XDG database and mailcap have no notion of 
> location within the file to open.

I am referring to cdr of the org-file-apps entries.
docview will correspond to `emacs' command. XDG will correspond to
`system'. And we have `default', which could detect Libre Software, if
installed.

>> I see Free Software support as dedicated files like ol-evince,
>> ol-okular, etc. The file functionality and common function may probably
>> be factored out into ol-file library.
>
> I am considering a single package, something like org-pdfviewer, that 
> has definitions for all popular viewers: evince, okular, firefox, 
> chromium, etc. I believed that user should explicitly configure 
> preferred viewer by either adding an entry with supplied function to 
> `org-file-apps' or this package has its own defcustoms and the entry 
> injected to some variable as you suggested in
> Ihor Radchenko. Re: [PATCH v2] org.el: Fix percent substitutions in 
> `org-open-file' Mon, 05 Sep 2022 13:46:41 +0800. 
> https://list.orgmode.org/875yi2xtj2.fsf@localhost
>
> The point of defcustoms in the package instead of (or in addition to) 
> `org-file-apps' is that evince and okular support more formats than PDF.

I understand your idea. What I am suggesting is to implement support for
a subset of popular viewers (the Libre ones) and add it to Org core.
Support for non-Libre viewers could be added ad third-party packages
based on the Org core implementation.

The default viewer may be customized by user according to, say,
org-file-apps-default-pdf-viewer defaulting to 'auto (detect).
This customization will only take effect when the PDF file entry in
org-file-apps sets the command to `default'.

Hope I made my idea more clear.

-- 
Ihor Radchenko,
Org mode contributor,
Learn more about Org mode at https://orgmode.org/.
Support Org development at https://liberapay.com/org-mode,
or support my work at https://liberapay.com/yantar92


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2022-09-21  8:37 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-02 20:07 Org mode links: Open a PDF file at a given page and highlight a given string Rodrigo Morales
2021-03-02 22:36 ` Kyle Meyer
2021-03-03 12:37   ` Maxim Nikulin
2021-09-27 16:39   ` Max Nikulin
2021-03-03  2:31 ` Juan Manuel Macías
2021-03-03 14:51   ` Maxim Nikulin
2021-03-03 16:11     ` Juan Manuel Macías
2021-03-05 13:02       ` Maxim Nikulin
2022-09-03 13:00 ` Max Nikulin
2022-09-20 11:54   ` Ihor Radchenko
2022-09-20 17:03     ` Max Nikulin
2022-09-21  8:17       ` Ihor Radchenko
2022-09-21  8:18       ` Ihor Radchenko

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).