In The Armchair

LaTeX Forward PDF Search with Emacs

Posted in Computers by Armchair Guy on November 15, 2010

I wrote a blog post on implementing inverse PDF search with okular and emacs here.  This post is about the reverse: forward search.  That is, with point at any position in the LaTeX source while editing in emacs, a keystroke causes okular to center the corresponding portion of the PDF in its viewable area. A nice overview of LaTeX synchronization can be found here.

In the comments on the inverse search post, B. Slade suggested the procedure at for forward search.  However, the instructions there require installation of AuCTeX version 11.86, while the latest version in the Ubuntu 10.04 repositories have is 11.85.

I managed to kludge a solution for the AuCTeX shipping with Ubuntu 10.04 by slightly modifying some emacs code I found here: Most of the work was already done by Mark Altern and earlier authors; the only change was to tell it to use the .pdf instead of the .dvi.

A note of caution.  Forward search with okular is not very convenient.  This is because okular redisplays the PDF document every time you do a forward search — with a side “contents” pane and also repositioning the PDF.  So if you’ve removed the space-hogging contents pane (by pressing F7 twice) and zoomed and positioned the PDF to your liking, doing a forward search will undo all of that.  You’ll have to remove the contents pane again and re-zoom and re-position.  This severely limits the usefulness of forward search.  There doesn’t seem to be a way around this for now.

Anyway, here are the steps.

  1. Follow instructions here to set up inverse search.
  2. Source for okular-search.el is at the end of this post.  Copy it and put it in a file called okular-search.el.
  3. In your .emacs file, add the following code:
    (add-to-list 'load-path "/path/to/okular-search.el")
    (require 'okular-search)
    (add-hook 'LaTeX-mode-hook (lambda () (local-set-key "\C-x\C-j" 'okular-jump-to-line)))
    (add-hook 'tex-mode-hook (lambda () (local-set-key "\C-x\C-j" 'okular-jump-to-line)))

That’s it. Press C-x C-j to open a new okular viewing window. Subsequent presses of C-x C-j will reposition the PDF in that okular window to correspond to whatever’s at point in emacs.

Here’s the code for okular-search.el:

;;; (X)Emacs frontend to forward search with kdvi. See the section on
;;; FORWARD SEARCH in the kdvi manual for more information on forward
;;; search, and for an explanation how to use this script. This script
;;; is a modified version of the script "xdvi-search.el" by Stefan
;;; Ulrich, version 2000/03/13. The
;;; modifications were performed by Stefan Kebekus
;;; . Tested with Emacs 20.7.1 and Xemacs 21.4.
;;; This program is free software; you can redistribute it and/or
;;; modify it under the terms of the GNU General Public License as
;;; published by the Free Software Foundation; either version 2 of the
;;; License, or (at your option) any later version.
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; General Public License for more details.
;;; You should have received a copy of the GNU General Public License
;;; along with this program; if not, write to the Free Software
;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
;;; 02110-1301, USA.
;;; Please report bugs or improvements, etc. via the "Report bug"-Menu
;;; of okular.

(defvar okular-script "okular"
  "*Name of start script for okular.")

(defun okular-jump-to-line ()
  "Call okular-script to perform a `forward search' for current file and line number.
See contents of okular-script for details.
If AucTeX is used, the value of TeX-master-file is used as filename
for the master .dvi file; else, the return value of okular-master-file-name
is used (which see)."
      (beginning-of-line 1)
      (let* (;;; current line in file, as found in the documentation
	     ;;; of emacs. Slightly non-intuitive.
	     (current-line (format "%d" (+ 1 (count-lines (point-min) (point)))))
	     ;;; name of the `main' .tex file, which is also used as .dvi basename:
	     (master-file (expand-file-name (if (fboundp 'TeX-master-file)
					     (TeX-master-file t)
					   (okular-get-masterfile (okular-master-file-name)))))
	     ;;; .dvi file name:
	     (pdf-file (concat (file-name-sans-extension master-file) ".pdf"))
	     ;;; current source file name.
	     (filename (expand-file-name (buffer-file-name))))
	(start-process "okular"
		       "okular-output" "okular" ;;; src-args
		      ;;; args for -sourceposition:
		       "--unique" (concat "file:" pdf-file "#src:" current-line filename)

(defun okular-get-masterfile (file)
  "Small helper function for AucTeX compatibility.
Converts the special value t that TeX-master might be set to
into a real file name."
  (if (eq file t)

(defun okular-master-file-name ()
  "Emulate AucTeX's TeX-master-file function.
Partly copied from tex.el's TeX-master-file and TeX-add-local-master."
  (if (boundp 'TeX-master)
    (let ((master-file (read-file-name "Master file (default this file): ")))
      (if (y-or-n-p "Save info as local variable? ")
	    (goto-char (point-max))
	    (if (re-search-backward "^\\([^\n]+\\)Local Variables:" nil t)
		(let* ((prefix (if (match-beginning 1)
				   (buffer-substring (match-beginning 1) (match-end 1))
		      (start (point)))
		  (re-search-forward (regexp-quote (concat prefix "End:")) nil t)
		  (if (re-search-backward (regexp-quote (concat prefix "TeX-master")) start t)
		      ;;; if TeX-master line exists already, replace it
			(beginning-of-line 1)
			(kill-line 1))
		    (beginning-of-line 1))
		  (insert prefix "TeX-master: " (prin1-to-string master-file) "\n"))
	      (insert "\n%%% Local Variables: "
;;; mode is of little use without AucTeX ...
;;;		      "\n%%% mode: " (substring (symbol-name major-mode) 0 -5)
		      "\n%%% TeX-master: " (prin1-to-string master-file)
		      "\n%%% End: \n"))
	    (message "(local variables written.)"))
	(message "(nothing written.)"))
      (set (make-local-variable 'TeX-master) master-file))))

(provide 'okular-search)

3 Responses

Subscribe to comments with RSS.

  1. B.Slade said, on December 30, 2010 at 9:18 pm

    Sometime in the past week whatever I had working before with forward search broke. I don’t know when, I don’t know how.

    I implemented the hack you give here. Many thanks for that.

    Question: why bind to C-x C-j? Why not C-c C-v?

    On the problems you mention with the contents panel/F7 annoyance etc.:
    (1) I had exactly the same problem with the bleedingmind procedure I was using before. But…:

    (2) The problem is limited (both with the old bleedingmind method and with your new hack) to documents which use the hyperref package. So I think it’s a limitation/quirk of Okular.

    • Armchair Guy said, on December 31, 2010 at 12:59 pm


      Good to hear this version is working for you! I found C-x C-j in the code I tweaked; I just didn’t change it is all. C-c C-v might make more sense.

      I hadn’t realized the connection with the hyperref package — all my files use it. Thanks for the clarification.

  2. beslayed said, on July 27, 2011 at 4:01 pm

    Have you updated to TeXlive 2011 yet? I’m having difficulty with forward search because of changes to synctex. Have asked about these various places (e.g. ); haven’t had much luck in getting a response.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: