- Questo topic ha 11 risposte, 2 partecipanti ed è stato aggiornato l'ultima volta 13 anni, 5 mesi fa da
egreg9.
-
CreatoreTopic
-
9 Marzo 2013 alle 8:42 #83468::
Ciao a tutti!
Questa è una domandona per i nostri maghi di TeX.
La classe suftesi definisce l’opzione style=* per impostare lo stile del documento.
L’opzione ha diverse uscite: style=roman1, style=italic1, ecc.
Il problema è che anche il pacchetto mdframed definisce un’opzione che si chiama style.
Provate a compilare questo codice:
`\documentclass[style=italic1]{suftesi}\usepackage{mdframed}
\begin{document}
\chapter{Title}
Test
\end{document}`
Appare un errore e la compilazione si blocca. Naturalmente ho fatto qualche ricerca.
mdframed definisce le opzioni con il pacchetto kvoptions; suftesi usa xkeyval, che però dovrebbe essere compatibile con keyval e compagnia.
Ho provato ad aggiungere dei prefissi alle mie opzioni, ma il problema rimane.
L’autore di mdframed fa questa osservazione: “l’opzione style di suftesi è globale e sarà eseguita da ogni pacchetto” ,
quindi suggerisce di eliminare l’opzione dalla lista \@classoptionlist. Provato, ma niente 🙁
Naturalmente se l’osservazione è corretta, ciò è un grosso problema, in linea teorica, per qualsiasi pacchetto.
Come se ne può venir fuori? Offro una birra ai primi tre che risolveranno il problema 😀 (una birra a testa, ovvio…)Chiaramente, se cambio nome all’opzione il problema non c’è più, ma vorrei evitarlo perché la classe non è più in versione beta.
Lo stesso avviene se mdframed cambia nome alla sua opzione, ma immagino che anche lui non voglia cambiare nome alle sue opzioni.
E poi rimane il rischio che il problema si presenti con altri pacchetti.
Si potrebbe pensare a una ridefinizione delle opzioni con il modulo l3keys di LaTeX3, sempre che questo possa risolvere il problema.
La soluzione piacerebbe ad Enrico :D, ma vorrei evitarla, sempre per lo stesso motivo: si tratterebbe di sconvolgere la classe che,
per il resto, mi pare abbastanza stabile.Ciao e grazie in anticipo!
Ivan
-
CreatoreTopic
-
AutoreRisposte
-
-
10 Marzo 2013 alle 18:41 #83469::
Ciao a tutti!Marco Daniel, uno degli autori di mdframed, ha risolto il bug che avevo segnalato nel primo post.
Questo il codice (le parti commentate servono solo per testarlo):
`
\documentclass[style=italic3,11pt]{suftesi}\makeatletter
\def\patteernstring{style=italic3}%\let\@classoptionslistorig\XKV@classoptionslist
\let\@classoptionslisttemp\@empty
\@for\tempsearch:=\XKV@classoptionslist\do{%
\ifx\tempsearch\@empty\else
\@expandtwoargs\in@{,\tempsearch,}{,\patteernstring,}%
\ifin@\wlog{***remove option style***} \else
\wlog{***add option \tempsearch***}
\edef\@classoptionslisttemp{\@classoptionslisttemp,\tempsearch}
\fi
\fi}%
\let\XKV@classoptionslist\@classoptionslisttemp%\edef\printorig{\@classoptionslistorig}
%\edef\printmodified{\@classoptionslist}\makeatother
\usepackage{mdframed}
\begin{document}
\chapter{Titolo}
\begin{mdframed}
ciao
\end{mdframed}%\printorig
%\printmodified
\end{document}
`In pratica è sufficiente aggiungere, all’interno della rispettiva definizione nel file di classe, la stringa
`
\def\patteernstring{style=*}
`
sostituendo a * il valore dell’opzione. Poi si deve aggiunge anche il resto del codice e il gioco è fatto.
Qualcuno mi sa spiegare in dettaglio il codice qui sopra?
Una parte è documentato in source2e. Forse qualcosa si può eliminare?Ciao
Ivan
-
10 Marzo 2013 alle 21:35 #83470::
ivan” post=82845Ciao a tutti!
Marco Daniel, uno degli autori di mdframed, ha risolto il bug che avevo segnalato nel primo post.
Questo il codice (le parti commentate servono solo per testarlo):
`
\documentclass[style=italic3,11pt]{suftesi}\makeatletter
\def\patteernstring{style=italic3}%\let\@classoptionslistorig\XKV@classoptionslist
\let\@classoptionslisttemp\@empty
\@for\tempsearch:=\XKV@classoptionslist\do{%
\ifx\tempsearch\@empty\else
\@expandtwoargs\in@{,\tempsearch,}{,\patteernstring,}%
\ifin@\wlog{***remove option style***} \else
\wlog{***add option \tempsearch***}
\edef\@classoptionslisttemp{\@classoptionslisttemp,\tempsearch}
\fi
\fi}%
\let\XKV@classoptionslist\@classoptionslisttemp%\edef\printorig{\@classoptionslistorig}
%\edef\printmodified{\@classoptionslist}\makeatother
\usepackage{mdframed}
\begin{document}
\chapter{Titolo}
\begin{mdframed}
ciao
\end{mdframed}%\printorig
%\printmodified
\end{document}
`In pratica è sufficiente aggiungere, all’interno della rispettiva definizione nel file di classe, la stringa
`
\def\patteernstring{style=*}
`
sostituendo a * il valore dell’opzione. Poi si deve aggiunge anche il resto del codice e il gioco è fatto.
Qualcuno mi sa spiegare in dettaglio il codice qui sopra?
Una parte è documentato in source2e. Forse qualcosa si può eliminare?Il codice semplicemente ricostruisce la lista delle opzioni globali [tt]\XKV@classoptionslist[/tt] facendo un ciclo sulla lista stessa e aggiungendo a una lista temporanea solo le opzioni che non sono quella da escludere. L’unica complicazione è che la procedura per confrontare due stringhe con le macro del nucleo di LaTeX è contorta e dura da digerire. Sarebbe più semplice se si dovesse eliminare una sola opzione.
Il problema maggiore è che devi ripetere la faccenda per ogni valore dell’opzione [tt]style[/tt] e mi pare che siano parecchie.
Questo si risolve con mezzi un po’ più potenti:
`\documentclass[style = italic3,11pt]{suftesi}\usepackage{expl3}
\makeatletter
\ExplSyntaxOn
\seq_new:N \l__suftesi_nonglobaloptions_seq
\seq_new:N \l__suftesi_givenoptions_seq
\bool_new:N \l__suftesi_keepoption_bool
\clist_new:N \l__suftesi_globaloptions_clist%%% Inserire, una per volta, le opzioni da escludere con '=' alla fine
\seq_put_right:Nn \l__suftesi_nonglobaloptions_seq { style= }
% \seq_put_right:Nn \l__suftesi_nonglobaloptions_seq {= } %%% Routine per eliminare le opzioni da non passare ai pacchetti
\seq_set_from_clist:NN \l__suftesi_givenoptions_seq \XKV@classoptionslist\seq_map_inline:Nn \l__suftesi_givenoptions_seq
{
\bool_set_true:N \l__suftesi_keepoption_bool
% eliminiamo gli spazi interni all'opzione
\tl_set:Nn \l__suftesi_option_tl { #1 }
\tl_remove_all:Nn \l__suftesi_option_tl { ~ }
\seq_map_inline:Nn \l__suftesi_nonglobaloptions_seq
{
\tl_if_in:NnT \l__suftesi_option_tl { ##1 }
{
\bool_set_false:N \l__suftesi_keepoption_bool
\seq_map_break:
}
}
% se il condizionale e' ancora vero, aggiungiamo l'opzione
\bool_if:NT \l__suftesi_keepoption_bool
{ \clist_put_right:Nn \l__suftesi_globaloptions_clist { #1 } }
}
\clist_set_eq:NN \XKV@classoptionslist \l__suftesi_globaloptions_clist
\ExplSyntaxOff\makeatother
\usepackage{mdframed}
\begin{document}
\chapter{Titolo}
\begin{mdframed}
ciao
\end{mdframed}%\printorig
%\printmodified
\end{document}`
Un po’ più breve, per la sola opzione [tt]style[/tt], ma facilmente ampliabile:
`\documentclass[style = italic3,11pt]{suftesi}\usepackage{expl3,l3regex}
\makeatletter
\ExplSyntaxOn
\regex_replace_all:nnN { style \s* = [^,]*? , } { , } \XKV@classoptionslist
\ExplSyntaxOff
\makeatother\usepackage{mdframed}
\begin{document}
\chapter{Titolo}
\begin{mdframed}
ciao
\end{mdframed}%\printorig
%\printmodified
\end{document}`
Ciao
Enrico
-
20 Marzo 2013 alle 14:17 #83471::
Purtroppo ho riscontrato un’altra incompatibilità, dovuta al fatto che
altri pacchetti definiscono le stesse opzioni di suftesi, magari con valori diversi,
usando xkeyval. Anche il pacchetto bookmark, per esempio, definisce l’opzione style=,
pertanto se si usa
`\documentclass[style=FSPLa]{suftesi}`
si ha un errore analogo, visto che bookmark non riconosce quel valore dell’opzione style.
Mi sorge quindi una questione.
Per quale motivo le opzioni di classe dovrebbero essere ereditate dai pacchetti?
Questo mi pare comporti soltanto dei problemi. Ma forse c’è un’utilità che non vedo.
C’è un modo per evitare tutto questo?Chiaramente la possibilità che altri pacchetti definiscano le stesse opzioni di suftesi non è
altissima, ma rimane non trascurabile. Forse il nome “style” è infelice, perché troppo comune.A questo punto, però, serve una soluzione generale.
Per evitare che ci siano incompatibilità con altri pacchetti,
tutte le opzioni definite dalla classe attraverso xkeyval
vanno eliminate da \XKV@classoptionslist.
L’ultima soluzione di Enrico è cristallina: una riga magica per opzione, e il gioco è fatto.
Mi viene il sospetto che sia però troppo semplice.
C’è qualche rischio che non riesco a vedere?
In caso contrario, mi appresto ad aggiungere le poche righe necessarie per
correggere questo bug nella prossima versione.Ciao
Ivan
-
20 Marzo 2013 alle 14:25 #83472::
ivan” post=83263Purtroppo ho riscontrato un’altra incompatibilità, dovuta al fatto che
altri pacchetti definiscono le stesse opzioni di suftesi, magari con valori diversi,
usando xkeyval. Anche il pacchetto bookmark, per esempio, definisce l’opzione style=,
pertanto se si usa
`\documentclass[style=FSPLa]{suftesi}`
si ha un errore analogo, visto che bookmark non riconosce quel valore dell’opzione style.
Mi sorge quindi una questione.
Per quale motivo le opzioni di classe dovrebbero essere ereditate dai pacchetti?
Questo mi pare comporti soltanto dei problemi. Ma forse c’è un’utilità che non vedo.
C’è un modo per evitare tutto questo?Chiaramente la possibilità che altri pacchetti definiscano le stesse opzioni di suftesi non è
altissima, ma rimane non trascurabile. Forse il nome “style” è infelice, perché troppo comune.A questo punto, però, serve una soluzione generale.
Per evitare che ci siano incompatibilità con altri pacchetti,
tutte le opzioni definite dalla classe attraverso xkeyval
vanno eliminate da \XKV@classoptionslist.
L’ultima soluzione di Enrico è cristallina: una riga magica per opzione, e il gioco è fatto.
Mi viene il sospetto che sia però troppo semplice.
C’è qualche rischio che non riesco a vedere?
In caso contrario, mi appresto ad aggiungere le poche righe necessarie per
correggere questo bug nella prossima versione.Non so se esista qualche trucco oberdiekiano per risolvere il problema in modo generale, provo a darci un’occhiata. La decisione di rendere globali, cioè passate a ogni pacchetto, le opzioni date alla classe è stata presa molto tempo fa, quando è stato scritto il nucleo di LaTeX2e e non ci si può fare più di tanto.
Purtroppo, come dici, [tt]style[/tt] è forse un po’ generico e magari [tt]sufstyle[/tt] sarebbe stato meglio.
In realtà il pacchetto xkeyval offre un modo per evitare il problema: pagina 19. Ma richiede che gli autori di pacchetti e pacchetti siano disciplinati e usino [tt][pkg]][/tt] [tt][cls][/tt] rispettivamente.
Ciao
Enrico
-
20 Marzo 2013 alle 15:05 #83473::
egreg9″ post=83264
Purtroppo ho riscontrato un’altra incompatibilità, dovuta al fatto che
altri pacchetti definiscono le stesse opzioni di suftesi, magari con valori diversi,
usando xkeyval. Anche il pacchetto bookmark, per esempio, definisce l’opzione style=,
pertanto se si usa
`\documentclass[style=FSPLa]{suftesi}`
si ha un errore analogo, visto che bookmark non riconosce quel valore dell’opzione style.
Mi sorge quindi una questione.
Per quale motivo le opzioni di classe dovrebbero essere ereditate dai pacchetti?
Questo mi pare comporti soltanto dei problemi. Ma forse c’è un’utilità che non vedo.
C’è un modo per evitare tutto questo?Chiaramente la possibilità che altri pacchetti definiscano le stesse opzioni di suftesi non è
altissima, ma rimane non trascurabile. Forse il nome “style” è infelice, perché troppo comune.A questo punto, però, serve una soluzione generale.
Per evitare che ci siano incompatibilità con altri pacchetti,
tutte le opzioni definite dalla classe attraverso xkeyval
vanno eliminate da \XKV@classoptionslist.
L’ultima soluzione di Enrico è cristallina: una riga magica per opzione, e il gioco è fatto.
Mi viene il sospetto che sia però troppo semplice.
C’è qualche rischio che non riesco a vedere?
In caso contrario, mi appresto ad aggiungere le poche righe necessarie per
correggere questo bug nella prossima versione.Non so se esista qualche trucco oberdiekiano per risolvere il problema in modo generale, provo a darci un’occhiata. La decisione di rendere globali, cioè passate a ogni pacchetto, le opzioni date alla classe è stata presa molto tempo fa, quando è stato scritto il nucleo di LaTeX2e e non ci si può fare più di tanto.
Purtroppo, come dici, [tt]style[/tt] è forse un po’ generico e magari [tt]sufstyle[/tt] sarebbe stato meglio.
In realtà il pacchetto xkeyval offre un modo per evitare il problema: pagina 19. Ma richiede che gli autori di pacchetti e pacchetti siano disciplinati e usino [tt][pkg]][/tt] [tt][cls][/tt] rispettivamente.
Ciao
EnricoAvevo già provato ad usare il prefisso […] e la famiglia {…} nella definizione delle chiavi di suftesi, ma non funzionava.
Ora ho provato ad aggiungere il prefisso nella definizione della chiave in mdframed.sty e in effetti l’errore non si ha più.
Rivedrò anch’io tutte le chiavi, aggiungendo un prefisso opportuno. Non l’ho fatto a suo tempo
perché non immaginavo niente di simile.
Però è strano che aggiungendo i prefissi in suftesi non cambi nulla,
anche perché ogni chiave è del tipo \prefix@family@key e se family non è dichiarato
viene preso il nome del file di classe. Quindi, immaginavo che ogni chiave fosse unica,
essendo unico il file di classe. Ma evidentemente non è così.
Intanto aggiungo i tuoi codici magici, così sono tranquillo.Per quanto riguarda il nome hai ragione: “sufstyle” è molto meglio.
Grazie!
Ciao
Ivan
-
31 Marzo 2013 alle 14:16 #83474::
Ho riscontrato un problemino nella soluzione di Enrico data qui sopra,
nel caso in cui l’opzione da cancellare dalla \XKV@classoptionslist sia l’ultima (o l’unica) passata alla classe:
Questo esempio produce infatti un errore:
`\documentclass[style=FSPLa]{suftesi}\usepackage{mdframed}
\begin{document}
\chapter{Titolo}
\begin{mdframed}
ciao
\end{mdframed}
\end{document}`Aggiungendo una virgola dopo l’opzione:
`\documentclass[style=FSPLa,]{suftesi}
`
funziona correttamente, ma è poco elegante.
In pratica lo si illude che ci sia un’altra opzione e poi non la si dichiara.
Ho provato a modificare il codice sopra:
`\regex_replace_all:nnN { style \s* = [^,]*? , } { , } \XKV@classoptionslist`
nel seguente, togliendo la seconda occorrenza della virgola:
`\regex_replace_all:nnN { style \s* = [^,]*? } { , } \XKV@classoptionslist`
e in questo modo l’esempio minimale in alto non produce errori.
Da quello che ho capito, il primo codice sostituisce la stringa “style=,” con “,”.
Quindi se c’è una sola opzione non trova la stringa, in quanto manca la virgola finale.
E questo spiega anche il fatto che aggiungendo la virgola non si hanno errori.La mia perplessità è questa? La virgola che ho eliminato serve a qualcosa che ignoro?
Ciao
Ivan
-
31 Marzo 2013 alle 14:48 #83475::
ivan” post=83714Ho riscontrato un problemino nella soluzione di Enrico data qui sopra,
[…]
La mia perplessità è questa? La virgola che ho eliminato serve a qualcosa che ignoro?Meglio ancora:
`\regex_replace_all:nnN { style \s* = [^,]*? (,|\Z) } { } \XKV@classoptionslist`
La ricerca è di [tt]style[/tt] seguito da zero o più spazi, un uguale e zero o più caratteri che non siano la virgola, fino alla prima virgola oppure alla fine della stringa che si denota con [tt]\Z[/tt] (il [tt]?[/tt] indica una ricerca non “vorace”, cioè che si ferma al primo *match*). Al posto di tutto questo non si mette niente.Attenzione a possibili generalizzazioni: se per caso hai opzioni che ammettano liste come argomenti, del tipo
`foo={abc,def}`
quell’espressione regolare non funzionerà.Ciao
Enrico
-
31 Marzo 2013 alle 17:58 #83476::
Grazie mille!Non riesco ancora a capire perché mai si è voluto che le opzioni globali venissero passate ai pacchetti.
Ammesso che ciò non abbia controindicazioni, qualcosa di simile potrebbe servire ad eliminare tutte le opzioni da \XKV@classoptionslist?
`\regex_replace_all:nnN { [^,]*? \s* = [^,]*? (,|\Z) } { } \XKV@classoptionslist
\regex_replace_all:nnN { [^,]*? \s* (,|\Z) } { } \XKV@classoptionslist
`
La prima riga dovrebbe eliminare le opzioni chiave=valore; la seconda quelle semplici.
Io l’ho provato e sembra funzionare.Quando viene letto il file di classe, le opzioni hanno già fatto il loro lavoro, o no?
E allora, perché conservarle in una lista e addirittura passarle ad ogni pacchetto?Ciao
Ivan
-
31 Marzo 2013 alle 18:11 #83477::
ivan” post=83726Grazie mille!
Non riesco ancora a capire perché mai si è voluto che le opzioni globali venissero passate ai pacchetti.
Ammesso che ciò non abbia controindicazioni, qualcosa di simile potrebbe servire ad eliminare tutte le opzioni da \XKV@classoptionslist?
`\regex_replace_all:nnN { [^,]*? \s* = [^,]*? (,|\Z) } { } \XKV@classoptionslist
\regex_replace_all:nnN { [^,]*? \s* (,|\Z) } { } \XKV@classoptionslist
`
La prima riga dovrebbe eliminare le opzioni chiave=valore; la seconda quelle semplici.
Io l’ho provato e sembra funzionare.Quando viene letto il file di classe, le opzioni hanno già fatto il loro lavoro, o no?
E allora, perché conservarle in una lista e addirittura passarle ad ogni pacchetto?Ciao
IvanSe vuoi eliminarle tutte, basta dire
`\def\XKV@classoptionslist{}`
Si può passare l’opzione [tt]draft[/tt] alla classe e tutti i pacchetti che la capiscono la usano. Questo è il motivo che ha fatto scegliere questa strategia. Giusta o sbagliata che sia, è quella. Altro esempio: invece di passare l’opzione [tt]italian[/tt] a tutti i pacchetti che se ne servono, la metti una volta sola.Ciao
Enrico
-
31 Marzo 2013 alle 18:21 #83478::
egreg9″ post=83728
Se vuoi eliminarle tutte, basta dire
`\def\XKV@classoptionslist{}`Si può passare l’opzione [tt]draft[/tt] alla classe e tutti i pacchetti che la capiscono la usano. Questo è il motivo che ha fatto scegliere questa strategia. Giusta o sbagliata che sia, è quella. Altro esempio: invece di passare l’opzione [tt]italian[/tt] a tutti i pacchetti che se ne servono, la metti una volta sola.
Quindi, ammesso che la classe non definisca alcuna opzione (tramite xkeyval) che si vuole
sia passata a qualche pacchetto, non ha alcun senso mantenere quella lista.
Mi pare che questo sia il caso di suftesi.
Eventualmente posso specificare nella doc che le opzioni dei pacchetti
devono essere date nei pacchetti e non nella classe.
Ma credo siano pochi quelli che mettono le opzioni dei pacchetti nella classe.
Il vantaggio c’è in pochissimo casi e comunque si risparmia poco.
Infatti anche se svuoto \@XKVclassooptionslist mi rimane comunque \@classoptionslist,
quindi quel meccanismo dovrebbe rimanere intatto per quasi tutti i casi.
Rimangono escluse le opzioni definite con xkeyval da qualche pacchetto. Svuotando
la lista verrebbero ignorate. Ma sono ben pochi i pacchetti che usano xkeyval. E credo di sapere il motivo 😀Ciao
Ivan
-
31 Marzo 2013 alle 18:41 #83479::
ivan” post=83730
Se vuoi eliminarle tutte, basta dire
`\def\XKV@classoptionslist{}`Si può passare l’opzione [tt]draft[/tt] alla classe e tutti i pacchetti che la capiscono la usano. Questo è il motivo che ha fatto scegliere questa strategia. Giusta o sbagliata che sia, è quella. Altro esempio: invece di passare l’opzione [tt]italian[/tt] a tutti i pacchetti che se ne servono, la metti una volta sola.
Quindi, ammesso che la classe non definisca alcuna opzione (tramite xkeyval) che si vuole
sia passata a qualche pacchetto, non ha alcun senso mantenere quella lista.
Mi pare che questo sia il caso di suftesi.
Eventualmente posso specificare nella doc che le opzioni dei pacchetti
devono essere date nei pacchetti e non nella classe.
Ma credo siano pochi quelli che mettono le opzioni dei pacchetti nella classe.
Il vantaggio c’è in pochissimo casi e comunque si risparmia poco.
Infatti anche se svuoto \@XKVclassooptionslist mi rimane comunque \@classoptionslist,
quindi quel meccanismo dovrebbe rimanere intatto per quasi tutti i casi.
Rimangono escluse le opzioni definite con xkeyval da qualche pacchetto. Svuotando
la lista verrebbero ignorate. Ma sono ben pochi i pacchetti che usano xkeyval. E credo di sapere il motivo 😀Mi pare sensato. In effetti xkeyval sembra occuparsi di togliere da [tt]\@classoptionlist[/tt] le opzioni del tipo “chiave=valore”. Se chiedo [tt]\show\@classoptionslist[/tt] prima di [tt]\RequirePackage{xkeyval}[/tt] vengono elencate tutte. Subito dopo invece rimangono quelle senza [tt]=[/tt].
Ciao
Enrico
-
-
AutoreRisposte
- Devi essere connesso per rispondere a questo topic.