Re: Opzioni di pacchetto con xkeyval

#48336
robitex
Amministratore del forum
    Up
    0
    Down
    ::


    Ecco un altro tema: creazione on the fly di chiavi xkeyval.
    Ammettiamo di voler gestire dimensioni attraverso la sintassi chiave valore. Vorremmo un comando per esempio \dim il cui argomento è appunto un assegnazione di una misura ad un registro (con sitassi TeX) \dimen.
    esempio:
    `\dim{a=100pt}
    \dim{b=1mm}
    `
    La sostanza di tutto questo è: prima di poter assegnare un valore ad una variabile occorre creare la chiave tramite gli opportuni comandi del pacchetto xkeyval.

    Allora basta che la prima e solo la prima volta che avviene una definizione venga creata l’oppurtuna chiave, per esempio con il codice:
    `\documentclass{report}
    \usepackage{xkeyval}

    \makeatletter
    \def\dim#1{%
    \setkeys*{dimfam}{#1}
    \ifx\XKV@rm\empty
    \setrmkeys{dimfam}—esisting key—%
    \else
    \expandafter\make@newkey\XKV@rm\@nil
    \setrmkeys{dimfam}—new key—%
    \fi
    }
    %
    \def\make@newkey#1=#2\@nil{%
    % creo la nuova dimensione
    \expandafter\newdimen\csname #1\endcsname
    %
    % creo la chiave ad essa associata
    \define@key{dimfam}{#1}{%
    \csname #1\endcsname=##1
    }
    }
    \makeatother

    \begin{document}
    \dim{xMain=1mm}Dimensione xMain=\the\xMain.

    \dim{xMain=100mm}Dimensione xMain=\the\xMain.
    \end{document}`

    Si può fare anche qualcosa di più interessante: definire variabili in funzione di altre. Basta caricare il pacchetto etex che rende disponibili le estensioni di etex appunto, e far lavorare il comando \dimexpr. Bellissimo direte voi (se non lo state dicendo ditelo immediatamente perché potrete scrivere \dim{a=10mm+4pt}\dim{b=\a/2}). Ecco il codice modificato:
    `\documentclass{report}
    \usepackage{etex}
    \usepackage{xkeyval}

    \makeatletter
    \def\dim#1{%
    \setkeys*{dimfam}{#1}
    \ifx\XKV@rm\empty
    \setrmkeys{dimfam}%
    \else
    \expandafter\make@newkey\XKV@rm\@nil
    \setrmkeys{dimfam}%
    \fi
    }
    %
    \def\make@newkey#1=#2\@nil{%
    % creo la nuova dimensione
    \expandafter\newdimen\csname #1\endcsname
    %
    % creo la chiave ad essa associata
    \define@key{dimfam}{#1}{%
    \csname #1\endcsname=\dimexpr##1\relax
    }
    }
    \makeatother

    \begin{document}

    \dim{xMain=1mm}Dimensione xMain=\the\xMain.

    \dim{xMain=100mm}Dimensione xMain=\the\xMain.

    \dim{xMain=\xMain/2}Dimensione xMain=\the\xMain.

    \dim{xMain=45pt+45pt}Dimensione xMain=\the\xMain.

    \dim{xMain=5pt+5pt}Dimensione xMain=\the\xMain.

    \dim{yMain=30pt}Dimensione yMain=\the\yMain.

    \dim{yMain=\xMain*2}Dimensione yMain=\the\yMain.

    \end{document}`

    Il tallone di Achille del comando \dim è che se si inseriscono alla prima chiamata, spazi prima e/o dopo il nome della chiave sono guai, mentre quello della sintassi è che la chiave è un nome standard (tipo a o b come abbiamo visto), mentre se vogliamo usarne il valore (a secondo membro) occorre che premettere il backslash per crearne la control sequence.
    Altra cosetta è che occorre tener presente la sintassi prevista per il comando \dimexpr (se interessati leggere anche questo post http://www.guit.sssup.it/phpBB2/viewtopic.php?t=7576 ), e che il tutto si basa sul fatto che la lista delle chiavi sconosciute è vuota (cosa che può nono essere se in altri unti del codice abbiamo usato la versione asteriscata di \setkeys).

    Bye

    Go to top