从.ps / .dvi / .pdf,转到Emacs中相应的.tex位置

时间:2011-04-20 23:28:56

标签: emacs latex

我正在使用Emacs编辑.tex文件。似乎有一种方法可以查看文档(.dvi或.ps),然后如果我们点击文档,我们可以转到Emacs中相应的.tex文件位置,任何人都可以告诉我如何配置Emacs意识到这个功能?

谢谢。

2 个答案:

答案 0 :(得分:2)

您想要SyncTeX,还应该查看tex.stackexchange.com

答案 1 :(得分:1)

如果你有一个行为良好的dbus系统,它应该在cvs-version中开箱即用。

如果你不(像我一样),或者你现在想使用版本11.86,你可以使用以下脚本。它们是其他人民努力的修改版本(见(c)和http://ubuntuforums.org/showthread.php?t=1716268)。

你只需在你的pdf文件中按住+左键单击(该文件当然必须有synctex信息)。

Evince-backward-search(注意shebang):

#!/usr/bin/python2
# -*- coding: utf-8 -*-

# Copyright (C) 2010 Jose Aliste <jose.aliste@gmail.com>
#               2011 Benjamin Kellermann <Benjamin.Kellermann@tu-dresden.de>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public Licence as published by the Free Software
# Foundation; either version 2 of the Licence, 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 MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public Licence for more
# details.
#
# You should have received a copy of the GNU General Public Licence along with
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# Street, Fifth Floor, Boston, MA  02110-1301, USA

import dbus, subprocess, time, re

RUNNING, CLOSED = range(2)

EV_DAEMON_PATH = "/org/gnome/evince/Daemon"
EV_DAEMON_NAME = "org.gnome.evince.Daemon"
EV_DAEMON_IFACE = "org.gnome.evince.Daemon"

EVINCE_PATH = "/org/gnome/evince/Evince"
EVINCE_IFACE = "org.gnome.evince.Application"

EV_WINDOW_IFACE = "org.gnome.evince.Window"



class EvinceWindowProxy:
    """A DBUS proxy for an Evince Window."""
    daemon = None
    bus = None

    def __init__(self, uri, editor, spawn = False, logger = None):
        self._log = logger
        self.uri = uri
        self.editor = editor
        self.status = CLOSED
        self.source_handler = None
        self.dbus_name = ''
        self._handler = None
        try:
            if EvinceWindowProxy.bus is None:
                EvinceWindowProxy.bus = dbus.SessionBus()

            if EvinceWindowProxy.daemon is None:
                EvinceWindowProxy.daemon = EvinceWindowProxy.bus.get_object(EV_DAEMON_NAME,
                                                EV_DAEMON_PATH,
                                                follow_name_owner_changes=True)
            EvinceWindowProxy.bus.add_signal_receiver(self._on_doc_loaded, signal_name="DocumentLoaded", 
                                                      dbus_interface = EV_WINDOW_IFACE, 
                                                      sender_keyword='sender')
            self._get_dbus_name(False)

        except dbus.DBusException:
            if self._log:
                self._log.debug("Could not connect to the Evince Daemon")

    def _on_doc_loaded(self, uri, **keyargs):
        if uri == self.uri and self._handler is None:
            self.handle_find_document_reply(keyargs['sender'])

    def _get_dbus_name(self, spawn):
        EvinceWindowProxy.daemon.FindDocument(self.uri,spawn,
                     reply_handler=self.handle_find_document_reply,
                     error_handler=self.handle_find_document_error,
                     dbus_interface = EV_DAEMON_IFACE)

    def handle_find_document_error(self, error):
        if self._log:
            self._log.debug("FindDocument DBus call has failed")

    def handle_find_document_reply(self, evince_name):
        if self._handler is not None:
            handler = self._handler
        else:
            handler = self.handle_get_window_list_reply
        if evince_name != '':
            self.dbus_name = evince_name
            self.status = RUNNING
            self.evince = EvinceWindowProxy.bus.get_object(self.dbus_name, EVINCE_PATH)
            self.evince.GetWindowList(dbus_interface = EVINCE_IFACE,
                          reply_handler = handler,
                          error_handler = self.handle_get_window_list_error)

    def handle_get_window_list_error (self, e):
        if self._log:
            self._log.debug("GetWindowList DBus call has failed")

    def handle_get_window_list_reply (self, window_list):
        if len(window_list) > 0:
            window_obj = EvinceWindowProxy.bus.get_object(self.dbus_name, window_list[0])
            self.window = dbus.Interface(window_obj,EV_WINDOW_IFACE)
            self.window.connect_to_signal("SyncSource", self.on_sync_source)
        else:
            #That should never happen. 
            if self._log:
                self._log.debug("GetWindowList returned empty list")

    def on_sync_source(self, input_file, source_link):
        print input_file + ":" + str(source_link[0])
        cmd = re.sub("%f",input_file,self.editor)
        cmd = re.sub("%l",str(source_link[0]), cmd)
        print cmd
        subprocess.call(cmd, shell=True)
        if self.source_handler is not None:
            self.source_handler(input_file, source_link)


## This file offers backward search in any editor.
##  evince_dbus  pdf_file  line_source input_file
if __name__ == '__main__':
    import dbus.mainloop.glib, gobject, glib, sys, os

    def print_usage():
        print """Usage: 
  evince_backward_search pdf_file "editorcmd %f %l"'
    %f ... TeX-file to load
    %l ... line to jump to
E.g.:
  evince_backward_search somepdf.pdf "gvim --servername somepdf --remote '+%l<Enter>' %f"
  evince_backward_search somepdf.pdf "emacsclient -a emacs --no-wait +%l %f"
  evince_backward_search somepdf.pdf "scite %f '-goto:%l'"
  evince_backward_search somepdf.pdf "lyxclient -g %f %l"
  evince_backward_search somepdf.pdf "kate --use --line %l"
  evince_backward_search somepdf.pdf "kile --line %l" """
        sys.exit(1)

    if len(sys.argv)!=3:
        print_usage()

    pdf_file = os.path.abspath(sys.argv[1])

    if not os.path.isfile(pdf_file):
        print_usage()

    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
    a = EvinceWindowProxy('file://' + pdf_file, sys.argv[2] ,True)


    loop = gobject.MainLoop()
    loop.run() 
# ex:ts=4:et:

Evince Forward Search:

#!/usr/bin/python2
# -*- coding: utf-8 -*-

# Copyright (C) 2010 Jose Aliste <jose.aliste@gmail.com>
#               2011 Benjamin Kellermann <Benjamin.Kellermann@tu-dresden.de>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public Licence as published by the Free Software
# Foundation; either version 2 of the Licence, 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 MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public Licence for more 
# details.
#
# You should have received a copy of the GNU General Public Licence along with
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# Street, Fifth Floor, Boston, MA  02110-1301, USA

# This file offers forward search for evince.

import dbus, subprocess, time, sys, os

def print_usage():
    print 'Usage: evince_forward_search pdf_file line_number tex_file\n   or: evince_forward_search pdf_file tex_file' 
    sys.exit(1)

if len(sys.argv)< 3 or len(sys.argv)>4: 
    print_usage()

if len(sys.argv)==4 :
    try:
        line_number = int(sys.argv[2])
    except ValueError:
        print_usage()

    pdf_file = os.path.abspath(sys.argv[1])
    tex_file = os.path.abspath(sys.argv[3])
if len(sys.argv)==3 :
    line_number  = 0
    pdf_file = os.path.abspath(sys.argv[1])
    tex_file = os.path.abspath(sys.argv[2])
try:
    bus = dbus.SessionBus()
    daemon = bus.get_object('org.gnome.evince.Daemon', '/org/gnome/evince/Daemon')
    dbus_name = daemon.FindDocument('file://' + pdf_file, True, dbus_interface = "org.gnome.evince.Daemon")
    window = bus.get_object(dbus_name, '/org/gnome/evince/Window/0')
except dbus.DBusException:
    print_exc()     

if len(sys.argv)==4 :
    window.SyncView(tex_file, (line_number,1), dbus_interface="org.gnome.evince.Window")

if len(sys.argv)==3 :
    subprocess.Popen(["evince",pdf_file])

Evince(我将它存储在我的〜/ bin中,但更合适的名称可能更好):

#!/bin/sh
EDITORCMD="emacsclient -a '' --no-wait +%l %f"
PDFFILE="$1"

~/bin/evince_forward_search "$@"

if [ -f "$PDFFILE" ];then
    if [ -f `basename "$PDFFILE" .pdf`.synctex.gz ];then
        ~/build/evince_backward_search "$PDFFILE" "$EDITORCMD"&
        BACKWARD_SEARCH_PID=$!
        echo $BACKWARD_SEARCH_PID
    fi
fi

if [ "$BACKWARD_SEARCH_PID" ];then
    echo "Killing $BACKWARD_SEARCH_PID"
    kill $BACKWARD_SEARCH_PID
fi

以下是我的Emacs-config(Org格式)中的相关剪辑:

*** Make Evince synctex friendly 
I want to use [[http://ubuntuforums.org/showthread.php?t%3D1716268][these scripts]] to make AUCTeX more synctex friendly.
The evince sh script is found [[file:~/bin/evince][here]].

The process is as follows:
 1. AUCTeX should call the ~/bin/evince rather than /usr/bin/evince
 2. local evince in turn call [[~/bin/evince_backward_search][evince_backward_search]] (with two
    arguments, pdf and editor) and  [[file:~/bin/evince_forward%20script][evince_forward script]] with two to
    three arguments
#+begin_src emacs-lisp
;;      ("Evince" ("evince" (mode-io-correlate " -p %(outpage)") " %o"))
(add-to-list 'TeX-view-program-list
(quote ("Evince2" ("~/bin/evince %o " (mode-io-correlate "%n ") "%t"))))
;;(setq TeX-view-program-selection (quote (((output-dvi style-pstricks) "dvips and gv") (output-dvi "xdvi") (output-pdf "Evince2") (output-html "xdg-open"))))
(add-to-list 'TeX-view-program-selection
         (quote (output-pdf "Evince2")))
#+end_src

整件事情可能很糟糕 - 我不是程序员!我只是将上述内容放在一起,以获得可行的解决方案。

注意:你不会得到红色框,突出显示cvs版本的AUCTeX中的当前tex文件行。