Problema con una ridefinizione di comando

  • Creatore
    Topic
  • #20545
    Up
    0
    Down
    ::


    Per non dover ridefinire i vari comandi di altri documenti ho pensato di ridefinire il comando section in modo che, oltre a svolgere il suo compito, si occupi di scrivere il testo in un file appropriato esterno.
    Il comando l’ho ridefinito nel seguente modo considerando le due versioni * e non
    `
    \def\oldesection{\relax}
    \let\oldsection=\section
    \def\seziones##1{\oldsection*{##1}}
    \def\sezione##1{\oldsection{##1}
    \relax
    \immediate\write \csname tf@a\thearticle\endcsname{\hskip 7pt \thesection. ##1\if@puntini \dotfill\else\hfill\fi \thepage\mbox{\quad}\par
    }}

    \def\section{\@ifstar\seziones\sezione}
    `
    Il codice funziona perfettamente se l’argomento di section non contiene altri comandi altrimenti mi da un errore che non riesco a interpretare.
    scrivendo \section{Ambiente \envname{Articolo}}
    con \envname definito come
    `
    \newcommand*\envname[1]{\textsf{#1}}
    `
    ottengo il seguente errore:
    {psfonts.map}] [2]
    Runaway argument?
    {\s@font }{articolo}\ifx \reserved@a \@empty \let \check@icl \@empty \ETC.
    ! Paragraph ended before \@sect was complete.

    \par
    l.90 \section{Ambiente \envname{articolo}}
    Qualcuno ha qualche idea su cosa può essere?

    Senza la ridefinizione del comando funziona tutto

