Re: Occultare un comando con parametri

#8777
Up
0
Down
::


Ciao a tutti. In questo messaggio cerco di fare un riassunto di tutto il discorso, mettendo in evidenza solo i punti essenziali.

Ormai siamo giunti alla fine, e, a parte un piccolo dubbio che mi è venuto in mente, il mio problema è risolto. Scrivo questo messaggio prevalentemente per ringraziare ev, che si chiedeva dove stava l’utilità nel problema che mi sono posto, facendo vedere a lui e a chiunque ne fosse interessato un esempio di applicazione reale dell’idea che mi era venuta.

Questo messaggio è lungo e articolato e serve da riassunto; chi non è interessato non occorre che perda tempo a leggerlo.

alla fine avrei preferito usare una versione (leggermente modificata) della sua [di egreg9], senza nulla togliere alla tua [di ev], che risolve il mio problema alla perfezione.

E invece, alla fine, pare che le cose vadano ancora meglio: le due soluzioni sembrano essersi “unificate” in una sola che prende il meglio di tutte e due. Fantastico! 🙂

In merito al significato dei comandi (almeno a me) misteriosi di cui dovevo cercare il significato:

non so cosa facciano ne’ \@ifstar

`\@ifstar\@gobble\@gobbleopt`
\@ifstar controlla se il comando è seguito dall’asterisco; se lo è, esegue \@gobble, altrimenti \@gobbleopt.

Bene, grazie, direi che questo spiega la sintassi del comando \@ifstar: se il test che conduce (controllare se il comando è seguito dall’asterisco) risulta essere vero, viene eseguito, in generale il primo comando proposto, altrimenti il secondo.

ne’ \@gobble

Il primo [\@gobble] mangia il suo argomento [l’argomento del comando nel quale esso è chiamato]

Benissimo; come leggo anche su questo messaggio, \@gobble “cancella” il primo carattere che trova (che non sia uno spazio bianco) oppure la prima stringa che trova raggruppata tra parentesi (graffe, ovviamente). In pratica si tratta dell’istruzione di cancellazione che andavo cercando. Chiaramente, bisognava anche sapere dove metterla (oltre a sapere che esisteva)…

Per quanto riguarda i nuovi comandi, invece:

`\newcommand\@gobbleopt[2][]{}`
[\@gobbleopt] mangia l’argomento obbligatorio e anche quello opzionale.

Ho idea che questo trucco mi sarà molto utile in futuro (e forse non solo a me…)

Ovviamente vorrai aggiungere a \not@a@section qualche comando di spaziatura.

Ma anche no, grazie, sono più che soddisfatto di com’è attualmente.

Non dovresti avere alcun problema di indice.

Confermo.

Ecco la storia integrale del perché ho voluto risolvere questo problema…

Tempo fa, per prepararmi ad un esame, mi sono messo a raccogliere dei testi degli esercizi di vecchi esami e a scriverli in una dispensa. Ho pensato di codificare il tutto nel seguente modo:

  • le consegne degli esercizi sono state scritte direttamente così come le ho trovate; il “titolo” dell’esercizio è stato codificato con una sezione (es. \section{Esercizio 4 del 12 aprile 1996});

  • quando degli esercizi simili facevano parte di un blocco logico comune, questo è stato codificato con un capitolo (es. \chapter{Esercizi sui B-tree});

  • se è stato possibile racchiudere blocchi comuni in ulteriori macroblocchi, questi ultimi sono stati codificati con delle parti (es. \part{Esercizi sugli alberi}).

A questo punto ho arricchito la dispensa con ulteriori caratteristiche messe a disposizione dal linguaggio (l’indice dei contenuti, le metainformazioni e i segnalibri di hyperref, le intestazioni di fancyhdr e così via) che potessero facilitare il reperimento delle informazioni. Anche per questo motivo, questa dispensa non l’ho mai stampata.

Io sono una persona a cui basta poco per distrarsi, e quindi, quando devo svolgere degli esercizi, desidero che il foglio sia il più “pulito” possibile. Ho pensato quindi che tutti gli strumenti messi a disposizione dal linguaggio che rendevano così facile la navigazione, nella carta stampata per me dovevano sparire.

