%% This is part of the OpTeX project, see http://petr.olsak.net/optex

\_codedecl \public {Prefixing and code syntax <2024-02-02>} % preloaded in format

   \_doc ---------
   All \TeX/ primitives have alternative control sequence `\_hbox` `\_string`, ...
   \_cod ---------

\let\_directlua = \directlua
\_directlua {
    % enable all TeX primitives with _ prefix
    tex.enableprimitives('_', tex.extraprimitives('tex'))
    % enable all primitives without prefixing
    tex.enableprimitives('', tex.extraprimitives())
    % enable all primitives with _ prefix
    tex.enableprimitives('_', tex.extraprimitives())
}

   \_doc ------------------
   \`\ea` is useful shortcut for `\expandafter`. We recommend to use always the
   private form of \`\_ea`
   because there is high probability that `\ea` will be redefined by the user.
   \nl
   \`\public` `\<sequence> \<sequence> ... ;` does
   `\let \<sequence> = \_<sequence>` for all sequences.
   \nl
   \`\private` `\<sequence> \<sequence> ...;` does
   `\let \_<sequence> = \<sequence>` for all sequences.
   \nl
   \`\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.
   \_cod -----------------

\_let\_ea =\_expandafter  % useful shortcut

\_long\_def \_xargs #1#2{\_ifx #2;\_else \_ea#1\_ea#2\_ea\_xargs \_ea #1\_fi}

\_def \_pkglabel{}
\_def \_public {\_xargs \_publicA}
\_def \_publicA #1{%
   \_checkexists \public {_\_csstring#1}%
   \_ea\_let \_ea#1\_csname  _\_csstring #1\_endcsname
}
\_def \_private {\_xargs \_privateA}
\_def \_privateA #1{%
   \_checkexists \private {\_csstring #1}%
   \_ea\_let \_csname  _\_csstring #1\_endcsname =#1%
}
\_def\_checkexists #1#2{\_unless \_ifcsname #2\_endcsname
   \_errmessage {\_string#1: \_bslash#2 must be declared}\_fi
}
\_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 -----------------------------
   We define the macros
   \`\_namespace` `{<pkg label>}`,  \`\_resetnamespace` `{<pkg label>}`, \`\_endnamespace`,
   \`\_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
      {The name space "#1" is used already, it cannot be used twice}%
      \_endinput
   \_else
      \_ea \_gdef \_csname _namesp:#1\_endcsname {}%
      \_resetnamespace{#1}\_fi
}
\_def\_resetnamespace #1{%
   \_unless \_ifx \_pkglabel\_empty \_endnamespace \_fi
   \_gdef \_pkglabel{_#1}%
   \_directlua{
      callback.add_to_callback("process_input_buffer",
        function (str)
           return string.gsub(str, "\_nbb[.]([a-zA-Z])", "\_nbb _#1_\_pcent 1")
        end, "_namespace")
   }%
}
\_def\_endnamespace {%
   \_directlua{ callback.remove_from_callback("process_input_buffer", "_namespace") }%
   \_gdef \_pkglabel{}%
}
\_def \_nspublic {\_xargs \_nspublicA}
\_def \_nspublicA #1{%
   \_checkexists \_nspublic {\_pkglabel _\_csstring #1}%
   \_ifcsname _eol:\_ea\_ignoreit\_pkglabel _\_csstring #1\_endcsname % defined by \eoldef
      \_slet {_eol:\_csstring #1}{_eol:\_ea\_ignoreit\_pkglabel _\_csstring #1}\_fi
   \_ea\_newpublic \_ea\_let \_ea#1\_csname \_pkglabel _\_csstring #1\_endcsname
}
\_def \_nsprivate {\_xargs \_nsprivateA}
\_def \_nsprivateA #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 %----------------------------------------------------


\sec[basic-code] Basic principles of \OpTeX/ sources

\secc[namespaces] Concept of namespaces of control sequences

\OpTeX/ sets the category code of the \"`_`" character to 11 (letter)
and it is never changed.\fnote
{This is only singular exception form category codes given by plain \TeX.}
So, we can always construct multiletter control sequence names from letters
`A`--`Z`, `a`--`z`, and `_`. The \"letter `_`" works in math mode as a subscript
constructor because it is set as math active character (see section~\ref[math-macros]).

We distinguish following namespaces for multiletter control sequences:
\begitems
* Only alphabetical names are in the {\em public namespace}. They are intended
  for end users when creating a document. Sometimes it is called {\em user
  namespace} too. For example `\hbox`, `\fontfam`, `\MyMacro`.
* Only alphabetical lowercase names prefixed by single \"`_`" are in the
  {\em private namespace}. It is used in \OpTeX/ internal macros.
  For example `\_hbox`, `\_fontsel`.
* Names in the form `\_<pkg>_<name>` are in the {\em package namespace},
  see section~\ref[pkg-namespace]. For example `\_qr_size`, `\_math_alist`.
* Names starting with two \"`_`" are in the {\em reserved namespace}. They can be
  used for internal control sequences in font family files or in similar cases.
* Other names which include \"`_`" but not as the first character can be used
  too, but with care, see the end of this section.
\enditems

All \TeX/ primitives are initialized with two control sequences with the
same meaning: {\em prefixed} control sequence
(in private namespace, for example `\_hbox`)
and {\em unprefixed} control sequence (in public namespace, for example `\hbox`).
All \OpTeX/ macros intended for end users are initialized in these two forms
too, for example `\_ref` and `\ref`.

Users can declare any control sequences in the public namespace without worrying
that \OpTeX/ behavior is changed. This is because \OpTeX/ uses exclusively
prefixed control sequences in its macros. For example, a user can declare
`\def\fi{finito}` and nothing bad happens, if the user doesn't use `\fi` in
its original primitive meaning. You don't have to know all \TeX/ primitives
and \OpTeX/ macros, you can declare control sequences for your use in the
public namespace without limitations and nothing bad will happen.

You can use control sequences from private or package namespace in
a \"read-only manner" without changing \OpTeX/ behavior too.
On the other hand, if you re-define a control sequence in the private name
space, the \OpTeX/ behavior can be changed. You can do it
but we suppose that you know what you are doing and what \OpTeX/
behavior is changed.

All multiletter control sequences declared by \OpTeX/ are defined in the private
namespace first (`\_def\_macro{...}`). If the declared control sequences are
intended for end users too then they are exported to the public namespace
after that. It is done by the \^`\public` macro:
\begtt \catcode`\<=13
\public <list of control sequences> ;
\endtt
For example \^`\public`` \foo \bar ;` does `\let\foo=\_foo`, `\let\bar=\_bar`.

