Pagine

2025-08-26

LaTeX: modificare un ambiente di lista

La modifica o l'introduzione di comandi in LaTeX è abbastanza semplice: in casi elementari basta usare i comandi \renewcommand (nel caso della modifica) e \newcommand (per la creazione di uno nuovo) e siamo a posto. La sintassi è:

\newcommand{nuovo_comando}{testo_da_inserire}

Spesso si ha la necessità di usare la stessa sequenza di comandi, modificando solo alcune parti. Occorre allora utilizzare i parametri, valori che vengono passati al codice, che li sostituisce ai segnaposto inseriti nel punto giusto. La sintassi è del tipo:

\newcommand{nome_comando}[numero_parametri]{codice_con_segnaposto}

ed i segnaposto sono identificati #1 (primo parametro), #2 (secondo parametro) e così via. Per esempio, nell'intestazione di un compito, potremmo inserire il nome dello studente (primo parametro), la classe (secondo parametro) e la data (terzo parametro); il comando potrebbe essere definito nel preambolo del documento come:

\newcommand{\intestazione}[3]{Studente: #1 Classe #2 Data #3}

Notiamo che è importante mantenere l'ordine previsto dei parametri; inoltre, diventano tutti obbligatori (a parte il primo, se forniamo il suo valore tra parentesi quadre.

Usando il pacchetto xparse (sulle installazioni recenti di LaTeX non è più necessario caricare questo pacchetto), è possibile usare un comando più flessibile:

\NewDocumentCommand\DueArgomenti{mm}{Nel testo c'è #1 ma anche #2}

I due caratteri m indicano che dobbiamo inserire due parametri obbligatori (dall'inglese mandatory); come prima, i loro segnaposti sono indicati con #1, #2; essendo obbligatori, la chiamata sarà come al solito:

\DueArgomenti{il primo}{il secondo}

e l'uscita sarà "Nel testo c'è il primo ma anche il secondo". Però questa nuova sintassi ci permette di definire tutti i parametri opzionali che vogliamo, definendo cosa deve succedere se non li forniamo. Mentre m indica un parametro obbligatorio, la sintassi O{valore_default} (vocale 'O' maiuscola) permette di indicare l'esistenza di un parametro e se questo non viene indicato, assume il valore indicato tra parentesi (e tale valore può anche essere vuoto). Per esempio:

\NewDocumentCommand\TreArgomenti{O{}O{Mario}m}{#1 #2 #3} \TreArgomenti{Rossi} % Mario Rossi - nessun parametro opzionale \TreArgomenti[dr]{Rossi} % dr Mario Rossi - solo il primo opzionale \TreArgomenti[dr][]{Rossi} % dr Rossi - il secondo è presente ma vuoto \TreArgomenti[][]{Rossi} % Rossi - opzionali tutti vuoti \TreArgomenti[]{Rossi} % Mario Rossi - il primo è vuoto, manca il secondo

Le stesse cose valgono anche per la definizione di ambienti LaTeX, come liste; la sintassi è la stessa di \newwnvironment, il comando da usare è \NewDocumentEnvironment, la cui sintassi è simile:

\NewDocumentEnvironment{nome_ambiente}{parametri} {codice_iniziale} {codice_finale}

Con queste conoscenze, ora costruirò un esempio un po' più complesso, usato per una mia necessità: volevo usare una lista numerata meno anonima di quella standard, con qualche piccolo inserto colorato, in modo da evidenziare ogni elemento (trattandosi di elementi piuttosto lunghi, mi serviva qualcosa di ben visibile, senza esagerare). Non volevo però ridefinire l'ambiente, per poter usare la lista predefinita in altri punti del documento.

Devo quindi definire un nuovo ambiente; volendo inserire dei colori, meglio caricare il pacchetto xcolor e, dato che dovrò giocare con la lista, inserisco anche il pacchetto enumitem:

\usepackage{enumitem} \usepackage{xcolor} \NewDocumentEnvironment{myenum}{} {}{}

Questo ambiente non fa nulla; facciamo in modo che sia lo stesso dell'ambiente standard, in modo da partire da una base nota:

\NewDocumentEnvironment{myenum}{} {\begin{enumerate}} {\end{enumerate}}

Ora aggiungiamo qualche opzione sulla lista nella parte iniziale:

{\begin{enumerate} [ left=0pt, % il numero parte a inizio testo labelsep=1.0em, % aumento spazio tra numero e testo itemsep=1.5em, % aumento spazio tra gli item label=\textcolor{red}{\fcolorbox{blue}{yellow}{\textbf{\arabic*}}} ] }

L'ultima riga già fornisce quello che cercavo: etichetta numerata in grassetto (\textbf{\arabic*}) e scritta in rosso (\textcolor{red}), all'interno di un riquadro con sfondo giallo e bordo blu (\fcolorbox{blue}{yellow}).

Il risultato non è male:

Mi viene però l'idea di inserire una riga blu all'inizio e alla fine dell'ambiente, per evidenziarlo. Allora, prima dell'apertura dell'ambiente enumerate, inserisco un comando \rule{colore}{spessore}, preceduto da un \color{colore}.
Mi accorgo subito di due cose: devo mettere questi comandi all'interno di parentesi {}, altrimenti il colore si propaga al testo seguente (tutti gli item in blu!); poi, sempre all'interno delle parentesi, devo far precedere il tutto da un nuovo paragrafo \par, in modo da terminare il testo precedente il nuovo ambiente e andare a capo prima di cominciare a numerare i paragrafi; alla fine il comando è

{\par\color{blue}\rule{\textwidth}{2pt}}

Per inserire la riga blu alla fine, devo usare la seconda parte del nuovo ambiente: subito dopo la chiusura \end{enumerate}, aggiungo:

\color{blue}\rule{\textwidth}{2pt}\vspace{1.0em}\par

dove per qualche motivo non servono le parentesi ed il nuovo paragrafo viene messo alla fine, per preparare le condizioni per il nuovo testo. Personalmente, ho preferito aggiungere un \vspace{1em} per allontanare un po' il testo che viene dopo la chiusura dell'ambiente.

L'effetto è ottimo, però sto diventando perfezionista (anche perché così imparo cose nuove!): vorrei che ogni item fosse separato dagli altri da una linea blu, magari più sottile di quelle iniziali/finali. L'unico modo per introdurre una riga per ogni item è di ridefinire il comando \item... e qui le cose si complicano: il comando è piuttosto delicato di suo, basta aggiungere un \par o altri tipi di spazi e la sua struttura non lo accetta, fornendo errori oscuri. Inoltre, tracciare una riga prima di ogni item, porta ad avere due righe all'inizio (una come inizio dell'ambiente, l'altra come inizio dell'item), il che porta a dover definire un contatore, che non tracci la riga se si tratta del primo item. Ancora: se modifichiamo l'item, dobbiamo poi ristabilirlo alla fine, altrimenti tutti gli ambienti enumerate lo useranno.

Il linguaggio TeX non è dei più intuitivi, per cui ho dovuto mischiare ricerche in rete e prove su prove. Dopo un bel po' tentativi infruttuosi (anche chiedendo aiuto all'AI, senza risultati apprezzabili), sono riuscito a mettere su un codice che funziona, anche se non sono sicuro del perché; su questo codice basta modificare qualcosa senza importanza... che subito smette di funzionare! Tuttavia, funziona, per cui lo pubblico. Contemporaneamente ho inserito la possibilità di usare dei parametri per i colori, impostando anche dei valori di default. Il listato finale, da inserire nel preambolo del documento, è il seguente:

\newcounter{colorenumcounter} % definizione di un contatore per evitare la riga sul primo item \NewDocumentEnvironment{myenum}{ O{blue} % colore delle righe di separazione O{red} % colore del testo del numero O{yellow}} % colore dello sfondo del numero { \par % nuova riga / stacca dal testo precedente \setcounter{colorenumcounter}{0} % inizializzo il contatore \let\olditem\item % salvo codice standard per comando \item \renewcommand{\item}{ % definisco nuovo codice per \item % riga vuota necessaria per mandare a capo la linea \stepcounter{colorenumcounter}% % aumento il contatore \ifnum\value{colorenumcounter}>1 % se non è il primo item... {\color{#1}\rule{\linewidth}{1pt}}% % disegno la linea \fi \olditem% % in ogni caso introduco il vecchio \item } {\color{#1}\rule{\textwidth}{2pt}}% % disegno la riga prima dell'inizio dell'ambiente \begin{enumerate} % inizio l'ambiente standard [ left=0pt, label=\textcolor{#2}{\fcolorbox{#1}{#3}{\textbf{\arabic*}}}, labelsep=1.0em, itemsep=1.5em, ] }{ \end{enumerate} % fine ambiente standard \par\vspace{1em}\color{#1}\rule{\textwidth}{2pt}\par % traccio linea colorata dopo l'ambiente \let\item\olditem % ristabilisco il vecchio codice, per gli ambienti successivi } % la chiamata con i valori di default: \begin{myenum} \item Prima riga \end{myenum} % mentre con uso di valori differenti: \begin{myenum}[red][yellow][blue] \item ... \end{myenum}

ed il risultato, con i valori di default è

Nota: Righe dove compaiono due segni di commenti (%): il primo, a fine riga del codice, deve essere mantenuto anche se si elimina quello che segue, per evitare che venga considerato il fine riga, che può portare anche ad errori oscuri.

Sarebbe anche possibile inserire come parametri gli spessori delle linee, oppure separare il colore della riga da quello del bordo del riquadro nel numero: basta aggiungere parametri all'inizio e poi inserirli nel posto giusto con #4, #5,...