file-ini.mklx /size: 7515 b    last modification: 2023-12-21 09:44
1%D \module
2%D   [       file=file-ini, % was supp-fil,
3%D        version=20110701, % 1995.10.10,
4%D          title=\CONTEXT\ File Macros,
5%D       subtitle=Helpers,
6%D           date=\currentdate,
7%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
8%C
9%C This module is part of the \CONTEXT\ macro||package and is
10%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
11%C details.
12
13%D \TEX\ operates on files, so one wouldn't wonder that there is a separate module
14%D for file commands. In \CONTEXT\ files are used for several purposes:
15%D
16%D \startitemize[packed]
17%D \item  general textual input
18%D \item  logging status information
19%D \item  saving registers, lists and references
20%D \item  buffering defered textual input
21%D \stopitemize
22%D
23%D When dealing with files we can load them as a whole, using the \type {\input}
24%D primitive or load them on a line||by||line basis, using \type {\read}. Writing is
25%D always done line by line, using \type {\write}.
26
27\writestatus{loading}{ConTeXt File Macros / Helpers}
28
29\registerctxluafile{file-ini}{}
30
31\unprotect
32
33%D \macros
34%D   {scratchread, scratchwrite}
35%D
36%D We define a scratch file for reading. Keep in mind that the number of files is
37%D limited to~16, so use this one when possible. We also define a scratch output
38%D file. In \MKIV\ and \LMTX\ we never use these file handles.
39
40\ifdefined\scratchread  \else \newread \scratchread  \fi
41\ifdefined\scratchwrite \else \newwrite\scratchwrite \fi
42
43%D Seldom needed:
44
45\permanent\def\openinputfile  #handle#name{\immediate\openin #handle={#name}\relax}
46\permanent\def\openoutputfile #handle#name{\immediate\openout#handle={#name}\relax}
47
48\permanent\def\closeinputfile #handle{\immediate\closein #handle\relax}
49\permanent\def\closeoutputfile#handle{\immediate\closeout#handle\relax}
50
51%D \macros
52%D   {writeln}
53%D
54%D This saves a few tokens:
55
56\permanent\def\writeln#handle{\write#handle{}}
57
58%D \macros
59%D   {pushendofline,popendofline}
60%D
61%D When we are loading files in the middle of the typesetting process, for instance
62%D when we load references, we have to be sure that the reading process does not
63%D generate so called 'spurious spaces'. This can be prevented by assigning the line
64%D ending character the \CATCODE\ comment. This is accomplished by
65%D
66%D \starttyping
67%D \pushendofline
68%D ... reading ...
69%D \popendofline
70%D \stoptyping
71
72\installsystemnamespace{eolstack}
73
74\newinteger\c_system_files_eol_level
75
76\permanent\protected\def\pushendofline
77  {\advanceby\c_system_files_eol_level\plusone
78   \expandafter\chardef\csname\??eolstack\the\c_system_files_eol_level\endcsname\catcode\endoflineasciicode
79   \catcode\endoflineasciicode\commentcatcode}
80
81\permanent\protected\def\popendofline
82  {\catcode\endoflineasciicode\csname\??eolstack\the\c_system_files_eol_level\endcsname
83   \advanceby\c_system_files_eol_level\minusone}
84
85\permanent\protected\def\restoreendofline
86  {\catcode\endoflineasciicode\endoflinecatcode}
87
88%D \macros
89%D   {startreadingfile,stopreadingfile}
90%D
91%D A low level capsule:
92
93\newinteger\readingfilelevel       % no longer needed
94\newtoks   \everystartreadingfile
95\newtoks   \everystopreadingfile
96
97\permanent\protected\def\startreadingfile% beter een every en \setnormalcatcodes
98  {\global\advanceby\readingfilelevel\plusone
99   \expand\everystartreadingfile
100   \pushcatcodetable       % saveguard
101   \setcatcodetable\ctxcatcodes
102   \pushregime}% temporarily this way
103
104\permanent\protected\def\stopreadingfile
105  {\popcatcodetable % saveguard
106   \popregime % temporarily this way
107   \expand\everystopreadingfile
108   \global\advanceby\readingfilelevel\minusone}
109
110%D \macros
111%D   {input, normalinput}
112%D
113%D Sometimes we run into troubles when \type {\input} wants to get expanded, e.g. in
114%D a \type {\write} (which happens in the metafun manual when we permit long MP
115%D lines). So, instead of fixing that, we go for a redefinition of \type {\input}.
116%D Of course it's better to use \type {\readfile} or \type {\processfile}.
117
118\permanent\def\inputgivenfile#name{\normalinput{#name}} % expands
119
120%D \macros
121%D   {doifelsefile}
122%D
123%D The next alternative only looks if a file is present. No loading is done. This
124%D one obeys the standard \TEX\ lookup.
125%D
126%D \starttyping
127%D \doiffileelse {filename} {found} {not found}
128%D \stoptyping
129
130\permanent\protected\def\doifelsefile     {\clf_doifelsefileexist}
131\permanent\protected\def\doifelsepath     {\clf_doifelsepathexist}
132\permanent\protected\def\doiffile    #name{\clf_doifelsefileexist{#name}\firstofoneargument\gobbleoneargument}
133\permanent\protected\def\doifnotfile #name{\clf_doifelsefileexist{#name}\gobbleoneargument\firstofoneargument}
134
135\aliased\let\doiffileelse\doifelsefile
136\aliased\let\doifpathelse\doifelsepath
137
138\aliased\let\doifelsefileexists\doifelsefile
139\aliased\let\doifelsepathexists\doifelsepath
140
141\aliased\let\doiffileexistselse\doifelsefileexists
142\aliased\let\doifpathexistselse\doifelsepathexists
143
144%D \macros
145%D   {doifparentfileelse}
146%D
147%D \starttyping
148%D \doifparentfileelse{filename}{yes}{no}
149%D \stoptyping
150
151\ifdefined\outputfilename \else \def\outputfilename{\jobname} \fi
152
153\permanent\protected\def\doifelseparentfile{\clf_doifelseparentfile}
154
155\aliased\let\doifparentfileelse\doifelseparentfile
156
157%D \macros
158%D   {splitfilename}
159%D
160%D \startbuffer
161%D \def\showfilesplit
162%D   {\bgroup \tttf
163%D      \hbox{(full: \splitofffull)}\space
164%D      \hbox{(path: \splitoffpath)}\space
165%D      \hbox{(base: \splitoffbase)}\space
166%D      \hbox{(name: \splitoffname)}\space
167%D      \hbox{(type: \splitofftype)}\space
168%D    \egroup}
169%D
170%D \splitfilename{c:/aa/bb/cc/dd.ee.ff} \showfilesplit \endgraf
171%D \splitfilename{c:/aa/bb/cc/dd.ee}    \showfilesplit \endgraf
172%D \splitfilename{c:/aa/bb/cc/dd}       \showfilesplit \endgraf
173%D
174%D \splitfilename{dd.ee.ff} \showfilesplit \endgraf
175%D \splitfilename{dd.ee}    \showfilesplit \endgraf
176%D \splitfilename{dd}       \showfilesplit \endgraf
177%D \stopbuffer
178%D
179%D \start \typebuffer \getbuffer \stop
180
181\newconstant\kindoffile   % 0=normal 1=full path spec (or http) / set at the lua end
182\newconstant\splitoffkind
183
184\mutable\def\splitoffroot{.}
185
186\mutable\lettonothing\splitofffull
187\mutable\lettonothing\splitoffpath
188\mutable\lettonothing\splitoffbase
189\mutable\lettonothing\splitoffname
190\mutable\lettonothing\splitofftype
191
192\permanent\protected\def\splitfilename{\clf_splitfilename}
193
194%D \macros
195%D   {doonlyonce, doinputonce, doendinputonce}
196%D
197%D Especially macropackages need only be loaded once. Repetitive loading not only
198%D costs time, relocating registers often leads to abortion of the processing
199%D because \TEX's capacity is limited. One can prevent multiple execution and
200%D loading by using one of both:
201%D
202%D \starttyping
203%D \doonlyonce{actions}
204%D \doinputonce{filename}
205%D \doendinputonce{filename}
206%D \stoptyping
207%D
208%D This command obeys the standard method for locating files. We could move this
209%D function to the \LUA\ end.
210
211\installsystemnamespace{fileonce}
212
213\permanent\protected\def\doonlyonce#whatever%
214  {\ifcsname\??fileonce#whatever\endcsname
215     \expandafter\gobbleoneargument
216   \else
217     \aliased\gletcsname\??fileonce#whatever\endcsname\relax
218     \expandafter\firstofoneargument
219   \fi}
220
221\permanent\protected\def\doinputonce#name%
222  {\doonlyonce{#name}{\doifelsefile{#name}{\inputgivenfile{#name}}\donothing}}
223
224\permanent\protected\def\doendinputonce#name%
225  {\ifcsname\??fileonce#name\endcsname
226     \expandafter\endinput
227   \fi}
228
229\permanent\protected\def\forgetdoingonce#whatever%
230  {\global\undefinevalue{\??fileonce#whatever}}
231
232\protect \endinput
233