2013-09-13 2 views
3

В настоящее время я использую emacs для создания и редактирования документов LaTeX. При компиляции я использую внешнюю программу для компиляции в pdf. Прямо сейчас, со следующим кодом в моем .emacs файле, emacs начнет компилировать документ в pdf всякий раз, когда я сохраню файл.Функция emacs после асинхронной команды

(defun auto-compile-latex() 
    (save-window-excursion 
    (async-shell-command (format "cd %s; scons -u" default-directory)))) 
(add-hook 'LaTeX-mode-hook '(lambda() 
    (add-hook 'after-save-hook 'auto-compile-latex nil 'make-it-local))) 

Я предпочитаю это более M-x compile, потому что я больше в привычку экономии, и он запускает в фоновом режиме, что позволяет мне продолжать работать. Однако, когда процесс компиляции заканчивается, я не получаю заметное уведомление.

В идеале, я хотел бы запускать следующую функцию всякий раз, когда процесс компиляции завершается.

(defun latex-compilation-status (exit-code) 
    (if (/= exit-code 0) 
     (setq mode-name (propertize mode-name 'face 'font-lock-warning-face)) 
    (setq mode-name (propertize mode-name 'face 'mode-line-highlight)))) 

Таким образом, я могу иметь цвет в строке режима автоматически меняться в зависимости от того, была ли компиляция успешно или нет. Однако, просматривая документацию emacs, я не нашел упоминания об крюке, который запускается после завершения async-shell-command. Я знаю, что есть сообщение в минибуфере, в котором указано состояние выхода подпроцесса, но если я набираю его в то время, его часто трудно заметить.

В качестве альтернативы, я могу дождаться завершения команды оболочки, а затем немедленно изменить цвет. Тем не менее, это делает все замораживание emacs во время компиляции, что нежелательно.

Как бы я хотел, чтобы это указание было применено в конце компиляции, без зависания emacs во время процесса?

ответ

0

Вот еще один вариант использования set-process-sentinel на основании предварительного полезного ответа на Francesco. Пожалуйста, будьте осторожны, однако, об использовании привязки let, чтобы определить start-process (что [в моем мнении] является определенным «no no»), потому что это вызовет начало процесса непосредственно перед его временем. [FYI: Nicolas получил меня из довольно много пробок в прошлом, поэтому, пожалуйста, не забудьте взять хороший твердый взгляд на его решение также.]

Emacs: if latexmk finishes okay, then show pdf, else display errors

Вы бы просто добавить функцию к последняя часть функции дело с успехом - т.е. (when (= 0 (process-exit-status p)) . . .:

(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) "\\.")) ".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") 
    (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 "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))))) 
+0

Это много глобальных переменных.Как насчет использования одной переменной с именами для хранения всех данных и извлечения значений из этого на другом конце? – phils

+0

Я хотел бы узнать лучший способ делать вещи, если бы вы могли быть настолько добры, чтобы привести пример или два. 'let' привязки не могут быть определены * внутри *' set-process-sentinel', потому что они отклоняются при попытке запустить эту функцию. Любые привязки 'let', определенные до *' set-process-sentinel', не могут использоваться внутри функции 'lambda (p e)', так как * ранее * 'let' привязки не распознаются в подфункции' lambda'. 'start-process' не может быть' let' bound, так как он запускается немедленно, как только он привязан. Моя цель состояла в том, чтобы все было встроено в одну аккуратную/чистую функцию. – lawlist

+0

'start process' и' concat' не смешиваются, даже с разделителем пробелов - например, '(concat arg-1" "arg-2)' отклоняется 'start-process', поэтому каждый аргумент должен быть отдельно прописано. – lawlist

0

Спасибо. Я закончил тем, что получил его, используя измененную версию кода закона. Теперь это изменило цвет при начале компиляции, затем снова меняет его, чтобы указать успех или неудачу.

;Automatically compile any latex documents when saved. 
(defun auto-compile-latex() 
    (setq mode-name (propertize mode-name 'face 'font-lock-string-face)) 
    (set-process-sentinel 
    (start-process-shell-command "latex-compile" "latex-compile" 
           (format "cd %s; scons -u" default-directory)) 
    'latex-compile-sentinel)) 
;Change the color after compilation. Still need to find the right hook to add it to. 
(defun latex-compile-sentinel (process event) 
    (if (string-equal event "finished\n") 
     (setq mode-name (propertize mode-name 'face 'mode-line-highlight)) 
    (setq mode-name (propertize mode-name 'face 'font-lock-warning-face)))) 
;Hooks for latex-mode 
(add-hook 'LaTeX-mode-hook '(lambda() 
    (add-hook 'after-save-hook 'auto-compile-latex nil 'make-it-local))) 

В качестве альтернативы пакет emacs-async не работал для этого использования. Я предполагаю, что это потому, что emacs-async запускает вторичные функции в отдельном процессе, , причем некоторые из переменных не распространяются обратно на родительский процесс.

+1

Часть 'if' может быть упрощена следующим образом:' (setq mode-name (propertize mode-name 'face (если (завершено равное событие \ n ")' mode-line-highlight 'font-lock-warning -грань)) '. – Stefan

0

Вы также можете организовать свой auto-compile-latex для запуска compile.

Смежные вопросы