- Questo topic ha 11 risposte, 2 partecipanti ed è stato aggiornato l'ultima volta 14 anni, 5 mesi fa da
egreg9.
-
CreatoreTopic
-
11 Giugno 2011 alle 17:12 #59892::
Ciao a tutti,desideravo porre il seguente quesito:
Prendiamo una macro definita con \newcommand che riceve un parametro
Il parametro è la stessa chiave di ricerca che si passa al comando \cite per fare riferimento a un elemento di BIBTEX.
Supponiamo che io abbia il seguente elemento nel mio file .bib:
@book{eco2005nome,
title={Il nome della rosa},
author={Eco, U.},
isbn={9788845246340},
series={Grandi tascabili Bompiani},
url={http://books.google.com/books?id=OV\_yAAAAMAAJ},
year={2005},
publisher={Tascabili Bompiani}
}Nel mio file .tex scrivo:
qualche cosa \CLAFE{eco2005nome} ancora qualche cosa
Vorrei che la macro \CLAFE, che riceve il parametro “eco2005nome” legga il file CLAFE.BIB estragga in diverse variabili il valore del “title”, di “year”. In modo che poi possa utilizzare, all’interno della macro ovviamente, questa variabili per fare altre cose.
\newcommand{\CLAFE}[1]
{
Ricevo il parametro #1 che conterrà “eco2005nome”
Leggo il file .bib con questa chiave
Imposto in una variabile, per esempio, ANNO, il valore del campo Year del record .Bib
Scrivo il contenuto di ANNO in corsivo, o in grassetto o altro ….
}Chiedo troppo ?
🙂Ciao a tutti e un grazie comunque.
CLAFE
-
CreatoreTopic
-
AutoreRisposte
-
-
11 Giugno 2011 alle 17:40 #59893::
Ciao a tutti,
desideravo porre il seguente quesito:
Prendiamo una macro definita con \newcommand che riceve un parametro
Il parametro è la stessa chiave di ricerca che si passa al comando \cite per fare riferimento a un elemento di BIBTEX.
Supponiamo che io abbia il seguente elemento nel mio file .bib:
@book{eco2005nome,
title={Il nome della rosa},
author={Eco, U.},
isbn={9788845246340},
series={Grandi tascabili Bompiani},
url={http://books.google.com/books?id=OV\_yAAAAMAAJ},
year={2005},
publisher={Tascabili Bompiani}
}Nel mio file .tex scrivo:
qualche cosa \CLAFE{eco2005nome} ancora qualche cosa
Vorrei che la macro \CLAFE, che riceve il parametro “eco2005nome” legga il file CLAFE.BIB estragga in diverse variabili il valore del “title”, di “year”. In modo che poi possa utilizzare, all’interno della macro ovviamente, questa variabili per fare altre cose.
\newcommand{\CLAFE}[1]
{
Ricevo il parametro #1 che conterrà “eco2005nome”
Leggo il file .bib con questa chiave
Imposto in una variabile, per esempio, ANNO, il valore del campo Year del record .Bib
Scrivo il contenuto di ANNO in corsivo, o in grassetto o altro ….
}Chiedo troppo ?
🙂Ciao a tutti e un grazie comunque.
CLAFE
Interessante problema.
`\documentclass[a4paper]{article}\usepackage{keyval}
\makeatletter
\def\define@reuse@key#1{%
\define@key{reuse}{#1}{\global\@namedef{\currentry @#1}{##1}}}
\define@reuse@key{title}
\define@reuse@key{author}
\define@reuse@key{isbn}
\define@reuse@key{series}
\define@reuse@key{url}
\define@reuse@key{year}
\define@reuse@key{publisher}
\define@reuse@key{journal}
%%% inserire tutti gli altri tipi che servono
%\define@reuse@key{}\def\book#1{\extractkey#1\@nil}
\let\article\book
\let\incollection\book
%%% Inserire tutti gli altri tipi che servono\def\extractkey#1,#2\@nil{\def\currentry{#1}\setkeys{reuse}{#2}}
\def\usebibdata#1#2{\@nameuse{#1@#2}}
\makeatother\newcommand{\bibinput}[1]{%
\begingroup\catcode`\@=0 \input{#1.bib}\endgroup}\bibinput{xyz} % il nome del file .bib
\begin{document}
\usebibdata{eco2005nome}{title}\usebibdata{eco2005nome}{year}
\end{document}`
Dovrai completare le due liste di comandi secondo lo schema dato; la prima lista per i campi, la seconda per i tipi di documento.Ciao
Enrico
-
11 Giugno 2011 alle 17:47 #59894
-
11 Giugno 2011 alle 17:49 #59895
-
11 Giugno 2011 alle 18:21 #59896::
Volevo dire che, a fronte di risposte di questo tipo, si può restare solo senza parole.
Non era poi così difficile. 🙂
Vediamo qual è l’idea. I file .bib sono strutturati secondo lo schema
`@entry{citekey,
field1={…},
field2={…},
…
}`
e questo ne fa un ottimo candidato per “keyval”. L’unico problema è estrarre la chiave di citazione. Vediamo con il tuo esempio del “Nome della rosa”.Definiamo \book in modo che raccolga tutta l’elemento della bibliografia come argomento e lo passiamo a \extractkey. Questo comando ha due argomenti delimitati, il primo termina alla prima virgola, il secondo è tutto il resto. Definiamo allora \currentry come il primo argomento, ci servirà in seguito, e passiamo il resto al comando \setkeys di keyval. Questo legge tutte le chiavi definite nello spazio “reuse” e che sono tutte dello stesso tipo: nel caso di “title=Il nome della rosa” il risultato è di eseguire
`\global\@namedef{\currentry @title}{Il nome della rosa}`
che equivale, nel nostro caso, a
`\global\def\eco2005nome@title{Il nome della rosa}`
Lo stesso viene eseguito su tutti i campi.Che ci resta da fare? Intanto la macro per usare questi dati; \usebibdata prende due argomenti: la chiave di citazione e il tipo di dato. A partire da questi costruisce il comando da eseguire; per esempio \usebibdata{eco2005nome}{title} esegue
`\eco2005nome@title`
che appunto stampa “Il nome della rosa”.Altra cosa da fare: nel file bib c’è scritto @book e non \book. Poco male: leggiamo il file in modo che \ sia un carattere normale e al suo posto si usi @:
`\newcommand\bibinput[1]{%
\begingroup\catcode`\@=0 \input{#1.bib}\endgroup}`
Quando si esegue \bibinput{xyz}, prima di leggere il file si dice a TeX che i comandi sono introdotti da @, quindi @book è come se fosse \book. Il tutto in un gruppo, quindi alla fine della lettura il carattere @ ritornerà al suo stato precedente. Per questo le definizioni dei vari comandi sono globali (\global\@namedef), altrimenti alla fine della lettura li perderemmo.Limitazioni. Non si può usare @ in uno dei campi o nella chiave di citazione. I campi vanno delimitati con le graffe (o con niente), non con le doppie virgolette come sarebbe possibile nella sintassi di BibTeX.
Ricordarsi di definire tutti i campi e i tipi di documento necessari. Per gli url c’è qualche problemino, ci penso.
Ciao
Enrico
-
11 Giugno 2011 alle 19:45 #59897::
Aggiungere, prima di \makeatother, la seguente definizione:
`\makeatletter
\newcommand{\usebibdataurl}[2][|]{%
\toks@=\expandafter\expandafter\expandafter{\usebibdata{#2}{url}}%
\toks@=\expandafter\expandafter\expandafter{\the\toks@}%
\toks@=\expandafter\expandafter\expandafter{\the\toks@}%
\scantokens\expandafter{\expandafter\url\expandafter#1\the\toks@#1\endinput}}
\makeatother
`
Così \usebibdataurl{eco2005nome} stamperà l’URL in modo corretto (e non c’è bisogno di scrivere \_). Nel caso il carattere | sia usato nell’URL, si può scrivere
`\usebibdataurl[!]{eco2005nome}`
Il carattere dato come argomento opzionale è quello per delimitare l’URL come nella sintassi
`\url!!`
che assomiglia a quella di \verb.Ciao
Enrico
-
12 Giugno 2011 alle 21:59 #59898::
Non so dire se gli anni di programmazione mi stanno aiutando a capire o se credo di aver capito ma in realtà così non è; sta di fatto che non conosco affatto TEX e alcune cose sono un pochino ostiche da digerire. Ma ci sto provando.
Credo, comunque, che questo problema sia una buona palestra …. potrebbe essere anche un interessante tema da proporre su ArsTecnica.
Metto in pratica le tue risposte … a prestissimo.
Ciao
CLAFE
-
13 Giugno 2011 alle 16:44 #59899::
Non so dire se gli anni di programmazione mi stanno aiutando a capire o se credo di aver capito ma in realtà così non è; sta di fatto che non conosco affatto TEX e alcune cose sono un pochino ostiche da digerire. Ma ci sto provando.
Credo, comunque, che questo problema sia una buona palestra …. potrebbe essere anche un interessante tema da proporre su ArsTecnica.
Metto in pratica le tue risposte … a prestissimo.
Ciao
CLAFEI concetti fondamentali per la prima risposta sono:
(1) l’interfaccia di keyval per la sintassi “chiave=valore”
(2) il cambiamento del codice di categoria di @ in modo che @book sia interpretato come se fosse \book
(3) l’istruzione \let per rendere equivalenti \book, \article e gli altri comandi necessari
(4) l’uso di \csname per ottenere una “memoria associativa”.
Per la seconda risposta il problema è un po’ più sottile. Quando scriviamo
`\usebibdata{eco2005nome}{url}`
otteniamo le espansioni successive
`\@nameuse{eco2005@url}
\eco2005nome@url
http://books.google.com/books?id=OV\_yAAAAMAAJ`
La questione è che non possiamo semplicemente scrivere
`\url|\usebibdata{eco2005nome}{url}|`
perché \url tratta ciò che viene dopo le sbarre quasi come \verb. Né possiamo usare il trucco
`\begingroup\edef\x{\endgroup\noexpand\url|\usebibdata{eco2005nome|}\x`
perché l’URL potrebbe contenere caratteri speciali che durante l’espansione completa darebbero problemi. Perciò occorre un approccio indiretto. Con
`\toks@=\expandafter\expandafter\expandafter{\usebibdata{eco2005nome}{url}}`
abbiamo, espandendo il primo \expandafter,
`\toks@=\expandafter{\@nameuse{eco2005@url}}`
e, espandendo il secondo,
`\toks@={\eco2005nome@url}`
Adesso eseguiamo
`\toks@=\expandafter\expandafter\expandafter{\the\toks@}`
che dà, espandendo il primo \expandafter,
`\toks@=\expandafter{\eco2005nome@url}`
e, espandendo ancora,
`\toks@={http://books.google.com/books?id=OV\_yAAAAMAAJ}`
Siamo a buon punto: nel registro \toks@ c’è quello che vogliamo trattare. Adesso lo passiamo a \scantokens, che rileggerà tutto come se fosse tirato su da un file esterno, quindi riassegnando i codici di categoria:
`\scantokens\expandafter{\expandafter\url\expandafter|\the\toks@|\endinput}`
Siccome \scantokens vuole una graffa dopo di sé, espande ciò che vede subito dopo, cioè \expandafter, che causa l’espansione del successivo \expandafter che causa l’espansione del successivo che a sua volta causa l’espansione di \the:
`\scantokens\expandafter{\expandafter\url\expandafter|\the\toks@|\endinput}`
Otteniamo dunque
`\scantokens{\url|http://books.google.com/books?id=OV\_yAAAAMAAJ|\endinput}`
che è come se avessimo scritto direttamente
`\url|http://books.google.com/books?id=OV\_yAAAAMAAJ|`
(l’istruzione \endinput serve per evitare di vedere la riga vuota che TeX aggiunge internamente ai file che richiama con \input e \scantokens è una forma speciale di \input).Le tre righe che cominciano con \toks@ potrebbero essere sostituite con
`\toks@=\expandafter…\expandafter{\usebibdata{#1}{url}`
dove … sta per un numero piuttosto elevato di \expandafter. Meglio fare un passo alla volta.Ciao
Enrico
-
23 Giugno 2011 alle 22:12 #59900
-
25 Giugno 2011 alle 9:24 #59901::
Aggiungo il codice per \usebibdataurl necessario se si usa hyperref, che è diverso dal precedente:
`\def\usebibdataurl#1{%
\scantokens{\url{\usebibdata{#1}{url}}\endinput}}`
Ciao
EnricoAdesso invece riporto una nuova versione del codice; se si carica hyperref il codice va dopo.
`\usepackage{keyval}
\makeatletter%%% Definizione delle variabili
\define@key{reuse}{currentkind}{\def\@tempa{#1}}
\define@key{reuse}{currententry}{\def\reuse@current{#1}}
\def\define@reuse@key#1{%
\define@key{reuse}{#1}{\global\@namedef{reuse@\reuse@current @#1}{##1}}}
\define@reuse@key{title}
\define@reuse@key{isbn}
\define@reuse@key{url}
\define@reuse@key{year}
\define@reuse@key{note}%%% La macro sostituita a @book, @article, eccetera
\def\reuse@find#1#{%
\lowercase{\edef\@tempa{\zap@space#1 \@empty}}%
\ifcsname reuse@type@\@tempa\endcsname
\expandafter\@gobble
\else
\begingroup\makeatother
\expandafter\reuse@extract
\fi}
\let\reuse@type@preamble\@empty
\let\reuse@type@string\@empty%%% la macro per estrarre i valori
\def\reuse@extract#1{\setkeys{reuse}{currententry=#1}\endgroup}%%% I due tipi da ignorare: @preamble e @string
\let\reuse@type@preamble\@empty
\let\reuse@type@string\@empty%%% La macro per gestire gli errori
\def\reuse@error#1#2{%
\PackageError{reuse}
{Undefined key `#1' or empty value for `#2'}
{The key you used is wrong or the value to `#2' has not been set}}%%% Le quattro macro a livello utente
\newcommand\newbibdata#1{\define@reuse@key{#1}}\def\usebibdata#1#2{\@ifundefined{reuse@#1@#2}
{\reuse@error{#1}{#2}}
{\@nameuse{reuse@#1@#2}}}\def\usebibdataurl#1{\@ifundefined{reuse@#1@#2}
{\reuse@error{#1}{url}}
{\@usebibdataurl{#1}}}\@ifpackageloaded{hyperref}{\@tempswatrue}{\@tempswafalse}
\if@tempswa
\def\@usebibdataurl#1{%
\scantokens{\url{\usebibdata{#1}{url}}\endinput}}
\else
\newcommand{\@usebibdataurl}[2][|]{%
\toks@=\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter{\usebibdata{#1}{url}}
\scantokens\expandafter{%
\expandafter\url\expandafter#1\the\toks@#1\endinput}}
\fi\newcommand{\bibinput}[1]{%
\begingroup
\catcode`\%=12
\let\KV@err=\@gobble
\let\KV@errx=\@gobble
\let\XKV@err=\@gobble
\begingroup\lccode`\~=`\@
\lowercase{\endgroup\let~}\reuse@find
\catcode`\@=\active \input{#1.bib}\endgroup}\makeatother`
Alla fine ho deciso per i quindici \expandafter. 🙂Ciao
Enrico
-
7 Luglio 2011 alle 19:07 #59902
-
18 Marzo 2012 alle 13:08 #59903
-
-
AutoreRisposte
- Devi essere connesso per rispondere a questo topic.