diff options
Diffstat (limited to 'macros/optex/base/prefixed.opm')
-rw-r--r-- | macros/optex/base/prefixed.opm | 178 |
1 files changed, 120 insertions, 58 deletions
diff --git a/macros/optex/base/prefixed.opm b/macros/optex/base/prefixed.opm index d15ee4140d..a599e0ec85 100644 --- a/macros/optex/base/prefixed.opm +++ b/macros/optex/base/prefixed.opm @@ -1,6 +1,6 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \public {Prefixing and code syntax <2021-08-16>} % preloaded in format +\_codedecl \public {Prefixing and code syntax <2022-11-25>} % preloaded in format \_doc --------- All \TeX/ primitives have alternative control sequence `\_hbox` `\_string`, ... @@ -21,15 +21,19 @@ private form of \`\_ea` because there is high probability that `\ea` will be redefined by the user. \nl - \`\public` `<sequence> <sequence> ... ;` does + \`\public` `\<sequence> \<sequence> ... ;` does `\let \<sequence> = \_<sequence>` for all sequences. \nl - \`\private` `<sequence> <sequence> ...;` does + \`\private` `\<sequence> \<sequence> ...;` does `\let \_<sequence> = \<sequence>` for all sequences. \nl - \`\_checkexists` `<where> <prefix><sequence>` prints error - if the control sequence propagated to - a new name space by `\public` etc. macros is not declared. + \`\newpublic``<do>\<sequence>` prints warning if `\<sequence>` + is declared already. Then runs `<do>\<sequence>`.\nl + \`\_checkexists` `<where> {<sequence-string>}` prints error + if the control sequence given by its name <sequence-string> + is not declared. This check is used in `\public`, `\private`, + `\_nspublic` and `\_nsprivate` macros in order to avoid mistakes + in names when declaring new control sequences. \nl \`\xargs` `<what> <sequence> <sequence> ... ;` does `<what><sequence>` for each sequences. @@ -42,62 +46,42 @@ \_def \_pkglabel{} \_def \_public {\_xargs \_publicA} \_def \_publicA #1{% - \_checkexists \public _#1% + \_checkexists \public {_\_csstring#1}% \_ea\_let \_ea#1\_csname _\_csstring #1\_endcsname } \_def \_private {\_xargs \_privateA} \_def \_privateA #1{% - \_checkexists \private {}#1% + \_checkexists \private {\_csstring #1}% \_ea\_let \_csname _\_csstring #1\_endcsname =#1% } -\_def\_checkexists #1#2#3{\_unless \_ifcsname #2\_csstring#3\_endcsname - \_errmessage {\_string#1: \_bslash#2\_csstring#3 must be declared}\_fi -} -\_public \public \private \xargs \ea ; - - \_doc ----------------------- - Each macro file should begin with \`\_codedecl` `\macro {<info>}`. - If the `\macro` is defined already then the `\endpinput` protects to read - such file more than once. Else the <info> is printed to the terminal - and the file is read.\nl - The {\`\_endcode`} is defined as `\endinput` in the `optex.ini` file. - \`\wterm` `{<text>}` prints the `<text>` to the terminal and to the `.log` file, - \`\wlog` `{<text>}` prints the `<text>` only to the `.log` file (as in plain \TeX) - \_cod ----------------------- - -\_def \_codedecl #1#2{% - \_ifx #1\_undefined \_wlog{#2}% - \_else \_ea \_endinput \_fi +\_def\_checkexists #1#2{\_unless \_ifcsname #2\_endcsname + \_errmessage {\_string#1: \_bslash#2 must be declared}\_fi } -\_def \_wterm {\_immediate \_write16 } -\_def \_wlog {\_immediate\_write-1 } % write on log file (only) - -\_public \wterm \wlog ; - - \_doc ------------------------ - The `\optexversion` and `\fmtname` are defined in the `optex.ini` file. - Maybe, somebody will need a private version of these macros. - \_cod ------------------------ - -\_private \optexversion \fmtname ; +\_def\_newpublic #1#2{\_unless\_ifx #2\_undefined + \_opwarning{\_string#2 is redefined% + \_ifx\_pkglabel\_empty \_else\_space by the \_ea\_ignoreit\_pkglabel\_space package\_fi}\_fi + #1#2% +} +\_public \public \private \newpublic \xargs \ea ; \_doc ----------------------------- - The `\_mathsbon` and `\_mathsboff` are defined in `math-macros.opm` file. - Now, we define the macros + We define the macros \`\_namespace` `{<pkg label>}`, \`\_resetnamespace` `{<pkg label>}`, \`\_endnamespace`, - \`\_nspublic` and \`\_nsprivate` + \`\_pkglabel`, \`\_nspublic`, and \`\_nsprivate` for package writers, see section~\ref[pkg-namespace].{\hbadness=2200\par} \_cod ----------------------------- \_def \_pkglabel{} \_def\_namespace #1{% - \_ifcsname namesp:#1\_endcsname \_errmessage + \_ifcsname _namesp:#1\_endcsname \_errmessage {The name space "#1" is used already, it cannot be used twice}% \_endinput - \_else \_resetnamespace{#1}\_fi + \_else + \_ea \_gdef \_csname _namesp:#1\_endcsname {}% + \_resetnamespace{#1}\_fi } \_def\_resetnamespace #1{% - \_ea \_gdef \_csname namesp:#1\_endcsname {}% + \_unless \_ifx \_pkglabel\_empty \_endnamespace \_fi \_gdef \_pkglabel{_#1}% \_directlua{ callback.add_to_callback("process_input_buffer", @@ -110,20 +94,60 @@ \_directlua{ callback.remove_from_callback("process_input_buffer", "_namespace") }% \_gdef \_pkglabel{}% } - \_def \_nspublic {\_xargs \_nspublicA} \_def \_nspublicA #1{% - \_checkexists \nspublic {\_pkglabel _}#1% - \_unless\_ifx #1\_undefined - \_opwarning{\_ea\_ignoreit\_pkglabel\_space redefines the meaning of \_string#1}\_fi - \_ea\_let \_ea#1\_csname \_pkglabel _\_csstring #1\_endcsname + \_checkexists \_nspublic {\_pkglabel _\_csstring #1}% + \_ea\_newpublic \_ea\_let \_ea#1\_csname \_pkglabel _\_csstring #1\_endcsname } \_def \_nsprivate {\_xargs \_nsprivateA} \_def \_nsprivateA #1{% - \_checkexists \nsprivate {}#1% + \_checkexists \_nsprivate {\_csstring #1}% \_ea\_let \_csname \_pkglabel _\_csstring #1\_endcsname =#1% } + \_doc ----------------------- + Each macro file should begin with \`\_codedecl` `\macro {<info>}`. + If the `\macro` is defined already then the `\endpinput` protects to read + such file more than once. Else the <info> is printed to the terminal + and the file is read. + The {\`\_endcode`} is defined as `\endinput` in the `optex.ini` file. + \`\wterm` `{<text>}` prints the `<text>` to the terminal and to the `.log` file, + \`\wlog` `{<text>}` prints the `<text>` only to the `.log` file (as in plain \TeX) + \_cod ----------------------- + +\_def \_codedecl #1#2{% + \_ifx #1\_undefined \_wlog{@:[\_basefilename\_currfile] #2}% + \_else \_ea \_endinput \_fi +} +\_def \_wterm {\_immediate \_write16 } +\_def \_wlog {\_immediate\_write-1 } % write on log file (only) + +\_public \wterm \wlog ; + + \_doc ----------------------------- + \`\currfile` returns the name of the current input file including its path.\nl + \`\basefilename``\currfile` returns base name of + the current file, without its path and extension.\nl + \`\_nofilepath` `<text>/<with>/<slashes>/\_fin` expands to the last segment + separated by slashes.\nl + \`\_nofileext` `<filename>.\_fin` expands to the file name without extension. + \_cod ----------------------------- + +\_def\_currfile{\_directlua{tex.print(status.filename)}} +\_def\_basefilename #1{\_ea\_nofileext\_expanded{\_ea\_ea\_ea\_nofilepath#1/\_fin}.\_fin} +\_def\_nofilepath #1/#2{\ifx#2\_fin #1\_else \_ea\_nofilepath \_ea#2\_fi} +\_def\_nofileext #1.#2\_fin{#1} + +\_public \currfile \basefilename ; + + \_doc ------------------------------ + We define \`\_fin` as a useless macro. Suppose that its meaning will be never + used for another control sequence. You can use `\_fin` as a final delimiter + of a list of tokens and your macro can ask `\ifx\_fin#1` in order to + decide that the list of tokens is finalized. + \_cod ------------------------------ + +\_protected\_long \_def \_fin \_fin {} \_endcode %---------------------------------------------------- @@ -216,25 +240,48 @@ features can be lost (printing percent character by `\%` for example). \secc Macro files syntax -Each segment of \OpTeX/ macros is stored in one file with `.opm` extension +Segments of \OpTeX/ macros or external macro packages +are stored in files with `.opm` extension (means OPtex Macros). Your local macros should be in a normal `*.tex` file. The code in macro files starts by \^`\_codedecl` and ends by \^`\_endcode`. The \^`\_endcode` is equivalent for `\endinput`, so documentation can follow. The \^`\_codedecl` has syntax: -\begtt -\_codedecl \sequence {Name <version>} +\begtt \catcode`<=13 \adef!{\string} +\_codedecl \sequence {<short title> !<<version>>} \endtt -If the mentioned `\sequence` is defined, then \^`\_codedecl` does the same as +If the mentioned `\sequence` is undefined then \^`\_codedecl` prints the message +\begtt \catcode`<=13 \adef!{\string} +@:[<file name>] <short title> !<<version>> +\endtt +to the log file and \TeX/ continues with reading the following macros. +If the `\sequence` is defined, then \^`\_codedecl` acts like `\endinput`: this protects from reading the file twice. We suppose, that `\sequence` is defined in the macro file. -It is possible to use the \^`\_doc` ... \^`\_cod` pair between the macro lines. -The documentation text should be here. It is ignored when macros are read -but it can be printed using `doc.opm` macros like in this documentation. - +It is possible to use the \^`\_doc` ... \^`\_cod` pair between the macro +definitions. The documentation text should be here. +It is ignored when macros are read. + +The \^`\_doc` ... \^`\_cod` parts can be printed after \^`\load[doc]` +using \~`\printdoc` macro, see section~\ref[doc]. +If you have created a documented macro file `pkgname.opm` then you can +put macros for creating your documentation between +first pair of \^`\_doc` ... \^`\_cod` used after \^`\_endcode`. +These macros should \^`\load[doc]` and must be finished by \^`\bye`. +Then you have code+documentation together in a single file and +user can generate the documentation of our package by +\^`\docgen` used at command line: +\begtt +optex -jobname pkgname-doc '\docgen pkgname' +\endtt +Example of a \^`\_doc` ... \^`\_cod` code used for creating the +documentation using \^`\docgen` can be found in the `math.opm` file. You can see +\ulink[https://petr.olsak.net/ftp/olsak/optex/math-doc.pdf]{its documentation}, especially +\ulink[https://petr.olsak.net/ftp/olsak/optex/math-doc.pdf\#ref:pkgtemplate] +{section about creating packages}. \secc[pkg-namespace] Name spaces for package writers @@ -255,12 +302,23 @@ The scope of the \^`\_namespace` command ends at the \^`\_endnamespace` command or when another \^`\_namespace` is used. This command checks if the same package label is not declared by the \^`\_namespace` twice. -The \^`\_nspublic` macro does `\let\foo = \_<pkg>_foo` when +\^`\_nspublic` `<list of sequences> ;` +does `\let\foo = \_<pkg>_foo` for each given sequence when \^`\_namespace{<pkg>}` is declared. Moreover, it prints a warning if `\foo` is defined already. The \^`\_nsprivate` macro does reverse operation to it without warnings. Example: you can define `\def\.macro{...}` and then set it to the user name space by `\_nspublic \macro;`. +It could happen that a package writer needs to declare a control sequence +(say `\foo`) directly without setting it in `\_<pkg>_foo` name space +followed by using \^`\_nspublic`. The \^`\newpublic` prefix should be used in this +case, for example `\_newpublic\_def\foo` or `\_newpublic\_chardef\foo` or +`\_newpublic{\_long\_def}\foo`. The \^`\newpublic``<do>\<sequence>` prints +a warning if the declared `\<sequence>` is defined already and then runs +`<do>\<sequence>`. The reason of the warning is the same as when +\^`\_nspublic` warns about doing re-declaration of control sequences already +declared. + Don't load other packages (which are using their own namespace) inside your namespace. Do load them before your \^`\_namespace`~`{<pkg>}` is initialized. Or close your namespace by \^`\_endnamespace` and open it again @@ -315,6 +373,10 @@ can look like. \endinput +2022-11-25 \_resetnamespace: moved \gdef\_namesp:#1 {} to \_namespace +2022-11-24 \newpublic introduced, \_checkexists with only two parameters. +2022-11-22 \currfile introduced and used in \_codedecl +2022-11-13 \_resetnamespace corrected 2021-08-16 \_wlog moved from basic macros, \_codedecl uses \_wlog only. 2021-04-25 \_checkexists introduced 2021-02-15 \_expandafter -> \_ea in \_codedecl |