- Questo topic ha 11 risposte, 4 partecipanti ed è stato aggiornato l'ultima volta 8 anni, 9 mesi fa da
robitex.
-
CreatoreTopic
-
17 Novembre 2017 alle 10:23 #111900
-
CreatoreTopic
-
AutoreRisposte
-
-
17 Novembre 2017 alle 11:37 #111901::
Matteo Dann” post=112212Ciao a tutti,
è possibile creare un nuovo comando che ricevendo una stringa di riferimento restituisca un testo che era stato in precedenza abbinato alla stringa (magari anch’esso con un nuovo \newcommand)?Grazie
Certo.
Uso spesso questa funzionalità anche se la sto abbandonando in favore di una tecnica più evoluta.`
\makeatletter
\def\set#1#2{\global\@namedef{namespacekey@#1}{#2}}
\def\get#1{%
\@ifundefined{namespacekey@#1}
{\GenericError{Undefined field `#1`}{The field you used has not been defined}{No doc to read!}{Define it!}}
{\@nameuse{namespacekey@#1}}%
}
\makeatother
`
Si può fare acnhe in LaTeX3, e sarebbe interessante….R.
-
17 Novembre 2017 alle 13:19 #111902
-
17 Novembre 2017 alle 18:57 #111903
-
17 Novembre 2017 alle 19:56 #111904::
Mi permetto di apportare qualche piccola correzione al codice di @robitex:
`
% My standard header for TeX.SX answers:
\documentclass[a4paper]{article} % To avoid confusion, let us explicitly
% declare the paper format.\usepackage[T1]{fontenc} % Not always necessary, but recommended.
% End of standard header. What follows pertains to the problem at hand.\usepackage[italian]{babel}
\makeatletter
\newcommand*\set[2]{\global\@namedef{namespacekey@#1}{#2}} % “\global”?
\newcommand*\get[1]{%
\@ifundefined{namespacekey@#1}{%
\GenericError
{}% continuation
{Undefined field `#1'}% error message
{No doc to read!}% reference to documentation
{The field you used has not been defined: define it!}% help
}{%
\@nameuse{namespacekey@#1}%
}%
}
\makeatother\set{saluto}{Ciao!}
\set{commiato}{Arrivederci!}\begin{document}
\get{saluto}
Carissimo \get{nome}, % errore: indefinito!
bla bla bla. \get{commiato}
\bigbreak
\set{saluto}{Buon giorno.}
\get{saluto}
\end{document}
`
Gli argomenti di [tt]\GenericError[/tt] erano sbagliati (nulla di grave, naturalmente!). Inoltre, mi domando se non sia il caso di esplorare la possibilità di rimuovere il [tt]\global[/tt] dal comando [tt]\set[/tt], rendendo le definiioni dei campi locali ai gruppi.Ciao.
—
Gustavo
-
18 Novembre 2017 alle 9:05 #111905::
Grazie mille @letteracdp.
Ho adattato il codice in fretta perché quello originale è incluso in un file .cls.
In sostituzione dell’originale \ClassError ho allora aperto il file source2e con il comando:
` $ texdoc source2e`
trovando il reference della macro \GenericError.
Mi chiedevo appunto cosa intendessero con il primo argomento ‘continuation’.Inoltre la stringa namespacekey può naturalmente essere cambiata a piacere.
Nessuno riesce a postare una soluzione LaTeX3?
Grazie.
R.
-
18 Novembre 2017 alle 12:57 #111906::
Nella documentazione leggibile ocn [tt]texdoc source2e[/tt] non c’è scritto molto sul significato dei 4 argomenti di [tt]\GenericError[/tt].
Però se vai a vedere come quei quattro argomenti vengono usati nella definizione dei vari comandi specifici \ClassError e \PackageError, vedi che il primo argomento viene usato per scrivere nel file .log e nella console il nome del pacchetto che si accorge dell’errore e che produce il messaggio. Per esempio il comando \packageError con tre argomenti ha la seguente definzione:`\gdef\PackageError#1#2#3{%
\GenericError{%
(#1)\@spaces\@spaces\@spaces\@spaces
}{%
Package #1 Error: #2%
}{%
See the #1 package documentation for explanation.%
}{#3}%
}`Commentando questo codice vediamo che i quattro argomenti di \GenericError sono:`\gdef\PackageError#1#2#3{%
\GenericError{%
(#1)\@spaces\@spaces\@spaces\@spaces% primo argomento
}{%
Package #1 Error: #2% Secondo argomento
}{%
See the #1 package documentation for explanation.% terzo argomento
}{#3}% quarto argomento
}`
In effetti gli argomenti da passare a \PackageError sono i seguenti
1° argomento: nome del pacchetto che scrive il messaggio d’errore
2° argomento: descrizione dell’errore
3° argomento: messaggio di aiuto che viene scritto dando il codice H nella console.Quindi il terzo argomento di \PackageError è il quarto di \GenericError, mentre il terzo di \GenericError è il messaggio fisso che indica di leggere la documentazione del pacchetto.
Il sorgente source2e potrebbe essere documentato meglio; anche se negli ultimi anni si è fatto molto in questo senso; il grosso della documentazione risale ancora ai commenti di Lamport nel file latex.ltx della versione 209 che con poche modifiche rispecchia il primo mark up LaTeX del 1985.
Pensa che noi “vecchi” abbiamo dovuto documentarci su quei commenti, perché non esisteva altra documentazione se non il TeXbook e la prima edizione del Manuale di Lamport, ovviamente (!) non inclusi in nessuna distribuzione del sistema TeX.
Per tua “consolazione” il comando \GenericError non è documentato nemmeno nel file di documentazione clsguide.pdf, che invece descrive abbastanza bene \ClassError e \PackageError.
-
18 Novembre 2017 alle 19:05 #111907::
robitex” post=112224[…]
Mi chiedevo appunto cosa intendessero con il primo argomento ‘continuation’.
[…]Serve a specificare una stringa da premettere a tutte le linee del messaggio d’errore (attenzione: non di aiuto) successive alla prima, ammesso che ce ne siano; infatti, di solito i messaggi d’errore sono molto sintetici.
Il motivo di ciò si spiega meglio con un esempio. Create una cartella vuota con un nome a vostra scelta, poi dentro di essa create un file di puro testo chiamato [tt]packageerrorxmpl.sty[/tt], con il seguente contenuto:
`
\NeedsTeXFormat{LaTeX2e}\relax % LaTeX2e is required!
\ProvidesPackage{packageerrorxmpl}
[2017/11/18 v1.00 Example of a package error message]
\PackageError{packageerrorxmpl}{%
An unusually long package error message\MessageBreak
(very long indeed!) that takes up 3 lines\MessageBreak
without actually saying anything useful%
}{%
A brief and uninformative help message.%
}
\endinput
`
Poi, sempre nella stessa cartella, salvate il seguente sorgente LaTeX (il nome che gli date non ha importanza):
`
\documentclass[a4paper]{article}
\usepackage[T1]{fontenc}
\usepackage[italian]{babel}
\usepackage{packageerrorxmpl}\begin{document}
Testo testo testo.
\end{document}
`
Compilandolo, apparirà il seguente messaggio d’errore:
`
! Package packageerrorxmpl Error: An unusually long package error message
(packageerrorxmpl) (very long indeed!) that takes up 3 lines
(packageerrorxmpl) without actually saying anything useful.See the packageerrorxmpl package documentation for explanation.
Type Hfor immediate help.
…l.10 }
?
`
(sempre che non abbiate impostato [tt]file_line_error_style = t[/tt], vedi sotto). La stringa [tt](packageerrorxmpl)[/tt] è appunto la stringa «di continuazione», e guardando il messaggio di errore si capisce che essa svolge la funzione di assicurare il corretto allineamento in verticale delle righe di testo che compongono il messaggio stesso; infatti, poiché la lunghezza della prima riga dipende dalla lunghezza del nome del pacchetto, il modo più semplice di dare alle righe successive la corretta indentazione è quello di premettere, anche a esse, una stringa di caratteri che contenga il nome del pacchetto; tale stringa contiene anche un numero di spazi opportunamente calcolato per avere lo stesso numero di caratteri della stringa [tt]! Package … Error: [/tt].Come già accennato, questo astuto trucco viene mandato a pallino se si imposta il flag [tt]file_line_error_style[/tt] a [tt]true[/tt], per cui gli autori di classi tendono a non utilizzare messaggi di errore lunghi più di una riga, confinando eventuali chiarimenti nel messaggio di aiuto a essi associato. Per gli avvertimenti, però, questo problema non c’è, ed ecco perché è invece abbastanza comune vedere messaggi di avvertimento lunghi più righe; eccone qui un esempio: 😉
`
Class letteracdp Warning: Some text that did not fit into the folded flap
(letteracdp) was moved into the main text below the folding;
(letteracdp) warning issued on input line 45.
`Ciao.
—
Gustavo
-
21 Novembre 2017 alle 9:59 #111908::
Ciao.
In attesa della versione LaTeX3 😀 ,vi allego quella (banale) per LuaTeX…
`% !TeX program = LuaTeX\directlua{
name_space_key = {}
}\def\set#1#2{\directlua{
local key, val = [[#1]], [[#2]]
if name_space_key[key] then
error([[Key already present]])
else
name_space_key[key] = val
end
}}\def\get#1{\directlua{
local key = [[#1]]
local val = name_space_key[key]
if val then
tex.sprint(val)
else
error([[Key not found]])
end
}}\set{ciao}{Hello World!}
\get{ciao}
\bye`Alla prossima
R.
-
22 Novembre 2017 alle 16:55 #111909::
robitex” post=112260Ciao.
In attesa della versione LaTeX3 😀 ,vi allego quella (banale) per LuaTeX…
`% !TeX program = LuaTeX\directlua{
name_space_key = {}
}\def\set#1#2{\directlua{
local key, val = [[#1]], [[#2]]
if name_space_key[key] then
error([[Key already present]])
else
name_space_key[key] = val
end
}}\def\get#1{\directlua{
local key = [[#1]]
local val = name_space_key[key]
if val then
tex.sprint(val)
else
error([[Key not found]])
end
}}\set{ciao}{Hello World!}
\get{ciao}
\bye`Alla prossima
R.Mi cito da solo 😉
solo perché mi son reso conto che in LuaTeX il comando \set non è necessario!
Si può usare la sintassi del costruttore di tabelle Lua…
Ecco un sorgente dimostrativo, scritto per LuaLaTeX:
`% !TeX program = LuaLaTeX% un preambolo invadente … per i font Open Type
\documentclass[a4paper]{article}
\usepackage{fontspec}
\usepackage{polyglossia}
\usepackage{microtype}
\usepackage{amsmath}
\usepackage{unicode-math}\defaultfontfeatures{Ligatures=TeX}
\setmainfont{Libertinus Serif}
\setmonofont{Libertinus Mono}
\setmathfont{Asana Math}\setmainlanguage[babelshorthands]{italian}
\frenchspacing% sintassi costruttore di tabelle lua
\directlua{
name_space_key_data = {
ciao = [=[Hello world!]=],
citta = [=[Milano]=],
paese = [=[Italia]=],
}
}\def\get#1{\directlua{
local key = [[#1]]
local val = name_space_key_data[key]
if val then
tex.sprint(val)
else
error([[Key not found]])
end
}}\begin{document}
Alla città di \get{citta} — che si trova in~\get{paese} — dico\dots\emph{\get{ciao}}
\end{document}
`Alla prossima.
R.
-
22 Novembre 2017 alle 17:29 #111910::
robitex” post=112269[…] mi son reso conto che in LuaTeX il comando \set non è necessario!
Si può usare la sintassi del costruttore di tabelle Lua…
[…]D’altra parte, fornire dello “zucchero sintattico” che usi solo le convenzioni di LaTeX, con il fine di non obbligare l’utente a imparare la sintassi di Lua e l’uso del comando [tt]\directlua[/tt], è una cosa che può valer la pena di fare, no? 🙂
Ciao.
—
Gustavo
-
22 Novembre 2017 alle 18:13 #111911::
letteracdp” post=112270
[…] mi son reso conto che in LuaTeX il comando \set non è necessario!
Si può usare la sintassi del costruttore di tabelle Lua…
[…]D’altra parte, fornire dello “zucchero sintattico” che usi solo le convenzioni di LaTeX, con il fine di non obbligare l’utente a imparare la sintassi di Lua e l’uso del comando [tt]\directlua[/tt], è una cosa che può valer la pena di fare, no? 🙂
Ciao.
—
GustavoCiao Gustavo.
La sintassi Lua, in particolare il costruttore di tabelle, ha in questo caso i sui vantaggi, secondo me.
Si possono “radunare” in un unico luogo nel sorgente, tutte le coppie chiavi valore senza che sia necessario implementare alcun parser.
Come TeX non è codice che l’utente dovrebbe utilizzare in modo diretto, così vale anche per Lua, del resto.
In altre, parole, Lua è molto più efficace nella gestione dati che non TeX, e in Lua(La)TeX possiamo usufruirne.
Grazie mille per il tuo intervento.
R.
-
-
AutoreRisposte
- Devi essere connesso per rispondere a questo topic.