emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Org mode links: Open a PDF file at a given page and highlight a give


From: Maxim Nikulin
Subject: Re: Org mode links: Open a PDF file at a given page and highlight a given string
Date: Fri, 5 Mar 2021 20:02:37 +0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.7.1

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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]