Interrompere la compilazione programmaticamente

  • Creatore
    Topic
  • #99859
    Liverpool
    Partecipante
      Up
      0
      Down
      ::


      Ho un codice che, in base a dei parametri inseriti dall’utente, può generare degli errori. Vorrei gestire questi errori con un messaggio del comando [tt]\errmessage[/tt] oppure [tt]\PackageError[/tt]. Il problema è che quei comandi generano il messaggio, ma non arrestano la compilazione in quel punto, perciò vengono generati anche i successivi messaggi d’errore che vorrei evitare di mostrare. Ecco un esempio veramente minimo, tanto per capirci:
      `\documentclass{article}

      \begin{document}
      \newcommand{\prova}{Prima versione}
      \prova
      \errmessage{Questo messaggio dovrebbe interrompere immediatamente la compilazione}
      \newcommand{\prova}{Seconda versione}
      \prova
      \end{document}`
      La soluzione che mi è venuta in mente è di usare un costrutto condizionale e inserire il messaggio di errore nel primo ramo e tutto il codice fino alla conclusione nel secondo. Il problema è che ho diverse fonti di errore e quindi mi troverei a gestire diversi condizionali annidati e il codice diventa illeggibile.
      Ho letto che c’è il comando [tt]\stop[/tt] di LaTeX che dovrebbe fare ciò che mi serve, ma genera comunque l’output. A parte questo che non mi sembra un problema, ci sono altre controindicazioni nell’utilizzo di questo comando? Voi come vi regolereste al mio posto?

      Grazie

    Visualizzazione 8 filoni di risposte
    • Autore
      Risposte
      • #99860
        OldClaudio
        Partecipante
          Up
          0
          Down
          ::


          Liverpool, secondo me una buona lettura di clsguide.pdf con texdoc ti potrebbe aiutare. Lò sono descritti \ClassError, \PackageError e \GenericError (non mi ricordo se c’è anche un \FileError, ma lo si può creare tramite \GenericError).

          Invece nel kernel di LATeX (file latex.ltx) ci sino le cose da mettere nel terzo argomento dei vari \…Error; hanno nomi misteriosi tipo \@eha, \@ehb, eccetera, che si capiscono leggendo il file latex.ltx; se ne possono definire altri o si può evitare del tutto l’uso di queste macro; essi dicono in sostanza le cose da fare se si immette il codice H dopo un arresto per errore.

          \errmessage è un messaggio di Plain, non è molto descrittivo; i comandi che ti ho indicato sopra sono molto più descrittivi, o lo sono se ci scrivi dentro delle cose sensate e chiare.

          Se poi usi i condizionali definiti da etoolbox, vedi che i loro ultimi due argomenti sono quelli che vengono eseguiti nel caso vero oppure nel caso falso; nessuno ti obbliga a innestare i vari condizionali uno dentro l’altro, perché ne puoi sempre lasciare uno vuoto.

          Non posso scendere in ulteriori dettagli, perché il tuo esempio non è molto preciso in merito alla moltitudine di errori di cui parli; nel senso che forse ti sei spiegato bene, ma io non ho capito.

          \stop è il comando da dare quando la tua console non contiene nessuna facility per “abortire” il job; da usarsi quando l’errore termina con un promp formato da un asterisco, non dal punto interrogativo; in altre parole quando sei davvero nei guai. Non è la stessa cosa del codice X richiesto al prompt formato dal punto interrogativo, perché questo dice al motore di compilazione di arrestare la compilazione salvando in uscita quanto già composto e spedito all’uscita. X è un modo delicato di terminare il job senza buttare a mare tutto; \stop fa “abortire” il job senza se e senza ma.

        • #99861
          Liverpool
          Partecipante
            Up
            0
            Down
            ::


            Grazie per le segnalazioni. Leggerò bene i documenti che mi hai indicato (perché clsguide l’ho sfogliato rapidamente) e ci penserò su. Tuttavia voglio precisare, anzi prima non l’ho detto affatto, che mi riferisco alla compilazione con l’opzione [tt]-interaction=nonstopmode[/tt].

            OldClaudio” post=99544Non posso scendere in ulteriori dettagli, perché il tuo esempio non è molto preciso in merito alla moltitudine di errori di cui parli; nel senso che forse ti sei spiegato bene, ma io non ho capito.

            L’esempio è minimale, ma rende l’idea. Se compili il codice con l’opzione [tt]-interaction=nonstopmode[/tt], nel log ottieni due messaggi d’errore: il primo generato da [tt]\errmessage[/tt], il secondo dalla doppia definizione del comando [tt]\prova[/tt]. Io vorrei che l’utente leggesse solo quello scritto da me, perché non voglio che abbia a che fare con messaggi oscuri (in questo caso il messaggio è semplice) e proprio perciò ho preparato un messaggio più chiaro. Inoltre vorrei che la compilazione si arrestasse subito, perché l’errore che descrivo è tale da rendere impossibile l’esecuzione. Il problema è che il messaggio che ho scritto viene inserito nel log, ma la compilazione va avanti e genera l’errore successivo.
            Come fare per pulire il log? Quello che avevo pensato era (applicato all’esempio):
            `\documentclass{article}

            \begin{document}
            \newcommand{\prova}{Prima versione}
            \prova
            \ifdefined\prova
            \errmessage{Questo messaggio dovrebbe interrompere immediatamente la compilazione}
            \else
            \newcommand{\prova}{Seconda versione}
            \fi
            \prova
            \end{document}`
            Nel ramo [tt]else[/tt] deve andare tutto ciò che va eseguito se non si verifica l’errore, ma se le sorgenti di errore sono parecchie, mi trovo a gestire una cascata di [tt]else[/tt] che rende il codice illeggibile e vorrei evitarlo.
            Perciò sono in cerca di un’alternativa e avevo adocchiato il comando [tt]\stop[/tt], solo che non so se e quanto faccia al caso mio.
            Spero di essere stato più chiaro.

            Ciao

          • #99862
            OldClaudio
            Partecipante
              Up
              0
              Down
              ::


              Be’, a tutto avrei pensato fuorché volessi una compilazione “interattiva” chiedendogli una compilazione batch.

              Se vuoi che la compilazione termini in nonstopomode devi usare codice molto diverso nel ramo dell’if che contiene l’errore, in pratica devi mettere un \end{document} (o comandi equivalenti) dentro il ramo dell’if corrispondente all’errore.

              Il tutto funzionerebbe decisamente meglio in errorstopmode. Io consiglierei errorstopmode come modalità normale di funzionamento e personalmente uso solo questa modalità. Mi sembra che le altre modalità di compilazione, specialmente nonstopmode, non siano fatte per gli umani, ma per le macchine

            • #99863
              Liverpool
              Partecipante
                Up
                0
                Down
                ::

                OldClaudio” post=99555Se vuoi che la compilazione termini in nonstopomode devi usare codice molto diverso nel ramo dell’if che contiene l’errore, in pratica devi mettere un \end{document} (o comandi equivalenti) dentro il ramo dell’if corrispondente all’errore.

                Ecco. E’ proprio questo che non riesco a gestire. Supponiamo che l’errore si trovi all’interno di un comando come questo (pensavo che l’esempio minimo precedente fosse sufficiente):
                `\documentclass{article}
                \usepackage{tikz}

                \tikzset{
                prova/.pic={
                \ifdim#1 pt>1pt
                \errmessage{Valore inaccettabile}
                \fi
                \draw ({asin(#1)},0) circle (1cm);
                } % chiude il comando pic
                } % chiude il comando tikzset

                \begin{document}
                \begin{tikzpicture}
                \pic {prova=2};
                \end{tikzpicture}
                \end{document}`
                Non posso mettere direttamente [tt]\end{document}[/tt] perché c’è ancora l’ambiente tikzpicture aperto; allora come faccio?

              • #99864
                OldClaudio
                Partecipante
                  Up
                  0
                  Down
                  ::


                  E che cosa succede quando premi X per un errore che richiede la terminazione immediata?

                  Niente; al massimo ti si dice che al momento di eseguire \end{document} eri all’interno di un gruppo di livello , proprio perché quel gruppo di tikzpicture non è stato chiuso (\begin e \end costituiscono un gruppo).

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


                    Forse questa discussione può aiutare:
                    rendere-un-documento-immodificabile-e-chiavi-di-processo
                    R.

                  • #99866
                    Liverpool
                    Partecipante
                      Up
                      0
                      Down
                      ::

                      OldClaudio” post=99574E che cosa succede quando premi X per un errore che richiede la terminazione immediata?

                      Niente; al massimo ti si dice che al momento di eseguire \end{document} eri all’interno di un gruppo di livello , proprio perché quel gruppo di tikzpicture non è stato chiuso (\begin e \end costituiscono un gruppo).

                      Alcuni editor, ad esempio Texmaker, hanno la compilazione rapida con l’opzione [tt]-interaction=nonstopmode[/tt] attiva di default. Ecco, io vorrei che un utente che usa uno di questi editor non debba leggere una serie di errori che a lui non dicono niente, ma semplicemente un unico messaggio chiaro al quale segue l’interruzione della compilazione.
                      In un esempio come l’ultimo che ho riportato, si può fare senza mettere il codice seguente nel ramo [tt]else[/tt]? Questo non sono riuscito a capire.

                      robitex” post=99591Forse questa discussione può aiutare:
                      rendere-un-documento-immodificabile-e-chiavi-di-processo
                      R.

                      Ho letto la discussione, ma quello che voglio fare io è bloccare la compilazione in un punto se l’utente inserisce un valore che non dovrebbe. Nell’esempio, se l’utente inserisce un valore superiore a 1, la compilazione si deve bloccare perché l’arcoseno non si può calcolare.

                      Ciao

                    • #99867
                      OldClaudio
                      Partecipante
                        Up
                        0
                        Down
                        ::


                        Tenuto conto che non si può arrestare una compilazione se non si è in outer vertical mode, la soluzione seguente`% !TEX TS-program = pdflatex

                        \documentclass{article}
                        \usepackage{tikz}

                        \newif\ifesci \escifalse
                        \newcommand\arrestatutto{\ifesci\expandafter\stop\fi}
                        \tikzset{
                        prova/.pic={%
                        \ifdim#1 pt>1pt
                        \typeout{^^J^^J ****************^^J
                        Valore inaccettabile
                        ^^J ****************^^J^^J}
                        \escitrue
                        \aftergroup\arrestatutto
                        \else
                        \draw ({asin(#1)},0) circle (1cm);
                        \fi
                        } % chiude il comando pic
                        } % chiude il comando tikzset

                        \begin{document}
                        \begin{tikzpicture}
                        \pic{prova=0.5};
                        \end{tikzpicture}

                        \begin{tikzpicture}
                        \pic {prova=2};
                        \end{tikzpicture}
                        \end{document}` a me funziona.

                      • #99868
                        Up
                        0
                        Down
                        ::


                        Altro vecchio filone riesumato (però, ne discutevate di cose carine, qui! :smile:). Come si può dire a TeX di mollare tutto, buttare a mare tutte le liste su cui sta lavorando e terminare adesso? Ho provato a cercare un po’ sul CTAN, ma sembra che nessuno si sia mai interessato alla faccenda. Be’, ecco un pacchetto abort, scritto in mezz’ora, che si fa carico dell’ingrato compito (è chiaro che TeX ci resta male, poverino! :wink:).

                        Il pacchetto offre l’opzione trace, il cui effetto è facile indovinare. Esso mette a disposizione il comando “\@abort” (non “\abort” per ovvie ragioni) che fa quel che il suo nome dice.
                        `
                        \NeedsTeXFormat{LaTeX2e}[1998/06/01] % LaTeX2e is required!
                        \ProvidesPackage{abort}
                        [2015/04/03 v0.01 (development)]
                        % This package defines the “\@abort” command, which tells TeX to throw away
                        % anything it is working on and to stop without doing anything else.
                        %
                        % For obvious reasons the command has been given a name containing an “@”.
                        \@ifdefinable\@abort@trace{\let\@abort@trace\@gobble}
                        \DeclareOption{trace}{%
                        \def\@abort@trace#1{\typeout{Exiting #1 mode.}}%
                        }
                        \DeclareOption{notrace}{\let\@abort@trace\@gobble}
                        \ExecuteOptions{notrace}
                        \ProcessOptions\relax
                        \newcommand*\@abort{%
                        \ifx\@abort@trace\@gobble
                        \nonstopmode
                        \fi
                        \ifmmode
                        \ifinner
                        \@abort@trace{(ordinary) math}
                        \let\@next $%
                        \else
                        \@abort@trace{display math}
                        \def\@next{$$}%
                        \fi
                        \else \ifhmode
                        \ifinner
                        \@abort@trace{restricted horizontal}
                        \let\@next\egroup
                        \else
                        \@abort@trace{(unrestricted) horizontal}
                        \let\@next\@@par
                        \fi
                        \else % vertical mode
                        \ifinner
                        \@abort@trace{inner vertical}
                        \let\@next\egroup
                        \else
                        % \@abort@trace{(outer) vertical}
                        \output{%
                        \setbox\z@ \box\@cclv
                        \deadcycles \z@
                        }%
                        \deadcycles \z@
                        \let\@next\@@end % after “\@@end”, “\@abort” will not be re-invoked
                        \fi
                        \fi \fi
                        \@next \@abort % exit current mode and retry
                        }
                        `
                        Pensate che possa servire a qualcosa?

                        Ciao.


                        Gustavo

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

                    Go to top