2010-04-28 18 views
9

Per inserire un po 'di dialogo utilizzando il pacchetto screenplay, devo usareComando personalizzato per ' begin {ambiente} ... end {ambiente}'

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

Diventa un po' noiosa dopo un mentre. È possibile specificare un comando personalizzato in modo che possa utilizzare qualcosa come

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

?

+0

a seconda dell'editor che si utilizza, si potrebbe voler esaminare anche un pacchetto snippet. – Mica

+0

+1 Questa è una domanda davvero interessante – Geoff

risposta

8

Prova questo:

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

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

Che funziona perfettamente. Grazie mille! – njt

+1

Questa è una buona risposta, ma se qualcuno sa come replicare il formato esatto richiesto dal poster originale, sarebbe bello vedere. – Geoff

+1

Penso che sia il più vicino possibile a ciò che vuole il poster. Ci devono essere delle parentesi attorno al testo, quindi LaTeX sa dove mettere '\ begin {dialogue}' e '\ end {dialogue}' correttamente. Inoltre, ho usato '\ dialogueline' nel caso in cui ci sia già un altro comando chiamato' \ dialogue', ma se questo non è il caso, allora il poster può sostituire '\ dialogueline' con' \ dialogue' se invece non causa errori. –

12

È possibile infatti ottenere esattamente quello che vuoi:

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

Questo codice deve essere \makeatletter-protected — sia circondato da \makeatletter/\makeatother (modificare: questo significa che si inserisce \makeatletter prima della definizione e \makeatother dopo di esso) o in un file .sty. Si noti che un ambiente denominato dialogue definisce un comando denominato \dialogue, quindi è necessario un nome diverso. Non cambiare la formattazione!

Il modo in cui funziona è che \dialogueline è un comando che non accetta argomenti, ma che si espande invece a più sequenze. Primo, un token di apertura di gruppo, per mettere tutto ciò che segue nel suo ambito. In secondo luogo, la sequenza \catcode`^^M=12. LaTeX assegna ciascuna lettera a catcode: un numero che dice di che tipo si tratta. Ad esempio, il backslash è catcode 0, il costruttore del nome-comando; le lettere sono catcode 11; e caratteri non stampabili, come il simbolo at, sono catcode 12. Questa sequenza rende ^^M, il carattere newline, ha catcode 12, quindi possiamo interagire con esso. Infine, scriviamo il comando \[email protected], che fa il sollevamento pesante.

Successivamente, definiamo \[email protected]. Lo facciamo all'interno di un gruppo in cui il carattere di nuova riga è catcode 12, così come lo sarà quando viene espanso lo \dialogueline. Si noti che questo è il motivo per cui non è possibile interrompere la seconda riga con una nuova riga — che sarebbe interpretata come testo. Successivamente, definiamo \[email protected] per prendere due argomenti, terminando con una nuova riga; si espande prendendo il primo argomento (che si passa tra parentesi) e passandolo come argomento all'ambiente dialogue e passando il secondo argomento (tutto dopo il primo e prima della fine della riga) come corpo dell'ambiente. Infine, \[email protected] termina il gruppo aperto in \dialogueline, in modo che la modifica al catcode di ^^M non sia visibile da nessun'altra parte. Detto questo, puoi scrivere

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

e tutto dovrebbe funzionare.

+0

Ottima risposta! (+1) – topskip

+1

È piuttosto intelligente. Non sapevo di "catcode" fino ad ora. Mentre la mia soluzione funzionerà per qualsiasi cosa inserita all'interno delle parentesi, la tua opererà per one-liner ed è più vicina alla sintassi richiesta dal richiedente. –

+0

Il trucco è in realtà meno su catcodes e altro su pattern matching in '\ def': potresti anche fare qualcosa come' \ gdef \ dialogueline @ EOL # 1: # 2 ^^ M' per essere in grado di scrivere '\ dialogueline Johnny: alcuni dialoghi. L'interruttore catcode è così che la fine di una linea non viene semplicemente trattata come carattere di spazio e ignorata, ma viene invece trattata come un carattere abbinabile. Hai ragione che questo può mettere fuori legge alcune stringhe valide (anche se alcune di queste possono essere permesse nascondendo la stringa abbinata in parentesi graffe, ad esempio '\ dialogueline {Alexander: the Great}: Die!'), Ma è bello per le scorciatoie e DSL incorporati. –

3

Se si assume che ogni finestra occupa un paragrafo (di solito, si inizia e termina con un'interruzione di paragrafo doppia-line), poi c'è un altro modo per avere \dialogue fare solo un argomento:

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

Quello il codice è un po 'sporco e non tardivo — imposta \everypar senza preoccuparsi del suo contenuto esistente — e Latex ha astrazioni più pulite per farlo, cosa che ho dimenticato, ma il principio dovrebbe essere chiaro.

+0

È intelligente, non avevo mai visto prima questa tecnica. –