- Questo topic ha 10 risposte, 4 partecipanti ed è stato aggiornato l'ultima volta 13 anni, 10 mesi fa da
franen.
-
CreatoreTopic
-
30 Ottobre 2012 alle 11:55 #80167::
Trovandomi di fronte ad un indica analitico piuttosto corposo (diciamo sulla ventina di pagine) mi era venuta l’idea di inserire nell’indice generale non solo la pagina iniziale ma anche quelle relative a gruppi di voci (ad esempio A-C, D-E, F-H eccetera). In questo modo la ricerca sarebbe facilitata, soprattutto adoperando i riferimenti incrociati nel file pdf.L’unico modo che ho trovato è quello di modificare manualmente il file .ind prodotto da makeindex inserendo qualcosa come
`
\phantomsection
\addcontentsline{toc}{section}{A-C}
`nei punti opportuni. Il metodo funziona (come si vede dall’immagine allegata), ma ovviamente è scomodissimo perché richiede di apportare modifiche manuali ad un file che poi viene riscritto da makeindex. Esiste un modo per automatizzare il procedimento?
Avrei voluto studiarmi bene come si creano i file .ist, ma non sono stato capace di trovare un documento che spieghi come fare e elenchi le opzioni disponibili. Qualcuno potrebbe aiutarmi e indicarmi dove reperirlo?
(Se può essere utile il mio libro fa uso della classe memoir)
Attachments:
You must be logged in to view attached files. -
CreatoreTopic
-
AutoreRisposte
-
-
30 Ottobre 2012 alle 12:05 #80168::
davidemania” post=79352Trovandomi di fronte ad un indica analitico piuttosto corposo (diciamo sulla ventina di pagine) mi era venuta l’idea di inserire nell’indice generale non solo la pagina iniziale ma anche quelle relative a gruppi di voci (ad esempio A-C, D-E, F-H eccetera). In questo modo la ricerca sarebbe facilitata, soprattutto adoperando i riferimenti incrociati nel file pdf.
L’unico modo che ho trovato è quello di modificare manualmente il file .ind prodotto da makeindex inserendo qualcosa come
`
\phantomsection
\addcontentsline{toc}{section}{A-C}
`nei punti opportuni. Il metodo funziona (come si vede dall’immagine allegata), ma ovviamente è scomodissimo perché richiede di apportare modifiche manuali ad un file che poi viene riscritto da makeindex. Esiste un modo per automatizzare il procedimento?
Avrei voluto studiarmi bene come si creano i file .ist, ma non sono stato capace di trovare un documento che spieghi come fare e elenchi le opzioni disponibili. Qualcuno potrebbe aiutarmi e indicarmi dove reperirlo?
(Se può essere utile il mio libro fa uso della classe memoir)
Confondi indice con segnalibri; nell’indice (generale) non metterei mai e poi mai questi riferimenti.
Non vedo come si possa automatizzare questa scelta arbitraria di gruppi di voci. Ma non dovrebbe essere difficile aggiungere un bookmark per ogni lettera. Ci penso.
Ciao
Enrico
-
30 Ottobre 2012 alle 12:12 #80169::
egreg9″ post=79353
Confondi indice con segnalibri; nell’indice (generale) non metterei mai e poi mai questi riferimenti.
Non vedo come si possa automatizzare questa scelta arbitraria di gruppi di voci. Ma non dovrebbe essere difficile aggiungere un bookmark per ogni lettera. Ci penso.
sui segnalibri hai ragione, non ho usato il termine giusto. L’aggiunta di un bookmark è facile, ma il problema è (ovviamente) che deve andare nel file .ind
intanto grazie
Davide
-
1 Novembre 2012 alle 7:43 #80170::
ho risolto il problema facendo un giro un po’ largo. In sostanza ho scritto un programmino (in c++ perché lo conosco, ma andrebbe ugualmente bene un altro linguaggio) che manipola il file .ind prodotto da makeindex inserendo i comandi per creare i bookmark di hyperref per il pdf.nel file .sty ho inserito questi comandi (ok il mio latex fa schifo, ma soprassediamo)
`
headings_flag 1
heading_prefix “\\vspace\{-6pt\}\\parbox\{\\columnwidth\}\{\\hspace\{0\\columnwidth\}\\centering\{\\normalsize — \\textbf\{”
heading_suffix “\} –\}\}\\vspace\{3pt\}\\nopagebreak\n\%bookmark\n”
`il codice del programma c++ è questo:
`
#include
#include
#includeusing namespace std;
const string bookmarks[] = {“A-C”, “D-F”, “G-I”, “J-L”,
“M-O”, “P-R”, “S-U”, “V-X”, “Y-Z”};const string token(“– \\textbf{“);
int main(int argc, char *argv[])
{
if(argc==1)
{
cout << "error: input file not specified"; return 1; } ifstream inputFile; ofstream outputFile; string inputFileName(argv[1]); string outputFileName("temp.txt"); inputFile.open(inputFileName.c_str(), ios::in); if(inputFile.is_open()) { cout << inputFileName << " opened for reading\n"; } else { cout << "failed to open " + inputFileName; return 1; } outputFile.open(outputFileName.c_str(), ios::out); if(outputFile.is_open()) { cout << "temporary file opened for reading\n"; } else { cout << "failed to open " + outputFileName; return 1; } string currentLine; char buffer[1024]; int lines=0; bool changeNextLine = false; bool changeThisLine = false; size_t found; int bookPos; while(!inputFile.eof()) { changeThisLine = changeNextLine; changeNextLine = false; inputFile.getline(buffer, 1024); currentLine = buffer; found = currentLine.find(token); if(found!=string::npos) { int pos = int(found)+token.length(); char letter = currentLine[pos]; if((letter-'A')%3 == 0) { bookPos = (letter-'A')/3; cout << "Found letter " << letter << endl; changeNextLine = true; } } outputFile << buffer << endl; if(changeThisLine) { outputFile << "\\phantomsection\n"; outputFile << "\\pdfbookmark[1]{" << bookmarks[bookPos] << "}" << "{indexbookmark" << bookmarks[bookPos][0] << "}\n"; } lines++; } inputFile.close(); outputFile.close(); remove(inputFileName.c_str()); rename(outputFileName.c_str(), inputFileName.c_str()); cout << inputFileName << " succesfully modified\n"; cout << lines << " lines processed\n"; return EXIT_SUCCESS; } ` dopo la sua esecuzione il file .ind diventa questo (ad esempio) ` \begin{theindex} \vspace{-6pt}\parbox{\columnwidth}{\hspace{0\columnwidth}\centering{\normalsize -- \textbf{A} --}}\vspace{3pt}\nopagebreak %bookmark \phantomsection \pdfbookmark[1]{A-C}{indexbookmarkA}` Praticamente cerca le righe nelle quali c'è una delle lettere di intestazione e una volta ogni tre aggiunge un bookmark. Il programma andrebbe richiamato dopo makeindex, passandogli come parametro il file .ind da questo ottenuto. Per automatizzare (uso TexnicCenter) ho copiato l'eseguibile del mio programma in "C:\Program Files" (ma qualsiasi posto va bene) e poi impostato il preprocessor di TexnicCenter in modo che lo richiami ogni volta prima di invocare Latex. L'immagine allegata mostra l'impostazione. [attachment=500]proprocessore.png[/attachment] In questo modo l'indice generale rimane pulito, mentre nel pdf si vedono i riferimenti che tutto sommato sono utili, e il procedimento funziona senza pensarci ogni volta che si compila il documento. [attachment=499]acrobat.png[/attachment] il programmino è fatto velocemente, non fornisce i risultati corretti se manca qualche lettera (ad esempio se nessuna voce comincia per "D" il segnalibro "D-F" non viene inserito... volendo comunque ci si mette poco a perfezionarlo. ciao DavideAttachments:
You must be logged in to view attached files. -
1 Novembre 2012 alle 9:10 #80171::
una piccola aggiunta, viene inserito un commento all’inizio per permettere al programma di sapere se il file è già stato modificato, nel qual caso esce senza far nulla`
#include
#include
#includeusing namespace std;
const string bookmarks[] = {“A-C”, “D-F”, “G-I”, “J-L”,
“M-O”, “P-R”, “S-U”, “V-X”, “Y-Z”};const string token(“– \\textbf{“);
const string modifiedMark = “%makebookmark”;int main(int argc, char *argv[])
{
if(argc==1)
{
cout << "error: input file not specified"; return 1; } ifstream inputFile; ofstream outputFile; string inputFileName(argv[1]); string outputFileName("temp.txt"); inputFile.open(inputFileName.c_str(), ios::in); if(inputFile.is_open()) { cout << inputFileName << " opened for reading\n"; } else { cout << "failed to open " + inputFileName; return 1; } outputFile.open(outputFileName.c_str(), ios::out); if(outputFile.is_open()) { cout << "temporary file opened for reading\n"; } else { cout << "failed to open " + outputFileName; return 1; } string currentLine; char buffer[1024]; int lines=0; bool changeNextLine = false; bool changeThisLine = false; size_t found; int bookPos; outputFile << modifiedMark << "\n"; while(!inputFile.eof()) { changeThisLine = changeNextLine; changeNextLine = false; inputFile.getline(buffer, 1024); currentLine = buffer; if(currentLine == modifiedMark) // file has been already processed { cout << "Index file already processed, skipping\n"; return 0; } found = currentLine.find(token); if(found!=string::npos) { int pos = int(found)+token.length(); char letter = currentLine[pos]; if((letter-'A')%3 == 0) { bookPos = (letter-'A')/3; cout << "Found letter " << letter << endl; changeNextLine = true; } } outputFile << buffer << endl; if(changeThisLine) { outputFile << "\\phantomsection\n"; outputFile << "\\pdfbookmark[1]{" << bookmarks[bookPos] << "}" << "{indexbookmark" << bookmarks[bookPos][0] << "}\n"; } lines++; } inputFile.close(); outputFile.close(); remove(inputFileName.c_str()); rename(outputFileName.c_str(), inputFileName.c_str()); cout << inputFileName << " succesfully modified\n"; cout << lines << " lines processed\n"; return EXIT_SUCCESS; } ` -
1 Novembre 2012 alle 10:51 #80172::
Con xindy una cosa del genere funziona (Non per fare i gruppi A-C, solo per inserire un segnalibro per ogni lettera!)`\documentclass{book}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{imakeidx}
\newcommand*{\lettergroupDefault}[1]{}
\newcommand*\lettergroup[1]{
\par\textbf{#1}\par
\pdfbookmark[1]{#1}{name-#1}
\nopagebreak
}
\makeindex[program=xindy]
\usepackage{hyperref}\begin{document}
Ciao
\index{Albatros}
\index{Èremo}
\index{Saltimbanco}\printindex
\end{document}`
Ma con due compilazioni… (perché?)
Fran
-
1 Novembre 2012 alle 11:13 #80173
-
1 Novembre 2012 alle 13:19 #80174
-
5 Novembre 2012 alle 10:54 #80175::
Ho approfittato di questo topic per rispolverare un po’ di LaTeX3. Propongo una soluzione che funziona (per quanto ho potuto sperimentare). Necessita di due compilazioni perché usa hyperref e non il pacchetto bookmark per creare i segnalibri. Spero che le spiegazioni nel codice siano abbastanza chiare.
Se qualcuno volesse dare consigli sulla struttura del codice, sarei felice.
Riporto file .te x e .ist.Fran
.tex:`\documentclass{book}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[italian]{babel}
\usepackage{xparse}
\usepackage{expl3}\ExplSyntaxOn
% creo una \seq avendo cura di accertarmi che sia vuota.
%In questa sequenza inserirò tutti i segnalibri
% man mano che verranno creati
\NewDocumentCommand{\createlists}{}{
\seq_clear_new:N \g_indexbkm_seq
% creo una \tl che conterrà il testo dei segnalibri
\tl_gclear_new:N \g_bkmtext_tl
% e una \tl che conterrà il testo dell'ultimo segnalibro creato
\tl_gclear_new:N \g_lastused_bkm_tl
}
% creo la funzione che inserisce i segnalibri nell'indice
\cs_new:Npn \create_bkm:n #1 { % l'unico argomento è l'argomento di \indexgroup (vedere il file .ist)
% estraggo da \lista_bkm il testo che il segnalibro deve mostrare,
% in funzione della lettera (cioè se ho la lettera B il segnalibro deve essere A-C).
% Inserisco questo testo nella tl \g_bkmtext_tl
\prop_get:NnN \lista_bkm {#1} \g_bkmtext_tl
% poi vedo qual è l'ultimo elemento di \g_indexbkm_seq,
% cioè l'ultimo segnalibro inserito e lo associo a \g_lastused_bkm_tl
\seq_get_right:NN \g_indexbkm_seq \g_lastused_bkm_tl
% se \g_lastused_bkm_tl e \g_bkmtext_tl sono uguali vuol dire
% che ho già inserito il segnalibro, altrimenti inserisco il segnalibro con \pdfbookmark
\tl_if_eq:NNTF \g_bkmtext_tl \g_lastused_bkm_tl {\scan_stop:} {
\pdfbookmark[1]{\tl_use:N \g_bkmtext_tl}{name-\g_bkmtext_tl}}
% inserisco il segnalibro appena creato nella \g_indexbkm_seq
\seq_put_right:Nx \g_indexbkm_seq { \g_bkmtext_tl }
}
% qui sotto la prop list con lettere e segnalibri associati.
\prop_new:N \lista_bkm
\prop_put:Nnn \lista_bkm {Numbers}{Numbers}
\prop_put:Nnn \lista_bkm {Numeri}{Numeri}
\prop_put:Nnn \lista_bkm {Symbols}{Symbols}
\prop_put:Nnn \lista_bkm {Simboli}{Simboli}
%%%%% la gestione di queste prime 4 voci è da ottimizzare%%%%
\prop_put:Nnn \lista_bkm {A}{A-C}
\prop_put:Nnn \lista_bkm {B}{A-C}
\prop_put:Nnn \lista_bkm {C}{A-C}
\prop_put:Nnn \lista_bkm {D}{D-F}
\prop_put:Nnn \lista_bkm {E}{D-F}
\prop_put:Nnn \lista_bkm {F}{D-F}
\prop_put:Nnn \lista_bkm {G}{G-I}
\prop_put:Nnn \lista_bkm {H}{G-I}
\prop_put:Nnn \lista_bkm {I}{G-I}
\prop_put:Nnn \lista_bkm {J}{J-L}
\prop_put:Nnn \lista_bkm {K}{J-L}
\prop_put:Nnn \lista_bkm {L}{J-L}
\prop_put:Nnn \lista_bkm {M}{M-O}
\prop_put:Nnn \lista_bkm {N}{M-O}
\prop_put:Nnn \lista_bkm {O}{M-O}
\prop_put:Nnn \lista_bkm {P}{P-R}
\prop_put:Nnn \lista_bkm {Q}{P-R}
\prop_put:Nnn \lista_bkm {R}{P-R}
\prop_put:Nnn \lista_bkm {S}{S-U}
\prop_put:Nnn \lista_bkm {T}{S-U}
\prop_put:Nnn \lista_bkm {U}{S-U}
\prop_put:Nnn \lista_bkm {V}{V-X}
\prop_put:Nnn \lista_bkm {W}{V-X}
\prop_put:Nnn \lista_bkm {X}{V-X}
\prop_put:Nnn \lista_bkm {Y}{Y-Z}
\prop_put:Nnn \lista_bkm {Z}{Y-Z}
% la funzione richiamata in stile.ist
\NewDocumentCommand{\insertmybookmark}{m}{%
\create_bkm:n {#1}
}
\ExplSyntaxOff\usepackage{imakeidx}
\makeindex[options= -s stile.ist]
\usepackage{hyperref}\begin{document}
Ciao
\index{Albatros}
\index{Burgundi}
\index{Èremo}
\index{Saltimbanco}
\index{Seppia}
\index{Toro}
\printindex
\end{document}` stile.ist:`% stile.ist
preamble ”
\\begin{theindex}
\\createlists
\\providecommand*\\indexgroup[1]{\\indexspace
\\item \\textbf{#1}\\insertmybookmark{#1}\\nopagebreak}
”postamble “\n\n\\end{theindex}\n”
group_skip ” %\n \\indexspace\n %\n”
headings_flag 1
heading_prefix ” %\n \\indexgroup{”
heading_suffix “}\n %\n”numhead_positive “Numbers”;
numhead_negative “Numbers”;
symhead_positive “Symbols”;
symhead_negative “Symbols”;`Edit: tolto dal codice un messaggio di errore che mi serviva per il debug.
-
5 Novembre 2012 alle 16:57 #80176::
Mi pare buono, anche se non sono del tutto convinto dell’uso della sequence.Difetti
1. Non usi prefissi per le tue variabili e funzioni; ci vogliono
2. La prima istruzione deve essere [tt]\seq_gclear_new:N[/tt]
3. L’ultima è, meglio, [tt]\seq_gput_right:NV \g_indexbkm_seq \g_bkmtext_tl[/tt] (aggiungi i prefissi, mi raccomando)Attento, però, che [tt]\seq_get_right:NN[/tt] assegna il valore alla variabile solo localmente. Quindi dovrai allocare [tt]\l_franen_lastused_bkm_tl[/tt] invece che [tt]\g_…[/tt] e cambiare di conseguenza il codice. Se proprio vuoi un’assegnazione globale devi farla in due passi:
`\seq_get_right:NN \g_franen_indexbkm_seq \l_franen_lastused_bkm_tl
\tl_gset_eq:NN \g_franen_lastused_bkm_tl \l_franen_lastused_bkm_tl`
ma non ne vedo realmente il motivo.Ciao
Enrico
-
6 Novembre 2012 alle 6:25 #80177
-
-
AutoreRisposte
- Devi essere connesso per rispondere a questo topic.