Mein Eindruck ist, dass viele vernünftige Leute das Problem haben, unter Windows texen zu wollen und bei schrecklichen Programmen wie LaTeX Editor oder TeXnicCenter hängen bleiben. Prinzipiell funktionieren die ja auch. Vielleicht nicht perfekt und manchmal sind sie hier oder da etwas unpraktisch, oder stürzen ab (beim Editiern von Text) - aber sie tun ihre Arbeit und, hey, es gibt ja auch nichts besseres.
Da ich völlig naiv mal einen ganz anderen Ansatz verfolgt habe, damit sehr zufrieden bin und gelegentlich darauf angesprochen werde, verfasse ich also jetzt diesen Blugpost. Als Zutaten brauchen wir
* Deinen Lieblingseditor - z.B. Notepad++
* Eine funktionierende MikTex-Installation inklusive dem großartigen Programm latexmk
* cygwin inklusive der zweckmäßigen Extraktions- und Berichtssprache Perl (für latexmk) und dem etwas verschrobenen Programm
make
* SumatraPDF - ein PDF-Viewer, der keinen Handle auf die geöffnete Datei behält, sondern diese zum Überschreiben freigibt und sogar noch überwacht, ob sie sich ändert und ggf. neu einließt
* AutoIt
* Optional: AutoHotkey
* Optional: Skripte für AutoHotkey / AutoIt zum Positionieren von Fenstern und für Latex-Shortcuts
Stelle sicher, dass beim Eintippen von pdflatex
auch wirklich PDF-Latex aufgerufen wird (Strg-C liefert die traurigste Fehlermeldung, die ein LR(k)-Parser je ausgegeben hat). Weiterhin sollte latexmk
ebenfalls funktionieren. Es ist also möglich, mit einem Aufruf von
latexmk -pdf MeineDatei.tex
Latex-Dateien nach PDF zu kompilieren. Das gleiche sollte mit
latexmk -pdf -pdflatex="pdflatex -interaction=nonstopmode -synctex=1" MeineDatei.tex
möglich sein, nur, dass dann noch synctex-Informationen mitgeschrieben werden, die es erst möglich machen, zwischen einem Text-Editor und einer PDF-Datei hin und herzuspringen. Dazu muss sowohl der PDF-Reader die Fähigkeit haben, einen Befehl zu einem bestimmten Ort in der Datei auszuführen (SumatraPDF kann dies) und der Texteditor das gleiche für einen bestimmten Ort in der LaTex-Datei (Notepad++ ist ebenfalls in der Lage dazu). Da ich in dieser Umgebung arbeite, werde ich das Verfahren anhand dieser Programme beschreiben, prinzipiell ist die Anleitung aber natürlich auch auf andere Umgebungen übertragbar.
Um zu Anfang einige Vokabeln zu Klären: Das Springen von der Latex-Datei zur entsprechenden Stelle in der PDF-Datei bezeichnet man als "Forward Search". Den dualen Vorgang, also das Springen von einer bestimmten Stelle in der PDF-Datei zu der entsprechenden Zeile im Latex-Quellcode bezeichnet man als "Inverse Search".
LaTeX kompilieren
Es wäre natürlich möglich, über das MenüRun
einfach pdflatex
aufzurufen. Notepad++ erlaubt natürlich, an Programme, die über Run
ausgeführt werden, Informationen wie die gerade bearbeitete Datei zu übergeben. Mit einem Befehl der Form
latexmk -pdf -pdflatex="pdflatex -interaction=nonstopmode -synctex=1" "$(CURRENT_DIRECTORY)\$(FILE_NAME)"
kann man etwa die gerade bearbeitete Datei kompilieren. Dies hat sich für mich in der Vergangenheit aber als nicht flexibel genug herausgestellt: Es ist so, dass ich gerne meine Inhalte auf mehrere Dateien aufteile und dann z.B. \input
verwende, um sie in einer "Haupt-Latex-Datei" zusammenzuführen. Gängige Latex-Editoren lösen dieses Problem über sogenannte Projekte - in diesen kann man dann einfach einstellen, welche .tex-Datei die primäre ist. Diese wird dann kompiliert, wenn man auf das Play-Button drückt.
Glücklicherweise haben viele Leute dieses oder ähnliche Probleme mit LaTeX und vor allem auch anderen Sprachen. Darum wurde das Programm make
erfunden. Wir werden es dazu einsetzen, Verzeichnisse quasi zu Projekt-Verzeichnissen zu machen. Wenn man make
aufruft, sucht es im aktuellen Arbeitsverzeichnis nach einer Datei mit dem Namen Makefile
. Mit dieser kann man steuern, was dann passieren soll. Ich nutze häufig eine Modifikation des folgenden Makefile
s:
.PHONY: all clean cleanall MeineDatei.pdf
all: MeineDatei.pdf
MeineDatei.pdf: MeineDatei.tex header.tex commands.tex biblio.bib chapter/*.tex content/*.tex
latexmk -silent -pdf -pdflatex="pdflatex -interaction=nonstopmode -synctex=1" -use-make MeineDatei.tex
test: MeineDatei.pdf
pdflatex MeineDatei
index: MeineDatei.pdf
makeindex MeineDatei
makeindex MeineDatei.nlo -s nomencl.ist -o MeineDatei.nls
latexmk -pdf -pdflatex="pdflatex -interaction=nonstopmode -synctex=1" -use-make MeineDatei.tex
clean:
latexmk -c
cleanall:
latexmk -C
rm -f MeineDatei.aux MeineDatei.tdo MeineDatei.bbl MeineDatei.loa MeineDatei.glo MeineDatei.nlo MeineDatei.nls MeineDatei.thm MeineDatei.synctex.gz
Ich habe weiter oben make
als ein etwas verschrobenes Programm bezeichnet. Dies liegt daran, dass die Einrückungen in obiger Datei Tabulatoren sein müssen. Ein Aufruf von make
im Verzeichnis der Makefile
ruft dann den gewünschten Befehl auf. Ausserdem sind folgende Argumente möglich
* make test
dies rufe ich auf, wenn mein Code einen Fehler enthält und ich möchte, dass pdflatex an der entsprechenden Stelle stehenbleibt, damit ich herausfinden kann, was der Fehler ist
* make clean
entfernt den LaTeX-Müll
* make cleanall
entfernt wirklich den ganzen LaTeX-Mull
* make index
Erstellt die nötigen Dateien für einen Index
Um nun den Komfort noch etwas zu erhöhen, habe ich folgendes AutoIt-Skript geschrieben:
WinActivate('C:\Windows')
Send('make{ENTER}!{TAB}')
Dies ist auf jeden Fall eine schlechte Dreckslösung, funktioniert aber für mich: Ich habe über Run
in Notepad++ einen Shortcut darauf erstellt. Beim Aufruft sucht es ein Command-Fenster, tippt make ein, drückt Enter und "Alt-Tab"t dann wieder zurück zu Notepad++. Verbesserungen erwünscht und werden gerne per e-Mail entgegen genommen, es funktioniert im Moment halt nur so wunderbar. Das ganze klappt natürlich nur, wenn auch ein Command-Fenster auf ist, dass im korrekten Arbeitsverzeichnis ist.
Forward Search
Soweit so gut: Nachdem das Kompilieren also funktioniert hat, wollen wir das Resultat auch anzeigen. Um die Vorwärtssuche zum Laufen zu bringen, müssen wir aus Notepad++ heraus SumatraPDF so aufrufen, sodass * das aktuelle Verzeichnis übergeben wird * die aktuelle Latex-Datei übergeben wird * die Zeilennummer in der Latex-Datei übergeben wird * SumatraPDF geöffnet wird, wenn es noch nicht geöffnet ist und die bereits existierende Instanz verwendet wird, wenn es bereits läuft * auf irgendeine geschickte Art und Weise die korrekte PDF-Datei geöffnet wird: Dies ist einfach, wenn man nur eine einzige Latex-Datei bearbeitet, die zugehörige PDF-Datei hat dann nämlich den gleichen Namen mit einer anderen Dateinamenerweiterung. Schwierig wird es vor allem, wenn man größere Projekte mit Latex realisiert (oder einfach nur sehr ordentlich ist) und z.B. per\input
andere Latex-Dateien einbindet und in diesen dann arbeitet.
Der letzte Punkt ist am schwierigsten. Ich habe es so gelöst, dass ich mit dem Befehl
"C:\Program Files (x86)\AutoIt3\AutoIt3.exe" "C:\System\Scripts\npp_forward.au3" "$(CURRENT_DIRECTORY)" "$(FILE_NAME)" $(CURRENT_LINE)
Aus Notepad++ heraus das folgende AutoIt-Skript aufrufe (Beschreibung über Funktionsweise als Kommentar):
; this script traverses from the CURRENT_DIRECTORY up the folder hierarchy, looking
; for pdf files. If it finds one or more, it tries the following (in this order):
; 1) If a Makefile exists, look for a line starting with all and execute the
; corresponding pdf-file
; 2) open FILE_NAME with the extension replaced by .pdf
; 3) try all file names from $ValidPdfNames (concated with .pdf)
; 4) open any of the pdf files
; and opens the correnspondig pdf-file at the given CURRENT_LINE
; call from Notepad++ like
; "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" "C:\path\to\this\npp_forward.au3" "$(CURRENT_DIRECTORY)" "$(FILE_NAME)" $(CURRENT_LINE)
; configure location of sumatra
Global $Sumatra = 'C:\Program Files (x86)\SumatraPDF\SumatraPDF.exe'
Global $ValidPdfNames[2] = [ 'main.pdf', 'skript.pdf' ]
; --------- end of configuration section ---------
; only go on, if 3 arguments are given
If $cmdLine[0] <> 3 Then
Exit
EndIf
Func RemoveExtension($Filename)
Return StringLeft($Filename, StringInStr($Filename, ".", Default, -1)-1)
EndFunc
Func RemoveLastPathPart($Folder)
Return StringLeft($Folder, StringInStr($Folder, '\', 0, -1)-1)
EndFunc
Func GetLastPathPart($Folder)
Return StringRight($Folder, StringLen($Folder)-StringInStr($Folder, '\', 0, -1))
EndFunc
Func PdfExist($Folder, $Filename)
Return FileExists($Folder & '\' & $Filename & '.pdf')
EndFunc
; name commandline arguments
$Folder = $cmdLine[1]
$Filename = $cmdLine[2]
$CurrentLine = $cmdLine[3]
$Basename = RemoveExtension($Filename)
; MsgBox(0, '', $Folder & @CRLF & $Filename & @CRLF & $CurrentLine)
Func CheckDir($Folder)
Local $Filename = False
Local $Search = FileFindFirstFile($Folder & '\*.pdf')
If $Search <> -1 Then
If FileExists($Folder & '\Makefile') Then
Local $fp = FileOpen($Folder & '\Makefile')
While 1
Local $Line = FileReadLine($fp)
If @error = -1 Then ExitLoop
If StringLeft($Line, 5) == 'all: ' Then
Local $temp = StringRight($Line, StringLen($Line)-5)
If FileExists($Folder & '\' & $temp) Then
$Filename = $Folder & '\' & $temp
EndIf
ExitLoop
EndIf
WEnd
EndIf
If Not $Filename Then
if PdfExist($Folder, $Basename) Then
$Filename = $Folder & '\' & $Basename & '.pdf'
Else
; try ValidPdfNames array
For $i=0 To UBound($ValidPdfNames) -1
if PdfExist($Folder, $ValidPdfNames[$i]) Then
$Filename = $Folder & '\' & $ValidPdfNames[$i] & '.pdf'
ExitLoop
EndIf
Next
; if not found, just take the first
$Filename = $Folder & '\' & FileFindNextFile($Search)
EndIf
EndIf
EndIf
FileClose($Search)
Return $Filename
EndFunc
; Change to Latex-Directory such that SumatraPDF will find the tex-file
FileChangeDir($Folder)
; Look for PDF files
$ThisFolder = $Folder
$PdfFile = CheckDir($ThisFolder)
While Not $PdfFile and $ThisFolder
$ThisFolder = RemoveLastPathPart($ThisFolder)
$PdfFile = CheckDir($ThisFolder)
WEnd
$TitleSearchString = GetLastPathPart($PdfFile)
; if no PDF file found, exit
If Not $PdfFile Then
Exit
EndIf
; execute sumatra PDF command
$run = '"' & $Sumatra & '" -reuse-instance "' & $PdfFile & '" -inverse-search "\"$(#0)\" \"%f\" -n%l" -forward-search "'& $Filename & '" ' & $CurrentLine
Run($run)
; wait for sumatra window
WinWaitActive($TitleSearchString)
; active notepad++ window
WinActivate($Folder & '\' & $Filename)
Inverse Search
Die Rückwärtssuche ist ungleich einfacher zu verwenden: Wenn man mit dem oben beschriebenen Parameter-synctex=1
kompilliert hat, wird eine zusätzliche Datei .synctex.gz
erstellt, die SumatraPDF ermöglicht, bei Doppelklick Wunder zu wirken: Trägt man unter Settings -> Options im Feld bei "Set inverse search command-line" folgende Zeichenkette ein
[code]
"$(#0)" "%f" -n%l
[/code]
so springt ein Doppelklick in die PDF-Datei an die richtige Stelle in Notepad++.
One Reply to “Latex unter Windows mit Vorschau und deinem Lieblingseditor”