There is an exception of the above mentioned principle. Control sequences
which are alternatives to math characters (`\alpha`, `\forall`, `\subset` etc.)
are declared only in public name space if they are not used in any internal
\OpTeX/ macros.

The macro \^`\private` does the reverse job of \^`\public` with the same syntax.
For example `\private \foo \bar ;` does `\let\_foo=\foo`, `\let\_bar=\bar`.
This should be used when an unprefixed variant of a control sequence is declared
already but we need the prefixed variant too.

In this documentation: if both variants of a control sequence are declared
(prefixed and unprefixed), then the accompanying text mentions only
the unprefixed variant. The code typically defines the prefixed variant
and then the \^`\public` (or `\_public`) macro is used.

The single-letter control sequences like `\%`, `\$`, `\^` etc. are not used
in internal macros. Users can redefine them, but (of course) some classical
features can be lost (printing percent character by `\%` for example).

It is very tempting to use control sequence names with `_` in order to
distinguish more words in the sequence name. If the first character isn't
`_` then such a name is outside private and package namespaces, so they can
be used for various purposes. For example `\my_control_sequence`. But there
is an exception: control sequences in the form `\<word>_` or `\<word>_<one-letter>`,
where <word> is a sequence of letters, are inaccessible, because they
are interpreted as `\<word>` followed by `_` or as `\<word>` followed by
`_<one-letter>`. This feature is activated because we want to write math
formulae as in plain \TeX, for example:
\begtt
  \int_a^b    ... is interpreted as \int _a^b
  \max_M      ... is interpreted as \max _M
  \alpha_{ij} ... is interpreted as \alpha _{ij}
