- Questo topic ha 14 risposte, 3 partecipanti ed è stato aggiornato l'ultima volta 18 anni, 9 mesi fa da
egreg9.
-
CreatoreTopic
-
17 Novembre 2007 alle 22:47 #18885
-
CreatoreTopic
-
AutoreRisposte
-
-
17 Novembre 2007 alle 23:04 #18886::
Vorrei creare un comando \cmd con questo comportamento.
Se chiamo \cmd esso mi deve dare a mentre se chiamo \cmd* mi deve dare b.
Lo potrei fare con il costrutto \if\case e scrivere \cmd[0] o \cmd[1]; ma io voglio sapere se e come farlo con l’asterisco.
`\newcommand\cmd{\@ifstar\@cmds\@cmd}
\newcommand\@cmds{b}
\newcommand\@cmd{a}`
Gli eventuali argomenti devono essere nella definizione di \@cmds e \@cmd. Si può adottare una definizione abbreviata se non ci sono argomenti:
`\newcommand{\cmd}{\@ifstar{b}{a}}`
Trovi parecchi esempi in latex.ltx; tutto va fra \makeatletter e \makeatother: tu lo sapevi di certo, altri magari si troverebbero in ambasce provando. 🙂Ciao
Enrico
-
17 Novembre 2007 alle 23:51 #18887
-
26 Novembre 2007 alle 18:40 #18888
-
27 Novembre 2007 alle 10:43 #18889::
E nel caso di ambiente stellato e non come si procede?
Io ad esempio voglio un ambiente chiamato oggetto. Se asteriscato deve essere uguale ad un ambiente chiamato primo mentre se non asteriscato deve essere uguale ad un ambiente chiamato secondo.
`\newenviroment{oggetto}{\primo}{\endprimo}
\newenvironment{pippo*}{\secondo}{\endsecondo}`
Troppo facile, no? Oppure, in modo più esoterico
`\let\oggetto\primo
\let\endoggetto\endprimo
\expandafter\let\csname oggetto*\endcsname\secondo
\expandafter\let\csname endoggetto*\endcsname\endsecondo`
E se per caso l’ambiente fosse “secondo*”?
`\newenvironment{oggetto*}{\begin{secondo*}}{\end{secondo*}}`
Ma qui si apre un gruppo in più, così si può adottare
`\makeatletter
\newenvironment{oggetto*}
{\@nameuse{secondo*}}
{\@nameuse{endsecondo*}}`
C’è la soluzione esoterica, per scrivere la quale occorre indossare il cappello a punta:
`\expandafter\let\csname oggetto*\expandafter
\endcsname\csname secondo*\endcsname
\expandafter\let\csname endoggetto*\expandafter
\endcsname\csname endsecondo*\endcsname`
Molto interessante: usa il fatto che l’espansione di \csname provoca l’espansione di tutto ciò che arriva al corrispondente \endcsname; quindi \expandafter all’interno provoca l’espansione del \csname seguente. Urca!Ciao
Enrico
-
27 Novembre 2007 alle 11:18 #18890
-
27 Novembre 2007 alle 11:40 #18891::
Molte grazie. 😀
Non pensavo fosse così facile.Comunque la prima definizione dovrebbe essere
`
\newenvironment{oggetto}{\primo}{\endprimo}
\newenvironment{oggetto*}{\secondo}{\endsecondo}`Piccola dimenticanza. Avevo scritto pippo e poi modificato con il nome proposto da te.
Basta ricordare che
(1) \begin{
} esegue un certo numero di comandi standard e alla fine
`\csname\endcsname`
(2) \end{} esegue
`\csname end\endcsname`
e poi un certo numero di comandi standard.è una lista di token che devono essere caratteri (indipendentemente dalla categoria, purché non caratteri di commento, ignorati o non validi o “escape”. Si può perfino definire
`\newenvironment{$$}{…}{…}`
oppure 😀
`\newenvironment{$&#@!#!#}{inizio insulti}{fine insulti}`
Ciao
Enrico
-
29 Novembre 2007 alle 11:49 #18892::
Un altro problema collegato a questo.Posso scrivere una cosa del genere, che naturalmente non funziona?
`
\let\chapter*\chapter`
Cioè \chapter* deve essere identico a \chapter.Ho provato anche a scrivere
`
\let\chapterns\chapter
\renewcommand\chapter{\@ifstar\chapterns\chapterns}
`Ma naturalmente non va.
In pratica voglio distruggere la versione asteriscata ridefinendola uguale a quella non asteriscata.
Ho provato anche con \let…\@gobble e \empty e a ridefinire ma nulla da fare.Ciao
Andrea
-
29 Novembre 2007 alle 12:06 #18893::
Un altro problema collegato a questo.
Posso scrivere una cosa del genere, che naturalmente non funziona?
`\let\chapter*\chapter`
Cioè \chapter* deve essere identico a \chapter.Ho provato anche a scrivere
`\let\chapterns\chapter
\renewcommand\chapter{\@ifstar\chapterns\chapterns}`
Ma naturalmente non va.In pratica voglio distruggere la versione asteriscata ridefinendola uguale a quella non asteriscata.
Ho provato anche con \let…\@gobble e \empty e a ridefinire ma nulla da fare.Non è come con gli “ambienti asteriscati”. Essenzialmente, un comando \pippo che ammette la variante * è definito come
`\newcommand\pippo{\@ifstar\pippostar\pipponostar}`
Nel caso di \chapter è un po’ diverso, nel senso che il controllo viene passato alla macro \secdef; se dai \show\chapter, avrai in risposta
`> \chapter=\long macro:
->
\secdef \@chapter \@schapter .`
Se adesso chiedi \show\secdef avrai
` \secdef=macro:
#1#2->\@ifstar {#2}{\@dblarg {#1}}.`
Quindi capisci che \secdef usa il primo argomento se non si trova subito dopo un *, altrimenti il secondo. Il tuo scopo si ottiene scrivendo
`\let\@schapter\@chapter`
Ciao
Enrico
-
29 Novembre 2007 alle 15:48 #18894
-
29 Novembre 2007 alle 16:25 #18895::
E se volessi fare la stessa cosa con le sezioni?
Non ti applichi. 🙂
\show\section ti dice che viene richiamato il comando \@startsection, il quale non dice molto. Allora si fa \show\@startsection e qui compare \@ifstar alla fine, dal quale si deduce che occorre ridefinire \@ssect come \@sect. Ma c’è un problema: così ridefinisci anche tutti i comandi da \section in giù.
Soluzione solo per \section:
`\let\orig@section\section
\def\section{\@ifstar\orig@section\orig@section}`
Così ti mangi l’eventuale * e vai avanti con l’originale \section.Ciao
Enrico
-
29 Novembre 2007 alle 18:25 #18896::
E se volessi fare la stessa cosa con le sezioni?
Non ti applichi. 🙂
Prima di tutto grazie.
Ad applicarmi mi applico avevo dato \show\section e non ci avevo capito un tubo.
In pratica la soluzione che avevo provato con chapter andava e va bene per le sezioni.
A proposito, per il capitolo la tua soluzione non funziona infatti \capitolo* dà errore mentre
`
\makeatletter
\let\oldchapter\chapter
\let\@schapter\oldchapter
\makeatother
`funziona.
Come vedi, Prof., ogni tanto mi applico. 😀
Alla prossima
Andrea
-
30 Novembre 2007 alle 8:22 #18897::
[quote]E se volessi fare la stessa cosa con le sezioni?
Non ti applichi. 🙂
Prima di tutto grazie.
Ad applicarmi mi applico avevo dato \show\section e non ci avevo capito un tubo.
In pratica la soluzione che avevo provato con chapter andava e va bene per le sezioni.
A proposito, per il capitolo la tua soluzione non funziona infatti \capitolo* dà errore mentre
`
\makeatletter
\let\oldchapter\chapter
\let\@schapter\oldchapter
\makeatother`funziona.[/quote]
`\makeatletter
\def\@schapter{\@dblarg{\@chapter}}
\makeatother`
Ciao
Enrico
-
30 Novembre 2007 alle 11:10 #18898
-
30 Novembre 2007 alle 11:37 #18899::
Scusa Enrico per cosa sta
`
\@dblarge
`
Provo anch’io ad applicarmi…È \@dblarg. Serve per fornire automaticamente un argomento opzionale se non è dato. La definizione di \@chapter è
`\def\@chapter[#1]#2{…}`
e quindi \@chapter si aspetta di trovare una parentesi quadra subito dopo. Dando \@dblarg{\@chapter} si hanno due casi
`\@dblarg{\@chapter}{arg}
\@dblarg{\@chapter}[optarg]{arg}`
Nel primo caso il risultato è come se si fosse dato
`\@chapter[arg]{arg}`
nel secondo invece risulta
`\@chapter[optarg]{arg}`
Naturalmente tutto questo è nascosto all’utente. Chi scrive \chapter{Pippo} non ha bisogno di sapere che “Pippo” non è in realtà l’argomento di \chapter (che di fatto non è una macro con argomenti :!:) né che, se scrive \chapter[Pluto]{Pippo}, non sta dando veramente un argomento opzionale a \chapter.La macro \chapter viene trasformata in
`\@dblarg{\@chapter}`
e, a questo punto, accade la magia di cui sopra.Riassumendo: se vuoi definire un comando \xxx che abbia un argomento opzionale e uno obbligatorio, con la clausola che se l’argomento opzionale manca sia considerato uguale a quello obbligatorio, le strade sono due:
`\newcommand{\xxx}[2][]{%
\def\next{#1}%
\ifx\next\@empty
\@xxx[#2]{#2}%
\else
\@xxx[#1]{#2}
\fi}
\def\@xxx[#1]#2{}`
Oppure si può scrivere
`\newcommand{\xxx}{\@dblarg{\@xxx}}
\def\@xxx[#1]#2{}`
Quale sia meglio, mi pare evidente.Ciao
Enrico
-
-
AutoreRisposte
- Devi essere connesso per rispondere a questo topic.