Visualizzazione 6 filoni di risposte
  • Autore
    Risposte
    • #20546
      Up
      0
      Down
      ::

      Per non dover ridefinire i vari comandi di altri documenti ho pensato di ridefinire il comando section in modo che, oltre a svolgere il suo compito, si occupi di scrivere il testo in un file appropriato esterno.
      Il comando l’ho ridefinito nel seguente modo considerando le due versioni * e non
      `
      \def\oldesection{\relax}
      \let\oldsection=\section
      \def\seziones##1{\oldsection*{##1}}
      \def\sezione##1{\oldsection{##1}
      \relax
      \immediate\write \csname tf@a\thearticle\endcsname{\hskip 7pt \thesection. ##1\if@puntini \dotfill\else\hfill\fi \thepage\mbox{\quad}\par
      }}

      \def\section{\@ifstar\seziones\sezione}
      `
      Il codice funziona perfettamente se l’argomento di section non contiene altri comandi altrimenti mi da un errore che non riesco a interpretare.
      scrivendo \section{Ambiente \envname{Articolo}}
      con \envname definito come
      `
      \newcommand*\envname[1]{\textsf{#1}}
      `
      ottengo il seguente errore:
      {psfonts.map}] [2]
      Runaway argument?
      {\s@font }{articolo}\ifx \reserved@a \@empty \let \check@icl \@empty \ETC.
      ! Paragraph ended before \@sect was complete.

      \par
      l.90 \section{Ambiente \envname{articolo}}
      Qualcuno ha qualche idea su cosa può essere?

      Senza la ridefinizione del comando funziona tutto

      Perché quei doppi #?

      E, già che ci sono, ti ricordo di togliere \immediate.

      Ciao
      Enrico

    • #20547
      Up
      0
      Down
      ::


      i doppi # sono dovuti al fatto che è definito all’interno di un comando contenitore che richiama la ridefinizione.

      Per quanto riguarda immediate sono obbligato a metterlo perché se si presentano due sezioni nella stessa pagina quando viene processato il valore di \thesection è lo stesso per entrambi le sezioni, cosa che non succede nel caso in cui si utlizzi \immediate.
      Senza immediate il problema non si pone tutto funziona perfettamente, ma i numeri scritti nel file sono errati.
      Anche il pacchetto minitoc è obbligato a scrivere \immediate per garantire l’integrità dei dati.

    • #20548
      Up
      0
      Down
      ::

      i doppi # sono dovuti al fatto che è definito all’interno di un comando contenitore che richiama la ridefinizione.

      Per quanto riguarda immediate sono obbligato a metterlo perché se si presentano due sezioni nella stessa pagina quando viene processato il valore di \thesection è lo stesso per entrambi le sezioni, cosa che non succede nel caso in cui si utlizzi \immediate.
      Senza immediate il problema non si pone tutto funziona perfettamente, ma i numeri scritti nel file sono errati.
      Anche il pacchetto minitoc è obbligato a scrivere \immediate per garantire l’integrità dei dati.

      Difficile dire qualcosa, se non indichi il vero codice e un esempio minimo.

      Quanto a \immediate: così avrai pure il numero di sezione giusto, ma non potrai essere sicuro di quello delle pagine.

      Ciao
      Enrico

    • #20549
      Up
      0
      Down
      ::


      Questo è l’esempio minimo che genera l’errore.
      `
      \documentclass[a4paper]{article}
      \makeatletter
      \def\contenutotoc{%
      \begingroup
      \makeatletter
      \@input{\jobname.abc}%
      \if@filesw
      \expandafter\newwrite\csname tf@abc\endcsname
      \immediate\openout \csname tf@abc\endcsname \jobname.abc\relax
      \fi
      \@nobreakfalse
      \endgroup}
      \def\chiudiscrittura{\closeout\csname tf@abc\endcsname}
      \def\cambiasezionetoc{
      \def\oldesection{\relax}
      \let\oldsection=\section
      \def\seziones##1{\oldsection*{##1}}
      \def\sezione##1{\oldsection{##1}
      \relax
      \immediate\write \csname tf@abc\endcsname{\hskip 7pt \thesection. ##1\hfill \thepage\mbox{\quad}\par
      }}

      \def\section{\@ifstar\seziones\sezione}
      \def\oldsubsection{\relax}
      \let\oldsubsection=\subsection
      \def\subsection##1{\oldsubsection{##1}
      \immediate\write \csname tf@abc\endcsname{\hskip 13pt \thesubsection. ##1\hfill\thepage\mbox{\quad}\par}
      }
      }
      \def\ripristinasezione{
      \let\section=\oldsection%
      \let\subsection=\oldsubsection%
      }
      \def\minisommario{
      \cambiasezionetoc
      \hrule
      \vskip 5pt
      \textsc{Table of Contents}\par
      \contenutotoc\par
      \vskip 7pt
      \hrule
      \vskip 15pt plus 5pt minus 3pt
      }
      \makeatother
      \newcommand*\envname[1]{\textsf{#1}}
      \begin{document}
      \minisommario
      \section{\envname{Prova}}
      \section{prova ancora}
      \end{document}`
      Se elimino \immediate funziona, ma sbaglia i numeri delle sezioni

    • #20550
      Up
      0
      Down
      ::

      Questo è l’esempio minimo che genera l’errore.
      `…`
      Se elimino \immediate funziona, ma sbaglia i numeri delle sezioni

      Il problema è che con \immediate non si usano i meccanismi di protezione dalle espansioni indesiderate che valgono mentre si è nella routine di output.

      Perciò con \immediate l’argomento \envname viene espanso e si va in grossissimi pasticci.

      Soluzione “moderna”: scrivi \unexpanded{##1} invece di ##1 dentro al \write; \unexpanded è un’estensione di e-TeX, e pdfTeX le incorpora. Se anche usi latex, va bene lo stesso, purché tu abbia una distribuzione recente.

      Ciao
      Enrico

    • #20551
      Up
      0
      Down
      ::


      Grazie Enrico, stavo provando varie soluzioni e questa funziona egregiamente.
      Stavo pensando qualcosa che facesse espandere thesection subito in un comando tipo
      \edef\testo{\thesection} per costringere l’espansione, ma non funziona.

      Rimane il fatto che usando immediate i numeri di pagina possono essere sballati. Probabilmente l’unica soluzione è quella di definirsi un comando tipo contentsline.
      Devo dire che mi sto divertendo a giocare con i meccanismi di latex.

    • #20552
      Up
      0
      Down
      ::


      Ho risolto ridefinendo e semplificando i comandi di latex standard per la gestione dei vari sommari. Ho dovuto però definire due nuovi counter.
      ecco il codice `
      \documentclass[a4paper]{article}
      \usepackage{lipsum}
      \makeatletter
      \def\contenutotoc{%
      \begingroup
      \makeatletter
      \@input{\jobname.abc}%
      \if@filesw
      \expandafter\newwrite\csname tf@abc\endcsname
      \immediate\openout \csname tf@abc\endcsname \jobname.abc\relax
      \fi
      \@nobreakfalse
      \endgroup}
      \def\chiudiscrittura{\closeout\csname tf@abc\endcsname}
      \def\cambiasezionetoc{
      \def\oldesection{\relax}
      \let\oldsection=\section
      \def\seziones##1{\oldsection*{##1}}
      \def\sezione##1{\oldsection{##1}
      \relax
      aggiungilinea{section}{##1} %%%%
      }

      \def\section{\@ifstar\seziones\sezione}
      \def\oldsubsection{\relax}
      \let\oldsubsection=\subsection
      \def\subsection##1{\oldsubsection{##1}
      \aggiungilinea{subsection}{##1} %%%%
      }
      }
      \def\ripristinasezione{
      \let\section=\oldsection%
      \let\subsection=\oldsubsection%
      }
      \def\minisommario{
      \cambiasezionetoc
      \hrule
      \vskip 5pt
      \textsc{Table of Contents}\par
      \contenutotoc\par
      \vskip 7pt
      \hrule
      \vskip 15pt plus 5pt minus 3pt
      }
      \newcounter{articolosezione} %%%%
      \newcounter {articolosottosezione}[articolosezione] %%%%
      \renewcommand \thearticolosezione {\@arabic\c@articolosezione.} %%%%
      \renewcommand\thearticolosottosezione {\thearticolosezione\@arabic\c@articolosottosezione.} %%%%
      \newcommand*\envname[1]{\textsf{#1}}
      \def\aggiungilinea#1#2{%%%%%
      \aggiungicontenuti{\protect\contenuti{#1}{#2}{\thepage}}} %%%%
      \long\def\aggiungicontenuti#1{%%%%
      \def\@out{\csname tf@abc\endcsname}%%%%
      \protected@write\@out %%%%
      {\let\label\@gobble \let\index\@gobble \let\glossary\@gobble}%%%%%
      {\string\mbox{}{#1}}}%%%%
      \def\contenuti#1{\csname s@#1\endcsname}%%%%
      \def\s@section#1#2{%%%%
      \stepcounter{articolosezione}%%%%
      \thearticolosezione\ #1 \hfill #2\par}%%%%
      \def\s@subsection#1#2{%%%
      \stepcounter{articolosottosezione}%%%%
      \hskip 15pt \thearticolosottosezione\ #1 \hfill #2\par}%%%%
      \makeatother

      \begin{document}
      \minisommario
      \section{Una \envname{Prova}}
      \lipsum[3]\lipsum[4]
      \subsection{Questa \`{e} una sottosezione}
      \lipsum[2]\lipsum[2]\lipsum[2]
      \section{prova ancora}
      \chiudiscrittura
      \end{document}`

      Ho indicato con %%% i cambiamenti rispetto alla prima versione. So di aver scoperto l’acqua calda, ma ho capito finalmente come funziona. E ho risolto usando write al posto di immediate\write il problema delle pagine.

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

Go to top