%D \module %D [ file=strc-reg, %D version=2008.10.20, %D title=\CONTEXT\ Structure Macros, %D subtitle=Registers, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. \writestatus{loading}{ConTeXt Structure Macros / Registers} \registerctxluafile{strc-reg}{} \unprotect \startcontextdefinitioncode % todo: tag:: becomes rendering % todo: language, character, linked, location % todo: fonts etc at sublevels (already defined) % \starttext % \placeregister[index] % \chapter{a} \index{93} \index{456} \index{***} \index{*} \index{@} % test \index{aa} test \startregister[index][x]{bb} test \page test \page test \page test \stopregister[index][x] % test \index{aa} test \setregisterentry[index][label=x,entries=bb] test \page test \page test \page test \finishregisterentry[index][label=x] % test \index{aa} test \setregisterentry[index][label=y] test \page test \page test \page test \finishregisterentry[index][label=y,entries=yy] % \stoptext % \index {entry} % \index[key] {entry} % \index[pageclass::] {entry} % \index[pageclass::key]{entry} % \index {textclass::entry} % \index[key] {textclass::entry} % \index[pageclass::] {textclass::entry} % \index[pageclass::key]{textclass::entry} % tzt variant with n entries, parameters and userdata (altnum) \installcorenamespace{register} \installcommandhandler\??register {register} \??register \let\strc_registers_setup_saved\setupregister \unexpanded\def\setupregister % maybe we should drop the plural form {\dotripleempty\strc_registers_setup} \def\strc_registers_setup[#1][#2][#3]% {\ifthirdargument \def\strc_registers_setup_step##1{\strc_registers_setup_saved[#1:##1][#3]}% \processcommalist[#2]\strc_registers_setup_step \else\ifsecondargument \strc_registers_setup_saved[#1][#2]% \else \strc_registers_setup_saved[#1]% \fi\fi} \unexpanded\def\setupregisters {\dosingleempty\strc_registers_setup_root} \def\strc_registers_setup_root[#1]% {\strc_registers_setup_saved[#1]\relax} \setupregister [\c!n=2, \c!balance=\v!yes, % \v!no komt niet zo vaak voor \c!align=\v!flushleft, \c!tolerance=\v!stretch, \c!before=\blank, %\c!after=, %\c!symbol=, \c!compress=\v!no, \c!interaction=\v!pagenumber, \c!alternative=\v!a, \c!distance=\emwidth, \c!style=\v!bold, \c!pagestyle=\v!slanted, \c!indicator=\v!yes, \c!criterium=\v!all, \c!check=\v!yes, % check for weird see usage %\c!command=, \c!referencing=\v!on, \c!location=\v!middle, %\c!maxwidth=, \c!number=\v!no, \c!unknownreference=\v!empty, \c!prefix=\v!both, %\c!expansion=, %\c!xmlsetup=, \c!pagenumber=\v!yes, \c!pageprefixconnector=\endash, \c!pagesegments=2:2, \c!file=\jobname, %\c!deeptextcommand=, % undefined by default ! \c!method=, % no default as we have them in the module, maybe some day in lang-* \c!numberorder=\v!numbers, % \v!characters \s!language=\currentmainlanguage]% % yes or no shared ? \setupregister [\c!label=, \c!entries=, \c!alternative=] \definemixedcolumns [\v!register] [\c!n=\registerparameter\c!n, \c!balance=\registerparameter\c!balance, \c!align=\registerparameter\c!align, \c!tolerance=\registerparameter\c!tolerance] %D \starttyping %D \setupregister[index][1][textcolor=darkred] %D \setupregister[index][2][textcolor=darkgreen,textstyle=bold] %D %D \placeregister[index][n=1] \blank[3*big] %D %D test \index{test+one} test \index{test+two} more \index{more} %D \stoptyping \newconditional\c_strc_registers_defining \setnewconstant\c_strc_registers_maxlevel \plusfive \ifdefined\Word \else \unexpanded\def\Word#1{#1} \fi \appendtoks \ifconditional\c_strc_registers_defining \else % todo: dosingle ... \settrue\c_strc_registers_defining \definemixedcolumns[\currentregister][\v!register]% first as otherwise it overloads start/stop \clf_defineregister{\currentregister}{\registerparameter\c!referencemethod}% \normalexpanded{\presetheadtext[\currentregister=\Word{\currentregister}]}% \setuevalue{\currentregister}{\dodoubleempty\strc_registers_insert_entry[\currentregister]}% \setuevalue{\e!see\currentregister}{\dodoubleempty\strc_registers_insert_see[\currentregister]}% %setuevalue{\e!coupled\currentregister}{\dolinkedregister{\currentregister}}% % historic ballast \setuevalue{\e!place\currentregister}{\placeregister[\currentregister]}% \setuevalue{\e!complete\currentregister}{\completeregister[\currentregister]}% \setuevalue{\e!setup\currentregister\e!endsetup}{\setupregister[\currentregister]}% \dorecurse\c_strc_registers_maxlevel{% weird, expanded should not be needed \normalexpanded{\defineregister[\currentregister:\recurselevel][\currentregister]}% %\defineregister[\currentregister:\recurselevel][\currentregister]% \letregisterparameter{\c!entries:\recurselevel}\empty % needed as we use detokenize (ok, we can \letregisterparameter{\c!keys :\recurselevel}\empty % avoid it, but it's faster too) }% % \setfalse\c_strc_registers_defining \fi \to \everydefineregister \appendtoks \clf_setregistermethod{\currentregister}{\registerparameter\c!referencemethod}% \to \everysetupregister %D Registering: \glet\currentregistername \empty \glet\currentregisternumber\!!zerocount \def\strc_registers_register_page_entry {\iftrialtypesetting \expandafter\gobblethreearguments \else \expandafter\strc_registers_register_page_entry_indeed \fi} \def\strc_registers_register_page_expand_xml_entries {\xmlstartraw \xdef\currentregisterentriesa{\registerparameter{\c!entries:1}}% \xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}% \xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}% \xmlstopraw \glet\currentregistercoding\s!xml} \def\strc_registers_register_page_expand_yes_entries {\xdef\currentregisterentriesa{\registerparameter{\c!entries:1}}% \xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}% \xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}% \glet\currentregistercoding\s!tex} \def\strc_registers_register_page_expand_nop_entries {\xdef\currentregisterentriesa{\detokenizedregisterparameter{\c!entries:1}}% \xdef\currentregisterentriesb{\detokenizedregisterparameter{\c!entries:2}}% \xdef\currentregisterentriesc{\detokenizedregisterparameter{\c!entries:3}}% \glet\currentregistercoding\s!tex} \def\strc_registers_register_page_expand_xml {\xmlstartraw \xdef\currentregisterentries{\registerparameter\c!entries}% \xmlstopraw \glet\currentregistercoding\s!xml} \def\strc_registers_register_page_expand_yes {\xdef\currentregisterentries{\registerparameter\c!entries}% \glet\currentregistercoding\s!tex} \def\strc_registers_register_page_expand_nop {\xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}% \glet\currentregistercoding\s!tex} \def\strc_registers_register_page_expand_xml_keys {\xmlstartraw \xdef\currentregisterkeysa{\registerparameter{\c!keys:1}}% \xdef\currentregisterkeysb{\registerparameter{\c!keys:2}}% \xdef\currentregisterkeysc{\registerparameter{\c!keys:3}}% \xmlstopraw} \def\strc_registers_register_page_expand_yes_keys {\xdef\currentregisterkeysa{\registerparameter{\c!keys:1}}% \xdef\currentregisterkeysb{\registerparameter{\c!keys:2}}% \xdef\currentregisterkeysc{\registerparameter{\c!keys:3}}} \def\strc_registers_register_page_entry_indeed#1#2#3% register data userdata {\begingroup \edef\currentregister{#1}% %\setupcurrentregister[\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]% \setupcurrentregister[#2]% \edef\currentregisterlabel {\registerparameter\c!label}% \edef\currentregisterexpansion{\registerparameter\c!expansion}% \edef\currentregisterownnumber{\registerparameter\c!ownnumber}% \xdef\currentregisterkeys {\registerparameter\c!keys}% \xdef\currentregisterentries {\registerparameter\c!entries}% \xdef\currentregisterxmlsetup {\registerparameter\c!xmlsetup}% \ifx\currentregisterentries\empty \ifx\currentregisterexpansion\s!xml \strc_registers_register_page_expand_xml_entries \else\ifx\currentregisterexpansion\v!yes \strc_registers_register_page_expand_yes_entries \else \strc_registers_register_page_expand_nop_entries \fi\fi \else \ifx\currentregisterexpansion\s!xml \strc_registers_register_page_expand_xml \else\ifx\currentregisterexpansion\v!yes \strc_registers_register_page_expand_yes \else \strc_registers_register_page_expand_nop \fi\fi \fi \ifx\currentregisterkeys\empty \ifx\currentregistercoding\s!xml \strc_registers_register_page_expand_xml_keys \else \strc_registers_register_page_expand_yes_keys \fi \fi \setnextinternalreference % we could consider storing register entries in a list which we % could then sort \glet\currentregistername\currentregister \xdef\currentregisternumber{\clf_storeregister % 'own' should not be in metadata metadata {% name {\currentregister}% coding {\currentregistercoding}% \ifx\currentregisterownnumber\v!yes own {\registerparameter\c!alternative}% can be used instead of pagenumber \fi \ifx\currentreferencecoding\s!xml xmlroot {\xmldocument} % only useful when text \fi \ifx\currentregisterxmlsetup\empty \else xmlsetup {\currentregisterxmlsetup}% \fi }% references {% \ifx\currentregisterlabel\empty \else label {\currentregisterlabel}% \fi % view {\interactionparameter\c!focus}% }% entries {% % we need a special one for xml, this is just a single one \ifx\currentregisterentries\empty entries { {\currentregisterentriesa}% {\currentregisterentriesb}% {\currentregisterentriesc}% } \else entry {\currentregisterentries}% \fi \ifx\currentregisterkeys\empty keys { {\currentregisterkeysa}% {\currentregisterkeysb}% {\currentregisterkeysc}% } \else key {\currentregisterkeys}% \fi }% userdata {\detokenize\expandafter{\normalexpanded{#3}}} }% \clf_setinternalreference internal \locationcount view {\interactionparameter\c!focus}% \relax % this will change \ifx\currentregisterownnumber\v!yes \glet\currentregistersynchronize\relax \else \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\currentregisternumber}% \fi \currentregistersynchronize % here? % needs thinking ... bla\index{bla}. will break before the . but adding a % penalty is also no solution \dostarttagged\t!registerlocation\currentregister \attribute\destinationattribute\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup \dotagregisterlocation \dostoptagged \endgroup} \unexpanded\def\dosetfastregisterentry#1#2#3#4#5% register entry key processor processor {\begingroup \edef\currentregister{#1}% \setnextinternalreference \glet\currentregistername\currentregister \xdef\currentregisternumber{\clf_storeregister {% metadata {% name {\currentregister}% } entries {% entry {#2}% key {#3}% }% processors {% entry {#4}% page {#5}% }% }% }% % overlap with the above % \clf_setinternalreference % internal \locationcount % view {\interactionparameter\c!focus}% \relax % this will change \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\currentregisternumber}% \currentregistersynchronize % here? \dostarttagged\t!registerlocation\currentregister \attribute\destinationattribute\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup \dotagregisterlocation \dostoptagged \endgroup} \let\dotagregisterlocation\relax % experiment \unexpanded\def\strc_registers_insert_entry[#1][#2]% {\def\currentregister{#1}% \edef\p_ownnumber{\registerparameter\c!ownnumber}% \ifx\p_ownnumber\v!yes \expandafter\strc_registers_insert_entry_yes \else \expandafter\strc_registers_insert_entry_nop \fi{#2}} % \def\strc_registers_insert_entry_nop#1#2% % {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}} % % \def\strc_registers_insert_entry_yes#1#2#3% % {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}} % % less tokens passed (nicer for tracing) .. could become installable \def\strc_registers_insert_entry_nop {\ifvmode \expandafter\strc_registers_insert_entry_nop_par \else \expandafter\strc_registers_insert_entry_nop_txt \fi} \def\strc_registers_insert_entry_yes {\ifvmode \expandafter\strc_registers_insert_entry_yes_par \else \expandafter\strc_registers_insert_entry_yes_txt \fi} \def\strc_registers_insert_entry_nop_par#1#2% {\flushatnextpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}} \def\strc_registers_insert_entry_yes_par#1#2#3% {\flushatnextpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}} \def\strc_registers_insert_entry_nop_txt#1#2% {\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}} \def\strc_registers_insert_entry_yes_txt#1#2#3% {\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}} \unexpanded\def\startregister{\doquadrupleempty\strc_registers_start_entry} \unexpanded\def\stopregister {\dodoubleargument\strc_registers_stop_entry} % a synonym, so that we can nest with overlap without syntax check problems \let\openregisterrange \startregister \let\closeregisterrange\stopregister \def\strc_registers_start_entry[#1][#2][#3][#4]#5% {\iffourthargument % #1=register #2=tag #3=own #4=sortkey #5=entry \doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,\c!alternative=#3,\c!keys={#4},\c!entries={#5}}{}}% \else % #1=register #2=tag #3=sortkey #5=entry \doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,\c!keys={#3},\c!entries={#5}}{}}% \fi} \def\strc_registers_stop_entry[#1][#2]% {\normalexpanded{\ctxlatecommand{extendregister("#1","#2")}}} \def\setregisterentry {\dotripleempty\strc_registers_set_entry} \def\finishregisterentry{\dotripleempty\strc_registers_finish_entry} % not yet document, not sure if this will stay: \def\strc_registers_set_entry [#1][#2][#3]{\doflushatpar{\strc_registers_register_page_entry{#1}{#2}{#3}}} \def\strc_registers_finish_entry[#1][#2][#3]{\strc_registers_finish_entry_indeed{#1}{#2}{#3}} \def\strc_registers_finish_entry_indeed#1#2#3% register data userdata {\begingroup \edef\currentregister{#1}% \setupcurrentregister[\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]% todo: fast setter \edef\currentregisterlabel {\registerparameter\c!label}% \edef\currentregisterexpansion{\registerparameter\c!expansion}% \edef\currentregisterownnumber{\registerparameter\c!ownnumber}% \xdef\currentregisterkeys {\registerparameter\c!keys}% \ifx\currentregisterexpansion\s!xml \xmlstartraw \xdef\currentregisterentries{\registerparameter\c!entries}% \xmlstopraw \glet\currentregistercoding\s!xml \else \ifx\currentregisterexpansion\v!yes \xdef\currentregisterentries{\registerparameter\c!entries}% \else \xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}% \fi \glet\currentregistercoding\s!tex \fi % I hate this kind of mess ... but it's a user request. \ifx\currentregisterentries\empty \normalexpanded{\ctxcommand{extendregister("\currentregister","\currentregisterlabel", { metadata = { \ifx\currentregisterownnumber\v!yes own = "\registerparameter\c!alternative", % can be used instead of pagenumber \fi }, userdata = \!!bs\detokenize{#3}\!!es })% }}% \else \normalexpanded{\ctxcommand{extendregister("\currentregister","\currentregisterlabel", { metadata = { % catcodes = \the\catcodetable, coding = "\currentregistercoding", \ifx\currentregisterownnumber\v!yes own = "\registerparameter\c!alternative", % can be used instead of pagenumber \fi }, entries = { % we need a special one for xml, this is just a single one \!!bs\currentregisterentries\!!es, \!!bs\currentregisterkeys\!!es }, userdata = \!!bs\detokenize{#3}\!!es }) }}% \fi \endgroup} % The following variants are meant for (for instance xml). There is some % overlap with previously defined macros. % % \starttext % \setstructurepageregister[index][entries=alpha]a % \setstructurepageregister[index][entries=gamma]g % \setstructurepageregister[index][entries=beta]b % \setstructurepageregister[index][entries:1=alpha,keys:1=z]a % \setstructurepageregister[index][entries:1=gamma,keys:1=x]g % \setstructurepageregister[index][entries:1=beta, keys:1=y]b % \index{alpha}a % \index{gamma}g % \index{beta}b % \placeregister[index][n=1] % \stoptext % some overlap with previous \unexpanded\def\setstructurepageregister {\dotripleempty\strc_registers_set} \def\strc_registers_set[#1][#2][#3]% [register][settings][userdata] {\doflushatpar{\strc_registers_register_page_entry{#1}{#2}{#3}}} \unexpanded\def\startstructurepageregister{\doquadrupleempty\strc_registers_start} \unexpanded\def\stopstructurepageregister {\dodoubleargument\strc_registers_stop} \let\openstructurepageregisterrange \startstructurepageregister \let\closestructurepageregisterrange\stopstructurepageregister \def\strc_registers_start[#1][#2][#3][#4]% [register][tag][settings][userdata] {\doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,#3}{#4}}} \def\strc_registers_stop[#1][#2]% {\normalexpanded{\ctxlatecommand{structures.registers.extend("#1","#2")}}} % So far. \unexpanded\def\strc_registers_insert_see[#1][#2]#3#4% {\doflushatpar{\strc_registers_insert_see_indeed{#1}{#2}{#3}{#4}}} \def\strc_registers_insert_see_indeed#1#2#3#4% register key entry seeword {\begingroup \edef\currentregister{#1}% \edef\currentregisterexpansion{\registerparameter\c!expansion}% \ifx\currentregisterexpansion\s!xml \xmlstartraw \xdef\currentregisterentries{\detokenize{#3}}% not ok yet \xdef\currentregisterseeword{\detokenize{#4}}% not ok yet \xmlstopraw \glet\currentregistercoding\s!xml \else \ifx\currentregisterexpansion\v!yes \xdef\currentregisterentries{#3}% not ok yet \xdef\currentregisterseeword{#4}% not ok yet \else \xdef\currentregisterentries{\detokenize{#3}}% not ok yet \xdef\currentregisterseeword{\detokenize{#4}}% not ok yet \fi \glet\currentregistercoding\s!tex \fi \setnextinternalreference % we could consider storing register entries in list \edef\temp{\clf_storeregister{% \temp grabs the nofentries metadata {% kind {see}% name {\currentregister}% }% references {% % view {\interactionparameter\c!focus}% }% entries {% % we need a special one for xml, this is just a single one entry {\currentregisterentries}% key {#2}% }% seeword {% text {\currentregisterseeword}% }% }}% \clf_setinternalreference internal \locationcount view {\interactionparameter\c!focus}% \relax % this will change \dostarttagged\t!registerlocation\currentregister \attribute\destinationattribute\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup \dotagregisterlocation \dostoptagged \endgroup} %D Rendering: % todo: c!language ipv s!language \let\utilityregisterlength\!!zerocount \def\determineregistercharacteristics {\dodoubleempty\strc_registers_determine_characteristics} \def\strc_registers_determine_characteristics[#1][#2]% {\begingroup \setupregister[#1][#2]% \edef\currentregister{\firstinset{#1}}% \normalexpanded{\endgroup\noexpand\xdef\noexpand\utilityregisterlength{\clf_analyzeregister {\currentregister}% {% language {\registerparameter\s!language}% method {\registerparameter\c!method}% numberorder {\registerparameter\c!numberorder}% compress {\registerparameter\c!compress}% criterium {\registerparameter\c!criterium}% pagenumber \ifx\registerpageseparatorsymbol\empty false\else true\fi }% }}% \ifcase\utilityregisterlength\relax \resetsystemmode\v!register \else \setsystemmode \v!register \fi} \newtoks\everyplaceregister \appendtoks \dontcomplain \to \everyplaceregister \newconditional\c_strc_registers_text_interaction \unexpanded\def\placeregister {\dodoubleempty\strc_registers_place} \def\strc_registers_place[#1][#2]% {\iffirstargument \begingroup %\forgetall \setupregister[#1][#2]% can be a list \edef\currentregister{\firstinset{#1}}% \the\everyplaceregister \ifnum\namedmixedcolumnsparameter\currentregister\c!n>\plusone \startmixedcolumns[\currentregister] \strc_registers_place_indeed{#1}% \stopmixedcolumns \else \strc_registers_place_indeed{#1}% \fi \endgroup \fi} \def\strc_registers_place_indeed#1% {\doifelse{\registerparameter\c!interaction}\v!text \settrue\setfalse\c_strc_registers_text_interaction \clf_processregister {#1}% {% language {\registerparameter\s!language}% method {\registerparameter\c!method}% numberorder {\registerparameter\c!numberorder}% check {\registerparameter\c!check}% compress {\registerparameter\c!compress}% criterium {\registerparameter\c!criterium}% pagenumber \ifx\registerpageseparatorsymbol\empty false\else true\fi }{% separatorset {\registerparameter\c!pageprefixseparatorset}% conversionset {\registerparameter\c!pageprefixconversionset}% starter {\registerparameter\c!pageprefixstarter}% stopper {\registerparameter\c!pageprefixstopper}% set {\registerparameter\c!pageprefixset}% segments {\registerparameter\c!pageprefixsegments}% connector {\registerparameter\c!pageprefixconnector}% }{% prefix {\registerparameter\c!pageprefix}% separatorset {\registerparameter\c!pageseparatorset}% conversionset {\registerparameter\c!pageconversionset}% starter {\registerparameter\c!pagestarter}% stopper {\registerparameter\c!pagestopper}% segments {\registerparameter\c!pagesegments}% }% \relax} \def\strc_registers_limited_entry#1% {\limitatetext{#1}\currentregistermaxwidth\unknown}% \appendtoks \edef\currentregistermaxwidth{\registerparameter\c!maxwidth}% \ifx\currentregistermaxwidth\empty \let\limitedregisterentry\firstofoneargument \else \let\limitedregisterentry\strc_registers_limited_entry \fi \to \everyplaceregister \unexpanded\def\completeregister {\dodoubleempty\strc_registers_complete} \def\strc_registers_complete[#1][#2]% {\iffirstargument \begingroup \edef\currentregister{\firstinset{#1}}% \normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\currentregister}},reference=\currentregister]}% \placeregister[#1][#2]% \page[\v!yes]% \stopnamedsection \endgroup \fi} % test case for collapsing (experimental, for Steffen Wolfrum) % % \starttext % \placeregister[index][compress=no] \blank[2*big] % \placeregister[index][compress=yes] \blank[2*big] % \placeregister[index][compress=all] \page % \dorecurse{10}{test 1:!\index{test} test \page} % \dorecurse{5} {test 2:\recurselevel \page} % \dorecurse{10}{test 3:!\index{test} test \page} % \dorecurse{5} {test 4:\recurselevel \page} % \dorecurse{1} {test 5:!\index{test} test \page} % \dorecurse{5} {test 6:\recurselevel \page} % \dorecurse{10}{test 7:!\index{test} test \page} % \dorecurse{5} {test 8:\recurselevel \page} % oeps \index{oeps} % xxxx \index{xxxx} % todo \index{todo} % \stoptext %D Character rendering (sections): \installcorenamespace{registerindicator} \def\defaultregistercharacter#1% {\edef\currentregistercharacter{#1}% \ifx\currentregistercharacter\empty % skip \else\ifx\currentregistercharacter\s!unknown % skip \else \edef\p_indicator{\registerparameter\c!indicator}% \ifx\p_indicator\v!yes \strc_registers_place_character_yes \else \strc_registers_place_character_nop \fi \fi\fi} \def\strc_registers_place_character_yes {\expandnamespaceparameter\??registerindicator\registerparameter\c!alternative\v!a{\currentregistercharacter}} \def\strc_registers_place_character_nop {\registerparameter\c!before \goodbreak} % a = \def\strc_registers_indicator_a#1#2% {\registerparameter\c!before % bugged, why does leftskip gets set: \vskip\lineheight\goodbreak\vskip-\lineheight \typo_injectors_check_register \begingroup \useregisterstyleandcolor\c!style\c!color \dontleavehmode \typo_injectors_mark_register \strut \iflocation \dosetdirectpagereference{\currentregister:\v!section:#1}% \fi \registerparameter\c!command{#2}% \endgroup \blank[\v!samepage]% \registerparameter\c!after \par \nobreak} % b = \def\strc_registers_indicator_b#1#2% {\registerparameter\c!before \typo_injectors_check_register \begingroup \useregisterstyleandcolor\c!style\c!color \dontleavehmode \typo_injectors_mark_register \strut \iflocation \dosetdirectpagereference{\currentregister:\v!section:#1}% \fi \registerparameter\c!command{#2}% \endgroup \registerparameter\c!after \nobreak} \setvalue{\??registerindicator a}#1{\strc_registers_indicator_a{#1}{#1}} \setvalue{\??registerindicator A}#1{\strc_registers_indicator_a{#1}{\WORD{#1}}} \setvalue{\??registerindicator b}#1{\strc_registers_indicator_b{#1}{#1}} \setvalue{\??registerindicator B}#1{\strc_registers_indicator_b{#1}{\WORD{#1}}} %D The following macros are the interface to the rendering. These are %D generated by \LUA. This might change. % \showinjector % \setinjector[register][2][\column] % % \starttext % first \index{first} % second \index{second} % third \index{third} % fourth \index{fourth} % \placeregister[index] % \stoptext \doinstallinjector\s!register %D Beware, we get funny side effects when a dangling \index precedes an %D placeindex as then flushing takes place inside the index. Took me hours %D to notice that. \newconstant \c_strc_registers_page_state % 0=nothing 1=page 2=see \newdimen \d_strc_registers_distance \unexpanded\def\startregisteroutput {\endgraf \begingroup \d_strc_registers_distance\registerparameter\c!distance\relax \dostarttaggedchained\t!register\currentregister\??register \forgeteverypar \forgetparindent \forgetparskip} \unexpanded\def\stopregisteroutput {\endgraf \dostoptagged \endgroup} \newdimen\d_strc_registers_hangindent \newcount\c_strc_registers_hangafter \unexpanded\def\usenestedregisterstyleandcolor#1#2% will change {\useregisterstyleandcolor#1#2% % how about style \ifconditional\c_strc_registers_text_interaction \ifx\currentcolorparameter\empty \else \resetinteractionparameter\c!color \resetinteractionparameter\c!contrastcolor \fi \fi} \unexpanded\def\startregisterentries#1% depth {\endgraf \begingroup \scratchcounter\ifnum#1>\c_strc_registers_maxlevel\c_strc_registers_maxlevel\else#1\fi\relax \dostarttagged\t!registerentries\empty \let\savedcurrentregister\currentregister \edef\currentregister{\currentregister:\number\scratchcounter}% \usenestedregisterstyleandcolor\c!textstyle\c!textcolor \ifnum\scratchcounter>\plusone \advance\leftskip\d_strc_registers_distance\relax \fi \d_strc_registers_hangindent\registerparameter\c!distance\relax \c_strc_registers_hangafter \plusone \blank[\v!samepage]% \let\currentregister\savedcurrentregister} \unexpanded\def\stopregisterentries {\endgraf \dostoptagged \endgroup} \unexpanded\def\startregisterentry#1% todo: level {\typo_injectors_check_register \begingroup \dostarttagged\t!registerentry\empty \global\setconstant\c_strc_registers_page_state\zerocount \hangindent\d_strc_registers_hangindent \hangafter \c_strc_registers_hangafter \typo_injectors_mark_register} \unexpanded\def\stopregisterentry {\endgraf \global\setconstant\c_strc_registers_page_state\zerocount \dostoptagged \endgroup} \unexpanded\def\startregistersection#1% title {\dostarttagged\t!registersection\empty \dostarttagged\t!registertag\empty \registercharacter{#1}\endgraf \dostoptagged} \unexpanded\def\stopregistersection {\dostoptagged \endgraf} \unexpanded\def\startregisterpages {\begingroup \dostarttagged\t!registerpages\empty \useregisterstyleandcolor\c!pagestyle\c!pagecolor \registerparameter\c!pageleft} \unexpanded\def\stopregisterpages {\registerparameter\c!pageright \dostoptagged \endgroup} \unexpanded\def\startregisterseewords {\begingroup \dostarttagged\t!registerpage\empty \useregisterstyleandcolor\c!pagestyle\c!pagecolor} \unexpanded\def\stopregisterseewords {\dostoptagged \endgroup} \unexpanded\def\registerpageseparator % todo: , configurable {\ifcase\c_strc_registers_page_state \hskip\d_strc_registers_distance\relax \or \dostarttagged\t!registerseparator\empty \registerpageseparatorsymbol % page \dostoptagged \or \dostarttagged\t!registerseparator\empty \registerpageseparatorsymbol % see \dostoptagged \fi} \unexpanded\def\registeronepagerangeseparator {|\endash|} % todo use \prewordbreak % \unexpanded\def\withregisterpagecommand#1#2#3#4% % {\def\currentregisterpageindex{#2}% % \iflocation % \goto{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]% % \else % \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}% % \fi} \unexpanded\def\withregisterpagecommand#1#2#3#4% {\ifcase#3\relax {\tt [entry\space not\space flushed]}% \else \def\currentregisterpageindex{#2}% \iflocation \strc_references_goto_internal{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]% \else \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}% \fi \fi} \unexpanded\def\pushcurrentregister#1% {\let\m_current_register\currentregister \edef\currentregister{#1}} \unexpanded\def\popcurrentregister {\let\currentregister\m_current_register} \unexpanded\def\registeronepage#1#2#3#4#5% #1:class #2:processor content {\pushcurrentregister{#1}% \edef\p_pagenumber{\registerparameter\c!pagenumber}% \ifx\p_pagenumber\v!no\else \registerpageseparator \global\setconstant\c_strc_registers_page_state\plusone \dostarttagged\t!registerpage\empty \withregisterpagecommand{#2}{#3}{#4}{#5}% \dostoptagged \fi \popcurrentregister} \newconditional\c_strc_registers_following \appendtoks \edef\p_compress{\registerparameter\c!compress}% \ifx\p_compress\v!text \settrue\c_strc_registers_following \letregisterparameter\c!compress\v!yes \else \setfalse\c_strc_registers_following \fi \to \everyplaceregister \unexpanded\def\registerpagerange#1#2#3#4#5#6#7#8% #1:class #2:processor content, content todo: -- configurable {\pushcurrentregister{#1}% \edef\p_pagenumber{\registerparameter\c!pagenumber}% \ifx\p_pagenumber\v!no\else \registerpageseparator \global\setconstant\c_strc_registers_page_state\plusone \dostarttagged\t!registerpagerange\empty \dostarttagged\t!registerfrompage\empty \withregisterpagecommand{#2}{#3}{#4}{#5}% \dostoptagged \ifconditional\c_strc_registers_following \ifnum#3=\numexpr#6-1\relax \labeltext{following:\s!singular}% \else \labeltext{following:\s!plural}% \fi \else \registeronepagerangeseparator \dostarttagged\t!registertopage\empty \withregisterpagecommand{#2}{#6}{#7}{#8}% \fi \dostoptagged \dostoptagged \fi \popcurrentregister} \unexpanded\def\defaultregisterentry#1#2#3#4#5% #1:class #2:processor #3:internal #4:seeindex #5:word {\pushcurrentregister{#1}% \def\currentregisterpageindex{#3}% \iflocation \def\currentregisterseeindex{#4}% \ifconditional\c_strc_registers_text_interaction \strc_references_goto_internal{\setlocationcolor\doapplyregisterentrycommand{#2}{#5}}[internal(#3)]% \else \doapplyregisterentrycommand{#2}{#5}% \fi \else \let\currentregisterseeindex\empty \doapplyregisterentrycommand{#2}{#5}% \fi \popcurrentregister} \unexpanded\def\doapplyregisterentrycommand#1#2% processor text {\dostarttagged\t!registercontent\empty \ifx\currentregisterseeindex\empty \else \dontleavehmode \dosetdirectpagereference{seeindex:\currentregisterseeindex}% maybe some day we will support an area \fi \applyprocessor{#1}{\registerparameter\c!textcommand{\limitedregisterentry{\registerparameter\c!deeptextcommand{#2}}}}% \dostoptagged} \unexpanded\def\doapplyregisterseecommand#1#2% {\ifx\currentregisterseeindex\empty \applyprocessor{#1}{#2}% \else\iflocation \strc_references_goto_internal{\applyprocessor{#1}{#2}}[seeindex:\currentregisterseeindex]% \else \applyprocessor{#1}{#2}% \fi\fi} \unexpanded\def\defaultregisterseeword#1#2#3#4#5#6#7% class i n #3:processor #4:internal #5:seeindex #6:word {\pushcurrentregister{#1}% \ifnum#2=\plusone \registerpageseparator \fi \global\setconstant\c_strc_registers_page_state\plustwo \def\currentregisterpageindex{#5}% \dostarttagged\t!registersee\empty \settrue\c_strc_registers_page_done \iflocation \def\currentregisterseeindex{#6}% \else \let\currentregisterseeindex\empty \fi \ifnum#2=\plusone \labeltexts\v!see{\doapplyregisterseecommand{#4}{#7}}% \else\ifnum#2=#3\relax \labeltexts\v!and{\doapplyregisterseecommand{#4}{#7}}% \else ,\space\doapplyregisterseecommand{#4}{#7}% \fi\fi \dostoptagged \popcurrentregister} \let\registerseeword \defaultregisterseeword \let\registerentry \defaultregisterentry \let\registercharacter\defaultregistercharacter %D A few specific rendering variants: % \def\doregisterpagelocation#1#2% % {\nextregisterpage % \hbox to 1em{\hss\doregisterpagehowto{#1}{#2}\hss}} % todo: \installregisterpagehandler % \def\MyRegisterPageCommand#1% % {#1\currentregisterpageuserdata{whatever}} % % \starttext % \setregisterentry[index][entries=aaa][whatever=f.] test \index{bbb} test % \placeregister[index][n=1,pagecommand=\MyRegisterPageCommand] % \stoptext \def\registerpageuserdata #1#2{\clf_registeruserdata#1{#2}} \def\currentregisterpageuserdata {\registerpageuserdata\currentregisterpageindex} % {#1} % not yet ok : new internal handler names \unexpanded\def\registerpagebuttonsymbol {\vrule\s!width\emwidth\s!height\exheight\s!depth\zeropoint\relax} \installcorenamespace{registersymbol} \setvalue{\??registersymbol n}% {\def\registerpageseparatorsymbol{,\space}} \setvalue{\??registersymbol a}% {\def\registerpageseparatorsymbol{,\space}} % now done via conversion \setvalue{\??registersymbol\v!none}% {\let\registerpageseparatorsymbol\empty \let\registeronepage \gobblefivearguments \let\registerpagerange\gobbleeightarguments} \setvalue{\??registersymbol 1}% {\let\registerpageseparatorsymbol\space \def\registeronepage {\symbol[1]\gobblefivearguments}% \def\registerpagerange{\symbol[1]\gobbleeightarguments}} \setvalue{\??registersymbol 2}% {\let\registerpageseparatorsymbol\space \def\registeronepage {\registerpagebuttonsymbol\gobblefivearguments}% \def\registerpagerange{\registerpagebuttonsymbol\gobbleeightarguments}} \unexpanded\def\setregisterpagerendering {\doifelse{\registerparameter\c!pagenumber}\v!no {\let \currentregisterpagesymbol\v!none} {\edef\currentregisterpagesymbol{\registerparameter\c!symbol}}% \ifx\currentregisterpagesymbol\empty \csname\??registersymbol n\endcsname \else\ifcsname\??registersymbol\currentregisterpagesymbol\endcsname \csname\??registersymbol\currentregisterpagesymbol\endcsname \else \let\registerpageseparatorsymbol\space \def\registeronepage {\registerparameter\c!symbol\gobblefivearguments}% \def\registerpagerange{\registerparameter\c!symbol\gobbleeightarguments}% \fi\fi} \appendtoks \setregisterpagerendering \to \everyplaceregister %D The linked register code will be reimplemented (not that hard) when it's needed %D again and/or when I'm bored. \def\findregisterinternal#1#2#3{\clf_findregisterinternal{#1}{#2}#3\relax} \unexpanded\def\pageofinternal #1{\clf_pageofinternal#1\relax} \unexpanded\def\linkedregisterentrylink#1#2#3#4% tag where before after {\iflocation \scratchcounter\findregisterinternal{#1}{#2}\currentregisternumber\relax\relax \ifcase\scratchcounter\else #3\relax \goto{\symbol[#2]}[internal(\the\scratchcounter)]% #4\relax \fi \else % \scratchcounter\findregisterinternal{#1}{#2}\currentregisternumber\relax\relax % \ifcase\scratchcounter\else % #3\relax % \pageofinternal\scratchcounter % #4\relax % \fi \fi} \unexpanded\def\linkedregisterentry#1% {\dontleavehmode \begingroup \setbox\scratchbox\hbox{#1}% \linkedregisterentrylink\currentregistername\v!previous\relax\nobreakspace \unhbox\scratchbox \linkedregisterentrylink\currentregistername\v!next\nobreakspace\relax \endgroup} \unexpanded\def\registerpacked#1#2% {\iflocation \hskip\d_strc_registers_distance\relax \nobreak \ifnum#1=#2\relax \goto{\symbol[\v!somewhere]}[internal(#1)]% \else \goto{\symbol[\v!first]}[internal(#1)]% \nobreakspace \goto{\symbol[\v!last]}[internal(#2)]% \fi \fi} %D Default index: \defineregister [\v!index] % [\v!indices] \stopcontextdefinitioncode \protect \endinput