Sezioni dell’indice analitico nella ToC generale

  • Creatore
    Topic
  • #80167
    Up
    0
    Down
    ::


    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.
Visualizzazione 9 filoni di risposte
  • Autore
    Risposte
    • #80168
      Up
      0
      Down
      ::

      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

    • #80169
      Up
      0
      Down
      ::

      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

    • #80170
      Up
      0
      Down
      ::


      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
      #include

      using 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 Davide

      Attachments:
      You must be logged in to view attached files.
    • #80171
      Up
      0
      Down
      ::


      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
      #include

      using 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; } `

    • #80172
      franen
      Partecipante
        Up
        0
        Down
        ::


        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

      • #80173
        OldClaudio
        Partecipante
          Up
          0
          Down
          ::


          Non ho capito a che cosa serva [tt]\hspace{0\columnwidth}[/tt]

          Se ti serve per passare in modo orizzontale ci sono altri sistemi più puliti che non uno spazio nullo (che comunque si scrive più comodamente con [tt]0pt[/tt]); per esempio [tt]\leavevmode[/tt].

        • #80174
          Up
          0
          Down
          ::


          ehm… non serve a niente 😳 infatti senza il risultato è identico. Dev’essere rimasto lì per errore dai tentativi precedenti.

        • #80175
          franen
          Partecipante
            Up
            0
            Down
            ::


            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.

          • #80176
            Up
            0
            Down
            ::


            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

          • #80177
            franen
            Partecipante
              Up
              0
              Down
              ::

              egreg9″ post=79506Mi pare buono, anche se non sono del tutto convinto dell’uso della sequence.

              Perché? Cosa sarebbe preferibile? Una clist?
              Grazie
              Fran

          Visualizzazione 9 filoni di risposte
          • Devi essere connesso per rispondere a questo topic.

          Go to top