\endtt
It is implemented using Lua code at input processor level, see
the section~\ref[math-macros] for more details. You can deactivate this feature by
\^`\mathsboff`. After this, you can still write
`$`$\int$`_a^b$` (Unicode) or `$\int _a^b$` % $∫_a^b$ (Unicode) or $\int _a^b$
without problems but `\int``_a^b` yields to undefined control sequence
`\int``_a`. You can activate this feature again by \^`\mathsbon`. The
effect will take shape from next line read from input file.


\secc Macro files syntax

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 \catcode`<=13 \adef!{\string}
\_codedecl \sequence {<short title> !<<version>>}
\endtt

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
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 your 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

Package writer should use internal names in the form `\_<pgk>_<sequence>`,
where `<pkg>` is a package label. For example:
`\_qr_utfstring` from `qrcode.opm` package.

The package writer does not need to write repeatedly `\_pkg_foo` `\_pkg_bar`
etc.\ again and again in the macro file.\fnote
{We have not adopted the idea from expl3 language:)}
When the \^`\_namespace` `{<pkg>}`
is declared at the beginning of the macro file then all occurrences of
`\.foo` will be replaced by `\_<pkg>_foo` at the input processor level.
The macro writer can write (and backward can read his/her code) simply with
`\.foo`, `\.bar` control sequences and `\_<pkg>_foo`, `\_<pkg>_bar`
control sequences are processed internally.
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.

\^`\_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 public namespace 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` namespace
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
(after other packages are loaded) by \^`\_resetnamespace`~`{<pkg>}`.

If the package writer needs to declare a control
sequence by \^`\newif`, then there is an exception of the rule described above. Use
\^`\_newifi\_if<pkg>_bar`, for example `\_newifi\_ifqr_incorner`.
Then the control sequences `\_qr_incornertrue` and
`\_qr_incornerfalse` can be used (or the sequences `\.incornertrue`
and `\.incornerfalse` when `\_namespace{qr}` is used).


\secc Summary about rules for external macro files published for \OpTeX/

If you are writing a macro file that is intended to be published for
\OpTeX/, then you are greatly welcome. You should follow these rules:

\begitems
* Don't use control sequences from the public namespace in the macro
  bodies if there is no explicit and documented reason to do this.
* Don't declare control sequences in the public namespace if there are no
  explicit and documented reasons to do this.
* Use control sequences from \OpTeX/ and primitive namespace
  in read-only mode, if there is not an explicit and documented reason to
  redefine them.
* Use `\_<pkg>_<name>` for your internal macros or `\.<name>` if the
  \^`\_namespace{<pkg>}` is declared. See section~\ref[pkg-namespace].
* Use \^`\load` (or better: `\_load`) for loading more external macros
  if you need them. Don't use `\_input` explicitly in such cases.
  The reason is: the external macro file is not loaded
  twice if another macro or the user needs it explicitly too.
* Use \^`\_codedecl` as your first command in the macro file and
  \^`\_endcode` to close the text of macros.
* Use \^`\_doc` ... \^`\_cod` pairs for documenting the code pieces.
* You can write more documentation after the \^`\_endcode` command.
* The \OpTeX/ catcodes are set when \^`\load` your package (i.e. plain \TeX/
  catcodes plus catcode of `_` is 11). If a catcode is changed during
  loading your package then it is forgot because \^`\load` returns to catcodes
  used before loading package. If you want to offer a catcode changing for
  users then insert it to a macro which can be used after loading.
\enditems

If the macro file accepts these recommendations then it should be
named by `<filename>.opm` where `<filename>` differs from file names
used directly in \OpTeX/ and from other published macros.
This extension `.opm` has precedence before `.tex` when
the \^`\load` macro is used.

The `math.opm` is a good example of how an external macro file for \OpTeX/
can look like. Another good and short example is
\ulink[https://tex.stackexchange.com/questions/684406\#684406]{here}.

\endinput

2024-02-02 \_nspublicA bug correction (#1 may be set as \outer)
2024-01-18 \_nspublic modified in order to \eoldef+\bracedparam
2023-01-30 doc. about namespaces rewritten
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
2020-02-14 released
