summaryrefslogtreecommitdiff
path: root/macros/optex/base/prefixed.opm
diff options
context:
space:
mode:
Diffstat (limited to 'macros/optex/base/prefixed.opm')
-rw-r--r--macros/optex/base/prefixed.opm178
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