Mi sono messo quindi a scrivere un secondo file (usando il copia e incolla quando potevo) in cui ho fatto sparire l’indice, le intestazioni, i numeri di pagina (perche’ gli esercizi non erano legati l’uno all’altro, e quindi potevano essere svolti indipendentemente), ho eliminato i comandi \part e \chapter, perché il raggruppamento non aveva più importanza, ho sostituito le occcorrenze di \section con \paragraph per diminuire la dimensione del testo della consegna (semanticamente scorretto, ma una volta stampato uno non vede il sorgente elettronico del documento), ho dato dei \newpage per lasciare lo spazio sufficiente per svolgere l’esercizio e così via. La dispensa, così riscritta, aveva quindi un senso ed una praticità, per me, e stavolta potevo stamparla davvero.

Questo è stato un lavorone; fatto una volta, rifarlo sarebbe stato solo una perdita di tempo. In questi giorni ho avuto proprio la necessità di rifarlo e ho preferito perdere un po’ più di tempo per semplificare il lavoro in modo da non doverlo rifare mai più, e grazie al GuIT il problema è risolto.

In breve, la soluzione è questa (l’esempio che propongo è reale; semplicemente, non ho scritto le consegne degli esercizi per non allungare troppo il post):

  • scrivere un solo sorgente, il file esempio.tex illustrato di seguito;

  • scrivere delle regole di formattazione varie per la produzione di una modalità “raccolta” della mia dispensa, quella pensata per essere “navigata”, non stampata, nel file raccolta.sty;

  • scrivere delle regole di formattazione varie per la produzione di una modalità per la stampa, in cui l’aspetto semantico e ipertestuale è ridotto al minimo, nel file stampa.sty.

Come già detto, questa idea l’ho presa in prestito dal mondo HTML + CSS; in questo ambito, infatti, non è raro che uno stesso documento venga formattato in modi differenti a seconda del mezzo con cui deve essere visualizzato.

Ecco il file esempio.tex con il contenuto; ho indentato un po’ male sperando di facilitare la leggibilità. Si noti che il file carica il pacchetto per la raccolta (raccolta.sty); i due pacchetti sono mutuamente esclusivi: o l’uno, o l’altro.
`\documentclass[a4paper,italian]{book}

\usepackage{raccolta}
%\usepackage{stampa}

\begin{document}

\frontmatter

\tableofcontents

\mainmatter

\pagestyle{fancy}

\part[Alberi]{Esercizi sugli alberi}
\chapter[BST]{Esercizi sui BST}
\section{Esercizio 1 del 7 dicembre 2004}
Bla, bla, bla\dots
\section{Esercizio 2 del 7 dicembre 2004}
Bla, bla, bla\dots
\chapter[RB-tree]{Esercizi sugli RB-tree}
\section{Esercizio 2 del 21 gennaio 1999}
Bla, bla, bla\dots
\section{Esercizio 1 del 10 dicembre 1994}
Bla, bla, bla\dots
\chapter[B-tree]{Esercizi sui B-tree}
\section{Esercizio 5 del 21 gennaio 2006}
Bla, bla, bla\dots
\section{Esercizio 7 del 19 dicembre 1991}
Bla, bla, bla\dots
\part[Grafi]{Esercizi sui grafi}
\chapter[Prim]{Esercizi sull'algoritmo di Prim}
\section{Esercizio 4 del 21 gennaio 1999}
Bla, bla, bla\dots
\chapter[Kruskal]{Esercizi sull'algoritmo di Kruskal}
\section{Esercizio 1 del 9 dicembre 1992}
Bla, bla, bla\dots
\end{document}`
Segue il file raccolta.sty, che permette di generare un documento per la navigazione; non lo commento perché non è rilevante ai fini del problema:
`\NeedsTeXFormat{LaTeX2e}

\ProvidesPackage{raccolta}[2006/04/20]

\RequirePackage[italian]{babel}
\RequirePackage{fancyhdr}
\RequirePackage[bookmarksopen,plainpages=false]{hyperref}

\hypersetup{%
pdfauthor={Pinco Pallino},%
pdftitle={Raccolta di esercizi di Algoritmi e Strutture Dati},%
pdfsubject={Esercizi per migliorare la pratica con gli algoritmi},%
}

\pagestyle{fancy}
\renewcommand{\chaptermark}[1]{\markboth{#1}{}}
\renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}}
\fancyhf{}
\fancyhead[LE,RO]{\thepage}
\fancyhead[RE]{\nouppercase{\leftmark}}
\fancyhead[LO]{\nouppercase{\rightmark}}
\renewcommand{\headrulewidth}{0pt}

\fancypagestyle{plain}{
\fancyhf{}
\renewcommand{\headrulewidth}{0pt}
}

\endinput`
Infine, il file stampa.sty, che contiene tutto il bel discorso che abbiamo fatto; i commenti salienti compaiono prima dei comandi:
`\NeedsTeXFormat{LaTeX2e}

% Il presente pacchetto, pensato per una dispensa di esercizi da svolgere,
% formatta il sorgente in modo tale che ogni esercizio (se la consegna non e`
% troppo lunga) venga posto in una singola pagina, affinché la persona che deve
% svolgerlo (a mano), dopo avere stampato la dispensa, abbia spazio sufficiente
% per poterlo risolvere.

