Skip to content

Scrivere con il testo semplice

Ciao utente del nostro sito, abbiamo scoperto la risposta alla tua domanda, scorri verso il basso e la troverai di seguito.

Soluzione:

Il kernel LaTeX fornisce la funzione filecontents per scrivere su file esterni senza doversi preoccupare dei codici di catalogo e simili. Nelle vecchie versioni di LaTeX (prima del 2019-10-01; vedere qui) l'ambiente filecontents ha apportato modifiche minime a questo ambiente, consentendo di utilizzarlo in qualsiasi punto del documento (la versione di LaTeX poteva essere utilizzata solo nel preambolo e non consentiva la sovrascrittura). Nelle versioni più recenti, questa funzionalità è inclusa anche nel kernel di LaTeX.

Per produrre

To be or not to be,
that is % the question

si usa:

documentclass{article}
% usepackage{filecontents} For older LaTeX releases
begin{document}
begin{filecontents*}[overwrite]{tmp.txt}
To be or not to be,
that is % the question
end{filecontents*}
end{document}

La versione stellata (filecontents*) omette l'intestazione che viene stampata nella versione standard dell'ambiente:

%% LaTeX2e file `tmp.txt'
%% generated by the `filecontents' environment
%% from source `test' on 2020/01/12.
%%
To be or not to be,
that is % the question

Un'aggiunta alla mia risposta (dichiaratamente pigra):

Se si vuole continuare a reinventare la ruota (che è molto più divertente, devo ammettere), si può creare un comando che si occupi dei comandi catcodeper voi. Qui fornisco un'implementazione di un comando verbwrite che fa il lavoro per voi.

La sintassi del comando è in qualche modo simile a quella di LaTeX verb: si può usare come verbwritefile{} o verbwritefile||. Per quest'ultima sintassi, qualsiasi carattere diverso da { può essere usato per delimitare il contenuto. Questo carattere, ovviamente, non può comparire in . Il vantaggio della seconda sintassi è che non si ha alcuna restrizione nel bilanciamento di { e } all'interno del contenuto del comando.

documentclass{article}

makeatletter
longdef@[email protected]@space#1#2#3{%
  let[email protected]=#1%
  def[email protected]{#2}%
  def[email protected]{#3}%
  futurelet@[email protected]@[email protected]}
def@[email protected]{%
  ifx@[email protected][email protected]
    let[email protected]@[email protected]
  else
    ifx@[email protected][email protected]
      let[email protected][email protected]
    else
      let[email protected][email protected]
    fi
  fi
  [email protected]}
{catcode` =12
{globallet[email protected]= }%
gdef@[email protected] {futurelet@[email protected]@[email protected]}}%
defverbwrite{%
  [email protected]*%
    {let@ifnextchar@[email protected]@spaceexpandafter[email protected]@gobble}%
    {let@ifnextchar[email protected][email protected]}}
