[Tex/LaTex] Setup SyncTeX with Emacs

auctexemacsevinceforward-inverse-searchUbuntu

I want to setup SyncTeX with Emacs, or, more specifically, with AUCTeX, and Evince in Ubuntu. How can I do that? I would like both forward search (from source to output) and inverse search (from output to source).

I have tried the following without success:

  • I tried to do as http://www.emacswiki.org/emacs/AUCTeX#toc19 describes but when I try backward search (Ctrl+left click) I get the following message in Emacs:

    apply: Wrong number of arguments: (lambda (file linecol) (let ((buf
    (get-buffer file)) (line (car linecol)) (col (cadr linecol))) (if
    (null buf) (message "Sorry, %s is not opened…" file)
    (switch-to-buffer buf) (goto-line (car linecol)) (unless (= col -1)
    (move-to-column col))))), 3

  • If I try the solution in http://ubuntuforums.org/showpost.php?p=11010827&postcount=12 I get the following message in Emacs:

    Symbol's value as variable is void: TeX-view-program-list

  • When I try http://ubuntuforums.org/showthread.php?p=11010827#post11010827 Emacs freezes a while and then I get the following message in Emacs:

    let*: D-Bus error: "Did not receive a reply. Possible causes include:
    the remote application did not send a reply, the message bus security
    policy blocked the reply, the reply timeout expired, or the network
    connection was broken."

I am using AUCTeX 11.86 with Emacs 23.3.1 and Evince 3.2.1 in Ubuntu 11.10.

Best Answer

I combined some of the links mentioned here, you will find the links in the source comments. This code supports:

  • Forward search (Emacs to Evince, via C-c C-v)
  • Backward/Inverse search (Evince to Emacs, via C-Mouse-1, that is Ctrl + "Left Click" in Evince)
  • Path names with spaces
  • Multifile setups (TeX files requested by Evince will be opened if they aren't open yet)
; SyncTeX basics

; un-urlify and urlify-escape-only should be improved to handle all special characters, not only spaces.
; The fix for spaces is based on the first comment on http://emacswiki.org/emacs/AUCTeX#toc20

(defun un-urlify (fname-or-url)
  "Transform file:///absolute/path from Gnome into /absolute/path with very limited support for special characters"
  (if (string= (substring fname-or-url 0 8) "file:///")
      (url-unhex-string (substring fname-or-url 7))
    fname-or-url))

(defun urlify-escape-only (path)
  "Handle special characters for urlify"
  (replace-regexp-in-string " " "%20" path))

(defun urlify (absolute-path)
  "Transform /absolute/path to file:///absolute/path for Gnome with very limited support for special characters"
  (if (string= (substring absolute-path 0 1) "/")
      (concat "file://" (urlify-escape-only absolute-path))
      absolute-path))


; SyncTeX backward search - based on http://emacswiki.org/emacs/AUCTeX#toc20, reproduced on https://tex.stackexchange.com/a/49840/21017

(defun th-evince-sync (file linecol &rest ignored)
  (let* ((fname (un-urlify file))
         (buf (find-file fname))
         (line (car linecol))
         (col (cadr linecol)))
    (if (null buf)
        (message "[Synctex]: Could not open %s" fname)
      (switch-to-buffer buf)
      (goto-line (car linecol))
      (unless (= col -1)
        (move-to-column col)))))

(defvar *dbus-evince-signal* nil)

(defun enable-evince-sync ()
  (require 'dbus)
  ; cl is required for setf, taken from: http://lists.gnu.org/archive/html/emacs-orgmode/2009-11/msg01049.html
  (require 'cl)
  (when (and
         (eq window-system 'x)
         (fboundp 'dbus-register-signal))
    (unless *dbus-evince-signal*
      (setf *dbus-evince-signal*
            (dbus-register-signal
             :session nil "/org/gnome/evince/Window/0"
             "org.gnome.evince.Window" "SyncSource"
             'th-evince-sync)))))

(add-hook 'LaTeX-mode-hook 'enable-evince-sync)


; SyncTeX forward search - based on https://tex.stackexchange.com/a/46157

;; universal time, need by evince
(defun utime ()
  (let ((high (nth 0 (current-time)))
        (low (nth 1 (current-time))))
   (+ (* high (lsh 1 16) ) low)))

;; Forward search.
;; Adapted from http://dud.inf.tu-dresden.de/~ben/evince_synctex.tar.gz
(defun auctex-evince-forward-sync (pdffile texfile line)
  (let ((dbus-name
     (dbus-call-method :session
               "org.gnome.evince.Daemon"  ; service
               "/org/gnome/evince/Daemon" ; path
               "org.gnome.evince.Daemon"  ; interface
               "FindDocument"
               (urlify pdffile)
               t     ; Open a new window if the file is not opened.
               )))
    (dbus-call-method :session
          dbus-name
          "/org/gnome/evince/Window/0"
          "org.gnome.evince.Window"
          "SyncView"
          (urlify-escape-only texfile)
          (list :struct :int32 line :int32 1)
  (utime))))

(defun auctex-evince-view ()
  (let ((pdf (file-truename (concat default-directory
                    (TeX-master-file (TeX-output-extension)))))
    (tex (buffer-file-name))
    (line (line-number-at-pos)))
    (auctex-evince-forward-sync pdf tex line)))

;; New view entry: Evince via D-bus.
(setq TeX-view-program-list '())
(add-to-list 'TeX-view-program-list
         '("EvinceDbus" auctex-evince-view))

;; Prepend Evince via D-bus to program selection list
;; overriding other settings for PDF viewing.
(setq TeX-view-program-selection '())
(add-to-list 'TeX-view-program-selection
         '(output-pdf "EvinceDbus"))

This will likely break for:

  • Path names with special characters other than spaces

I used these helpful links:

I tested with

  • Emacs 24.2
  • Evince 3.4.0
  • OpenSUSE 12.2