\ProvidesPackage{stampa}[2006/04/20]

\RequirePackage[italian]{babel}
\RequirePackage{fancyhdr}

% Poiche' qualcuno potrebbe voler svolgere gli esercizi nell'ordine che
% preferisce (o, comunque, alcuni esercizi potrebbe non volerli svolgere
% affatto), non ha senso tenere conto di una numerazione sequenziale delle
% pagine.

\pagestyle{fancy}
\fancyhf{}
\renewcommand{\headrulewidth}{0pt}

% Giusta o sbagliata che sia, l'istruzione seguente permette di aumentare di
% parecchio la giustezza del testo, e riduce i margini, in modo da fornire uno
% spazio maggiore per chi deve scrivere.

\RequirePackage[top=2cm,left=2cm,right=2cm,bottom=2cm]{geometry}

% I comandi \part e \chapter vengono azzerati dal comando \not@a@section;
% per quanto riguarda \section, non si vuole che esso venga eliminato del
% tutto, ma solo che esso risulti scritto piu` in piccolo. Si vuole comunque
% che non compaia nell'indice…

\setcounter{tocdepth}{0}

% … e inoltre, se il titolo di una sezione e` semplicemente il testo della
% consegna, a chi deve svolgere l'esercizio non dovrebbe interessare che
% l'esercizio in questione sia la sezione 4.3 di un possibile capitolo
% dedicato ai grafi.

\setcounter{secnumdepth}{0}

% Il nuovo comando \not@a@section si prefigge lo scopo di “annullare” (rendere
% vuoti) i comandi di sezionamento; per fare cio` chiama \@gobble in presenza
% di un comando di sezionamento non numerato e \@gobbleopt in presenza di un
% sezionamento numerato, che potrebbe avere un titolo opzionale.

\def\not@a@section{\@ifstar\@gobble\@gobbleopt}

% Il nuovo comando \@gobbleopt “annulla” sia l'argomento obbligatorio che
% quello opzionale del comando in cui viene chiamato.

\newcommand\@gobbleopt[2][]{}

% I comandi \part e \chapter vengono “annullati”.

\let\part\not@a@section
\let\chapter\not@a@section

% Il comando \section viene riformattato in modo da essere scritto molto piu`
% in piccolo, come \paragraph. In piu` viene chiamata l'istruzione \clearpage
% che fornisce a chi deve svolgere l'esercizio lo spazio bianco in cui poterlo
% risolvere (a mano, dopo averlo stampato) dal momento che inserisce il testo
% dell'esercizio [la \section] successivo[a] appena alla pagina seguente; in
% questo modo, per ogni facciata c'e` un solo esercizio (a meno di consegne
% troppo lunghe).

\renewcommand{\section}{\@startsection
{section}% Il nome.
{1}% Il livello.
{\z@}% L'indentazione.
{3.25ex \@plus1ex \@minus.2ex}% Lo spazio prima.
{-1em}% Lo spazio dopo.
{\normalfont\normalsize\bfseries\clearpage}} % Lo stile.

\endinput`
Chi è interessato può provare a compilare per vedere la differenza con i due pacchetti.
L’ultimo dubbio che mi è venuto: se sintatticamente è corretto chiamare \clearpage dentro a \section codì direttamente oppure se si può fare di meglio; comunque, questa sarebbe solo una chicca.

Grazie a tutti per la bontà dei vostri suggerimenti e per la vostra pazienza! A presto! 🙂

Go to top