Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

i want to let emacs automatically open pdf file after i type C-c C-c dvi2ps2pdf RET, so i add the following code in my .emacs file

;;dvi2ps2pdf
(add-to-list 'TeX-command-list
 (list "dvi2ps2pdf" " dvips %s.dvi | ps2pdf %s.ps %s.pdf | SumatraPDF %o"
 'TeX-run-command nil t))

it works fine, well, until i find that it fails if the tex file, say, foo.tex, has \usepackage{psfrag} in it as follows,

% foo.tex
\documentclass{article}
\usepackage{psfrag}
\begin{document}
\[ e^x=\sum_{n=0}^{\infty}\frac{x^n}{n!}\]
\end{document}

SumatraPDF would open foo.dvi instead of foo.pdf.

if i type C-c C-n and start all over, it works fine again, as long as i do not compile and produce a new foo.div.

after compiling and foo.div is created,

if i replace %o with %f, SumatraPDF would open foo.ps

if i replace %o with %s.pdf, SumatraPDF would open two broken files foo and .pdf

if i replace SumatraPDF %o with start \"\" %s.pdf, Adobe Reader will correctly open foo.pdf

this is frustrating. how can i edit the code to let SumatraPDF take over everything? and how to use those substitution %o %f %s properly? excuse me that i'm really inexperienced, but it seems that they belong to different conventions? thanks very much!

UPDATE


with @giordano's help, i tend to believe that this is a inherent problem of SumatraPDF (Adobe Reader too, i think).

i think there's no problem on linux or mac. on windows, however, in DOS commands, i find that the following are the same, say,

  • copy foo.pdf bar.pdf
  • copy "foo".pdf bar.pdf
  • copy "foo.pdf" bar.pdf
  • ...

other external commands such as dvips and ps2pdf do not distinguish the cases, either. SumatraPDF, however, treats foo.pdf or "foo.pdf" as one same file, and "foo".pdf as two separate files foo and .pdf and even opens them.

i think that's why SumatraPDF always fails to open %s.pdf. it is a file name parsing flaw, if i'm right, SumatraPDF is not intend to open files like .pdf on windows system, and it should be able to detect that automatically.

p.s.

i also tried to manipulate the string %s.pdf(="foo".pdf) and tried to strip the double quotes in ways of lisp or DOS command. the quotes won't go away and i failed miserably due to inexperience.

do you guys have any ideas? thanks!

UPDATE


thanks to @giordano, i gave a shot on cygwin. (i had cygwin install for doc view anyway, no trouble at all.) it turns out that SumatraPDF works completely fine on cygwin, i.e., it accepts file names such as "foo".pdf. so i decided to redirect all command line calls to cygwin. i added the following to .emacs file (see emacswiki),

 ;; Sets your shell to use cygwin's bash, if Emacs finds it's running
  ;; under Windows and c:\cygwin exists. Assumes that C:\cygwin\bin is
  ;; not already in your Windows Path (it generally should not be).
  ;;
  (let* ((cygwin-root "c:/cygwin")
         (cygwin-bin (concat cygwin-root "/bin")))
    (when (and (eq 'windows-nt system-type)
         (file-readable-p cygwin-root))

      (setq exec-path (cons cygwin-bin exec-path))
      (setenv "PATH" (concat cygwin-bin ";" (getenv "PATH")))

      ;; By default use the Windows HOME.
      ;; Otherwise, uncomment below to set a HOME
      ;;      (setenv "HOME" (concat cygwin-root "/home/eric"))

      ;; NT-emacs assumes a Windows shell. Change to bash.
      (setq shell-file-name "bash")
      (setenv "SHELL" shell-file-name) 
      (setq explicit-shell-file-name shell-file-name)))

after that, SumatraPDF recognizes %s.pdf just fine.

there is one problem, though. dvi2ps runs differntly on cygwin and cannot proceed, i put the question somewhere else.

p.s.

code of SumatraPDF has been improved to accomodate cases like "foo".pdf. hopefully we'll see how it work very soon.

share|improve this question
    
If it's a bug you should really report it to Emacs (M-x report-emacs-bug RET) or AUCTeX (M-x TeX-submit-bug-report RET) instead of trying to work around. If it will be fixed upstream, everyone will benefit, not just you ;-). –  giordano Oct 13 '13 at 9:20
    
i think i'll try to report this to SumatraPDF first :) –  davyjones Oct 13 '13 at 10:15
    
One option would be to become more comfortable with command-line and set up your own function similar to my first example, which obviates the need to rely upon AUCTeX. Another option would be for you to open up tex.el and take a look at (defcustom TeX-expand-list . . . and perhaps create your own variables that format file names in a manner that SumatraPDF likes. You can customize your own variable in whatever format you like -- e.g., by using split-string, and concat. –  lawlist Oct 13 '13 at 21:41
    
In my first example, I used: (setq base-file (car (split-string (buffer-file-name) "\\."))) and (setq pdf-file (concat base-file ".pdf")). If your buffer-file-name is c:/davy/jones/foo.tex, then base-file is c:/davy/jones/foo. Then, pdf-file concatenates a .pdf onto the end of base-file. This gives you a *.pdf file name that SumatraPDF likes. My line of code (start-process "displayline" nil sumatra "-forward-search" tex-file line pdf-file) is shorthand for C:/SumatraPDF/SumatraPDF.exe -forward-search c:/davy/jones/foo.tex [line-number] c:/davy/jones/foo.pdf. –  lawlist Oct 13 '13 at 22:09

2 Answers 2

The solution is much simpler than what you've done so far: define a single command that runs latex, dvips and ps2pdf. In this way, when TeX-PDF-mode is active the PDF will be opened by your default PDF viewer without any further change. In your init file you can add something like this:

(add-to-list
      'TeX-command-list
      '("dvi2ps2pdf" "%(latex) %s && dvips %s.dvi && ps2pdf %s.ps %s.pdf" TeX-run-command nil t))

I'm not familiar with DOS batch scripting, in UNIX shells && is the logic AND, the following command is run if the previous one exits successfully, I don't know what's the batch analogous.

share|improve this answer
    
@giodano,great! thanks very much! the only thing i need to do is to stay in the pdflatex mode. btw, what if i want to perform this in the dvi mode and i do not want to switch to the pdf mode to open the pdf file, otherwise i would get the dvi file to open, or in the presence of psfrag package, the ps file will open in gsview? –  davyjones Oct 11 '13 at 15:48
    
@davyjones it wouldn't be a clean solution, but you can append SumatraPDF %s.pdf to the list of programs to be run by the dvi2ps2pdf command. –  giordano Oct 11 '13 at 17:09
    
@giodano,saddly simply appending does not work... as i stated in the original question, that would cause SumatraPDF to open two broken file, say, foo and .pdf. i think we could define a function viewpdf first as found in link, but i would not how to use it inside the double quotes again, do you have any suggestions? many thanks again! –  davyjones Oct 11 '13 at 17:25
    
@davyjones has the file spaces in its name? Appending && okular %s.pdf (Okular is my PDF viewer) works for me. Try protecting the file name with quotes: \"%s.pdf\" instead of simply %s.pdf. –  giordano Oct 11 '13 at 17:31
    
@giodano, sadly, it failed again... SumatraPDF will open two broken files, one with no name, the other with name bar".pdf". if i use SumatraPDF .\\%s.pdf, SumatraPDF will open one broken file named "bar".pdf. it still fails if i change SumatraPDF to AcroRd32. is it because i'm using emacs+auctex on windows system? –  davyjones Oct 11 '13 at 20:04

The following is a function that does not rely upon AUCTeX -- the function essentially uses five command lines (similar to using a terminal) along with some lisp mixed in to generate the output buffer and then delete it if the build was successful. For this example, I chose to use latexmk and pdflatex that were installed through Tex Live 2013 for Windows. The function uses nesting / chaining of set-process-sentinel and start-process to run several asynchronous processes -- the latter process executing upon a successful completion of the prior process. The ingredients for the latexmkrc file are user defined, and a sample is included in the function doc-string.

     (1) exit SumatraPDF;

     (2) delete auxiliary files including the *.pdf from a previous build;

     (3) build a new *.pdf file;

     (4) display the new *.pdf in SumatraPDF with forward sync; and,

     (5) delete the auxiliary files except the new *.pdf.

There is a bug in pdflatex that occurs when a *.pdf build fails -- i.e., pdflatex<PID>.fls is not renamed to <jobname>.fls -- cleaning with latexmk will not delete pdflatex<PID>.fls and those files will accumulate with each failed build. Rather than using a command line to delete all of the pdflatex<PID>.fls, I chose to simply turn off the recorder within the latexmkrc file. This is just a personal preference for working-around the bug.

(defun latexmk ()
".latexmkrc contains the following entries:
  $pdflatex = 'pdflatex -file-line-error -synctex=1 %O %S';
  $pdf_mode = 1;
  $recorder = 0;
  $clean_ext = 'synctex.gz synctex.gz(busy) aux fdb_latexmk log';"
(interactive)
  (setq tex-file (buffer-file-name))
  (setq base-file (car (split-string (buffer-file-name) "\\.tex")))
  (setq pdf-file (concat base-file ".pdf"))
  (setq line (format "%d" (line-number-at-pos)))
  (setq sumatra "c:/Program Files/SumatraPDF/SumatraPDF.exe")
  (setq tex-output (concat "*" (file-name-nondirectory buffer-file-name) "*") )
  (setq latexmk "c:/texlive/2013/bin/win32/latexmk.exe")
  (setq latexmkrc "y:/.0.emacs/.latexmkrc-nt")
  (if (buffer-modified-p)
    (save-buffer))
  (delete-other-windows)
  (set-window-buffer (split-window-horizontally) (get-buffer-create tex-output))
  (with-current-buffer tex-output (erase-buffer))
  (start-process "tskill" nil "c:/WINDOWS/system32/tskill.exe" "SumatraPDF")
  (set-process-sentinel 
    (start-process "deep-clean" nil latexmk "-C" "-r" latexmkrc tex-file)
    (lambda (p e) (when (= 0 (process-exit-status p))
      (set-process-sentinel 
        (start-process "compile" tex-output latexmk "-r" latexmkrc tex-file)
        (lambda (p e) (when (= 0 (process-exit-status p))
          (if (get-buffer-process (get-buffer tex-output))
            (process-kill-without-query (get-buffer-process (get-buffer tex-output))))
          (kill-buffer tex-output)
          (delete-other-windows)
          (switch-to-buffer (get-file-buffer tex-file))
          (start-process "displayline" nil sumatra "-forward-search" tex-file line pdf-file)
          (sit-for 2)
          (start-process "clean" nil latexmk "-c" "-r" latexmkrc tex-file))))))))

The following is an example for using AUCTeX with SumatraPDF and forward sync.

(setq TeX-PDF-mode t)

(setq TeX-source-correlate-mode t)

(setq TeX-source-correlate-method 'synctex)

(setq TeX-view-program-selection '((output-pdf "sumatra")))

(eval-after-load "tex" '(progn

  (add-to-list 'TeX-expand-list '("%(tex-file-name)" (lambda ()
    (concat "\"" (buffer-file-name) "\""))))

  (add-to-list 'TeX-expand-list '("%(pdf-file-name)" (lambda ()
    (concat
      "\"" (car (split-string (buffer-file-name) "\\.tex"))
      ".pdf" "\""))))

  (add-to-list 'TeX-expand-list '("%(line-number)" (lambda ()
    (format "%d" (line-number-at-pos)))))

  (add-to-list 'TeX-view-program-list
    '("sumatra" ("\"c:/Program Files/SumatraPDF/SumatraPDF.exe\" -forward-search %(tex-file-name) %(line-number) %(pdf-file-name)")) t)))

(defun TeX-MultiTeX ()
"Still need to fix clean without confirmation -- need to turn 'View' into
  a process which can be monitored for successful completion before clean."
(interactive)
  (setq TeX-source-correlate-start-server nil)
  (setq TeX-clean-confirm t)
  (if (buffer-modified-p)
    (save-buffer))
  (set-process-sentinel
    (TeX-command "LaTeX" 'TeX-master-file)
      (lambda (p e)
        (when (= 0 (process-exit-status p))
          (TeX-command "View" 'TeX-active-master 0)
          (TeX-command "Clean" 'TeX-master-file)))))

The following is an example similar to the first one, but geared towards OSX and Skim:

(defun latexmk ()
  ".latexmkrc contains the following entries (WITHOUT the four backslashes):
  $pdflatex = 'pdflatex -file-line-error -synctex=1 %O %S && (cp \"%D\" \"%R.pdf\")';
  $pdf_mode = 1;
  $out_dir = '/tmp';"
(interactive)
  (setq tex-file buffer-file-name)
  (setq pdf-file (concat "/tmp/"
    (car (split-string (file-name-nondirectory buffer-file-name) "\\.tex")) ".pdf"))
  (setq line (format "%d" (line-number-at-pos)))
  (setq skim "/Applications/Skim.app/Contents/SharedSupport/displayline")
  (setq tex-output (concat "*" (file-name-nondirectory buffer-file-name) "*") )
  (setq latexmk "/usr/local/texlive/2012/texmf-dist/scripts/latexmk/latexmk.pl")
  (setq latexmkrc "/Users/HOME/.0.data/.0.emacs/.latexmkrc")
  (setq exit-skim-script (concat "tell application \"skim\" to quit"))
  (if (buffer-modified-p)
    (save-buffer))
  (delete-other-windows)
  (set-window-buffer (split-window-horizontally) (get-buffer-create tex-output))
  (with-current-buffer tex-output (erase-buffer))
  (set-process-sentinel 
    (start-process "exit-skim" nil "osascript" "-e" exit-skim-script)
    (lambda (p e) (when (= 0 (process-exit-status p))
      (set-process-sentinel 
        (start-process "clean" nil latexmk "-C" "-r" latexmkrc tex-file)
        (lambda (p e) (when (= 0 (process-exit-status p))
          (set-process-sentinel 
            (start-process "compile" tex-output latexmk "-r" latexmkrc tex-file)
            (lambda (p e) (when (= 0 (process-exit-status p))
              (start-process "displayline" nil skim "-b" line pdf-file tex-file)
              (switch-to-buffer (get-file-buffer tex-file))
              (if (get-buffer-process (get-buffer tex-output))
                (process-kill-without-query (get-buffer-process (get-buffer tex-output))))
              (kill-buffer tex-output)
              (delete-other-windows)))))))))))

This last example is similar to the second one, but geared towards OSX and Skim:

(setq TeX-PDF-mode t)

(setq TeX-source-correlate-mode t)

(setq TeX-source-correlate-method 'synctex)

(setq TeX-view-program-selection '((output-pdf "Skim")))

(eval-after-load "tex" '(progn

  (add-to-list 'TeX-expand-list '("%(tex-file-name)" (lambda ()
    (concat "\"" (buffer-file-name) "\""))))

  (add-to-list 'TeX-expand-list '("%(pdf-file-name)" (lambda ()
    (concat
      "\"" (car (split-string (buffer-file-name) "\\.tex"))
      ".pdf" "\""))))

  (add-to-list 'TeX-expand-list '("%(line-number)" (lambda ()
    (format "%d" (line-number-at-pos)))))

  (add-to-list 'TeX-view-program-list
    '("Skim" ("/Applications/Skim.app/Contents/SharedSupport/displayline -o %(line-number) %(pdf-file-name) %(tex-file-name)")) t)))

(defun TeX-MultiTeX ()
"Still need to fix clean without confirmation -- need to turn 'View' into
  a process which can be monitored for successful completion before clean."
(interactive)
  (setq TeX-source-correlate-start-server nil)
  (setq TeX-clean-confirm t)
  (if (buffer-modified-p)
    (save-buffer))
  (set-process-sentinel
    (TeX-command "LaTeX" 'TeX-master-file)
      (lambda (p e)
        (when (= 0 (process-exit-status p))
          (TeX-command "View" 'TeX-active-master 0)
          (TeX-command "Clean" 'TeX-master-file)))))
share|improve this answer
    
i'm sure it would work in some way, but it does not seem to help. in comparison, switching to pdf mode would be more advisable. thanks all the same! –  davyjones Oct 13 '13 at 8:29
    
This code bypasses AUCTeX completely and launches Sumatra automatically upon a successful compilation. –  lawlist Oct 13 '13 at 8:49
    
that's nice. i see it invokes pdflatex directly, and pdflatex is the future. but i'm afraid some .tex file just need to go thru the latex->dvi->ps->pdf process. –  davyjones Oct 13 '13 at 9:13
    
I added a sample of how to use AUCTeX with Sumatra. Unfortunately, I believe a macro is necessary due to the way TeX-view and TeX-active-master are written within tex-buf.el. (TeX-command "LaTeX" 'TeX-master-file) must be run first, and then there must be a break, and then you can run (TeX-command "View" 'TeX-master-file) -- that is why a macro was used (because they cannot be linked together in one function without a break between the two). –  lawlist Oct 13 '13 at 10:21
1  
thanks again, although i'm having a hard time digesting your code. i think in pdf mode, things are a lot easier. based on @giodano's idea below, adding (add-to-list 'TeX-command-list '("pdflatexmk" pdflatex %s && SumatraPDF %o" TeX-run-command nil t)) to .emacs file would have sufficed. of course, you could append other options to pdflatex such as --synctex' or --shell-escape etc.. just type C-c C-c pdflatexmk RET, the compiled the pdf will pop out inside SumatraPDF, provided the .tex file is error free. –  davyjones Oct 13 '13 at 12:21

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.