2010-04-28 12 views
9

Um ein Bit des Dialogs mit dem screenplay Paket zu geben, ichBenutzerdefinierte Befehl für ‚ {Umgebung} begin ... end {Umgebung}‘

\begin{dialogue}{Johnny} Some dialogue. \end{dialogue} 
\begin{dialogue}{Jane} I see. \end{dialogue} 

Es wird ein bisschen langweilig nach einem verwenden während. Ist es möglich, einen benutzerdefinierten Befehl anzugeben, so dass ich stattdessen etwas verwenden kann?

+0

Je nachdem, welchen Editor Sie verwenden, sollten Sie sich auch ein Snippets-Paket ansehen. – Mica

+0

+1 Dies ist eine wirklich interessante Frage – Geoff

Antwort

8

Versuchen Sie folgendes:

\newcommand{\dialogueline}[2]{\begin{dialogue}{#1} #2 \end{dialogue}} 

% Usage example: 
\dialogueline{Johnny}{Some dialogue.} 
\dialogueline{Jane}{I see.} 
+0

Das funktioniert perfekt. Vielen Dank! – njt

+1

Dies ist eine gute Antwort, aber wenn jemand weiß, wie man das exakte Format repliziert, das vom ursprünglichen Poster verlangt wird, wäre es schön zu sehen. – Geoff

+1

Ich denke, das ist so nah wie möglich, was das Poster will. Es muss Klammern um den Text geben, damit LaTeX weiß, wo er '\ begin {dialogue}' und '\ end {dialogue}' richtig platzieren soll. Außerdem habe ich '\ dialogueline' verwendet, falls bereits ein anderer Befehl namens' \ dialogue' vorhanden ist, aber wenn das nicht der Fall ist, kann das Poster '\ dialogueline' durch' \ dialogue ersetzen, wenn es keine Fehler verursacht. –

12

Sie können in der Tat genau das bekommen, was Sie wollen:

\newcommand{\dialogueline}{\begingroup\catcode`\^^M=12 \[email protected]} 
{\catcode`\^^M=12\gdef\[email protected]#1#2^^M{\begin{dialogue}{#1}#2\end{dialogue}\endgroup}} 

Dieser Code muss \makeatletter-protected — entweder durch \makeatletter/\makeatother (bearbeiten umgeben sein: Diese bedeutet, dass Sie \makeatletter vor der Definition und \makeatother nach) oder in eine .sty Datei setzen. Beachten Sie, dass eine Umgebung mit dem Namen dialogue einen Befehl mit dem Namen \dialogue definiert. Daher benötigen Sie einen anderen Namen. Ändern Sie nicht die Formatierung!

Die Art und Weise, wie es funktioniert, ist \dialogueline ist ein Befehl, der keine Argumente, sondern stattdessen zu mehreren Sequenzen erweitert. Erstens, ein Gruppenöffnertoken, um alles, was folgt, in seinen eigenen Bereich zu bringen. Zweitens, die \catcode`^^M=12 Sequenz. LaTeX weist jedem Buchstaben eine catcode zu: eine Zahl, die angibt, um welchen Typ es sich handelt. Zum Beispiel ist der Backslash catcode 0, der Befehlsname-Konstruktor; Buchstaben sind Catcode 11; und Nicht-Buchstaben-Druckzeichen, wie das At-Zeichen, sind der catcode 12. Diese Sequenz macht ^^M, das Newline-Zeichen, den catcode 12, so dass wir damit interagieren können. Schließlich schreiben wir den Befehl \[email protected], der das schwere Heben ausführt.

Als nächstes definieren wir \[email protected]. Wir tun dies innerhalb einer Gruppe, in der das Newline-Zeichen catcode 12 ist, genauso wie es sein wird, wo \dialogueline erweitert wird. Beachten Sie, dass dies ist, warum Sie die zweite Zeile mit einem Zeilenumbruch — nicht brechen können, würde es als Text interpretiert werden. Als nächstes definieren wir \[email protected], um zwei Argumente zu nehmen, die mit einer neuen Zeile enden; Es wird erweitert, indem das erste Argument (das Sie in geschweiften Klammern übergeben) übergeben und als Argument an die dialogue-Umgebung übergeben wird und das zweite Argument (alles nach dem ersten und vor dem Ende der Zeile) als Rumpf der Umgebung übergeben wird. Schließlich beendet \[email protected] die in \dialogueline geöffnete Gruppe, so dass die Änderung des Catcodes von ^^M nirgendwo anders sichtbar ist. Angesichts dieser können Sie schreiben

\dialogueline{Johnny} Some dialogue. 
\dialogueline{Jane} I see. 

und alles sollte funktionieren.

+0

Sehr gute Antwort! (+1) – topskip

+1

Das ist ziemlich schlau. Ich wusste bisher noch nichts von '\ catcode'. Während meine Lösung für alles funktioniert, was in die geschweiften Klammern gesetzt wird, funktioniert Ihre Arbeit für Einzeiler und ist näher an der vom Fragesteller angeforderten Syntax. –

+0

Der Trick ist eigentlich weniger über catcodes und mehr über Mustervergleich in '\ def': Sie könnten auch etwas wie' \ gdef \ dialogueline @ EOL # 1: # 2 ^^ M' machen, um '\ dialogueline schreiben zu können Johnny: Einige Dialoge. Der catcode-Schalter ist so eingestellt, dass das Ende einer Zeile nicht nur als Leerzeichen behandelt und ignoriert wird, sondern stattdessen als zusammenpassendes Zeichen behandelt wird. Sie haben recht, dass dies einige gültige Strings verbieten könnte (obwohl einige davon erlaubt sein können, indem Sie die passende Zeichenkette in geschweiften Klammern verbergen, zB '\ dialogueline {Alexander: der Große}: Die!'), Aber es ist gut für Shortcuts und eingebettete DSLs –

3

Wenn Sie davon ausgehen, dass jeder Dialog einen Absatz einnimmt (in der Regel, es beginnt und endet mit einer Doppellinie Absatzumbruch), dann gibt es eine andere Art und Weise \dialogue nehmen nur ein Argument zu haben:

 
\newif\indialog \indialogfalse 
\def\dialogue#1{\ifindialog \end{dialogue}#1\begin{dialog}\else 
       \everypar={\end{dialogue}\indialogfalse \everypar={}}#1\indialogtrue\begin{dialogue} 
       \fi} 

That Code ist irgendwie schmutzig und un-Latexy — es setzt \everypar ohne sich um seinen vorhandenen Inhalt zu kümmern — und Latex hat sauberere Abstraktionen dafür, die ich vergessen habe, aber das Prinzip sollte klar sein.

+0

Das ist clever, ich hatte diese Technik noch nie gesehen. –