def[email protected]#1{%
  begingroup
    catcode`^^M=13
    newlinechar`^^M
    letdo@makeother dospecials
    catcode`{=1
    @ifnextcharbgroup
      {catcode`}= 2relax[email protected]#1}%
      {catcode`{=12relax[email protected]#1}}
def[email protected]#1#2{%
    immediatewrite#1{unexpanded{#2}}%
  endgroup}
def[email protected]#1#2{%
  def[email protected]##1##2#2{%
    [email protected]##1{##2}}%
  [email protected]#1}
makeatother

begin{document}
newwritefile
immediateopenoutfile=tmp.txt
verbwritefile {1-To be or not to be,
that is % the question}
verbwrite*file {2-To be or not to be,
that is % the question}
verbwritefile|3-To be or not to be,
that is } the {question|
verbwritefile$4-Être ou ne pas être,
вот в чем вопрос$
verbwritefile}5-Être ou ne pas être,
вот в чем вопрос}
closeoutfile
end{document}

Tenete presente che ho impiegato 68 minuti per scrivere questo comando, quindi non è certo quello che si può definire robusto. Procedete con cautela 🙂

Correzione 1: Impedisce l'espansione del testo usando ε-TeX unexpanded (grazie a jfbu 🙂

Correzione 2: Prevenire la tokenizzazione prematura del delimitatore (grazie ancora a jfbu 🙂

Caratteristica 1: Aggiunta una versione stellata che ignora gli spazi prima del delimitatore del contenuto verbatim.

Correzione 3: Consente effettivamente } come delimitatore "altro" (verbwritefile}stuff}) (grazie a Ulrich Diez 🙂

Correggere 4: Correzione di una caratteristica errata della funzione 1. L'effetto dell'elemento * rimarrebbe per ulteriori chiamate a verbwrite una volta utilizzato.


Nelle spiegazioni che seguono scrivo (La)TeX nei punti in cui desidero indicare che quanto scritto è valido per il TeX "puro" e quindi è valido anche per il LaTeX. Lo faccio per chi non sa che LaTeX è fondamentalmente TeX più un insieme di macro che formano il formato LaTeX e che vengono caricate automaticamente quando si esegue latex.exe/il latex-binary.


Suggerisco di usare il file filecontents*-ambiente.

Si tenga presente che esiste anche un pacchetto LaTeX 2ε contenuti del file che rimuove alcune delle limitazioni che accompagnano l'opzione filecontents*-del kernel LaTeX 2ε.


Se si è in vena di reinventare la ruota, si può scrivere una macro che fa

  • passare al regime del codice-categoria verbatim,
  • commuta il codice di gatto della parola fine (solitamente ^^M/ASCII-Return) a 12, in modo che ASCII-return sia trattato come le cifre e i segni di punteggiatura,
  • leggere e tokenizzare in base a tale codice l'argomento contenente il testo che deve essere scritto sul file
  • tagliare i caratteri di inizio e fine riga da quel testo
  • scrivere il testo sul file avendo endlinechar anche come newlinechar.

In (La)TeX ci sono diverse fasi di elaborazione dell'input.

(La)TeX legge l'input TeX, ad esempio un file di input .tex, riga per riga.

Nella fase di pre-elaborazione, i singoli caratteri che formano la riga vengono convertiti nella codifica interna dei caratteri di (La)TeX. (Nei motori (La)TeX della vecchia scuola, la codifica interna dei caratteri è ASCII. Nei motori basati su XeTeX o LuaTeX, la codifica interna dei caratteri è utf-8, di cui ASCII è un sottoinsieme). Quindi tutti i caratteri di spazio (numero di codice 32 sia in ASCII che in utf-8, cioè in tutte le codifiche che vengono prese in considerazione come codifica interna dei caratteri di un motore (La)TeX) che si trovano all'estremità destra della riga verranno rimossi. Quindi, all'estremità destra della riga verrà inserito un carattere il cui numero di punto di codice nella codifica interna dei caratteri di (La)TeX (cioè ASCII o utf-8) corrisponde al numero del parametro intero endlinechar. Di solito il valore del parametro intero endlinechar è 13, mentre il numero del punto di codice 13 sia in ASCII che in utf-8, cioè in tutte le codifiche che vengono prese in considerazione come codifica interna dei caratteri di un motore (La)TeX, denota il numero ⟨RETURN⟩-carattere. Ciò significa che: Di solito un ⟨RITORNO⟩-viene inserito all'estremità destra della riga.

Una volta terminato, inizia la fase di tokenizzazione: In questa fase (La)TeX prende i caratteri che formano la riga come istruzioni per inserire i token nel flusso dei token. Questa è la fase in cui si comincia a parlare dei cosiddetti token, ad esempio i token di sequenze di controllo (che sono di due tipi: token di parole di controllo e token di simboli di controllo) e i token di caratteri. I token di caratteri consistono in codici di caratteri che indicano il numero di punto di codice nella codifica interna dei caratteri di (La)TeX e in codici di categoria. I codici categoria consentono ai caratteri di avere un significato speciale per il motore (La)TeX. Ad esempio, il codice di categoria del carattere backslash è solitamente 0 (escape). Un carattere il cui codice di categoria è 0 al momento della tokenizzazione fa sì che (La)TeX raccolga il nome di un token di sequenza di controllo e successivamente inserisca tale token di sequenza di controllo nel token-stream. Ad esempio, il codice di categoria della parentesi graffa di apertura è solitamente 1 (inizio del raggruppamento) e il codice di categoria della parentesi graffa di chiusura è solitamente 2 (fine del raggruppamento), mentre i token di carattere con codice di categoria 1 (inizio del raggruppamento) devono essere usati per introdurre gruppi (ad esempio, argomenti di macro costituiti da più token o scope locali per assegnazioni come le macro-definizioni o la funzione ⟨testo bilanciato⟩ con cose come scantokens) e i caratteri-token del codice di categoria 2 (fine raggruppamento) devono essere utilizzati per indicare ciò che non appartiene più al gruppo in questione. Ulteriori informazioni sui codici di categoria sono disponibili su https://en.wikibooks.org/wiki/TeX/catcode.

Dopo la tokenizzazione, si ha un "flusso di tokens". L'elaborazione del flusso di token comprende cose come l'espansione di token espandibili (ad esempio, macro-token, ad esempio, primitive espandibili come string o csname...endcsname) e (successivamente) l'esecuzione di assegnazioni, la creazione di caselle, ecc.

Quando legge e tokenizza un file di input .tex, (La)TeX - durante la fase di pre-elaborazione - rimuove gli spazi a ogni fine riga e inserisce un carattere di fine riga a ogni fine riga.

Pertanto la sequenza di input

immediatewritefile{
To be or not to be,
that is % the question
}

sarà trattata da (La)TeX al momento della tokenizzazione, cioè dopo la pre-elaborazione, come

immediatewritefile{⟨character due to endline-char-insertion⟩
To be or not to be,⟨character due to endline-char-insertion⟩
that is % the question⟨character due to endline-char-insertion⟩
}⟨character due to endline-char-insertion⟩

Di solito il carattere di fine riga è ^^Mcioè ⟨RETURN⟩.

Quindi la sequenza di input di cui sopra sarà solitamente trattata da (La)TeX al momento della tokenizzazione come

immediatewritefile{⟨^^M/RETURN-character⟩
To be or not to be,⟨^^M/RETURN-character⟩
that is % the question⟨^^M/RETURN-character⟩
}⟨^^M/RETURN-character⟩

(La risposta alla domanda su quali token (La)TeX inserirà nel flusso di token quando incontrerà un ⟨^M/RETURN-carattere⟩ dipende dal codice di categoria che al momento della tokenizzazione è assegnato al carattere . ⟨^M/RETURN-character⟩.

Di solito il codice di categoria del carattere ⟨^M/RETURN-character⟩ è 5 (fine riga), il che significa che, a seconda dello stato dell'apparato di lettura di (La)TeX, o (nello stato S=saltare gli spazi vuoti) non c'è alcun token o (nello stato M=nel mezzo di una riga) un token-spazio (=un token-carattere di categoria-codice 10(spazio) e codice-carattere 32 (32 è il numero del carattere-spazio nella codifica interna dei caratteri di (La)TeX) o (nello stato N=circa l'inizio di una nuova riga) un par-verrà inserito un token par.

Nel caso in cui il codice di categoria 12(altro) sia assegnato al carattere ⟨^M/Carattere di ritorno⟩(La)TeX inserirà un carattere-token del codice di categoria 12(altro) e del codice di carattere 13 (13 è il numero del carattere ⟨RETURN-character⟩ nella codifica interna dei caratteri di (La)TeX) nel token-stream. Tale token può essere elaborato come qualsiasi altro token di carattere).

Oltre a questo, (La)TeX - in fase di scrittura - inserisce in ogni caso alla fine dell'argomento di un write-alla fine dell'argomento di un comando write, quella sequenza di caratteri/byte che, sulla piattaforma in uso, serve a terminare le righe all'interno dei file di testo.

Quindi, supponendo che si sia riusciti a far accettare a LaTeX il carattere percentuale come un carattere ordinario, il comando write -otterrà qualcosa di simile a:

⟨token due to ^^M/RETURN-character⟩To be or not to be,⟨token due to ^^M/RETURN-character⟩that is % the question⟨token due to ^^M/RETURN-character⟩

Al momento della scrittura, un

⟨platform-dependent sequence for ending the line⟩

sarà allegato.

Se il codice della categoria del carattere di fine riga/ del carattere ⟨^M/Carattere di ritorno⟩ era 5 (fine riga) al momento della tokenizzazione dell'input, la sequenza

⟨space⟩To be or not to be,⟨space⟩that is % the question⟨space⟩⟨platform-dependent sequence for ending the line⟩

verrà scritta nel file esterno.

Se il codice di categoria del carattere di fine riga/del carattere ⟨^M/Carattere di ritorno⟩ era 12(ritorno) al momento della tokenizzazione dell'input, la sequenza

^^MTo be or not to be,^^Mthat is % the question^^M⟨platform-dependent sequence for ending the line⟩

verrà scritta nel file esterno.

Si può fare in modo che al momento della scrittura una sequenza ⟨^M/Carattere di ritorno⟩ produca anche il carattere dipendente dalla piattaforma per terminare la linea⟩. assegnando il parametro intero newlinechar il valore del parametro intero endlinechar.

Se si fa anche questo, la sequenza

⟨platform-dependent sequence for ending the line⟩To be or not to be,⟨platform-dependent sequence for ending the line⟩that is % the question⟨platform-dependent sequence for ending the line⟩⟨platform-dependent sequence for ending the line⟩

verrà scritta nel file esterno.

Ma in questo modo si potrebbero ottenere righe vuote indesiderate.

Per questo motivo, si potrebbe voler applicare una routine per rimuovere le righe iniziali e finali dovuti all'inserimento di caratteri di fine riga⟩. dall'intero argomento prima di lasciare che writefaccia il lavoro di scrittura.


Un esempio di codifica potrebbe assomigliare a questo:

documentclass{article}

makeatletter

begingroup
catcode`^^M=12relax%
@firstofone{%
  endgroup%
  newcommand*gobbleendl{}defgobbleendl ^^M{}%
  newcommandtrimendls[2]{innertrimleadendl{#2}#1^^Mrelax{#1}}%
  newcommand*innertrimleadendl{}%
  definnertrimleadendl#1#2^^M#3relax#4{%
    ifxrelax#2relaxexpandafter@firstoftwoelseexpandafter@secondoftwofi%
    {%
      ifxrelax#4relaxexpandafter@firstoftwoelseexpandafter@secondoftwofi%
      {trimtrailendl{}{#1}}%
      {expandaftertrimtrailendlexpandafter{gobbleendl#4}{#1}}%
    }%
    {trimtrailendl{#4}{#1}}%
  }%
  newcommand*trimtrailendl[2]{%
    innertrimtrailendl{#2}.#1relax.^^Mrelax.relaxrelax{#1}%
  }%
  newcommand*innertrimtrailendl{}%
  definnertrimtrailendl#1#2^^Mrelax.#3relaxrelax#4{%
    ifxrelax#3relaxexpandafter@firstoftwoelseexpandafter@secondoftwofi%
    {def@tempa{#4}}%
    {expandafterdefexpandafter@tempaexpandafter{@gobble#2}}%
    @[email protected]@tempa%
    newlinechar=endlinechar%
    immediatewrite#1{@tempa}%
  }%
}%

newcommandimmediateverbatimwrite[1]{%
  begingroup
  letdo=@makeother
  dospecials
  catcode` =10 %We don't want to allow space as verb-arg-delimiter.
                 %Thus let's remove spaces when grabbing undelimited arguments.
  %endlinechar=`^^M%
  %catcode`endlinechar=5 %
  bracefork{#1}%
}%
begingroup
catcode`(=1 %
catcode`{=12 %
@firstofone(%
  endgroup
  newcommandbracefork[2](%
    catcode` =12relax
    catcodeendlinechar=12 %
    ifx{#2expandafter@firstoftwoelseexpandafter@secondoftwofi
    (%
      catcode`{=1 %
      catcode`}=2 %
      internalfilewritercaller(#1}(}%
    }(%
      internalfilewritercaller(#1}(#2}%
    }%
  }%
}%
newcommandinternalfilewritercaller[2]{%
  def@tempa##1#2{internalfilewriter{#1}{##1}}%
  ifxrelax#2relaxexpandafter@firstoftwoelseexpandafter@secondoftwofi
  {expandafterexpandafter
   expandafter@tempa
   expandafterexpandafter
   expandafter{%
   expandafter@gobblestring}}%
  {@tempa}%
}
newcommandinternalfilewriter[2]{%
  trimendls{#2}{#1}%
  endgroup
}%
makeatother

begin{document}

newwritefile
immediateopenoutfile=tmp.txtrelax

Aimmediateverbatimwrite{file}
{
être ou ne pas être.
That is % the question.
}B%
C%
%
Dimmediateverbatimwrite{file}  |
}être ou ne pas être.
That is % the question.
|E%
F

immediatecloseoutfile

end{document}

Con questo esempio si ottiene

  • un file pdf con la sequenza ABCDEF. (Questo dimostra che non vengono introdotti/inseriti spazi/qualsiasi altro carattere).
  • un file di testo il cui nome è tmp.txt e il cui contenuto è:
    être ou ne pas être.⟨linebreak⟩
    That is % the question.⟨linebreak⟩
    }être ou ne pas être.⟨linebreak⟩
    That is % the question.⟨linebreak⟩

    A causa delle interruzioni di riga, gli editor che mostrano anche i numeri di riga potrebbero visualizzare il file come

    1 être ou ne pas être.
    2 That is % the question.
    3 }être ou ne pas être.
    4 That is % the question.
    5

A proposito: Con (La)TeX è non possibile mantenere gli spazi alla fine delle righe.

Il motivo è che (La)TeX legge e tokenizza l'input riga per riga e una delle prime cose che fa (nella fase di pre-elaborazione) a ogni riga di input (prima ancora di aggiungere il carattere di fine riga e iniziare a tokenizzare la riga) è rimuovere tutti gli spazi che si trovano alla fine delle righe.

Quindi un input (La)TeX come

code⟨space⟩⟨space⟩
more code⟨space⟩⟨space⟩⟨space⟩⟨space⟩⟨space⟩
even more code⟨space⟩⟨space⟩

sarà in ogni caso pre-processato a

code⟨character due to endline-char-insertion⟩more code⟨character due to endline-char-insertion⟩even more code⟨character due to endline-char-insertion⟩

prima che avvenga qualsiasi altra elaborazione/tokenizzazione ecc.

Recensioni e valutazioni degli articoli

Se hai qualche esitazione e un modo per migliorare il nostro post, puoi scrivere una recensione e la analizzeremo volentieri.



Utilizzate il nostro motore di ricerca

Ricerca
Generic filters

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.