Utilizzo \newcommand

  • Creatore
    Topic
  • #111900
    Up
    0
    Down
    ::


    Ciao 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

Visualizzazione 10 filoni di risposte
  • Autore
    Risposte
    • #111901
      robitex
      Amministratore del forum
        Up
        0
        Down
        ::

        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.

      • #111902
        Up
        0
        Down
        ::


        Grazie mille!
        Scusa l’ignoranza, ma potresti anche mostrarmi un’applicazione del codice (così su due piedi mi è abbastanza oscuro 👿 )?

      • #111903
        robitex
        Amministratore del forum
          Up
          0
          Down
          ::


          Tipo:

          `
          % nel preambolo
          \set{ciao}[Hello World!]

          % nel documento tutte le volte che si vuole
          \get{ciao}
          `
          R.

        • #111904
          Up
          0
          Down
          ::


          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

        • #111905
          robitex
          Amministratore del forum
            Up
            0
            Down
            ::


            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.

          • #111906
            OldClaudio
            Partecipante
              Up
              0
              Down
              ::


              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.

            • #111907
              Up
              0
              Down
              ::

              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 H for 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

            • #111908
              robitex
              Amministratore del forum
                Up
                0
                Down
                ::


                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.

              • #111909
                robitex
                Amministratore del forum
                  Up
                  0
                  Down
                  ::

                  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.

                • #111910
                  Up
                  0
                  Down
                  ::

                  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

                • #111911
                  robitex
                  Amministratore del forum
                    Up
                    0
                    Down
                    ::

                    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.


                    Gustavo

                    Ciao 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.

                Visualizzazione 10 filoni di risposte
                • Devi essere connesso per rispondere a questo topic.

                Go to top