% \iffalse meta-comment
% 
% File: linguistix.dtx
% 
% ----------------------------------------------------------
% The LaTeX bundle LinguisTiX v0.5d
% Copyright © 2022, 2023, 2024, 2025 निरंजन
% 
% This program is free software: you can redistribute it
% and/or modify it under the terms of the GNU General Public
% License as published by the Free Software Foundation,
% either version 3 of the License, or (at your option) any
% later version.
% 
% This program is distributed in the hope that it will be
% useful, but WITHOUT ANY WARRANTY; without even the implied
% warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
% PURPOSE. See the GNU General Public License for more
% details.
% 
% You should have received a copy of the GNU General Public
% License along with this program. If not, see
% <https://www.gnu.org/licenses/>.
% ----------------------------------------------------------
% 
% \fi
% \iffalse
%<*internal>
\iffalse
%</internal>
%<*readme>
------------------------------------------------------------
Bundle:       LinguisTiX
Version:      v0.5d
Author:       निरंजन
Description:  Enhanced support for linguistics.
Repository:   puszcza.gnu.org.ua/projects/linguistix
License:      GPLv3+, GFDLv1.3+
------------------------------------------------------------
%</readme>
%<*internal>
\fi
%</internal>
%<*driver>
\begin{filecontents}[overwrite]{\jobname.bib}
@book{bringhurst,
  title             = {The elements of typographic style},
  author            = {Bringhurst, Robert},
  date              = {2004},
  publisher         = {Point Roberts, WA: Hartley \& Marks,
                        Publishers},
  edition           = {4}
}
@online{alan,
  author  = {Munn, Alan and Gregorio, Enrico},
  title   = {{\textsf{ExPex} fails with
    \textsf{unicode-math}. How to avoid the clash?}},
  url     = {https://tex.stackexchange.com/q/703094},
  date    = {2023-12-05},
  urldate = {2025-07-11}
}
\end{filecontents}
\documentclass{l3doc}
\usepackage{linguistix}
\usepackage{xcolor}
\usepackage{longtable}
\usepackage{fontawesome5}
\usepackage[sc]{gfdl}
\usepackage{hyperxmp}
\usepackage{unicode-math}
\usepackage[verbose=silent]{microtype}
\usepackage{cleveref}
\usepackage{hologo}
\usepackage[style=apa,backend=biber]{biblatex}
\addbibresource{\jobname.bib}

\setlength{\LTpost}{0pt}
\setlength{\LTcapwidth}{4.5in}

\linguistix{old style one}

\DeclareMicrotypeAlias{NewCMUncial10-Book.otf}{TU-basic}
\setquotestyle{british}

\colorlet{lngxredcolor}{red!50!black}
\colorlet{lngxgreencolor}{green!50!black}
\colorlet{lngxbluecolor}{blue!50!black}

\setmathfont[version=emptyset]{NewCMMath-Book.otf}

\urlstyle{tt}

\hypersetup{%
  unicode,%
  colorlinks,%
  linkcolor              = {lngxredcolor},
  citecolor              = {lngxgreencolor},
  urlcolor               = {lngxbluecolor},
  pdftitle               = {The LinguisTiX bundle},%
  pdfauthor              = {निरंजन},%
  pdfsubject             = {%
    Enhanced support for linguistics.%
  },%
  pdfcreator             = {निरंजन},%
  pdfkeywords            = {Linguistics, LaTeX},%
  pdfcopyright           = {%
    The LaTeX bundle linguistix\textLF
    Copyright © 2022, 2023, 2024, 2025 निरंजन\textLF
    Permission is granted to copy, distribute and/or modify
    this document under the terms of the GNU Free
    Documentation License, Version 1.3 or any later version
    published by the Free Software Foundation; with no
    Invariant Sections, no Front-Cover Texts, and no
    Back-Cover Texts. A copy of the license is included in
    the section entitled ‘GNU Free Documentation License’.%
  },%
  pdflicenseurl          = {%
    https://www.gnu.org/licenses/fdl-1.3.txt%
  }%
}%

\newfontfamily\newcmnewone[%
  IgnoreFontspecFile,%
  Numbers                = {OldStyle}%
]{NewCM10-Book.otf}

\newfontfamily\newcmnewnum[%
  IgnoreFontspecFile%
]{NewCM10-Book.otf}

\newfontfamily\mrfnt[%
  IgnoreFontspecFile,%
  Script                 = {Devanagari},%
  Language               = {Marathi},%
  Renderer               = {HarfBuzz}%
]{Mukta-Light.ttf}

\newfontfamily\lngxcondensed[%
  IgnoreFontspecFile,%
  FakeStretch            = {0.6},%
  BoldFont               = {NewCMMono10-Bold.otf},%
  ItalicFont             = {NewCMMono10-BookItalic.otf},%
  Renderer               = {HarfBuzz}%
]{NewCMMono10-Book.otf}

\gfdlcopyrightholders{%
  \texorpdfstring{%
    {%
      \mrfnt
      निरंजन%
    }
    (\href{mailto:hi.niranjan@pm.me}{%
      \ttfamily
      hi.niranjan@pm.me%
    })%
  }{%
    निरंजन%
  }%
}

\gfdlcopyrightableyears{2022, 2023, 2024, 2025}

\gfdlcopyrightdescription{The \lngxpkg\ bundle}

\makeatletter

\setlength{\columnsep}{2pc}
\setlength{\columnseprule}{0.2pt}

\NewDocumentCommand \lngxtoc {  } {%
  %% Courtesy: John Kormylo
  %% https://tex.stackexchange.com/a/606678
  %% CC-BY-SA 4.0 International
  \setcounter{tocdepth}{1}
  \section*{%
    \makebox[\linewidth][l]{\contentsname}%
    \@mkboth{%
      \MakeUppercase{\contentsname}%
    }{%
      \MakeUppercase{\contentsname}%
    }%
  }%
  \begin{multicols}{2}%
    \small
    \begingroup
    \hypersetup{hidelinks}%
    \@starttoc{toc}%
    \endgroup
  \end{multicols}%
}

\NewDocumentCommand \lngxdocumentation { m } {%
  \section[\csname lngx#1logo\endcsname]{%
    \csname lngx#1logo\endcsname\hfill
    \hyperref[lngx#1l3]{%
      \footnotesize\LaTeX3-interface%
    } \textbar{}
    \hyperref[lngx#1imp]{%
      \footnotesize Implementation%
    }%
  }%
  \label{lngx#1doc}%
  \addtocontents{toc}{%
    % Courtesy: samcarter
    % https://topanswers.xyz/tex?q=8120
    % LPPL 1.3c+
    \hspace*{0.5em}%
    \texorpdfstring{%
      \begingroup
      \scriptsize
      Interface\dots\
      \hyperref[lngx#1l3]{%
        \color{lngxredcolor}%
        \textsf{%
          \pageref{lngx#1l3}%
        }%
      };
      \scriptsize
      Implementation\dots\
      \hyperref[lngx#1l3]{%
        \color{lngxredcolor}%
        \texttt{%
          \addfontfeatures{%
            Numbers=OldStyle,CharacterVariant={6}%
          }%
          \pageref{lngx#1imp}%
        }%
      }%
      \endgroup
    }{%
      \csname lngx#1logo\endcsname
    }%
  }%
}

\NewDocumentCommand \lngxinterface { m } {%
  \phantomsection
  \subsection*{%
    \csname lngx#1logo\endcsname\hfill
    \hyperref[lngx#1doc]{%
      \footnotesize Documentation%
    } \textbar{}
    \hyperref[lngx#1imp]{%
      \footnotesize Implementation%
    }%
  }%
  \label{lngx#1l3}%
}

\NewDocumentCommand \lngximplementation { m } {%
  \phantomsection
  \subsection*{%
    \csname lngx#1logo\endcsname\hfill
    \hyperref[lngx#1doc]{%
      \footnotesize Documentation%
    } \textbar{}
    \hyperref[lngx#1l3]{%
      \footnotesize\LaTeX3-interface%
    }%
  }%
  \label{lngx#1imp}%
}

\NewDocumentCommand \bLaTeX {  } {%
  (\kern-0.035em\relax
  L\kern-.81ex\relax
  \raisebox{.6ex}{\textsc{a}}\kern-.23ex\relax
  )\kern-0.065em\relax
  \hbox{T}\kern-.4ex\relax
  \raisebox{-.5ex}{E}\kern-.3ex\relax
  X%
}
\makeatother

\colorlet{lngxpurplecolor}{blue!50!red}

\def\lngxtval{%
  \begingroup
  \color{lngxredcolor}
  true%
  \endgroup
  \,|\,false%
}

\def\lngxfval{%
  true%
  \begingroup
  \color{lngxredcolor}
  \,|\,false%
  \endgroup
}

\ExplSyntaxOn
\msg_redirect_name:nnn { l3doc }
                       { foreign-internal }
                       { none }

\RenewDocumentCommand \lngxlogo { O{} } {%
  \group_begin:
  \hypersetup { hidelinks }
  \hyperref [
    lngx
    \IfBlankTF { #1 } { } { #1 doc }
  ] {
    \lngx_logo_font:
    LinguisTi
    \color_group_begin:
    \color_select:n { lngx_purple_color }
    X
    \color_group_end:
    \IfBlankF { #1 } { - #1 }
  }
  \group_end:
}

\NewDocumentCommand \fn { v }{
  \phantomsection
  \__codedoc_function_index:n  { #1 }
  \__codedoc_function_label:nN { #1 } \c_false_bool
  #1
}

\RenewDocumentCommand \MacroLongFont {  } {
  \lngxcondensed
}
\ExplSyntaxOff

\begin{document}
\DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
% \title{^^A
%   \phantomsection\label{lngx}^^A
%   The \lngxpkg\ bundle^^A
% }
% \author{{\mrfnt निरंजन}}
% \date{^^A
%   July 11, 2025 (v0.5d)\\[1ex]^^A
%   {^^A
%     \small\faIcon{home}\quad
%     \url{^^A
%       https://ctan.org/pkg/linguistix^^A
%     }\\[0.5ex]^^A
%     \small\faIcon{git-alt}\quad
%     \url{^^A
%       https://puszcza.gnu.org.ua/projects/linguistix^^A
%     }\\[0.5ex]^^A
%     \small\faIcon[regular]{comments}\quad
%     \url{^^A
%       https://matrix.to/\#/\#linguistix:matrix.org^^A
%     }^^A
%   }^^A
% }
% 
% \maketitle
% 
% \begin{documentation}
% 
% \begin{abstract}
%   There are quite a few \LaTeX\ packages that support
%   typesetting in linguistics, but most of them lack a
%   modern \LaTeX-like users syntax as well as a programming
%   interface. The \lngxpkg\ bundle fills this gap. It
%   contains several packages enhancing the general support
%   for linguistics in \LaTeX. This is a comprehensive
%   documentation of the same comprising of three parts. The
%   first one is the general users manual, the second one
%   documents the programming interface of the bundle,
%   whereas the last one is the documented implementation of
%   all the packages.
% \end{abstract}
% 
% \lngxtoc ^^A Custom command defined in the preamble.
%
% \newpage
% 
% ^^A Based on egreg’s answer:
% ^^A https://tex.stackexchange.com/a/102849
% \begingroup
% \thispagestyle{empty}^^A no header and footer.
% \vspace*{\stretch{1}}^^A some space at the top.
% \itshape             ^^A to get the text in italics.
% \raggedleft          ^^A flush to the right margin.
% Dedicated to Renuka who taught me rigour under the guise
% of linguistics\dots
% \par                 ^^A end the paragraph
% \vspace{\stretch{3}} ^^A space at bottom is thrice that
% \endgroup
% \newpage
% 
% \section{Introduction}
% 
% Linguistics is a discipline that studies the phenomenon of
% language and for this linguists analyse data from
% languages across the globe. In order to be able to present
% the data that is collected for this, linguists use several
% representational methods that lead to a fiasco when their
% typesetting is considered. In order to understand the
% complexity of the task at hand, first, let’s have a look
% at some of the problem cases first. If you are an
% impatient user and are just willing to read the
% users manual, you may skip reading the current section and
% start with \cref{lngxbasedoc} and the ones following it.
% 
% \subsection{Phonetic symbols}
% 
% Speech sounds are the building blocks of many human
% languages and the data collected from languages demands an
% unambiguous method of representation which is served by
% the International Phonetic Alphabet. For the longest time,
% the \textsc{tipa} package
% (\url{https://ctan.org/pkg/tipa}) was the one that
% produced phonetic symbols in \bLaTeX. Visually, it matches
% the default Computer Modern design of \bLaTeX, but
% \textsc{tipa} is not Unicode. It is set in a legacy
% encoding. With the recent developments, the New Computer
% Modern family supports all the \textsc{ipa} characters
% (even the ones that are missing in \textsc{tipa}). They
% are created keeping in mind the principles of Knuth’s
% Computer Modern. Additionally, the family also supports
% sans serif (recommended in presentations) and mono
% (recommended in coding context) families. It supports two
% weights, i.e., book and regular respectively. The book
% weight is slightly thicker than the regular weight, but
% the regular one matches the thickness of the Computer
% Modern design. Because of the increased thickness, the
% former looks better. The current document, for example, is
% typeset in the book weight of New Computer Modern. If you
% are like me, you probably don’t like using
% non-\LaTeX-fonts. The good news is that the requirements
% of linguistics are very well fulfilled by the recent
% developments in the New Computer modern family and it
% \emph{does} belong to the fraternity of \LaTeX-fonts.
% 
% Apart from this, there are some other advantages of the
% New Computer Modern fonts. The \textsc{ipa} distinguishes
% between \ipatext{a} and \ipatext{ɑ}, but unfortunately, in
% Italic shape, the latter is a variant of the former. E.g.,
% |[a\textit{a}]| produces \enquote{[a\textit{a}]}. Whenever
% an author uses Italic shape for their transcription and
% use |a|, a wrong \textsc{ipa} symbol is printed with most
% fonts. This problem was kindly acknowledged by Antonis
% Tsolomitis, the developer of New Computer Modern. In the
% stylistic set dedicated for linguistics, the correct shape
% was added to the Italic shape by him. Thus,
% |\ipatext{a\textit{a}}| (a command from \lngxipalogo)
% renders \enquote{\ipatext{a\textit{a}}}. The package
% enables New Computer Modern family with stylistic set 05
% dedicated for \textsc{ipa}. It also adds the brackets or
% slashes around the argument as explained in
% \cref{lngxipadoc}.
% 
% A similar problem is with the character |g|. E.g.,
% |[g\textit{g}]| produces \enquote{[g\textit{g}]}. Here,
% the situation is the other way round. The upright
% \enquote{g} is not recognised by the \textsc{ipa}. The
% \textsc{ipa} charts generally have the upright version of
% the Italic shape. To see what this means, try
% |\ipatext{g\textit{g}}|. It produces
% \ipatext{g\textit{g}} and not [g\textit{g}].
% 
% In order to avail all of these features, I have set New
% Computer Modern as the default font-family of \lngxpkg.
% The bundle provides options to control these defaults.
% Users can use their preferred text and \textsc{ipa} fonts.
% There also is an option to use the regular weight of NewCM
% instead of the book weight.
% 
% \section{Planned}
% 
% I plan to develop this bundle further in order to support
% the typesetting of good quality examples with interlinear
% glossing. My model is to imitate the output of the
% \pkg{expex} package, but with a modern \LaTeX-like syntax.
% I also plan to provide support for glossing. Currently the
% \pkg{leipzig} package is used, but it has some unresolved
% bugs. Some syntactic improvements are also possible, I
% believe.
% 
% \section{Funding}
% 
% I am a doctorate student without a fellowship (thanks to
% our education policies!) currently sustaining only with a
% full time job unrelated to linguistics that consumes most
% of my working hours. At times, it becomes difficult to
% continue the research, the job and the passion development
% projects. \lngxpkg\ needs funding in order to sustain. If
% you think you can support it, you can contact me on the
% email \textsc{id} found on the front page.
% 
% As of 2025-05-29, I have recieved funding from the \TeX\
% users group’s \TeX\ development fund. They have decided to
% support the development of \enquote{linguistix-glossing}
% (the logo will be available once the package is ready).
% 
% \section{Acknowledgements}
% 
% This package relies the most on the New Computer Modern
% font family. I would like to express my gratitude to
% Antonis Tsolomitis who tirelessly worked on the set of
% \textsc{ipa} symbols and brought back the good old charm
% of \textsc{tipa}’s design in the modern Unicode world. I
% would like to thank Renuka and Avinash who taught me
% linguistics. They nourished my passion, helped me pursue
% my love for the subject as well as the computation that
% came along with it. I could have never imagined myself
% working on a package written in \LaTeX3’s syntax. Not so
% long ago, I used to find it very complicated. It’s mostly
% Jonathan Spratte and Florent Rougon’s help (and, at times,
% scolding :P) that helped me get used to it. I would also
% like to mention C.V.\ Radhakrishnan for being an important
% part of my journey in \LaTeX. Lastly, to all the free
% software people who have created this friendly and
% supportive world for people by investing their precious
% time and resources!
% 
% Hardly in a week after the initial release, the \TeX\
% users group decided to financially support the development
% of a planned package in the bundle. I am grateful to them
% for their support.
% 
% \section*{Documentation}
% 
% The bundle is comprised of several packages that are
% developed for different purposes. In order to load all the
% packages of the bundle, one can issue:
%
% \begin{verbatim}
%     \usepackage{linguistix}
% \end{verbatim}
% 
% This is the easiest method for getting all of
% \lngxpkg\ in one go. But, if you don’t need all the
% packages of the bundle, you may load the required packages
% separately. We will start with the elementary package that
% sets up things for other packages of the bundle.
% 
% \lngxdocumentation{base}
% 
% This package provides a single command that is used in all
% the other packages of the bundle. The command is:
% 
% \begin{function}{\linguistix}
% \begin{syntax}
% \marg{key-value-list}
% \end{syntax}
% We have a single set of keys for the entire bundle. Each
% package appends keys to the same set. The argument of this
% central processor command is the comma-separated
% \meta{key-value-list}. So you can load any package of
% \lngxpkg\ and use the \cs[no-index]{linguistix} command.
% The only exception to this is \lngxnfsslogo. We will see
% how it is different in its section.
% \end{function}
% 
% \lngxdocumentation{fixpex}
% 
% This package offers a fix for the clash between
% \pkg{expex} and \pkg{unicode-math}. It provides a single
% command.
% 
% \begin{function}{\umgla}
% This is a replica of the \pkg{unicode-math}-|\gla|. Since
% the \pkg{expex}-|\gla| is more relevant in linguistics, I
% set it as the default. If one needs to use
% \pkg{unicode-math}-|\gla|, they can use this command.
% \end{function}
% 
% \lngxdocumentation{fonts}
% 
% This is a package that loads the New Computer Modern
% family for the entire document. The package sets fonts for
% both text and math. It has keys for customisation for
% both. Note that just loading this package does \emph{not}
% provide any support for \textsc{ipa}. For that one needs
% \lngxipalogo\ separately.
% 
% Antonis suggested a typographic enhancement for the logo
% of \LaTeX. The default logo scales the \enquote{A} and
% that affects the \enquote{colour} of the font. This is why
% I renew the logo with the code given by Antonis. The
% original logo is also available with an alternative
% command.
%
% \begin{function}{\LaTeX,\ogLaTeX}
% \begin{syntax}
% {\normalfont\LaTeX}
% {\normalfont\ogLaTeX}
% \end{syntax}
% \end{function}
% 
% The package provides only these commands. Let’s now have a
% look at the keys provided for the text.
% 
% \subsection{Text}
% 
% Most keys of this package are prefixed with the |text| in
% order to distinguish them from the maths and \textsc{ipa}
% ones. There aren’t any commands provided by the package.
% Most of the important features of the \pkg{fontspec}
% packakge are variablised with \pkg{l3keys}.
% 
% The \enquote{old style numbers} have varying heights. Some
% numbers have ascenders and some have descenders (e.g.,
% 6789). According to \cite{bringhurst}, this makes them
% easier to read in running text. Lining numbers, on the
% other hand have uniform heights. They go well with all
% capital text (rare). Thus, for the general text, I enable
% this setting by default in \lngxfontslogo.
% 
% Apart from that, the New Computer Modern font family
% provides an old-style shape for the number \enquote{1}
% (this exact shape!), but it is provided as a character
% variant. Different fonts may use these arbitrary slots for
% any character’s alternation. Therefore this setting should
% not be loaded blindly. Let’s have a look at the keys that
% can be employed to change these behaviours.
% 
% \begin{function}{old style numbers,old style one}
% \begin{syntax}
% = \marg{truth value}\hfill\lngxtval
% = \marg{truth value}\hfill\lngxfval
% \end{syntax}
% If one wants to disable old style numbers, they may use
% the |old style numbers| key with the |false| value
% (default is |true|)\footnote{The possible and the default
%   values of keys are given at the right side in the
%   documentation and the defaults are highlighted in
%   red.}. Note that printing of old style numbers
% also depends on whether the font you select has old style
% numbers or not. The relevant settings are added by the
% package to the font automatically, but while selecting the
% font, make sure whether the old style table is present in
% the font or not.
% 
% Suppose one wants the alternative shape of number
% \enquote{1} from the New Computer Modern family, they may
% use the key |old style one| (default is false; adding
% |true| is optional).
% \end{function}
% 
% Let’s have a look at the three way distinction we get
% because of this.
% 
% \begin{quote}
%   {\newcmnewone 0123456789}\hfill
%   \begingroup
%   \ttfamily\footnotesize\color{lngxredcolor}^^A
%   Old style with default 1^^A
%   \endgroup
% 
%   0123456789\hfill
%   \texttt{\footnotesize Old style with the old 1}^^A
% 
%   {\newcmnewnum 0123456789}\hfill
%   \texttt{\footnotesize Lining}^^A
% \end{quote}
% 
% \begin{function}{^^A
% newcm,newcm sans,newcm mono,^^A
% newcm regular,newcm regular sans,newcm regular mono^^A
% }
% These are some keys that come in handy for setting New
% Computer Modern defaults. All the necessary values are
% stored in these. The keys that have |regular| in their
% names refer to the \enquote{regular} variants of New
% Computer Modern fonts. These variants match the colour and
% widths of the Latin Modern fonts. One may use these keys
% to override the changed defaults.
% \end{function}
% 
% \subsection{Maths}
% 
% \lngxfontslogo\ sets maths fonts also. In order to control
% the settings related to maths, the following keys can be
% used.
% 
% \begin{function}{^^A
%   math,math features,math bold,math bold features^^A
% }
% \begin{syntax}
% = \marg{math font}
% = \marg{math font features}
% = \marg{bold math font}
% = \marg{bold math font features}
% \end{syntax}
% The |math| and |math bold| keys set the respective fonts
% (i.e., regular and bold fonts for mathematics
% respectively). The keys suffixed with |features| set the
% font features of the same.
% \end{function}
% 
% \begin{function}{bourbaki's empty set}
% \begin{syntax}
% = \marg{truth value}\hfill\lngxtval
% \end{syntax}
% In \bLaTeX, the default shape of the \enquote{empty set}
% symbol is: \enquote{\mathversion{emptyset}$\emptyset$},
% but the symbol used by the Bourbaki group is still
% considered more correct and preferred by many (including
% me). New Computer Modern Math fonts provide it as a
% character variant that I activate by default. Thus
% |$\emptyset$| always renders: \enquote{$\emptyset$} and
% not: \enquote{\mathversion{emptyset}$\emptyset$}. In order
% to change this behaviour, one may use this key and set it
% to false for getting the slashed-zero of original \bLaTeX.
% Hail plumbers union, \emph{\textsc{iykyk}! ;-)}
% \end{function}
% 
% \lngxdocumentation{ipa}
% 
% This package sets the fonts exclusively for the
% \textsc{ipa}. The commands provided for switching to the
% \textsc{ipa} control all serif, sans serif and typewriter
% families. This package can be loaded standalone for
% loading \textsc{ipa} fonts as well as some switch commands
% useful in running text. New Computer Modern provides a
% special stylistic set dedicated for linguistics. It is
% enabled for \textsc{ipa} fonts automatically with this
% package. Only the legally marked up \textsc{ipa} is
% affected by the customisation provided by this package.
% For switching to the \textsc{ipa}, \lngxipalogo\ provides
% one command with a starred variant.
% 
% \begin{function}{\ipatext,\ipatext*}
% \begin{syntax}
% \marg{phonetic transcription}
% \marg{phonemic transcription}
% \end{syntax}
% This is a command that resembles with the
% \pkg{\textsc{tipa}} command \cs[no-index]{textipa}. I have
% deliberately kept it distinct from it so that just in case
% somebody wants to use their old \textsc{tipa} code in a
% Unicode document, the commands won’t clash (I highly
% discourage doing this, though). The command comes with a
% starred variant. The behaviour of the un-starred command
% is to print the argument in brackets for phonetic
% transcription, e.g.: |\ipatext{aɪ̯ pʰiː eɪ̯}|^^A
% \,$\longrightarrow$\,\ipatext{aɪ̯ pʰiː eɪ̯} whereas the
% starred version prints it in slashes for phonemic
% transcription, e.g.: |\ipatext*{aɪ̯ pʰiː eɪ̯}|^^A
% \,$\longrightarrow$\,\ipatext*{aɪ̯ pʰiː eɪ̯}.
% \end{function}
% 
% Suppose someone just wants to load the font without the
% brackets or slashes, they cann use the following command
% for switching to the \textsc{ipa} without adding the
% aforementioned.
% 
% \begin{function}{\lngxipa}
% This also is a command that switches to the
% \textsc{ipa}-only features (default as well as user
% added). This command, of course, leaks and that’s why
% \emph{should} be delimited. E.g., the following code
% lines produce {\lngxipa [aɪ̯ pʰiː eɪ̯]} and {\lngxipa /aɪ̯
% pʰiː eɪ̯/} respectively:
% 
% \begin{verbatim}
%     {\lngxipa [aɪ̯ pʰiː eɪ̯]}
%     {\lngxipa /aɪ̯ pʰiː eɪ̯/}
% \end{verbatim}
% \end{function}
% 
% \begin{function}{^^A
% ipa newcm,ipa newcm sans,ipa newcm mono,^^A
% ipa newcm regular,ipa newcm regular sans,^^A
% ipa newcm regular mono^^A
% }
% All the \textsc{ipa} fonts are stored in variables as
% seen in \cref{lngxfontstable} and \cref{lngxtltable}.
% These keys reset the \textsc{ipa}-only fonts to New
% Computer Modern. They can be used even for resetting to
% New Computer Modern from another \textsc{ipa} font. In
% order to change or reset to the \textsc{ipa} defaults
% these keys can be used. They store the names of the New
% Computer Modern font family in the variables concerning
% \textsc{ipa}. The keys that contain |regular| in their
% name use the regular version of New Computer Modern that
% matches the colour of Latin Modern.
% \end{function}
% 
% Let’s now see the combined table of font keys provided by
% both \lngxfontslogo\ and \lngxipalogo.
% 
% \begingroup
% \begin{longtable}{%
%   l%
%   >{%
%     \lngxcondensed
%     \addfontfeature{FakeStretch=0.8}%
%   }l%
%   >{%
%     \lngxcondensed
%     \addfontfeature{FakeStretch=0.8}%
%   }l%
% }
%   \toprule
%   Family
%     & \lngxfontslogo
%       & \lngxipalogo \\
%   \midrule
%   \endfirsthead
%   \toprule
%   Family
%     & \lngxfontslogo
%       & \lngxipalogo \\
%   \midrule
%   \endhead
%   \midrule
%   \multicolumn{3}{r}{^^A
%     \small
%     \emph{Continued on the next page\dots}^^A
%   } \\
%   \bottomrule
%   \endfoot
%   \midrule
%   \multicolumn{3}{r}{^^A
%     \small
%     \emph{End of the table\dots}^^A
%   } \\
%   \bottomrule
%   \addlinespace
%   \caption{^^A
%     Font keys provided by \lngxfontslogo\ and \lngxipalogo
%   }\label{lngxfontstable}\\
%   \endlastfoot
%   Serif
%     & \fn{text upright}
%       & \fn{ipa upright} \\
%     & \fn{text upright features}
%       & \fn{ipa upright features} \\
%     & \fn{text bold upright}
%       & \fn{ipa bold upright} \\
%     & \fn{text bold upright features}
%       & \fn{ipa bold upright features} \\
%     & \fn{text italic}
%       & \fn{ipa italic} \\
%     & \fn{text italic features}
%       & \fn{ipa italic features} \\
%     & \fn{text bold italic}
%       & \fn{ipa bold italic} \\
%     & \fn{text bold italic features}
%       & \fn{ipa bold italic features} \\
%     & \fn{text slanted}
%       & \fn{ipa slanted} \\
%     & \fn{text slanted features}
%       & \fn{ipa slanted features} \\
%     & \fn{text bold slanted}
%       & \fn{ipa bold slanted} \\
%     & \fn{text bold slanted features}
%       & \fn{ipa bold slanted features} \\
%     & \fn{text swash}
%       & \fn{ipa swash} \\
%     & \fn{text swash features}
%       & \fn{ipa swash features} \\
%     & \fn{text bold swash}
%       & \fn{ipa bold swash} \\
%     & \fn{text bold swash features}
%       & \fn{ipa bold swash features} \\
%     & \fn{text small caps}
%       & \fn{ipa small caps} \\
%     & \fn{text small caps features}
%       & \fn{ipa small caps features} \\
%   \midrule
%   Sans serif
%     & \fn{text sans upright}
%       & \fn{ipa sans upright} \\
%     & \fn{text sans upright features}
%       & \fn{ipa sans upright features} \\
%     & \fn{text sans bold upright}
%       & \fn{ipa sans bold upright} \\
%     & \fn{text sans bold upright features}
%       & \fn{ipa sans bold upright features} \\
%     & \fn{text sans italic}
%       & \fn{ipa sans italic} \\
%     & \fn{text sans italic features}
%       & \fn{ipa sans italic features} \\
%     & \fn{text sans bold italic}
%       & \fn{ipa sans bold italic} \\
%     & \fn{text sans bold italic features}
%       & \fn{ipa sans bold italic features} \\
%     & \fn{text sans slanted}
%       & \fn{ipa sans slanted} \\
%     & \fn{text sans slanted features}
%       & \fn{ipa sans slanted features} \\
%     & \fn{text sans bold slanted}
%       & \fn{ipa sans bold slanted} \\
%     & \fn{text sans bold slanted features}
%       & \fn{ipa sans bold slanted features} \\
%     & \fn{text sans swash}
%       & \fn{ipa sans swash} \\
%     & \fn{text sans swash features}
%       & \fn{ipa sans swash features} \\
%     & \fn{text sans bold swash}
%       & \fn{ipa sans bold swash} \\
%     & \fn{text sans bold swash features}
%       & \fn{ipa sans bold swash features} \\
%     & \fn{text sans small caps}
%       & \fn{ipa sans small caps} \\
%     & \fn{text sans small caps features}
%       & \fn{ipa sans small caps features} \\
%   \midrule
%   Monospaced
%     & \fn{text mono upright}
%       & \fn{ipa mono upright} \\
%     & \fn{text mono upright features}
%       & \fn{ipa mono upright features} \\
%     & \fn{text mono bold upright}
%       & \fn{ipa mono bold upright} \\
%     & \fn{text mono bold upright features}
%       & \fn{ipa mono bold upright features} \\
%     & \fn{text mono italic}
%       & \fn{ipa mono italic} \\
%     & \fn{text mono italic features}
%       & \fn{ipa mono italic features} \\
%     & \fn{text mono bold italic}
%       & \fn{ipa mono bold italic} \\
%     & \fn{text mono bold italic features}
%       & \fn{ipa mono bold italic features} \\
%     & \fn{text mono slanted}
%       & \fn{ipa mono slanted} \\
%     & \fn{text mono slanted features}
%       & \fn{ipa mono slanted features} \\
%     & \fn{text mono bold slanted}
%       & \fn{ipa mono bold slanted} \\
%     & \fn{text mono bold slanted features}
%       & \fn{ipa mono bold slanted features} \\
%     & \fn{text mono swash}
%       & \fn{ipa mono swash} \\
%     & \fn{text mono swash features}
%       & \fn{ipa mono swash features} \\
%     & \fn{text mono bold swash}
%       & \fn{ipa mono bold swash} \\
%     & \fn{text mono bold swash features}
%       & \fn{ipa mono bold swash features} \\
%     & \fn{text mono small caps}
%       & \fn{ipa mono small caps} \\
%     & \fn{text mono small caps features}
%       & \fn{ipa mono small caps features} \\
% \end{longtable}
% \endgroup
% 
% \lngxdocumentation{logos}
% 
% This is a small package that provides commands for
% printing logos of the \lngxpkg\ bundle. The logo is
% printed in New Computer Modern Uncial font. It uses purple
% colour for the \enquote{X} in it and it is defined using
% \pkg{l3color} module. It provides one command that takes
% an optional argument. Obviously it is ‘|protect|ed’. It is
% as follows:
% 
% \begin{function}{\lngxlogo}
% \begin{syntax}
% \oarg{package name}
% \end{syntax}
% The logo of the \meta{package name} from the \lngxpkg\
% bundle is printed with this command, e.g.,
% |\lngxlogo{fonts}|\,$\longrightarrow$\,\lngxlogo{fonts}.
% \end{function}
% 
% Sometimes, the logos might be required to be used in an
% expandable way, but optional arguments are not supported
% in expandable commands. Thus we create separate commands
% for separate packages. Even these ones have the |lngx|
% prefix. It is followed by the package name, e.g., |fonts|
% or |ipa| and finally the suffix |logo|. In the context of
% \pkg{hyperref}, their behaviour is different than in the
% context of normal text. The commands and their are as
% follows:
% 
% \begin{function}[EXP]{^^A
%   \lngxpkg,\lngxbaselogo,\lngxfontslogo,\lngxipalogo,^^A
%   \lngxlogoslogo,\lngxnfsslogo^^A
% }
% \begin{syntax}
% \lngxpkg
% \lngxbaselogo
% \lngxfontslogo
% \lngxipalogo
% \lngxlogoslogo
% \lngxnfsslogo
% \end{syntax}
% \end{function}
% 
% \lngxdocumentation{nfss}
% 
% This is an extension package to the existing \textsc{nfss}
% scheme of \LaTeX. The \textsc{nfss} mainly works on the
% four facets of the text.
% 
% \begin{enumerate}
% \item Encoding
% \item Family
% \item Shape
% \item Series
% \end{enumerate}
% 
% These facets are reset to default by the |\normalfont| and
% |\selectfont| commands. These commands work on some
% internals that are reset with every usage of some commands
% that set them, e.g., |\rmfamily|, |\bfseries|. There isn’t
% any way to control this unless some internals are touched
% and there might be incidences where one does want to
% control them, e.g., try compiling the following code in
% Lua\LaTeX.
% 
% \rule{0.7\linewidth}{0.5pt}
% 
% \begin{verbatim}
%     \documentclass{article}
% 
%     \begin{document}
%     \makeatletter
%     \fontencoding{OT1}\sffamily\itshape\bfseries
%     \selectfont
%     \f@encoding\ | \f@family\ | \f@series\ | \f@shape\quad
%     \normalfont
%     \f@encoding\ | \f@family\ | \f@series\ | \f@shape
%     \end{document}
% \end{verbatim}
% 
% \rule{0.7\linewidth}{0.5pt}
% 
% \medskip
% 
% As can be seen in the output, the first line shows the
% text in \textsc{ot}1 encoding, sans family, bold series
% and Italic shape. After |\normalfont|, every aspect of the
% text is reset to the default one. The default encoding is
% \textsc{tu}. We can see \textsc{tu} instead of
% \textsc{ot}1 after |\normalfont|. So is the case with
% family (default: |\rmfamily|), series (default:
% |\mdseries|) and shape (default: |\upshape|). This usually
% is okay, but sometimes it doesn’t fit the requirement.
% E.g., the following might be used with the intention of
% switching from the \textsc{ipa} font to the text font, but
% as can be seen, it doesn’t really change anything.
% 
% \rule{0.7\linewidth}{0.5pt}
% 
% \begin{verbatim}
%     \documentclass{article}
%     \usepackage{linguistix-fonts}
%     \usepackage{linguistix-ipa}
%     \linguistix{%
%       text upright           = {KpRoman-Regular.otf},%
%       text upright features  = {Color={green}},%
%       ipa upright            = {KpSans-Regular.otf},%
%       ipa upright features   = {Color={red}}%
%     }
% 
%     \begin{document}
%     test \lngxipa test \normalfont test
%     \end{document}
% \end{verbatim}
% 
% \rule{0.7\linewidth}{0.5pt}
% 
% \medskip
% 
% The reason for this is the way \cs{lngxipa} is defined. It
% resets |\rmdefault|, |\sfdefault| and |\ttdefault| and
% uses |\normalfont| to initialise this new super font
% family (see:
% \url{https://tex.stackexchange.com/a/729805}). Setting a
% \enquote{super} font family effectively changes the
% behaviour of |\normalfont| permanently. By the way, this
% is not just something that \lngxpkg\ has to deal with.
% This situation may arise whenever one wants to have a font
% family command that sets all serif, sans serif and
% monospaced font families. \lngxnfsslogo\ is useful in such
% cases. It introduces the concept of \enquote{super} font
% family. It shouldn’t be confused with
% \pkg{\hologo{LaTeX2e}}’s \enquote{meta} font family. It
% refers to |rm|, |sf| or |tt| in the kernel. Note that, as
% of now, \hologo{LaTeX2e} does \emph{not} provide any
% public interface to save \enquote{meta} family, as well
% as, the current encoding, series and shape. This package
% provides control over these facets. Let’s have a look at
% the macros it provides.
% 
% \begin{function}[EXP]{^^A
% \IfEncodingTF,\IfEncodingT,\IfEncodingF,\CurrentEncoding
% }
% \begin{syntax}
% \marg{encoding} \marg{true code} \marg{false code}
% \marg{encoding} \marg{true code}
% \marg{encoding} \marg{false code}
% \end{syntax}
% If the current encoding matches with the given
% \meta{encoding}, it selects the true branch; false
% otherwise. The \cs{CurrentEncoding} macro expands to the
% current encoding.
% \end{function}
% 
% \begin{function}[EXP]{^^A
% \IfMetaFamilyTF,\IfMetaFamilyT,\IfMetaFamilyF,^^A
% \CurrentMetaFamily
% }
% \begin{syntax}
% \marg{meta family} \marg{true code} \marg{false code}
% \marg{meta family} \marg{true code}
% \marg{meta family} \marg{false code}
% \end{syntax}
% If the current meta family matches with the given
% \meta{meta family}, it selects the true branch; false
% otherwise. The \cs{CurrentMetaFamily} macro expands to the
% current meta family.
% \end{function}
% 
% \begin{function}[EXP]{^^A
% \IfSuperFamilyTF,\IfSuperFamilyT,\IfSuperFamilyF,^^A
% \CurrentSuperFamily
% }
% \begin{syntax}
% \marg{super family} \marg{true code} \marg{false code}
% \marg{super family} \marg{true code}
% \marg{super family} \marg{false code}
% \end{syntax}
% If the current super family matches with the given
% \meta{super family}, it selects the true branch; false
% otherwise. The \cs{CurrentSuperFamily} macro expands to
% the current super family.
% \end{function}
% 
% \begin{function}[EXP]{^^A
%   \IfSeriesTF,\IfSeriesT,\IfSeriesF,\CurrentSeries
% }
% \begin{syntax}
% \marg{series} \marg{true code} \marg{false code}
% \marg{series} \marg{true code}
% \marg{series} \marg{false code}
% \end{syntax}
% If the current series matches with the given
% \meta{series}, it selects the true branch and false
% otherwise. The \cs{CurrentSeries} macro expands to the
% current series.
% \end{function}
% 
% \begin{function}[EXP]{^^A
%   \IfShapeTF,\IfShapeT,\IfShapeF,\CurrentShape
% }
% \begin{syntax}
% \marg{shape} \marg{true code} \marg{false code}
% \marg{shape} \marg{true code}
% \marg{shape} \marg{false code}
% \end{syntax}
% If the current series matches with the given \meta{shape},
% it selects the true branch and false otherwise. The
% \cs{CurrentShape} macro expands to the current shape.
% \end{function}
% 
% \begin{function}{\superfontfamily}
% \begin{syntax}
% \marg{family \textsc{id}}^^A
% \marg{rm=\marg{rm \textsc{nfss}},\ignorespaces^^A
% sf=\marg{sf \textsc{nfss}},tt=\marg{tt \textsc{nfss}}}
% \end{syntax}
% Every super font family has a \meta{family \textsc{id}},
% even the default one (i.e., |default|). This command
% creates a super family with the given \meta{family
% \textsc{id}}s. The \meta{meta family keys} argument
% accepts a list of specific keys, |rm|, |sf| and |tt|. They
% take the \textsc{nfss} family names of these meta families
% as arguments. One may define a font with, say,
% |\newfontfamily|, pass the |NFSSkeys=|\marg{key} option to
% it and use the \meta{key} in the suitable \meta{meta
% family key}. Note that using all these keys is \emph{not}
% mandatory. A super family may have $\leq 3$ keys.
% \end{function}
% 
% \begin{function}{^^A
% \softsuperfontfamily,\softersuperfontfamily,^^A
% \softestsuperfontfamily
% }
% \begin{syntax}
% \marg{\textsc{id}}\ignorespaces^^A
% \marg{encoding,family,series,shape}
% \marg{\textsc{id}}
% \marg{\textsc{id}}
% \end{syntax}
% These commands loads the super font family with the given
% \meta{\textsc{id}}. The attributes listed in the second
% argument are the only choices available. The required
% super font family is loaded and the listed attributes are
% reset to the ones that were active before. All the four
% are not required. The number of attributes may be $\leq
% 4$. The \cs{softernormalfont} command excludes encoding
% and reactivates all the other attributes, whereas the
% \cs{softestnormalfont} command reactivates all of them.
% \end{function}
% 
% \begin{function}{^^A
% \softnormalfont,\softernormalfont,\softestnormalfont
% }
% \begin{syntax}
% \marg{encoding,family,series,shape}
% \end{syntax}
% Similar to \cs{softsuperfontfamily} and friends, these
% commands switch back to the default super font family, but
% reactivate the previously active font attributes. The
% argument to \cs{softnormalfont} takes the list of the
% required font attributes. It can have $\leq 4$ values. Now
% try the following example:
% \end{function}
% 
% \rule{0.7\linewidth}{0.5pt}
% 
% \begin{verbatim}
%     \documentclass{article}
%     \usepackage{linguistix}
%     \linguistix{%
%       text upright features  = {Color={green}},%
%       ipa upright features   = {Color={red}}%
%     }
% 
%     \begin{document}
%     test \lngxipa test \softernormalfont test\par
%     \makeatletter
%     \sffamily\itshape\bfseries
%     \f@family\ | \f@series\ | \f@shape\quad
%     \softnormalfont{series}
%     \f@family\ | \f@series\ | \f@shape
%     \end{document}
% \end{verbatim}
% 
% \rule{0.7\linewidth}{0.5pt}
% 
% \medskip
% 
% Better? :-)
% 
% \section*{^^A
%   \texorpdfstring{^^A
%     \LaTeX3 interface for programmers^^A
%   }{^^A
%     LaTeX3 interface for programmers^^A
%   }^^A
% }
% 
% In this section, we take a look at the public \LaTeX3
% commands of the bundle. These can be considered stable and
% can be used in production code.
% 
% \lngxinterface{base}
% 
% \begin{function}{\lngx_set_keys:n}
% \begin{syntax}
% \meta{keyval list}
% \end{syntax}
% This is the base command for \cs{linguistix}. It takes a
% comma separated list of \meta{keyval list} and parses it.
% \end{function}
% 
% \lngxinterface{fixpex}
% 
% No \LaTeX3 function provided by this package.
% 
% \lngxinterface{fonts}
% 
% \begin{function}{^^A
%   \g_lngx_old_style_bool,\g_lngx_old_style_one_bool,^^A
%   \g_lngx_bourbaki_bool
% }
% These are the two booleans that are used to check if the
% old style numbers, the old style one (i.e., \enquote{1})
% and Bourbaki’s emtpy set symbol (i.e.,
% \enquote{$\emptyset$}) is asked by the user.
% \end{function}
% 
% \begin{function}{^^A
%   \lngx_set_main_font:nn,\lngx_set_main_font:ee,^^A
%   \lngx_set_sans_font:nn,\lngx_set_sans_font:ee,^^A
%   \lngx_set_mono_font:nn,\lngx_set_mono_font:ee,^^A
%   \lngx_set_math_font:nn,\lngx_set_math_font:ee
% }
% \begin{syntax}
% \marg{features} \marg{font}
% \marg{features} \marg{font}
% \marg{features} \marg{font}
% \marg{features} \marg{font}
% \end{syntax}
% These commands take two arguments, expand them if the
% |:ee| variant is used. These are wrapper commands around
% the font-setting commands of \pkg{fontspec} and
% \pkg{unicode-math}, i.e.,  |\setmainfont|, |\setsansfont|,
% |\setmonofont| and |\setmathfont|. The \meta{features} are
% passed to the optional argument and the \meta{font} is
% passed to the mandatory argument of the respective command
% from the aforementioned list.
% \end{function}
% 
% \lngxinterface{ipa}
% 
% This package provides a few wrapper functions around
% \pkg{fontspec}’s commands.
% 
% \begin{function}{^^A
%   \lngx_set_main_ipa_font:nn,^^A
%   \lngx_set_main_ipa_font:ee,^^A
%   \lngx_main_ipa:,lngx_ipa_rm_nfss^^A
% }
% \begin{syntax}
% \marg{features} \marg{font}
% \end{syntax}
% These functions set the \textsc{ipa} fonts for the serif
% variants. The \meta{font} is set with \meta{features} for
% the serif \textsc{ipa}. The command to switch to this
% family is \cs{lngx_main_ipa:}. It can be accessed with the
% \textsc{nfss} family |lngx_ipa_rm_nfss|.
% \end{function}
% 
% \begin{function}{^^A
%   \lngx_set_sans_ipa_font:nn,^^A
%   \lngx_set_sans_ipa_font:ee,^^A
%   \lngx_sans_ipa:,lngx_ipa_sf_nfss^^A
% }
% \begin{syntax}
% \marg{features} \marg{font}
% \end{syntax}
% These functions set the \textsc{ipa} fonts for the sans
% variants. The \meta{font} is set with \meta{features} for
% the sans \textsc{ipa}. The command to switch to this
% family is \cs{lngx_sans_ipa:}. It can be accessed with the
% \textsc{nfss} family |lngx_ipa_sf_nfss|.
% \end{function}
% 
% \begin{function}{^^A
%   \lngx_set_mono_ipa_font:nn,^^A
%   \lngx_set_mono_ipa_font:ee,^^A
%   \lngx_mono_ipa:,lngx_ipa_tt_nfss^^A
% }
% \begin{syntax}
% \marg{features} \marg{font}
% \end{syntax}
% These functions set the \textsc{ipa} fonts for the mono
% variants. The \meta{font} is set with \meta{features} for
% the mono \textsc{ipa}. The command to switch to this
% family is \cs{lngx_mono_ipa:}. It can be accessed with the
% \textsc{nfss} family |lngx_ipa_nfss_nfss|.
% \end{function}
% 
% \begin{function}{\lngx_ipa:,lngx_ipa}
% The \cs{lngx_ipa:} command loads the super family
% |lngx_ipa| (see the documentation of \lngxnfsslogo. The
% \cs{lngx_ipa:} function has a user-side command
% \cs{lngxipa} too.
% \end{function}
% 
% \subsection*{Variables for fonts and features}
% 
% Now we look at the table that summarises the |tl|s that
% are used by the package for saving serif, sans serif and
% monospaced fonts and their features. Note that this table
% also lists the |tl|s used by the \lngxipalogo\ package.
% 
% \begin{longtable}{%
%   >{%
%     \lngxcondensed
%     \addfontfeature{FakeStretch=0.525}%
%   }l%
%   >{%
%     \lngxcondensed
%     \addfontfeature{FakeStretch=0.525}%
%   }l%
%   >{%
%     \lngxcondensed
%     \addfontfeature{FakeStretch=0.525}%
%   }l%
% }
%   \toprule
%   \multicolumn{1}{l}{Serif}
%     & \multicolumn{1}{l}{Sans serif}
%       & \multicolumn{1}{l}{Monospaced} \\
%   \midrule
%   \endfirsthead
%   \toprule
%   \multicolumn{1}{l}{Serif}
%     & \multicolumn{1}{l}{Sans serif}
%       & \multicolumn{1}{l}{Monospaced} \\
%   \midrule
%   \endhead
%   \midrule
%   \multicolumn{3}{r}{^^A
%     \small
%     \emph{Continued on the next page\dots}^^A
%   } \\
%   \bottomrule
%   \endfoot
%   \midrule
%   \multicolumn{3}{r}{^^A
%     \small
%     \emph{End of the table\dots}^^A
%   } \\
%   \bottomrule
%   \addlinespace
%   \caption{^^A
%     Variables for fonts and font features provided by
%     \lngxfontslogo\ and \lngxipalogo
%   }\label{lngxtltable}\\
%   \endlastfoot
%   \fn{\g_lngx_text_upright_tl}
%     & \fn{\g_lngx_text_sans_upright_tl}
%       & \fn{\g_lngx_text_mono_upright_tl} \\
%   \fn{\g_lngx_ipa_upright_tl}
%     & \fn{\g_lngx_ipa_sans_upright_tl}
%       & \fn{\g_lngx_ipa_mono_upright_tl} \\
%   \fn{\g_lngx_text_upright_features_tl}
%     & \fn{\g_lngx_text_sans_upright_features_tl}
%       & \fn{\g_lngx_text_mono_upright_features_tl} \\
%   \fn{\g_lngx_ipa_upright_features_tl}
%     & \fn{\g_lngx_ipa_sans_upright_features_tl}
%       & \fn{\g_lngx_ipa_mono_upright_features_tl} \\
%   \fn{\g_lngx_text_bold_upright_tl}
%     & \fn{\g_lngx_text_sans_bold_upright_tl}
%       & \fn{\g_lngx_text_mono_bold_upright_tl} \\
%   \fn{\g_lngx_ipa_bold_upright_tl}
%     & \fn{\g_lngx_ipa_sans_bold_upright_tl}
%       & \fn{\g_lngx_ipa_mono_bold_upright_tl} \\
%   \fn{\g_lngx_text_bold_upright_features_tl}
%     & \fn{\g_lngx_text_sans_bold_upright_features_tl}
%       & \fn{\g_lngx_text_mono_bold_upright_features_tl} \\
%   \fn{\g_lngx_ipa_bold_upright_features_tl}
%     & \fn{\g_lngx_ipa_sans_bold_upright_features_tl}
%       & \fn{\g_lngx_ipa_mono_bold_upright_features_tl} \\
%   \fn{\g_lngx_text_italic_tl}
%     & \fn{\g_lngx_text_sans_italic_tl}
%       & \fn{\g_lngx_text_mono_italic_tl} \\
%   \fn{\g_lngx_ipa_italic_tl}
%     & \fn{\g_lngx_ipa_sans_italic_tl}
%       & \fn{\g_lngx_ipa_mono_italic_tl} \\
%   \fn{\g_lngx_text_italic_features_tl}
%     & \fn{\g_lngx_text_sans_italic_features_tl}
%       & \fn{\g_lngx_text_mono_italic_features_tl} \\
%   \fn{\g_lngx_ipa_italic_features_tl}
%     & \fn{\g_lngx_ipa_sans_italic_features_tl}
%       & \fn{\g_lngx_ipa_mono_italic_features_tl} \\
%   \fn{\g_lngx_text_bold_italic_tl}
%     & \fn{\g_lngx_text_sans_bold_italic_tl}
%       & \fn{\g_lngx_text_mono_bold_italic_tl} \\
%   \fn{\g_lngx_ipa_bold_italic_tl}
%     & \fn{\g_lngx_ipa_sans_bold_italic_tl}
%       & \fn{\g_lngx_ipa_mono_bold_italic_tl} \\
%   \fn{\g_lngx_text_bold_italic_features_tl}
%     & \fn{\g_lngx_text_sans_bold_italic_features_tl}
%       & \fn{\g_lngx_text_mono_bold_italic_features_tl} \\
%   \fn{\g_lngx_ipa_bold_italic_features_tl}
%     & \fn{\g_lngx_ipa_sans_bold_italic_features_tl}
%       & \fn{\g_lngx_ipa_mono_bold_italic_features_tl} \\
%   \fn{\g_lngx_text_slanted_tl}
%     & \fn{\g_lngx_text_sans_slanted_tl}
%       & \fn{\g_lngx_text_mono_slanted_tl} \\
%   \fn{\g_lngx_ipa_slanted_tl}
%     & \fn{\g_lngx_ipa_sans_slanted_tl}
%       & \fn{\g_lngx_ipa_mono_slanted_tl} \\
%   \fn{\g_lngx_text_slanted_features_tl}
%     & \fn{\g_lngx_text_sans_slanted_features_tl}
%       & \fn{\g_lngx_text_mono_slanted_features_tl} \\
%   \fn{\g_lngx_ipa_slanted_features_tl}
%     & \fn{\g_lngx_ipa_sans_slanted_features_tl}
%       & \fn{\g_lngx_ipa_mono_slanted_features_tl} \\
%   \fn{\g_lngx_text_bold_slanted_tl}
%     & \fn{\g_lngx_text_sans_bold_slanted_tl}
%       & \fn{\g_lngx_text_mono_bold_slanted_tl} \\
%   \fn{\g_lngx_ipa_bold_slanted_tl}
%     & \fn{\g_lngx_ipa_sans_bold_slanted_tl}
%       & \fn{\g_lngx_ipa_mono_bold_slanted_tl} \\
%   \fn{\g_lngx_text_bold_slanted_features_tl}
%     & \fn{\g_lngx_text_sans_bold_slanted_features_tl}
%       & \fn{\g_lngx_text_mono_bold_slanted_features_tl} \\
%   \fn{\g_lngx_ipa_bold_slanted_features_tl}
%     & \fn{\g_lngx_ipa_sans_bold_slanted_features_tl}
%       & \fn{\g_lngx_ipa_mono_bold_slanted_features_tl} \\
%   \fn{\g_lngx_text_swash_tl}
%     & \fn{\g_lngx_text_sans_swash_tl}
%       & \fn{\g_lngx_text_mono_swash_tl} \\
%   \fn{\g_lngx_ipa_swash_tl}
%     & \fn{\g_lngx_ipa_sans_swash_tl}
%       & \fn{\g_lngx_ipa_mono_swash_tl} \\
%   \fn{\g_lngx_text_swash_features_tl}
%     & \fn{\g_lngx_text_sans_swash_features_tl}
%       & \fn{\g_lngx_text_mono_swash_features_tl} \\
%   \fn{\g_lngx_ipa_swash_features_tl}
%     & \fn{\g_lngx_ipa_sans_swash_features_tl}
%       & \fn{\g_lngx_ipa_mono_swash_features_tl} \\
%   \fn{\g_lngx_text_bold_swash_tl}
%     & \fn{\g_lngx_text_sans_bold_swash_tl}
%       & \fn{\g_lngx_text_mono_bold_swash_tl} \\
%   \fn{\g_lngx_ipa_bold_swash_tl}
%     & \fn{\g_lngx_ipa_sans_bold_swash_tl}
%       & \fn{\g_lngx_ipa_mono_bold_swash_tl} \\
%   \fn{\g_lngx_text_bold_swash_features_tl}
%     & \fn{\g_lngx_text_sans_bold_swash_features_tl}
%       & \fn{\g_lngx_text_mono_bold_swash_features_tl} \\
%   \fn{\g_lngx_ipa_bold_swash_features_tl}
%     & \fn{\g_lngx_ipa_sans_bold_swash_features_tl}
%       & \fn{\g_lngx_ipa_mono_bold_swash_features_tl} \\
%   \fn{\g_lngx_text_small_caps_tl}
%     & \fn{\g_lngx_text_sans_small_caps_tl}
%       & \fn{\g_lngx_text_mono_small_caps_tl} \\
%   \fn{\g_lngx_ipa_small_caps_tl}
%     & \fn{\g_lngx_ipa_sans_small_caps_tl}
%       & \fn{\g_lngx_ipa_mono_small_caps_tl} \\
%   \fn{\g_lngx_text_small_caps_features_tl}
%     & \fn{\g_lngx_text_sans_small_caps_features_tl}
%       & \fn{\g_lngx_text_mono_small_caps_features_tl} \\
%   \fn{\g_lngx_ipa_small_caps_features_tl}
%     & \fn{\g_lngx_ipa_sans_small_caps_features_tl}
%       & \fn{\g_lngx_ipa_mono_small_caps_features_tl} \\
% \end{longtable}
% 
% \lngxinterface{logos}
% 
% There are only two \LaTeX3 functions provided by this
% package.
% 
% \begin{function}{\lngx_logo_font:}
% This function switches to the New Computer Modern Uncial
% font family.
% \end{function}
% 
% \begin{function}{lngx_purple_color}
% I don’t like the default purple colour of the \pkg{xcolor}
% package (i.e., \colorbox{purple}{\phantom{x}}\,). Thus I
% have created a new colour using \pkg{l3color} module. It
% can be accessed using this variable. The color looks like:
% \colorbox{lngxpurplecolor}{\phantom{x}}.
% \end{function}
% 
% \lngxinterface{nfss}
% 
% This subsection discusses the programming interface
% \lngxnfsslogo\ provides.
% 
% \begin{function}[EXP]{^^A
% \c_lngx_default_rmdefault_tl,^^A
% \c_lngx_default_sfdefault_tl,^^A
% \c_lngx_default_ttdefault_tl
% }
% \begin{syntax}
% \normalfont\normalsize^^A
% These |tl|s expand to the default values of the fonts^^A
% set at the |begindocument/end| hook. These are not^^A
% supposed to be changed and hence they are set with^^A
% the |c| prefix.
% \end{syntax}
% \end{function}
% 
% \begin{function}[EXP]{^^A
% \l_lngx_current_encoding_tl,^^A
% \l_lngx_current_meta_family_tl,^^A
% \l_lngx_current_super_family_tl,^^A
% \l_lngx_current_series_tl,^^A
% \l_lngx_current_shape_tl
% }
% \begin{syntax}
% \normalfont\normalsize^^A
% These |tl|s expand to the current values of encoding,^^A
% meta family, super family, series and shape^^A
% respectively. Note that these are updated time to time^^A
% by the commands that change them (package-internal or^^A
% \LaTeX-internal).
% \end{syntax}
% \end{function}
% 
% \begin{function}[EXP,pTF]{^^A
% \lngx_if_encoding:n,\lngx_if_meta_family:n,^^A
% \lngx_if_super_family:n,\lngx_if_series:n,\lngx_if_shape:n
% }
% \begin{syntax}
% \marg{encoding}
% \marg{encoding}\marg{true code}\marg{false code}
% \marg{meta font family}
% \marg{meta font family}\marg{true code}\marg{false code}
% \marg{super font family}
% \marg{super font family}\marg{true code}\marg{false code}
% \marg{series}
% \marg{series}\marg{true code}\marg{false code}
% \marg{shape}
% \marg{shape}\marg{true code}\marg{false code}
% \end{syntax}
% \end{function}
% 
% \begin{function}[EXP,pTF]{^^A
% \lngx_if_meta_family_rm:,\lngx_if_meta_family_sf:,^^A
% \lngx_if_meta_family_tt:
% }
% \begin{syntax}
% \phantom{x}
% \marg{true code}\marg{false code}
% \phantom{x}
% \marg{true code}\marg{false code}
% \phantom{x}
% \marg{true code}\marg{false code}
% \end{syntax}
% These conditionals select the true branch if the |rm|,
% |sf|, |tt| families (respectively) are active, false
% otherwise.
% \end{function}
% 
% \begin{function}[EXP,pTF]{^^A
% \lngx_if_series_md:,\lngx_if_series_bf:
% }
% \begin{syntax}
% \phantom{x}
% \marg{true code}\marg{false code}
% \phantom{x}
% \marg{true code}\marg{false code}
% \end{syntax}
% These conditionals select the true branch if the |md|,
% |bf| series (respectively) are active, false otherwise.
% \end{function}
% 
% \begin{function}[EXP,pTF]{^^A
% \lngx_if_shape_up:,\lngx_if_shape_it:,^^A
% \lngx_if_shape_sc:,\lngx_if_shape_ssc:,^^A
% \lngx_if_shape_sl:,\lngx_if_shape_sw:,^^A
% \lngx_if_shape_ulc:
% }
% \begin{syntax}
% \phantom{x}
% \marg{true code}\marg{false code}
% \phantom{x}
% \marg{true code}\marg{false code}
% \phantom{x}
% \marg{true code}\marg{false code}
% \phantom{x}
% \marg{true code}\marg{false code}
% \phantom{x}
% \marg{true code}\marg{false code}
% \phantom{x}
% \marg{true code}\marg{false code}
% \phantom{x}
% \marg{true code}\marg{false code}
% \end{syntax}
% These conditionals select the true branch if the |up|,
% |it|, |sc|, |ssc|, |sl|, |sw|, |ulc| shapes (respectively)
% are active, false otherwise.
% \end{function}
% 
% \begin{function}{\lngx_super_font_family:nn}
% \begin{syntax}
% \marg{family \textsc{id}}^^A
% \marg{rm=\marg{rm \textsc{nfss}},\ignorespaces^^A
% sf=\marg{sf \textsc{nfss}},tt=\marg{tt \textsc{nfss}}}
% \end{syntax}
% This function takes an \meta{\textsc{id}} and sets the
% |rm|, |sf|, |tt| values as requested by the user and
% creates a super font family.
% \end{function}
% 
% \begin{function}{^^A
% \lngx_soft_super_font_family:nn,^^A
% \lngx_softer_super_font_family:n,^^A
% \lngx_softest_super_font_family:n
% }
% \begin{syntax}
% \marg{\textsc{id}}\ignorespaces^^A
% \marg{encoding,family,series,shape}
% \marg{\textsc{id}}
% \marg{\textsc{id}}
% \end{syntax}
% The \cs{lngx_soft_super_font_family:nn} sets super family
% marked by the \meta{\textsc{id}} and reactivates the
% currently active font attributes listed in the second
% argument. The other two do the same, but without the list.
% the |softer| one omits the encoding and the |softest| one
% reactivate all of them.
% \end{function}
% 
% \begin{function}{^^A
% \lngx_soft_normal_font:n,^^A
% \lngx_softer_normal_font:,^^A
% \lngx_softest_normal_font:
% }
% \begin{syntax}
% \marg{\textsc{id}}
% \end{syntax}
% Quite similar to the soft super family functions, these
% ones set the default font family and reactivate the font
% attributes. The |soft| one sets the attributes listed in
% the argument. The |softer| one omits encoding and
% reactivates the rest and the |softest| one reactivates
% all.
% \end{function}
% \end{documentation}
% 
% \newpage
% 
% \begin{implementation}
% \section*{Implementation}
% 
% In this section the code of this bundle is documented.
% Each package in the bundle is documented in a separate
% subsection.
% 
% \subsection*{\lngxpkg}
% 
% Provide the package with its basic information.
%    \begin{macrocode}
%<*package>
\ProvidesExplPackage{linguistix}
                    {2025-07-11}
                    {v0.5d}
                    {%
                      The ‘LinguisTiX’ bundle: Enhanced
                      support for linguistics.%
                    }
%    \end{macrocode}
% When one loads \lngxpkg, all the packages of the bundle
% are loaded automatically. That’s the only content of the
% umbrella package \lngxpkg. All the packages are loaded
% conditionally (i.e., only if not loaded already).
%    \begin{macrocode}

\IfPackageLoadedF { linguistix-base } {
  \RequirePackage { linguistix-base }
}
\IfPackageLoadedF { linguistix-fonts } {
  \RequirePackage { linguistix-fonts }
}
\IfPackageLoadedF { linguistix-ipa } {
  \RequirePackage { linguistix-ipa }
}
\IfPackageLoadedF { linguistix-logos } {
  \RequirePackage { linguistix-logos }
}
\IfPackageLoadedF { linguistix-nfss } {
  \RequirePackage { linguistix-nfss }
}
%</package>
%    \end{macrocode}
% \newpage
% \lngximplementation{base}
% Set the essentials of the package.
%    \begin{macrocode}
%<*base>
\ProvidesExplPackage{linguistix-base}
                    {2025-07-11}
                    {v0.5d}
                    {%
                      The base package of the ‘LinguisTiX’
                      bundle.%
                    }
%    \end{macrocode}
% \begin{macro}{\lngx_set_keys:n}
% I use the \pkg{l3keys} module of \LaTeX3 for creating the
% key-values used in this bundle. In order to get a
% singleton parser for all the packages of the bundle, I
% have create this parsing command that is used throughout
% the bundle.
%    \begin{macrocode}

\cs_new_protected:Npn \lngx_set_keys:n #1 {
  \keys_set:nn { lngx _ keys } { #1 }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\linguistix}
% I equate this command with a user-side macro here and end
% the \lngxbaselogo\ package.
%    \begin{macrocode}

\cs_gset_eq:NN \linguistix \lngx_set_keys:n
%</base>
%    \end{macrocode}
% \end{macro}
% \newpage
% \lngximplementation{fixpex}
% The \pkg{unicode-math} defines |\gla| which clashes with
% the same command defined by the \pkg{expex} package. Of
% course, the \pkg{expex}-|\gla| is more relevant in
% linguistics. Thus I will save that and provide a new
% command for the \pkg{unicode-math}-|\gla|. This is not
% relevant to people who are not using \pkg{expex}. Thus,
% the settings are loaded only conditionally.
%    \begin{macrocode}
%<*fixpex>
\ProvidesExplPackage{linguistix-fixpex}
                    {2025-07-11}
                    {v0.5d}
                    {%
                      The base package of the ‘LinguisTiX’
                      bundle.%
                    }
%    \end{macrocode}
% This package is useful only if either \pkg{expex} or
% \pkg{unicode-math} is loaded. Otherwise, it is of no use.
% Thus, I create a message when either of them is not
% loaded.
%    \begin{macrocode}

\msg_new:nnn { fixpex } { pkg_not_loaded } {
  The~ ‘linguistix-fixpex’~ package~ is~ a~ first-aid~
  for~ resolving~ the~ conflict~ between~ ‘unicode-math’~
  and\\ ‘expex’.~ It~ should~ only~ be~ used~ if~ at~ least~
  one~ of~ these~ two~ is~ loaded.~ Here~
  ‘linguistix-fixpex’~ can~\\ be~ omitted~ since~ you~ are~
  not~ using~ ‘#1’.
}
%    \end{macrocode}
% I first start the hook |begindocument/before|.
%    \begin{macrocode}

\hook_gput_code:nnn { begindocument / before } { . } {
%    \end{macrocode}
% The \pkg{unicode-math} package defines |\gla| after
% |\begin{document}|, so the fix needs to be added after
% that is done. For that, I start the |begindocument/end|
% hook.
%    \begin{macrocode}
  \IfPackageLoadedTF { expex } {
    \IfPackageLoadedTF { unicode-math } {
      \hook_gput_code:nnn { begindocument / end } { . } {
%    \end{macrocode}
% \begin{macro}{\umgla}
% This replicates the \pkg{unicode-math}-|\gla| for future
% use.
%    \begin{macrocode}
        \cs_set_eq:NN \umgla \gla
%    \end{macrocode}
% \end{macro}
% The \pkg{expex}-|\gla| is then equated to the internal
% function of the package that does the actual function
% \parencite{alan}.
%    \begin{macrocode}
        \cs_set_eq:NN \gla   \glw@gla
      }
%    \end{macrocode}
% In the false branch of \pkg{unicode-math}, I issue an info
% message that is not visible on the terminal, but is
% printed in the log file.
%    \begin{macrocode}
    } {
      \msg_info:nnn { fixpex } { pkg_not_loaded } {
        unicode-math
      }
    }
%    \end{macrocode}
% Similarly, I do it for \pkg{expex}.
%    \begin{macrocode}
  } {
    \msg_info:nnn { fixpex } { pkg_not_loaded } {
      expex
    }
  }
}
%</fixpex>
%    \end{macrocode}
% \newpage
% \lngximplementation{fonts}
% Package essentials first.
%    \begin{macrocode}
%<*font>
\ProvidesExplPackage{linguistix-fonts}
                    {2025-07-11}
                    {v0.5d}
                    {%
                      The font-assistant package of the
                      ‘LinguisTiX’ bundle.%
                    }
%    \end{macrocode}
% I load \lngxbaselogo\ and \pkg{unicode-math} (if they are
% not already loaded).
%    \begin{macrocode}

\IfPackageLoadedF { linguistix-base } {
  \RequirePackage { linguistix-base }
}

\IfPackageLoadedF { unicode-math } {
  \RequirePackage { unicode-math }
}

\IfPackageLoadedF { linguistix-fixpex } {
  \RequirePackage { linguistix-fixpex }
}
%    \end{macrocode}
% \begin{macro}{\LaTeX,\ogLaTeX}
% We save the original code for the |\LaTeX| logo and then
% renew the command.
%    \begin{macrocode}

\NewCommandCopy \ogLaTeX \LaTeX

\RenewDocumentCommand \LaTeX {  } {%
  L\kern-.81ex\relax
  \raisebox{.6ex}{\textsc{a}}\kern-.23ex\relax
  \hbox{T}\kern-.4ex\relax
  \raisebox{-.5ex}{E}\kern-.3ex\relax
  X%
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{^^A
% old style numbers,\g_lngx_old_style_bool,^^A
% old style one,\g_lngx_old_style_one_bool,^^A
% bourbaki's empty set,\g_lngx_bourbaki_bool
% }
% I use the |.bool_gset:N| key-type of \pkg{l3keys} for
% developing these boolean keys.
%    \begin{macrocode}

\keys_define:nn { lngx _ keys } {
  old~ style~ numbers
  .bool_gset:N           = {
    \g_lngx_old_style_bool
  },
  old~ style~ one
  .bool_gset:N           = {
    \g_lngx_old_style_one_bool
  },
  bourbaki's~ empty~ set
  .bool_gset:N           = {
    \g_lngx_bourbaki_bool
  }
}
%    \end{macrocode}
% \end{macro}
% \newpage
% \begin{macro}{^^A
% text upright,text upright features,text bold upright,text
% bold upright features,text italic,text italic
% features,text bold italic,text bold italic features,text
% slanted,text slanted features,text bold slanted,text bold
% slanted features,text swash,text swash features,text bold
% swash,text bold swash features,text small caps,text small
% caps features,^^A
% \g_lngx_text_upright_tl,^^A
% \g_lngx_text_upright_features_tl,^^A
% \g_lngx_text_bold_upright_tl,^^A
% \g_lngx_text_bold_upright_features_tl,^^A
% \g_lngx_text_italic_tl,^^A
% \g_lngx_text_italic_features_tl,^^A
% \g_lngx_text_bold_italic_tl,^^A
% \g_lngx_text_bold_italic_features_tl,^^A
% \g_lngx_text_slanted_tl,^^A
% \g_lngx_text_slanted_features_tl,^^A
% \g_lngx_text_bold_slanted_tl,^^A
% \g_lngx_text_bold_slanted_features_tl,^^A
% \g_lngx_text_swash_tl,\g_lngx_text_swash_features_tl,^^A
% \g_lngx_text_bold_swash_tl,^^A
% \g_lngx_text_bold_swash_features_tl,^^A
% \g_lngx_text_small_caps_tl,^^A
% \g_lngx_text_small_caps_features_tl
% }
% I save the names of the fonts in |tl| variables. This
% section creates the keys for serif text fonts. All these
% keys have a common pattern of code. For the convenience of
% maintenance, I have created a comma-separated-list and
% used the elements of this list inside the common code.
% (See: \url{https://topanswers.xyz/tex?q=8074#a7689}.)
%    \begin{macrocode}

\clist_map_inline:nn {
  upright,
  bold~ upright,
  italic,
  bold~ italic,
  slanted,
  bold~ slanted,
  swash,
  bold~ swash,
  small~ caps
} {
%    \end{macrocode}
% The key-names can contain spaces, but the variables can’t.
% I set a temporary variable and convert the spaces into
% underscores. Note that |#1| means the elements of the
% |clist| here.
%    \begin{macrocode}
  \tl_set:Nn \l_tmpa_tl { #1 }
  \tl_replace_all:Nnn \l_tmpa_tl { ~ } { _ }
  \tl_gclear_new:c {
    g _ lngx _ text _ \l_tmpa_tl _ features _ tl
  }
%    \end{macrocode}
% All the keys here are prefixed with the word |text| in
% order to distinguish them from the keys provided by the
% \lngxipalogo\ package. The argument of these keys should
% be expanded for which I use |.tl_gset_e:c| type of
% \pkg{l3keys}.
%    \begin{macrocode}
  \keys_define:nn { lngx _ keys } {
    text~ #1
    .tl_gset_e:c           = {
      g _ lngx _ text _ \l_tmpa_tl _ tl
    },
%    \end{macrocode}
% Each of these keys is followed by its respective
% |features| key which is supposed to take an appending
% argument. The |.tl|-type keys don’t support this. I create
% this key with the |.code:n| type. Like before, first I set
% a temporary variable for space-to-underscore conversion,
% use it with the |\tl_put_right:ce| call for appending.
%    \begin{macrocode}
    text~ #1~ features
    .code:n                = {
      \tl_set:Nn \l_tmpb_tl { #1 }
      \tl_replace_all:Nnn \l_tmpb_tl { ~ } { _ }
      \tl_put_right:ce {
        g _ lngx _ text _ \l_tmpb_tl _ features _ tl
      } { ##1 , }
%    \end{macrocode}
% Lastly, we clear the temporary |tl|s.
%    \begin{macrocode}
      \tl_clear:N \l_tmpb_tl
    }
  }
  \tl_clear:N \l_tmpa_tl
}
%    \end{macrocode}
% \end{macro}
% \newpage
% \begin{macro}{^^A
% text sans upright,text sans upright features,text sans
% bold upright,text sans bold upright features,text sans
% italic,text sans italic features,text sans bold
% italic,text sans bold italic features,text sans
% slanted,text sans slanted features,text sans bold
% slanted,text sans bold slanted features,text sans
% swash,text sans swash features,text sans bold swash,text
% sans bold swash features,text sans small caps,text sans
% small caps features,^^A
% \g_lngx_text_sans_upright_tl,^^A
% \g_lngx_text_sans_upright_features_tl,^^A
% \g_lngx_text_sans_bold_upright_tl,^^A
% \g_lngx_text_sans_bold_upright_features_tl,^^A
% \g_lngx_text_sans_italic_tl,^^A
% \g_lngx_text_sans_italic_features_tl,^^A
% \g_lngx_text_sans_bold_italic_tl,^^A
% \g_lngx_text_sans_bold_italic_features_tl,^^A
% \g_lngx_text_sans_slanted_tl,^^A
% \g_lngx_text_sans_slanted_features_tl,^^A
% \g_lngx_text_sans_bold_slanted_tl,^^A
% \g_lngx_text_sans_bold_slanted_features_tl,^^A
% \g_lngx_text_sans_swash_tl,^^A
% \g_lngx_text_sans_swash_features_tl,^^A
% \g_lngx_text_sans_bold_swash_tl,^^A
% \g_lngx_text_sans_bold_swash_features_tl,^^A
% \g_lngx_text_sans_small_caps_tl,^^A
% \g_lngx_text_sans_small_caps_features_tl
% }
% With this same mechanism, the keys for sans serif fonts
% are developed.
%    \begin{macrocode}

\clist_map_inline:nn {
  upright,
  bold~ upright,
  italic,
  bold~ italic,
  slanted,
  bold~ slanted,
  swash,
  bold~ swash,
  small~ caps
} {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \tl_replace_all:Nnn \l_tmpa_tl { ~ } { _ }
  \tl_gclear_new:c {
    g _ lngx _ text _ sans _ \l_tmpa_tl _ features _ tl
  }
  \keys_define:nn { lngx _ keys } {
    text~ sans~ #1
    .tl_gset_e:c           = {
      g _ lngx _ text _ sans _ \l_tmpa_tl _ tl
    },
    text~ sans~ #1~ features
    .code:n                = {
      \tl_set:Nn \l_tmpb_tl { #1 }
      \tl_replace_all:Nnn \l_tmpb_tl { ~ } { _ }
      \tl_put_right:ce {
        g _ lngx _ text _ sans _ \l_tmpb_tl _ features _ tl
      } { ##1 , }
      \tl_clear:N \l_tmpb_tl
    }
  }
  \tl_clear:N \l_tmpa_tl
}
%    \end{macrocode}
% \end{macro}
% \newpage
% \begin{macro}{^^A
% text mono upright,text mono upright features,text mono
% bold upright,text mono bold upright features,text mono
% italic,text mono italic features,text mono bold
% italic,text mono bold italic features,text mono
% slanted,text mono slanted features,text mono bold
% slanted,text mono bold slanted features,text mono
% swash,text mono swash features,text mono bold swash,text
% mono bold swash features,text mono small caps,text mono
% small caps features,^^A
% \g_lngx_text_mono_upright_tl,^^A
% \g_lngx_text_mono_upright_features_tl,^^A
% \g_lngx_text_mono_bold_upright_tl,^^A
% \g_lngx_text_mono_bold_upright_features_tl,^^A
% \g_lngx_text_mono_italic_tl,^^A
% \g_lngx_text_mono_italic_features_tl,^^A
% \g_lngx_text_mono_bold_italic_tl,^^A
% \g_lngx_text_mono_bold_italic_features_tl,^^A
% \g_lngx_text_mono_slanted_tl,^^A
% \g_lngx_text_mono_slanted_features_tl,^^A
% \g_lngx_text_mono_bold_slanted_tl,^^A
% \g_lngx_text_mono_bold_slanted_features_tl,^^A
% \g_lngx_text_mono_swash_tl,^^A
% \g_lngx_text_mono_swash_features_tl,^^A
% \g_lngx_text_mono_bold_swash_tl,^^A
% \g_lngx_text_mono_bold_swash_features_tl,^^A
% \g_lngx_text_mono_small_caps_tl,^^A
% \g_lngx_text_mono_small_caps_features_tl
% }
% Here, with the same setup, I develop the keys for
% monospaced fonts.
%    \begin{macrocode}

\clist_map_inline:nn {
  upright,
  bold~ upright,
  italic,
  bold~ italic,
  slanted,
  bold~ slanted,
  swash,
  bold~ swash,
  small~ caps
} {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \tl_replace_all:Nnn \l_tmpa_tl { ~ } { _ }
  \tl_gclear_new:c {
    g _ lngx _ text _ mono _ \l_tmpa_tl _ features _ tl
  }
  \keys_define:nn { lngx _ keys } {
    text~ mono~ #1
    .tl_gset_e:c           = {
      g _ lngx _ text _ mono _ \l_tmpa_tl _ tl
    },
    text~ mono~ #1~ features
    .code:n                = {
      \tl_set:Nn \l_tmpb_tl { #1 }
      \tl_replace_all:Nnn \l_tmpb_tl { ~ } { _ }
      \tl_put_right:ce {
        g _ lngx _ text _ mono _ \l_tmpb_tl _ features _ tl
      } { ##1 , }
      \tl_clear:N \l_tmpb_tl
    }
  }
  \tl_clear:N \l_tmpa_tl
}
%    \end{macrocode}
% \end{macro}
% \newpage
% \begin{macro}{^^A
%   math,math features,math bold,math bold features^^A
% }
% The following are the keys set for math. They use the same
% mechanism as before.
%    \begin{macrocode}

\keys_define:nn { lngx _ keys } {
  math
  .tl_gset_e:c           = {
    g _ lngx _ math _ tl
  },
  math~ features
  .tl_gset_e:c           = {
    g _ lngx _ math _ features _ tl
  },
  math~ bold
  .tl_gset_e:c           = {
    g _ lngx _ math _ bold _ tl
  },
  math~ bold~ features
  .code:n                = {
    \tl_put_right:ce {
      g _ lngx _ math _ bold _ features _ tl
    } { #1 }
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{newcm}
% This key is of type |.meta:n|. It sets certain other keys
% that enable the New Computer Modern fonts in all serif,
% serif and monospaced families.
%    \begin{macrocode}

\keys_define:nn { lngx _ keys } {
  newcm
  .meta:n                = {
    text~
    upright                = {
      NewCM10-Book.otf
    },
    text~
    bold~ upright          = {
      NewCM10-Bold.otf
    },
    text~
    italic                 = {
      NewCM10-BookItalic.otf
    },
    text~
    bold~ italic           = {
      NewCM10-BoldItalic.otf
    },
    math                   = {
      NewCMMath-Book.otf
    },
    math~ bold             = {
      NewCMMath-Bold.otf
    },
    text~
    sans~ upright          = {
      NewCMSans10-Book.otf
    },
    text~
    sans~ bold~ upright    = {
      NewCMSans10-Bold.otf
    },
    text~
    sans~ italic           = {
      NewCMSans10-BookOblique.otf
    },
    text~
    sans~ bold~ italic     = {
      NewCMSans10-BoldOblique.otf
    },
    text~
    mono~ upright          = {
      NewCMMono10-Book.otf
    },
    text~
    mono~ bold~ upright    = {
      NewCMMono10-Bold.otf
    },
    text~
    mono~ italic           = {
      NewCMMono10-BookItalic.otf
    },
    text~
    mono~ bold~ italic     = {
      NewCMMono10-BoldOblique.otf
    }
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{newcm sans}
% This is a |.meta:n| key that sets the default fonts to the
% sans family.
%    \begin{macrocode}

\keys_define:nn { lngx _ keys } {
  newcm~ sans
  .meta:n                = {
    text~
    upright                = {
      NewCMSans10-Book.otf
    },
    text~
    bold~ upright          = {
      NewCMSans10-Bold.otf
    },
    text~
    italic                 = {
      NewCMSans10-BookOblique.otf
    },
    text~
    bold~ italic           = {
      NewCMSans10-BoldOblique.otf
    }
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{newcm mono}
% This is a |.meta:n| key that sets the default fonts to the
% monospaced family.
%    \begin{macrocode}

\keys_define:nn { lngx _ keys } {
  newcm~ mono
  .meta:n                = {
    text~
    upright                = {
      NewCMMono10-Book.otf
    },
    text~
    bold~ upright          = {
      NewCMMono10-Bold.otf
    },
    text~
    italic                 = {
      NewCMMono10-BookItalic.otf
    },
    text~
    bold~ italic           = {
      NewCMMono10-BoldOblique.otf
    }
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{newcm regular}
% This is a |.meta:n| key that sets the default fonts to the
% regular variant of the New Computer Modern family.
%    \begin{macrocode}

\keys_define:nn { lngx _ keys } {
  newcm~ regular
  .meta:n                = {
    text~
    upright                = {
      NewCM10-Regular.otf
    },
    text~
    bold~ upright          = {
      NewCM10-Bold.otf
    },
    text~
    italic                 = {
      NewCM10-Italic.otf
    },
    text~
    bold~ italic           = {
      NewCM10-BoldItalic.otf
    },
    math                   = {
      NewCMMath-Regular.otf
    },
    math~ bold             = {
      NewCMMath-Bold.otf
    },
    text~
    sans~ upright          = {
      NewCMSans10-Regular.otf
    },
    text~
    sans~ bold~ upright    = {
      NewCMSans10-Bold.otf
    },
    text~
    sans~ italic           = {
      NewCMSans10-Oblique.otf
    },
    text~
    sans~ bold~ italic     = {
      NewCMSans10-BoldOblique.otf
    },
    text~
    mono~ upright          = {
      NewCMMono10-Regular.otf
    },
    text~
    mono~ bold~ upright    = {
      NewCMMono10-Bold.otf
    },
    text~
    mono~ italic           = {
      NewCMMono10-Italic.otf
    },
    text~
    mono~ bold~ italic     = {
      NewCMMono10-Bold.otf
    }
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{newcm regular sans}
% This is a |.meta:n| key that sets the default fonts to the
% regular sans variant of the New Computer Modern family.
%    \begin{macrocode}

\keys_define:nn { lngx _ keys } {
  newcm~ regular~ sans
  .meta:n                = {
    text~
    upright                = {
      NewCMSans10-Regular.otf
    },
    text~
    bold~ upright          = {
      NewCMSans10-Bold.otf
    },
    text~
    italic                 = {
      NewCMSans10-Oblique.otf
    },
    text~
    bold~ italic           = {
      NewCMSans10-BoldOblique.otf
    }
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{newcm regular mono}
% This is a |.meta:n| key that sets the default fonts to the
% regular monospaced variant of the New Computer Modern
% family.
%    \begin{macrocode}

\keys_define:nn { lngx _ keys } {
  newcm~ regular~ mono
  .meta:n                = {
    text~
    upright                = {
      NewCMMono10-Regular.otf
    },
    text~
    bold~ upright          = {
      NewCMMono10-Bold.otf
    },
    text~
    italic                 = {
      NewCMMono10-Italic.otf
    },
    text~
    bold~ italic           = {
      NewCMMono10-Bold.otf
    }
  }
}
%    \end{macrocode}
% \end{macro}
% By default, we load the |newcm| key that loads all the New
% Computer Modern fonts in its book variant.
%    \begin{macrocode}

\lngx_set_keys:n {
  newcm,
%    \end{macrocode}
% Then we load the |bourbaki's empty set| boolean. This gets
% read later while setting the math font.
%    \begin{macrocode}
  bourbaki's~ empty~ set,
%    \end{macrocode}
% Lastly we load the |old style numbers| boolean.
%    \begin{macrocode}
  old~ style~ numbers
}
%    \end{macrocode}
% We need HarfBuzz renderer whenever Lua\LaTeX\ is used. For
% that we add the required feature to the feature-lists of
% all the fonts.
%    \begin{macrocode}

\sys_if_engine_luatex:T {
  \lngx_set_keys:n {
    text~
    upright~ features      = {
      Renderer               = { HarfBuzz }
    },
    text~ sans~
    upright~ features      = {
      Renderer               = { HarfBuzz }
    },
    text~ mono~
    upright~ features      = {
      Renderer               = { HarfBuzz }
    }
  }
}
%    \end{macrocode}
% \begin{macro}{^^A
% \lngx_set_main_font:nn,\lngx_set_sans_font:nn,^^A
% \lngx_set_mono_font:nn,\lngx_set_math_font:nn^^A
% }
% Since I use many conditionals and values while setting the
% fonts, here, I develop a few wrappers around the font
% commands. The |\cs_generate_variant:Nn| line comes in
% handy to generate the argument-expanding versions of the
% default wrapper-commands.
%    \begin{macrocode}

\cs_new_protected:Npn \lngx_set_main_font:nn #1#2 {
  \setmainfont [ #1 ] { #2 }
}

\cs_new_protected:Npn \lngx_set_sans_font:nn #1#2 {
  \setsansfont [ #1 ] { #2 }
}

\cs_new_protected:Npn \lngx_set_mono_font:nn #1#2 {
  \setmonofont [ #1 ] { #2 }
}

\cs_new_protected:Npn \lngx_set_math_font:nn #1#2 {
  \setmathfont [ #1 ] { #2 }
}

\cs_generate_variant:Nn \lngx_set_main_font:nn { ee }
\cs_generate_variant:Nn \lngx_set_sans_font:nn { ee }
\cs_generate_variant:Nn \lngx_set_mono_font:nn { ee }
\cs_generate_variant:Nn \lngx_set_math_font:nn { ee }
%    \end{macrocode}
% \end{macro}
% Now I start the pre-|begindocument| hook. New Computer
% Modern comes in two sizes for some shapes, 8 and 10. They
% matter for micro-typographic perfection. I have a little
% complicated checking for providing support for the entire
% New Computer Modern family. First I check if the font that
% is set to be the main font is New Computer Modern or not.
% For that, searching for the keyword |NewCM| suffices.
%    \begin{macrocode}

\hook_gput_code:nnn { begindocument / before } { . } {
  \tl_if_in:cnT {
    g _ lngx _ text _ upright _ tl
  } { NewCM } {
%    \end{macrocode}
% The Book weight of New Computer Modern consistently has
% |Book| in all its font-file-names. I test over that to
% distinguish it from the regular weight. In the true branch
% of it, I add the size features as required by
% \pkg{fontspec} for setting size-specific fonts.
%    \begin{macrocode}
    \tl_if_in:cnTF {
      g _ lngx _ text _ upright _ tl
    } { Book } {
      \lngx_set_keys:n {
        text~
        upright~ features      = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCM08-Book.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCM10-Book.otf
              }
            }
          }
        }
      }
%    \end{macrocode}
% In the false branch, the same settings are used for the
% regular variant.
%    \begin{macrocode}
    } {
      \lngx_set_keys:n {
        text~
        upright~ features      = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCM08-Regular.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCM10-Regular.otf
              }
            }
          }
        }
      }
    }
  }
%    \end{macrocode}
% When the |newcm sans| key is loaded, sans fonts are set as
% main fonts. All the sans variants have |NewCMSans| in
% their file-names. I repeat the same check for this case.
% This is on purpose loaded later, so that the features
% loaded by the previous snippet are overridden by this one
% in case the main font is sans\footnote{^^A
%   The test for |NewCM| matches with fonts that have
%   |NewCMSans| too and this is the fastest test I could
%   think of. Suggestions for alternative methods are highly
%   welcome.^^A
% }.
%    \begin{macrocode}
  \tl_if_in:cnT {
    g _ lngx _ text _ upright _ tl
  } { NewCMSans } {
    \tl_if_in:cnTF {
      g _ lngx _ text _ upright _ tl
    } { Book } {
      \lngx_set_keys:n {
        text~
        upright~ features      = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCMSans08-Book.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCMSans10-Book.otf
              }
            }
          }
        }
      }
    } {
      \lngx_set_keys:n {
        text~
        upright~ features      = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCMSans08-Regular.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCMSans10-Regular.otf
              }
            }
          }
        }
      }
    }
  }
%    \end{macrocode}
% Italic fonts also have this size variant, so here we
% repeat the same checks for Italic.
%    \begin{macrocode}
  \tl_if_in:cnT {
    g _ lngx _ text _ italic _ tl
  } { NewCM } {
    \tl_if_in:cnTF {
      g _ lngx _ text _ italic _ tl
    } { Book } {
      \lngx_set_keys:n {
        text~
        italic~ features       = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCM08-BookItalic.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCM10-BookItalic.otf
              }
            }
          }
        }
      }
    } {
      \lngx_set_keys:n {
        text~
        italic~ features       = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCM08-Italic.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCM10-Italic.otf
              }
            }
          }
        }
      }
    }
  }
  \tl_if_in:cnT {
    g _ lngx _ text _ italic _ tl
  } { NewCMSans } {
    \tl_if_in:cnTF {
      g _ lngx _ text _ italic _ tl
    } { Book } {
      \lngx_set_keys:n {
        text~
        italic~ features       = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCMSans08-BookOblique.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCMSans10-BookOblique.otf
              }
            }
          }
        }
      }
    } {
      \lngx_set_keys:n {
        text~
        italic~ features       = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCMSans08-Oblique.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCMSans10-Oblique.otf
              }
            }
          }
        }
      }
    }
  }
%    \end{macrocode}
% By default, I have set sans fonts from this family in a
% different set of variables. I repeat the same checks again
% for those variables. These coexist with the serif
% variables.
%    \begin{macrocode}
  \tl_if_in:cnT {
    g _ lngx _ text _ sans _ upright _ tl
  } { NewCMSans } {
    \tl_if_in:cnTF {
      g _ lngx _ text _ upright _ tl
    } { Book } {
      \lngx_set_keys:n {
        text~ sans~
        upright~ features      = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCMSans08-Book.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCMSans10-Book.otf
              }
            }
          }
        }
      }
    } {
      \lngx_set_keys:n {
        text~ sans~
        upright~ features      = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCMSans08-Regular.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCMSans10-Regular.otf
              }
            }
          }
        }
      }
    }
  }
  \tl_if_in:cnT {
    g _ lngx _ text _ sans _ italic _ tl
  } { NewCMSans } {
    \tl_if_in:cnTF {
      g _ lngx _ text _ italic _ tl
    } { Book } {
      \lngx_set_keys:n {
        text~ sans~
        italic~ features       = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCMSans08-BookOblique.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCMSans10-BookOblique.otf
              }
            }
          }
        }
      }
    } {
      \lngx_set_keys:n {
        text~ sans~
        italic~ features       = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCMSans08-Oblique.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCMSans10-Oblique.otf
              }
            }
          }
        }
      }
    }
  }
%    \end{macrocode}
% Now I load the fonts and features. I am using variables
% that need to be loaded at the end so that all the
% intermediate user-given changes are also read and
% considered. Every sub-font (e.g., bold font, Italic font)
% is stored in a |tl|. Here I save the features as required
% by \pkg{fontspec} in \lngxpkg\ feature keys.
%    \begin{macrocode}
  \lngx_set_keys:n {
    text~
    upright~ features      = {
      UprightFont          = {
        \g_lngx_text_upright_tl
      },
      UprightFeatures        = {
        \g_lngx_text_upright_features_tl
      },
      ItalicFont           = {
        \g_lngx_text_italic_tl
      },
      ItalicFeatures         = {
        \g_lngx_text_italic_features_tl
      },
      BoldFont             = {
        \g_lngx_text_bold_upright_tl
      },
      BoldFeatures           = {
        \g_lngx_text_bold_upright_features_tl
      },
      BoldItalicFont       = {
        \g_lngx_text_bold_italic_tl
      },
      BoldItalicFeatures     = {
        \g_lngx_text_bold_italic_features_tl
      },
%    \end{macrocode}
% The New Computer Modern fonts don’t have the following
% shapes, but other fonts may have them, so I load the
% variables conditionally (i.e., only if they are not
% empty).
%    \begin{macrocode}
      \tl_if_empty:cF {
        g _ lngx _ text _ slanted _ tl
      } {
        SlantedFont            = {
          \g_lngx_text_slanted_tl
        },
        \tl_if_empty:cF {
          g _ lngx _ text _ slanted _ features _ tl
        } {
          SlantedFeatures        = {
            \g_lngx_text_slanted_features_tl
          },
        }
      }
      \tl_if_empty:cF {
        g _ lngx _ text _ bold _ slanted _ tl
      } {
        BoldSlantedFont        = {
          \g_lngx_text_bold_slanted_tl
        },
        BoldSlantedFeatures    = {
          \g_lngx_text_bold_slanted_features_tl
        },
      }
      \tl_if_empty:cF {
        g _ lngx _ text _ swash _ tl
      } {
        SwashFont              = {
          \g_lngx_text_swash_tl
        },
        SwashFeatures          = {
          \g_lngx_text_swash_features_tl
        },
      }
      \tl_if_empty:cF {
        g _ lngx _ text _ bold _ swash _ tl
      } {
        BoldSwashFont          = {
          \g_lngx_text_bold_swash_tl
        },
        BoldSwashFeatures      = {
          \g_lngx_text_bold_swash_features_tl
        },
      }
      \tl_if_empty:cF {
        g _ lngx _ text _ small _ caps _ tl
      } {
        SmallCapsFont          = {
          \g_lngx_text_small_caps_tl
        },
        SmallCapsFeatures      = {
          \g_lngx_text_small_caps_features_tl
        }
      }
    },
%    \end{macrocode}
% Exactly like serif fonts, I develop the feature-set for
% sans and mono fonts.
%    \begin{macrocode}
    text~ sans~
    upright~ features      = {
      UprightFont            = {
        \g_lngx_text_sans_upright_tl
      },
      UprightFeatures        = {
        \g_lngx_text_sans_upright_features_tl
      },
      BoldFont               = {
        \g_lngx_text_sans_bold_upright_tl
      },
      BoldFeatures           = {
        \g_lngx_text_sans_bold_upright_features_tl
      },
      ItalicFont             = {
        \g_lngx_text_sans_italic_tl
      },
      ItalicFeatures         = {
        \g_lngx_text_sans_italic_features_tl
      },
      BoldItalicFont         = {
        \g_lngx_text_sans_bold_italic_tl
      },
      BoldItalicFeatures     = {
        \g_lngx_text_sans_bold_italic_features_tl
      },
      \tl_if_empty:cF {
        g _ lngx _ text _ sans _ slanted _ tl
      } {
        SlantedFont            = {
          \g_lngx_text_sans_slanted_tl
        },
        SlantedFeatures        = {
          \g_lngx_text_sans_slanted_features_tl
        },
      }
      \tl_if_empty:cF {
        g _ lngx _ text _ sans _ bold _ slanted _ tl
      } {
        BoldSlantedFont        = {
          \g_lngx_text_sans_bold_slanted_tl
        },
        BoldSlantedFeatures    = {
          \g_lngx_text_sans_bold_slanted_features_tl
        },
      }
      \tl_if_empty:cF {
        g _ lngx _ text _ sans _ swash _ tl
      } {
        SwashFont              = {
          \g_lngx_text_sans_swash_tl
        },
        SwashFeatures          = {
          \g_lngx_text_sans_swash_features_tl
        },
      }
      \tl_if_empty:cF {
        g _ lngx _ text _ sans _ bold _ swash _ tl
      } {
        BoldSwashFont          = {
          \g_lngx_text_sans_bold_swash_tl
        },
        BoldSwashFeatures      = {
          \g_lngx_text_sans_bold_swash_features_tl
        },
      }
      \tl_if_empty:cF {
        g _ lngx _ text _ sans _ small _ caps _ tl
      } {
        SmallCapsFont          = {
          \g_lngx_text_sans_small_caps_tl
        },
        SmallCapsFeatures      = {
          \g_lngx_text_sans_small_caps_features_tl
        }
      }
    },
    text~ mono~
    upright~ features      = {
      UprightFont            = {
        \g_lngx_text_mono_upright_tl
      },
      UprightFeatures        = {
        \g_lngx_text_mono_upright_features_tl
      },
      BoldFont               = {
        \g_lngx_text_mono_bold_upright_tl
      },
      BoldFeatures           = {
        \g_lngx_text_mono_bold_upright_features_tl
      },
      ItalicFont             = {
        \g_lngx_text_mono_italic_tl
      },
      ItalicFeatures         = {
        \g_lngx_text_mono_italic_features_tl
      },
      BoldItalicFont         = {
        \g_lngx_text_mono_bold_italic_tl
      },
      BoldItalicFeatures     = {
        \g_lngx_text_mono_bold_italic_features_tl
      },
      \tl_if_empty:cF {
        g _ lngx _ text _ mono _ slanted _ tl
      } {
        SlantedFont            = {
          \g_lngx_text_mono_slanted_tl
        },
        SlantedFeatures        = {
          \g_lngx_text_mono_slanted_features_tl
        },
      }
      \tl_if_empty:cF {
        g _ lngx _ text _ mono _ bold _ slanted _ tl
      } {
        BoldSlantedFont        = {
          \g_lngx_text_mono_bold_slanted_tl
        },
        BoldSlantedFeatures    = {
          \g_lngx_text_mono_bold_slanted_features_tl
        },
      }
      \tl_if_empty:cF {
        g _ lngx _ text _ mono _ swash _ tl
      } {
        SwashFont              = {
          \g_lngx_text_mono_swash_tl
        },
        SwashFeatures          = {
          \g_lngx_text_mono_swash_features_tl
        },
      }
      \tl_if_empty:cF {
        g _ lngx _ text _ mono _ bold _ swash _ tl
      } {
        BoldSwashFont          = {
          \g_lngx_text_mono_bold_swash_tl
        },
        BoldSwashFeatures      = {
          \g_lngx_text_mono_bold_swash_features_tl
        },
      }
      \tl_if_empty:cF {
        g _ lngx _ text _ mono _ small _ caps _ tl
      } {
        SmallCapsFont          = {
          \g_lngx_text_mono_small_caps_tl
        },
        SmallCapsFeatures      = {
          \g_lngx_text_mono_small_caps_features_tl
        }
      }
    }
  }
  \bool_if:NT \g_lngx_old_style_bool {
    \lngx_set_keys:n {
      text~
      upright~ features      = {
        Numbers                = { OldStyle }
      },
      text~ sans~
      upright~ features      = {
        Numbers                = { OldStyle }
      }
    }
    \tl_if_in:cnT {
      g_lngx_math_tl
    } { NewCM } {
      \bool_if:NT \g_lngx_old_style_one_bool {
        \lngx_set_keys:n {
          text~
          upright~ features      = {
            CharacterVariant       = { 6 }
          },
          text~ sans~
          upright~ features      = {
            CharacterVariant       = { 6 }
          }
        }
      }
    }
  }
  \tl_if_in:cnT {
    g _ lngx _ math _ tl
  } { NewCM } {
    \bool_if:NT \g_lngx_bourbaki_bool {
      \lngx_set_keys:n {
        math~ features         = {
          CharacterVariant       = { 1 }
        }
      }
    }
  }
%    \end{macrocode}
% If the New Computer Modern fonts are used, we don’t need
% their |.fontspec| files as I already have incorporated all
% their settings in the package itself. So I have used the
% |IgnoreFontspecFile| option for \pkg{fontspec}.
%    \begin{macrocode}
  \tl_if_in:cnT {
    g _ lngx _ text _ upright _ tl
  } { NewCM } {
    \lngx_set_keys:n {
      text~
      upright~ features        = {
        IgnoreFontspecFile
      }
    }
  }
  \tl_if_in:cnT {
    g _ lngx _ text _ sans _ upright _ tl
  } { NewCM } {
    \lngx_set_keys:n {
      text~
      sans~ upright~ features  = {
        IgnoreFontspecFile
      }
    }
  }
  \tl_if_in:cnT {
    g _ lngx _ text _ mono _ upright _ tl
  } { NewCM } {
    \lngx_set_keys:n {
      text~
      mono~ upright~ features  = {
        IgnoreFontspecFile
      }
    }
  }
  \lngx_set_main_font:ee {
    \g_lngx_text_upright_features_tl
  } {
    \g_lngx_text_upright_tl
  }
  \lngx_set_sans_font:ee {
    \g_lngx_text_sans_upright_features_tl
  } {
    \g_lngx_text_sans_upright_tl
  }
  \lngx_set_mono_font:ee {
    \g_lngx_text_mono_upright_features_tl
  } {
    \g_lngx_text_mono_upright_tl
  }
  \lngx_set_math_font:ee {
    \g_lngx_math_features_tl
  } {
    \g_lngx_math_tl
  }
}
%</font>
%    \end{macrocode}
% \newpage
% \lngximplementation{ipa}
%    \begin{macrocode}
%<*ipa>
\ProvidesExplPackage{linguistix-ipa}
                    {2025-07-11}
                    {v0.5d}
                    {%
                      A package for typesetting the IPA
                      (International Phonetic Alphabet) from
                      the ‘LinguisTiX’ bundle.%
                    }
%    \end{macrocode}
% Then, I load \pkg{unicode-math}, \lngxnfsslogo\ and
% \lngxbaselogo\ (if they are not already loaded).
%    \begin{macrocode}

\IfPackageLoadedF { unicode-math } {
  \RequirePackage { unicode-math }
}

\IfPackageLoadedF { linguistix-base } {
  \RequirePackage { linguistix-base }
}

\IfPackageLoadedF { linguistix-nfss } {
  \RequirePackage { linguistix-nfss }
}

\IfPackageLoadedF { linguistix-fixpex } {
  \RequirePackage { linguistix-fixpex }
}
%    \end{macrocode}
% \begin{macro}{\ipatext,\ipatext*}
% The |\ipatext| command along with its starred variant is
% developed here.
% \begin{macrocode}

\NewDocumentCommand \ipatext { s m } {
  \IfBooleanTF { #1 } {
    {
      \lngxipa
      / #2 /
    }
  } {
    {
      \lngxipa
      [ #2 ]
    }
  }
}
%    \end{macrocode}
% \end{macro}
% \newpage
% \begin{macro}{^^A
% ipa upright,ipa upright features,ipa bold upright,ipa bold
% upright features,ipa italic,ipa italic features,ipa bold
% italic,ipa bold italic features,ipa slanted,ipa slanted
% features,ipa bold slanted,ipa bold slanted features,ipa
% swash,ipa swash features,ipa bold swash,ipa bold swash
% features,ipa small caps,ipa small caps features,^^A
% \g_lngx_ipa_upright_tl,^^A
% \g_lngx_ipa_upright_features_tl,^^A
% \g_lngx_ipa_bold_upright_tl,^^A
% \g_lngx_ipa_bold_upright_features_tl,^^A
% \g_lngx_ipa_italic_tl,^^A
% \g_lngx_ipa_italic_features_tl,^^A
% \g_lngx_ipa_bold_italic_tl,^^A
% \g_lngx_ipa_bold_italic_features_tl,^^A
% \g_lngx_ipa_slanted_tl,^^A
% \g_lngx_ipa_slanted_features_tl,^^A
% \g_lngx_ipa_bold_slanted_tl,^^A
% \g_lngx_ipa_bold_slanted_features_tl,^^A
% \g_lngx_ipa_swash_tl,^^A
% \g_lngx_ipa_swash_features_tl,^^A
% \g_lngx_ipa_bold_swash_tl,^^A
% \g_lngx_ipa_bold_swash_features_tl,^^A
% \g_lngx_ipa_small_caps_tl,^^A
% \g_lngx_ipa_small_caps_features_tl
% }
% These variables store the values for fonts and features
% for the serif \textsc{ipa}.
%    \begin{macrocode}

\clist_map_inline:nn {
  upright,
  bold~ upright,
  italic,
  bold~ italic,
  slanted,
  bold~ slanted,
  swash,
  bold~ swash,
  small~ caps
} {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \tl_replace_all:Nnn \l_tmpa_tl { ~ } { _ }
  \tl_gclear_new:c {
    g _ lngx _ ipa _ \l_tmpa_tl _ features _ tl
  }
  \keys_define:nn { lngx _ keys } {
    ipa~ #1
    .tl_gset_e:c           = {
      g _ lngx _ ipa _ \l_tmpa_tl _ tl
    },
    ipa~ #1~ features
    .code:n                = {
      \tl_set:Nn \l_tmpb_tl { #1 }
      \tl_replace_all:Nnn \l_tmpb_tl { ~ } { _ }
      \tl_put_right:ce {
        g _ lngx _ ipa _ \l_tmpb_tl _ features _ tl
      } { ##1 , }
      \tl_clear:N \l_tmpb_tl
    }
  }
  \tl_clear:N \l_tmpa_tl
}
%    \end{macrocode}
% \end{macro}
% \newpage
% \begin{macro}{^^A
% ipa sans upright,ipa sans upright features,ipa sans bold
% upright,ipa sans bold upright features,ipa sans italic,ipa
% sans italic features,ipa sans bold italic,ipa sans bold
% italic features,ipa sans slanted,ipa sans slanted
% features,ipa sans bold slanted,ipa sans bold slanted
% features,ipa sans swash,ipa sans swash features,ipa sans
% bold swash,ipa sans bold swash features,ipa sans small
% caps,ipa sans small caps features,^^A
% \g_lngx_ipa_sans_upright_tl,^^A
% \g_lngx_ipa_sans_upright_features_tl,^^A
% \g_lngx_ipa_sans_bold_upright_tl,^^A
% \g_lngx_ipa_sans_bold_upright_features_tl,^^A
% \g_lngx_ipa_sans_italic_tl,^^A
% \g_lngx_ipa_sans_italic_features_tl,^^A
% \g_lngx_ipa_sans_bold_italic_tl,^^A
% \g_lngx_ipa_sans_bold_italic_features_tl,^^A
% \g_lngx_ipa_sans_slanted_tl,^^A
% \g_lngx_ipa_sans_slanted_features_tl,^^A
% \g_lngx_ipa_sans_bold_slanted_tl,^^A
% \g_lngx_ipa_sans_bold_slanted_features_tl,^^A
% \g_lngx_ipa_sans_swash_tl,^^A
% \g_lngx_ipa_sans_swash_features_tl,^^A
% \g_lngx_ipa_sans_bold_swash_tl,^^A
% \g_lngx_ipa_sans_bold_swash_features_tl,^^A
% \g_lngx_ipa_sans_small_caps_tl,^^A
% \g_lngx_ipa_sans_small_caps_features_tl
% }
% These variables store the values for fonts and features
% for the sans \textsc{ipa}.
%    \begin{macrocode}

\clist_map_inline:nn {
  upright,
  bold~ upright,
  italic,
  bold~ italic,
  slanted,
  bold~ slanted,
  swash,
  bold~ swash,
  small~ caps
} {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \tl_replace_all:Nnn \l_tmpa_tl { ~ } { _ }
  \tl_gclear_new:c {
    g _ lngx _ ipa _ mono _ \l_tmpa_tl _ features _ tl
  }
  \keys_define:nn { lngx _ keys } {
    ipa~ mono~ #1
    .tl_gset_e:c           = {
      g _ lngx _ ipa _ mono _ \l_tmpa_tl _ tl
    },
    ipa~ mono~ #1~ features
    .code:n                = {
      \tl_set:Nn \l_tmpb_tl { #1 }
      \tl_replace_all:Nnn \l_tmpb_tl { ~ } { _ }
      \tl_put_right:ce {
        g _ lngx _ ipa _ mono _ \l_tmpb_tl _ features _ tl
      } { ##1 , }
      \tl_clear:N \l_tmpb_tl
    }
  }
  \tl_clear:N \l_tmpa_tl
}
%    \end{macrocode}
% \end{macro}
% \newpage
% \begin{macro}{^^A
% ipa mono upright,ipa mono upright features,ipa mono bold
% upright,ipa mono bold upright features,ipa mono italic,ipa
% mono italic features,ipa mono bold italic,ipa mono bold
% italic features,ipa mono slanted,ipa mono slanted
% features,ipa mono bold slanted,ipa mono bold slanted
% features,ipa mono swash,ipa mono swash features,ipa mono
% bold swash,ipa mono bold swash features,ipa mono small
% caps,ipa mono small caps features,^^A
% \g_lngx_ipa_mono_upright_tl,^^A
% \g_lngx_ipa_mono_upright_features_tl,^^A
% \g_lngx_ipa_mono_bold_upright_tl,^^A
% \g_lngx_ipa_mono_bold_upright_features_tl,^^A
% \g_lngx_ipa_mono_italic_tl,^^A
% \g_lngx_ipa_mono_italic_features_tl,^^A
% \g_lngx_ipa_mono_bold_italic_tl,^^A
% \g_lngx_ipa_mono_bold_italic_features_tl,^^A
% \g_lngx_ipa_mono_slanted_tl,^^A
% \g_lngx_ipa_mono_slanted_features_tl,^^A
% \g_lngx_ipa_mono_bold_slanted_tl,^^A
% \g_lngx_ipa_mono_bold_slanted_features_tl,^^A
% \g_lngx_ipa_mono_swash_tl,^^A
% \g_lngx_ipa_mono_swash_features_tl,^^A
% \g_lngx_ipa_mono_bold_swash_tl,^^A
% \g_lngx_ipa_mono_bold_swash_features_tl,^^A
% \g_lngx_ipa_mono_small_caps_tl,^^A
% \g_lngx_ipa_mono_small_caps_features_tl
% }
% These variables store the values for fonts and features
% for the monospaced \textsc{ipa}.
%    \begin{macrocode}

\clist_map_inline:nn {
  upright,
  bold~ upright,
  italic,
  bold~ italic,
  slanted,
  bold~ slanted,
  swash,
  bold~ swash,
  small~ caps
} {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \tl_replace_all:Nnn \l_tmpa_tl { ~ } { _ }
  \tl_gclear_new:c {
    g _ lngx _ ipa _ sans _ \l_tmpa_tl _ features _ tl
  }
  \keys_define:nn { lngx _ keys } {
    ipa~ sans~ #1
    .tl_gset_e:c           = {
      g _ lngx _ ipa _ sans _ \l_tmpa_tl _ tl
    },
    ipa~ sans~ #1~ features
    .code:n                = {
      \tl_set:Nn \l_tmpb_tl { #1 }
      \tl_replace_all:Nnn \l_tmpb_tl { ~ } { _ }
      \tl_put_right:ce {
        g _ lngx _ ipa _ sans _ \l_tmpb_tl _ features _ tl
      } { ##1 , }
      \tl_clear:N \l_tmpb_tl
    }
  }
  \tl_clear:N \l_tmpa_tl
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{ipa newcm}
% This key sets New Computer Modern fonts in all weights,
% all families in the context of \textsc{ipa}.
%    \begin{macrocode}

\keys_define:nn { lngx _ keys } {
  ipa~ newcm
  .meta:n                = {
    ipa~
    upright                = {
      NewCM10-Book.otf
    },
    ipa~
    bold~ upright          = {
      NewCM10-Bold.otf
    },
    ipa~
    italic                 = {
      NewCM10-BookItalic.otf
    },
    ipa~
    bold~ italic           = {
      NewCM10-BoldItalic.otf
    },
    ipa~
    slanted                = {
      NewCM10-Book.otf
    },
    ipa~
    bold~ slanted          = {
      NewCM10-Bold.otf
    },
    ipa~
    swash                  = {
      NewCM10-Book.otf
    },
    ipa~
    bold~ swash            = {
      NewCM10-Bold.otf
    },
    ipa~
    small~ caps            = {
      NewCM10-Book.otf
    },
    ipa~
    sans~ upright          = {
      NewCMSans10-Book.otf
    },
    ipa~
    sans~ bold~ upright    = {
      NewCMSans10-Bold.otf
    },
    ipa~
    sans~ italic           = {
      NewCMSans10-BookOblique.otf
    },
    ipa~
    sans~ bold~ italic     = {
      NewCMSans10-BoldOblique.otf
    },
    ipa~
    sans~ slanted          = {
      NewCMSans10-BookOblique.otf
    },
    ipa~
    sans~ bold~ slanted    = {
      NewCMSans10-BoldOblique.otf
    },
    ipa~
    sans~ swash            = {
      NewCMSans10-Book.otf
    },
    ipa~
    sans~ bold~ swash      = {
      NewCMSans10-Bold.otf
    },
    ipa~
    sans~ small~ caps      = {
      NewCMSans10-Book.otf
    },
    ipa~
    mono~ upright          = {
      NewCMMono10-Book.otf
    },
    ipa~
    mono~ bold~ upright    = {
      NewCMMono10-Bold.otf
    },
    ipa~
    mono~ italic           = {
      NewCMMono10-BookItalic.otf
    },
    ipa~
    mono~ bold~ italic     = {
      NewCMMono10-BoldOblique.otf
    },
    ipa~
    mono~ slanted          = {
      NewCMMono10-Book.otf
    },
    ipa~
    mono~ bold~ slanted    = {
      NewCMMono10-BoldOblique.otf
    },
    ipa~
    mono~ swash            = {
      NewCMMono10-Book.otf
    },
    ipa~
    mono~ bold~ swash      = {
      NewCMMono10-Bold.otf
    },
    ipa~
    mono~ small~ caps      = {
      NewCMMono10-Book.otf
    }
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{ipa newcm sans}
% This key sets New Computer Modern sans fonts in all
% weights, all families in the context of \textsc{ipa}.
%    \begin{macrocode}

\keys_define:nn { lngx _ keys } {
  ipa~ newcm~ sans
  .meta:n                = {
    ipa~
    upright                = {
      NewCMSans10-Book.otf
    },
    ipa~
    bold~ upright          = {
      NewCMSans10-Bold.otf
    },
    ipa~
    italic                 = {
      NewCMSans10-BookOblique.otf
    },
    ipa~
    bold~ italic           = {
      NewCMSans10-BoldOblique.otf
    },
    ipa~
    slanted                = {
      NewCMSans10-BookOblique.otf
    },
    ipa~
    bold~ slanted          = {
      NewCMSans10-BoldOblique.otf
    },
    ipa~
    swash                  = {
      NewCMSans10-Book.otf
    },
    ipa~
    bold~ swash            = {
      NewCMSans10-Bold.otf
    },
    ipa~
    small~ caps            = {
      NewCMSans10-Book.otf
    }
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{ipa newcm mono}
% This key sets New Computer Modern monospaced fonts in all
% weights, all families in the context of \textsc{ipa}.
%    \begin{macrocode}

\keys_define:nn { lngx _ keys } {
  ipa~ newcm~ mono
  .meta:n                = {
    ipa~
    upright                = {
      NewCMMono10-Book.otf
    },
    ipa~
    bold~ upright          = {
      NewCMMono10-Bold.otf
    },
    ipa~
    italic                 = {
      NewCMMono10-BookItalic.otf
    },
    ipa~
    bold~ italic           = {
      NewCMMono10-BoldOblique.otf
    },
    ipa~
    slanted                = {
      NewCMMono10-Book.otf
    },
    ipa~
    bold~ slanted          = {
      NewCMMono10-BoldOblique.otf
    },
    ipa~
    swash                  = {
      NewCMMono10-Book.otf
    },
    ipa~
    bold~ swash            = {
      NewCMMono10-Bold.otf
    },
    ipa~
    small~ caps            = {
      NewCMMono10-Book.otf
    }
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{ipa newcm regular}
% This key sets New Computer Modern regular serif fonts in
% all weights, all families in the context of \textsc{ipa}.
%    \begin{macrocode}

\keys_define:nn { lngx _ keys } {
  ipa~ newcm~ regular
  .meta:n                = {
    ipa~
    upright                = {
      NewCM10-Regular.otf
    },
    ipa~
    bold~ upright          = {
      NewCM10-Bold.otf
    },
    ipa~
    italic                 = {
      NewCM10-Italic.otf
    },
    ipa~
    bold~ italic           = {
      NewCM10-BoldItalic.otf
    },
    ipa~
    slanted                = {
      NewCM10-Regular.otf
    },
    ipa~
    bold~ slanted          = {
      NewCM10-Bold.otf
    },
    ipa~
    swash                  = {
      NewCM10-Regular.otf
    },
    ipa~
    bold~ swash            = {
      NewCM10-Bold.otf
    },
    ipa~
    small~ caps            = {
      NewCM10-Regular.otf
    },
    ipa~
    sans~ upright          = {
      NewCMSans10-Regular.otf
    },
    ipa~
    sans~ bold             = {
      NewCMSans10-Bold.otf
    },
    ipa~
    sans~ italic           = {
      NewCMSans10-Oblique.otf
    },
    ipa~
    sans~ bold~ italic     = {
      NewCMSans10-BoldOblique.otf
    },
    ipa~
    sans~ slanted          = {
      NewCMSans10-Regular.otf
    },
    ipa~
    sans~ bold~ slanted    = {
      NewCMSans10-Bold.otf
    },
    ipa~
    sans~ swash            = {
      NewCMSans10-Regular.otf
    },
    ipa~
    sans~ bold~ swash      = {
      NewCMSans10-Bold.otf
    },
    ipa~
    sans~ small~ caps      = {
      NewCMSans10-Regular.otf
    },
    ipa~
    mono~ upright          = {
      NewCMMono10-Regular.otf
    },
    ipa~
    mono~ bold             = {
      NewCMMono10-Bold.otf
    },
    ipa~
    mono~ italic           = {
      NewCMMono10-Italic.otf
    },
    ipa~
    mono~ bold~ italic     = {
      NewCMMono10-Bold.otf
    },
    ipa~
    mono~ slanted          = {
      NewCMMono10-Regular.otf
    },
    ipa~
    mono~ bold~ slanted    = {
      NewCMMono10-Bold.otf
    },
    ipa~
    mono~ swash            = {
      NewCMMono10-Regular.otf
    },
    ipa~
    mono~ bold~ swash      = {
      NewCMMono10-Bold.otf
    },
    ipa~
    mono~ small~ caps      = {
      NewCMMono10-Regular.otf
    }
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{ipa newcm regular sans}
% This key sets New Computer Modern regular sans fonts in
% all weights, all families in the context of \textsc{ipa}.
%    \begin{macrocode}

\keys_define:nn { lngx _ keys } {
  ipa~ newcm~ sans~ regular
  .meta:n                = {
    ipa~
    upright                = {
      NewCMSans10-Regular.otf
    },
    ipa~
    bold                   = {
      NewCMSans10-Bold.otf
    },
    ipa~
    italic                 = {
      NewCMSans10-Oblique.otf
    },
    ipa~
    bold~ italic           = {
      NewCMSans10-BoldOblique.otf
    },
    ipa~
    slanted                = {
      NewCMSans10-Regular.otf
    },
    ipa~
    bold~ slanted          = {
      NewCMSans10-Bold.otf
    },
    ipa~
    swash                  = {
      NewCMSans10-Regular.otf
    },
    ipa~
    bold~ swash            = {
      NewCMSans10-Bold.otf
    },
    ipa~
    small~ caps            = {
      NewCMSans10-Regular.otf
    }
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{ipa newcm regular mono}
% This key sets New Computer Modern regular monospaced fonts
% in all weights, all families in the context of
% \textsc{ipa}.
%    \begin{macrocode}

\keys_define:nn { lngx _ keys } {
  ipa~ newcm~ mono~ regular
  .meta:n                = {
    ipa~
    upright                = {
      NewCMMono10-Regular.otf
    },
    ipa~
    bold                   = {
      NewCMMono10-Bold.otf
    },
    ipa~
    italic                 = {
      NewCMMono10-Italic.otf
    },
    ipa~
    bold~ italic           = {
      NewCMMono10-Bold.otf
    },
    ipa~
    slanted                = {
      NewCMMono10-Regular.otf
    },
    ipa~
    bold~ slanted          = {
      NewCMMono10-Bold.otf
    },
    ipa~
    swash                  = {
      NewCMMono10-Regular.otf
    },
    ipa~
    bold~ swash            = {
      NewCMMono10-Bold.otf
    },
    ipa~
    small~ caps            = {
      NewCMMono10-Regular.otf
    }
  }
}
%    \end{macrocode}
% \end{macro}
% We set the |ipa newcm| key by default.
%    \begin{macrocode}

\lngx_set_keys:n {ipa~ newcm}
%    \end{macrocode}
% If Lua\LaTeX\ is loaded, the |HarfBuzz| renderer is
% selected by default.
%    \begin{macrocode}

\sys_if_engine_luatex:T {
  \lngx_set_keys:n {
    ipa~
    upright~ features      = {
      Renderer               = { HarfBuzz }
    },
    ipa~ sans~
    upright~ features      = {
      Renderer               = { HarfBuzz }
    },
    ipa~ mono~
    upright~ features      = {
      Renderer               = { HarfBuzz }
    }
  }
}
%    \end{macrocode}
% \begin{macro}{^^A
%   \lngx_set_main_ipa_font:nn,\lngx_main_ipa:,^^A
%   lngx_ipa_rm_nfss,^^A
%   \lngx_set_sans_ipa_font:nn,\lngx_sans_ipa:,^^A
%   lngx_ipa_sf_nfss,^^A
%   \lngx_set_mono_ipa_font:nn,\lngx_mono_ipa:,^^A
%   lngx_ipa_tt_nfss^^A
% }
% Here, I develop font-setting commands for \textsc{ipa}.
% These commands are set with |\setfontfamily|, so they
% keep overriding the definitions of the same command names.
% These commands set \textsc{nfss} families that we use
% later for setting the \textsc{ipa} fonts. These functions
% and \textsc{nfss} families are public, but manipulating
% them has effects (mostly desired) at several other places,
% so use them with caution.
%    \begin{macrocode}

\cs_new_protected:Npn \lngx_set_main_ipa_font:nn #1#2 {
  \setfontfamily \lngx_main_ipa: [
    #1,
    NFSSFamily             = { lngx _ ipa _ rm _nfss }
  ] { #2 }
}

\cs_new_protected:Npn \lngx_set_sans_ipa_font:nn #1#2 {
  \setfontfamily \lngx_sans_ipa: [
    #1,
    NFSSFamily             = { lngx _ ipa _ sf _nfss }
  ] { #2 }
}

\cs_new_protected:Npn \lngx_set_mono_ipa_font:nn #1#2 {
  \setfontfamily \lngx_mono_ipa: [
    #1,
    NFSSFamily             = { lngx _ ipa _ tt _nfss }
  ] { #2 }
}

\cs_generate_variant:Nn \lngx_set_main_ipa_font:nn { ee }
\cs_generate_variant:Nn \lngx_set_sans_ipa_font:nn { ee }
\cs_generate_variant:Nn \lngx_set_mono_ipa_font:nn { ee }
%    \end{macrocode}
% \end{macro}
% \begin{macro}{lngx_ipa}
% Here, I create a \enquote{super font family} with
% |\lngx_super_font_family:nn|, a macro provided by
% \lngxnfsslogo. Please see the documentation of that
% package for more information. Note that |lngx_ipa| is a
% super family responsible for all the \textsc{ipa}-related
% functions of the package. It is associated with the
% \textsc{nfss} families defined just now for the
% \textsc{ipa}.
%    \begin{macrocode}

\lngx_super_font_family:nn { lngx _ ipa } {
  rm                     = { lngx _ ipa _ rm _ nfss },
  sf                     = { lngx _ ipa _ sf _ nfss },
  tt                     = { lngx _ ipa _ tt _ nfss }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\lngxipa,\lngx_ipa:}
% I use |\lngx_softer_super_font_family:n| provided by
% \lngxnfsslogo for defining this switch to the
% \textsc{ipa}.
%    \begin{macrocode}

\cs_new_protected:Npn \lngx_ipa: {
  \lngx_softer_super_font_family:n { lngx _ ipa }
}

\cs_set_eq:NN \lngxipa \lngx_ipa:
%    \end{macrocode}
% \end{macro}
% Now, I have used the exact same method that I described in
% the implementation of \lngxfontslogo\ for setting the size
% variants. This is done with lazy evaluation, just before
% |\begin{document}|.
%    \begin{macrocode}

\hook_gput_code:nnn { begindocument / before } { . } {
  \tl_if_in:cnT {
    g _ lngx _ ipa _ upright _ tl
  } { NewCM } {
    \tl_if_in:cnTF {
      g _ lngx _ ipa _ upright _ tl
    } { Book } {
      \lngx_set_keys:n {
        ipa~
        upright~ features      = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCM08-Book.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCM10-Book.otf
              }
            }
          }
        }
      }
    } {
      \lngx_set_keys:n {
        ipa~
        upright~ features      = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCM08-Regular.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCM10-Regular.otf
              }
            }
          }
        }
      }
    }
  }
  \tl_if_in:cnT {
    g _ lngx _ ipa _ upright _ tl
  } { NewCMSans } {
    \tl_if_in:cnTF {
      g _ lngx _ ipa _ upright _ tl
    } { Book } {
      \lngx_set_keys:n {
        ipa~
        upright~ features      = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCMSans08-Book.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCMSans10-Book.otf
              }
            }
          }
        }
      }
    } {
      \lngx_set_keys:n {
        ipa~
        upright~ features      = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCMSans08-Regular.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCMSans10-Regular.otf
              }
            }
          }
        }
      }
    }
  }
  \tl_if_in:cnT {
    g _ lngx _ ipa _ italic _ tl
  } { NewCM } {
    \tl_if_in:cnTF {
      g _ lngx _ ipa _ italic _ tl
    } { Book } {
      \lngx_set_keys:n {
        ipa~
        italic~ features       = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCM08-BookItalic.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCM10-BookItalic.otf
              }
            }
          }
        }
      }
    } {
      \lngx_set_keys:n {
        ipa~
        italic~ features       = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCM08-Italic.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCM10-Italic.otf
              }
            }
          }
        }
      }
    }
  }
  \tl_if_in:cnT {
    g _ lngx _ ipa _ italic _ tl
  } { NewCMSans } {
    \tl_if_in:cnTF {
      g _ lngx _ ipa _ italic _ tl
    } { Book } {
      \lngx_set_keys:n {
        ipa~
        italic~ features       = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCMSans08-BookOblique.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCMSans10-BookOblique.otf
              }
            }
          }
        }
      }
    } {
      \lngx_set_keys:n {
        ipa~
        italic~ features       = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCMSans08-Oblique.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCMSans10-Oblique.otf
              }
            }
          }
        }
      }
    }
  }
  \tl_if_in:cnT {
    g _ lngx _ ipa _ sans _ upright _ tl
  } { NewCMSans } {
    \tl_if_in:cnTF {
      g _ lngx _ ipa _ upright _ tl
    } { Book } {
      \lngx_set_keys:n {
        ipa~ sans~
        upright~ features      = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCMSans08-Book.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCMSans10-Book.otf
              }
            }
          }
        }
      }
    } {
      \lngx_set_keys:n {
        ipa~ sans~
        upright~ features      = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCMSans08-Regular.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCMSans10-Regular.otf
              }
            }
          }
        }
      }
    }
  }
  \tl_if_in:cnT {
    g _ lngx _ ipa _ sans _ italic _ tl
  } { NewCMSans } {
    \tl_if_in:cnTF {
      g _ lngx _ ipa _ italic _ tl
    } { Book } {
      \lngx_set_keys:n {
        ipa~ sans~
        italic~ features       = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCMSans08-BookOblique.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCMSans10-BookOblique.otf
              }
            }
          }
        }
      }
    } {
      \lngx_set_keys:n {
        ipa~ sans~
        italic~ features       = {
          SizeFeatures           = {
            {
              Size                   = {-8},
              Font                   = {
                NewCMSans08-Oblique.otf
              }
            },
            {
              Size                   = {8-},
              Font                   = {
                NewCMSans10-Oblique.otf
              }
            }
          }
        }
      }
    }
  }
%    \end{macrocode}
% Now, I set the keys with the appropriate values and end
% the package.
%    \begin{macrocode}
  \lngx_set_keys:n {
    ipa~ upright~ features   = {
      UprightFont            = {
        \g_lngx_ipa_upright_tl
      },
      UprightFeatures        = {
        \g_lngx_ipa_upright_features_tl
      },
      BoldFont                 = {
        \g_lngx_ipa_bold_upright_tl
      },
      BoldFeatures             = {
        \g_lngx_ipa_bold_upright_features_tl
      },
      ItalicFont               = {
        \g_lngx_ipa_italic_tl
      },
      ItalicFeatures           = {
        \g_lngx_ipa_italic_features_tl
      },
      BoldItalicFont           = {
        \g_lngx_ipa_bold_italic_tl
      },
      BoldItalicFeatures       = {
        \g_lngx_ipa_bold_italic_features_tl
      },
      \tl_if_empty:cF {
        g _ lngx _ ipa _ slanted _ tl
      } {
        SlantedFont              = {
          \g_lngx_ipa_slanted_tl
        },
        \tl_if_empty:cF {
          g _ lngx _ ipa _ slanted _ features _ tl
        } {
          SlantedFeatures          = {
            \g_lngx_ipa_slanted_features_tl
          },
        }
      }
      \tl_if_empty:cF {
        g _ lngx _ ipa _ bold _ slanted _ tl
      } {
        BoldSlantedFont          = {
          \g_lngx_ipa_bold_slanted_tl
        },
        \tl_if_empty:cF {
          g _ lngx _ ipa _ bold _ slanted _ features _ tl
        } {
          BoldSlantedFeatures      = {
            \g_lngx_ipa_bold_slanted_features_tl
          },
        }
      }
      \tl_if_empty:cF {
        g _ lngx _ ipa _ swash _ tl
      } {
        SwashFont                = {
          \g_lngx_ipa_swash_tl
        },
        \tl_if_empty:cF {
          g _ lngx _ ipa _ swash _ features _ tl
        } {
          SwashFeatures            = {
            \g_lngx_ipa_swash_features_tl
          },
        }
      }
      \tl_if_empty:cF {
        g _ lngx _ ipa _ bold _ swash _ tl
      } {
        BoldSwashFont            = {
          \g_lngx_ipa_bold_swash_tl
        },
        \tl_if_empty:cF {
          g _ lngx _ ipa _ bold _ swash _ features _ tl
        } {
          BoldSwashFeatures        = {
            \g_lngx_ipa_bold_swash_features_tl
          },
        }
      }
      \tl_if_empty:cF {
        g _ lngx _ ipa _ small _ caps _ tl
      } {
        SmallCapsFont            = {
          \g_lngx_ipa_small_caps_tl
        }
        \tl_if_empty:cF {
          g _ lngx _ ipa _ small _ caps _ features _ tl
        } {
          SmallCapsFeatures        = {
            \g_lngx_ipa_small_caps_features_tl
          }
        }
      }
    },
    ipa~
    sans~ upright~ features  = {
      UprightFont              = {
        \g_lngx_ipa_sans_upright_tl
      },
      UprightFeatures          = {
        \g_lngx_ipa_sans_upright_features_tl
      },
      BoldFont                 = {
        \g_lngx_ipa_sans_bold_upright_tl
      },
      BoldFeatures             = {
        \g_lngx_ipa_sans_bold_upright_features_tl
      },
      ItalicFont               = {
        \g_lngx_ipa_sans_italic_tl
      },
      ItalicFeatures           = {
        \g_lngx_ipa_sans_italic_features_tl
      },
      BoldItalicFont           = {
        \g_lngx_ipa_sans_bold_italic_tl
      },
      BoldItalicFeatures       = {
        \g_lngx_ipa_sans_bold_italic_features_tl
      },
      \tl_if_empty:cF {
        g _ lngx _ ipa _ slanted _ tl
      } {
        SlantedFont              = {
          \g_lngx_ipa_slanted_tl
        },
        \tl_if_empty:cF {
          g _ lngx _ ipa _ slanted _ features _ tl
        } {
          SlantedFeatures          = {
            \g_lngx_ipa_slanted_features_tl
          },
        }
      }
      \tl_if_empty:cF {
        g _ lngx _ ipa _ sans _ bold _ slanted _ tl
      } {
        BoldSlantedFont          = {
          \g_lngx_ipa_sans_bold_slanted_tl
        },
        \tl_if_empty:cF {
          g _ lngx _ ipa _ sans _ bold _ slanted _ features
          _ tl
        } {
          BoldSlantedFeatures      = {
            \g_lngx_ipa_sans_bold_slanted_features_tl
          },
        }
      }
      \tl_if_empty:cF {
        g _ lngx _ ipa _ sans_ swash _ tl
      } {
        SwashFont                = {
          \g_lngx_ipa_sans_swash_tl
        },
        \tl_if_empty:cF {
          g _ lngx _ ipa _ sans_ swash _ features _ tl
        } {
          SwashFeatures            = {
            \g_lngx_ipa_sans_swash_features_tl
          },
        }
      }
      \tl_if_empty:cF {
        g _ lngx _ ipa _ sans _ bold _ swash _ tl
      } {
        BoldSwashFont            = {
          \g_lngx_ipa_sans_bold_swash_tl
        },
        \tl_if_empty:cF {
          g _ lngx _ ipa _ sans _ bold _ swash _ features _
          tl
        } {
          BoldSwashFeatures        = {
            \g_lngx_ipa_sans_bold_swash_features_tl
          },
        }
      }
      \tl_if_empty:cF {
        g _ lngx _ ipa _ sans _ small _ caps _ tl
      } {
        SmallCapsFont            = {
          \g_lngx_ipa_sans_small_caps_tl
        }
        \tl_if_empty:cF {
          g _ lngx _ ipa _ sans _ small _ caps _ features _
          tl
        } {
          SmallCapsFeatures        = {
            \g_lngx_ipa_sans_small_caps_features_tl
          }
        }
      }
    },
    ipa~
    mono~ upright~ features  = {
      UprightFont              = {
        \g_lngx_ipa_mono_upright_tl
      },
      UprightFeatures          = {
        \g_lngx_ipa_mono_upright_features_tl
      },
      BoldFont                 = {
        \g_lngx_ipa_mono_bold_upright_tl
      },
      BoldFeatures             = {
        \g_lngx_ipa_mono_bold_upright_features_tl
      },
      ItalicFont               = {
        \g_lngx_ipa_mono_italic_tl
      },
      ItalicFeatures           = {
        \g_lngx_ipa_mono_italic_features_tl
      },
      BoldItalicFont           = {
        \g_lngx_ipa_mono_bold_italic_tl
      },
      BoldItalicFeatures       = {
        \g_lngx_ipa_mono_bold_italic_features_tl
      },
      \tl_if_empty:cF {
        g _ lngx _ ipa _ mono _ slanted _ tl
      } {
        SlantedFont              = {
          \g_lngx_ipa_mono_slanted_tl
        },
        \tl_if_empty:cF {
          g _ lngx _ ipa _ mono _ slanted _ features _ tl
        } {
          SlantedFeatures          = {
            \g_lngx_ipa_mono_slanted_features_tl
          },
        }
      }
      \tl_if_empty:cF {
        g _ lngx _ ipa _ mono _ bold _ slanted _ tl
      } {
        BoldSlantedFont          = {
          \g_lngx_ipa_mono_bold_slanted_tl
        },
        \tl_if_empty:cF {
          g _ lngx _ ipa _ mono _ bold _ slanted _ features
          _ tl
        } {
          BoldSlantedFeatures    = {
            \g_lngx_ipa_mono_bold_slanted_features_tl
          },
        }
      }
      \tl_if_empty:cF {
        g _ lngx _ ipa _ mono _ swash _ tl
      } {
        SwashFont                = {
          \g_lngx_ipa_mono_swash_tl
        },
        \tl_if_empty:cF {
          g _ lngx _ ipa _ mono _ swash _ features _ tl
        } {
          SwashFeatures            = {
            \g_lngx_ipa_mono_swash_features_tl
          },
        }
      }
      \tl_if_empty:cF {
        g _ lngx _ ipa _ mono _ bold _ swash _ tl
      } {
        BoldSwashFont            = {
          \g_lngx_ipa_mono_bold_swash_tl
        },
        \tl_if_empty:cF {
          g _ lngx _ ipa _ mono _ bold _ swash _ features _
          tl
        } {
          BoldSwashFeatures        = {
            \g_lngx_ipa_mono_bold_swash_features_tl
          },
        }
      }
      \tl_if_empty:cF {
        g _ lngx _ ipa _ mono _ small _ caps _ tl
      } {
        SmallCapsFont            = {
          \g_lngx_ipa_mono_small_caps_tl
        }
        \tl_if_empty:cF {
          g _ lngx _ ipa _ mono _ small _ caps _ features _
          tl
        } {
          SmallCapsFeatures        = {
            \g_lngx_ipa_mono_small_caps_features_tl
          }
        }
      }
    }
  }
  \tl_if_in:cnT {
    g _ lngx _ ipa _ upright _ tl
  } { NewCM } {
    \lngx_set_keys:n {
      ipa~
      upright~ features        = {
        IgnoreFontspecFile,
        StylisticSet             = { 5 }
      }
    }
  }
  \tl_if_in:cnT {
    g _ lngx _ ipa _ sans _ upright _ tl
  } { NewCM } {
    \lngx_set_keys:n {
      ipa~ sans~
      upright~ features        = {
        IgnoreFontspecFile,
        StylisticSet             = { 5 }
      }
    }
  }
  \tl_if_in:cnT {
    g _ lngx _ ipa _ mono _ upright _ tl
  } { NewCM } {
    \lngx_set_keys:n {
      ipa~ mono~
      upright~ features        = {
        IgnoreFontspecFile,
        StylisticSet             = { 5 }
      }
    }
  }
  \lngx_set_main_ipa_font:ee {
    \g_lngx_ipa_upright_features_tl
  } {
    \g_lngx_ipa_upright_tl
  }
  \lngx_set_sans_ipa_font:ee {
    \g_lngx_ipa_sans_upright_features_tl
  } {
    \g_lngx_ipa_sans_upright_tl
  }
  \lngx_set_mono_ipa_font:ee {
    \g_lngx_ipa_mono_upright_features_tl
  } {
    \g_lngx_ipa_mono_upright_tl
  }
}
%</ipa>
%    \end{macrocode}
% \newpage
% \lngximplementation{logos}
%    \begin{macrocode}
%<*logos>
\ProvidesExplPackage{linguistix-logos}
                    {2025-07-11}
                    {v0.5d}
                    {%
                      Logos of the ‘LinguisTiX’ bundle..%
                    }
%    \end{macrocode}
% The \pkg{fontspec} package (if not already loaded).
%    \begin{macrocode}

\IfPackageLoadedF { fontspec } {
  \RequirePackage { fontspec }
}
%    \end{macrocode}
% \begin{macro}{\lngx_logo_font:}
% This is a command that switches to the New Computer Modern
% Uncial font family.
% \begin{macrocode}

\newfontfamily \lngx_logo_font: [
  IgnoreFontspecFile,
  UprightFont            = { NewCMUncial10-Book.otf },
  UprightFeatures        = {
    SizeFeatures           = {
      {
        Size                   = {-8},
        Font                   = {NewCMUncial08-Book.otf}
      },
      {
        Size                   = {8-},
        Font                   = {NewCMUncial10-Book.otf}
      },
    }
  },
  BoldFont               = { NewCMUncial10-Bold.otf },
  BoldFeatures           = {
    SizeFeatures           = {
      {
        Size                   = {-8},
        Font                   = {NewCMUncial08-Bold.otf}
      },
      {
        Size                   = {8-},
        Font                   = {NewCMUncial10-Bold.otf}
      },
    }
  },
  Renderer               = { HarfBuzz }
]{ NewCMUncial10-Book.otf }
%    \end{macrocode}
% \end{macro}
% \begin{macro}{lngx_purple_color}
% The following defines the |lngx_purple_color|.
%    \begin{macrocode}

\color_set:nn { lngx _ purple _ color } { blue ! 50 ! red }
%    \end{macrocode}
% \end{macro}
% Here, I define the commands for printing various logos.
% \begin{macro}{\lngxlogo}
%    \begin{macrocode}

\NewDocumentCommand \lngxlogo { O{} } {%
  \group_begin:
  \lngx_logo_font:
  LinguisTi
  \color_group_begin:
  \color_select:n { lngx_purple_color }
  X
  \color_group_end:
  \IfBlankF { #1 } { - #1 }
  \group_end:
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\lngxpkg}
% Since we need expandable commands, I use the non-protected
% function, |\cs_new:Npn| for defining them.
%    \begin{macrocode}

\cs_new:Npn \lngxpkg {
  \IfPackageLoadedTF { hyperref } {
    \texorpdfstring {
      \lngxlogo
    } {
      LinguisTiX
    }
  } {
    \lngxlogo
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{^^A
%   \lngxbaselogo,\lngxfontslogo,\lngxipalogo,^^A
%   \lngxlogoslogo,\lngxnfsslogo
% }
% Here, I define all the logos with a |clist|. The package
% names are stored in the |clist| and then used at
% appropriate positions.
%    \begin{macrocode}

\clist_map_inline:nn {
  base,
  examples,
  fixpex,
  fonts,
  ipa,
  logos,
  nfss
} {
%    \end{macrocode}
% |#1| is substituted with the package name. First, for the
% command-name itself, then as the optional argument of
% |\lngxlogo| and then in the \textsc{pdf}-string.
%    \begin{macrocode}
  \cs_new:cpn { lngx #1 logo } {
    \texorpdfstring {
      \lngxlogo [ #1 ]
    } {
      LinguisTiX - #1
    }
  }
}
%</logos>
%    \end{macrocode}
% \end{macro}
% \lngximplementation{nfss}
%    \begin{macrocode}
%<*nfss>
\ProvidesExplPackage{linguistix-nfss}
                    {2025-07-11}
                    {v0.5d}
                    {%
                      An extension to the core NFSS commands
                      from the ‘LinguisTiX’ bundle.%
                    }
%    \end{macrocode}
% I need a few temporary |tl|s. I declare them here. As
% noted by the use of |__|, these are package-internal
% |tl|s. Even though I don’t have any intention to change
% them, these are better not touched by the users.
%    \begin{macrocode}

\tl_new:N \l__lngx_normalfont_tmp_tl
\tl_new:N \l__lngx_selectfont_tmp_tl
\tl_new:N \l__lngx_family_tmp_tl
\tl_new:N \l__lngx_nfss_tmp_tl
%    \end{macrocode}
% These |tl|s are required for saving some values that are
% accessed later by the package as well as by the users.
%    \begin{macrocode}

\tl_new:N \l_lngx_current_encoding_tl
\tl_new:N \l_lngx_current_meta_family_tl
\tl_new:N \l_lngx_current_super_family_tl
\tl_new:N \l_lngx_current_series_tl
\tl_new:N \l_lngx_current_shape_tl
%    \end{macrocode}
% \begin{macro}{^^A
% \c_lngx_default_rmdefault_tl,^^A
% \c_lngx_default_sfdefault_tl,^^A
% \c_lngx_default_ttdefault_tl
% }
% Here, I start the |begindocument/end| hook. After the
% document has started, a lot of initialisation can be
% assumed to have happened. I set some publicly available
% |tl|s here.
%    \begin{macrocode}

\hook_gput_code:nnn { begindocument / end } { . } {
  \tl_const:Ne \c_lngx_default_rmdefault_tl { \rmdefault }
  \tl_const:Ne \c_lngx_default_sfdefault_tl { \sfdefault }
  \tl_const:Ne \c_lngx_default_ttdefault_tl { \ttdefault }
%    \end{macrocode}
% \end{macro}
% \begin{macro}{^^A
% \l_lngx_current_encoding_tl,^^A
% \l_lngx_current_meta_family_tl,^^A
% \l_lngx_current_super_family_tl,^^A
% \l_lngx_current_series_tl,^^A
% \l_lngx_current_shape_tl
% }
% First, I set the value |default| for the initial super
% font family.
%    \begin{macrocode}
  \tl_set:Nn \l_lngx_current_super_family_tl { default }
%    \end{macrocode}
% The current encoding is saved in the relevant |tl|.
%    \begin{macrocode}
  \tl_set:Ne \l_lngx_current_encoding_tl {
    \encodingdefault
  }
%    \end{macrocode}
% If the class is beamer, the font-family is automatically
% set to sans. Otherwise, mostly it is serif. Sadly, there
% is no public facing interface for confidently saying this,
% but as of now, this seems to be the picture. I check the
% current class and set the family |tl| accordingly.
%    \begin{macrocode}
  \IfClassLoadedTF { beamer } {
    \tl_set:Ne \l_lngx_current_meta_family_tl { sf }
  } {
    \tl_set:Ne \l_lngx_current_meta_family_tl { rm }
  }
%    \end{macrocode}
% Here, the series and shape |tl|s are set to their
% defaults.
%    \begin{macrocode}
  \tl_set:Ne \l_lngx_current_series_tl { md }
  \tl_set:Ne \l_lngx_current_shape_tl { up }
}
%    \end{macrocode}
% \end{macro}
% The |\normalfont| command overrides the encoding. I trick
% the command by saving the encoding that was active before
% |\normalfont| in a temporary |tl|.
%    \begin{macrocode}

\hook_gput_code:nnn { cmd / normalfont / before } { . } {
  \tl_set:Ne \l__lngx_normalfont_tmp_tl { \f@encoding }
}
%    \end{macrocode}
% After the processing of |\normalfont|, I equate the
% temporary |tl| with the one that the package is tracking.
% This way, the effect of |\normalfont| remains unchanged,
% but we still save the values that were there before using
% it. Only encoding needs this special setting. Other
% attributes aren’t reset by |\normalfont|.
%    \begin{macrocode}

\hook_gput_code:nnn { cmd / normalfont / after } { . } {
  \tl_set_eq:NN \l_lngx_current_encoding_tl
                \l__lngx_normalfont_tmp_tl
  \tl_clear:N   \l__lngx_normalfont_tmp_tl
}
%    \end{macrocode}
% Similar thing is done by |\selectfont| too. I repeat the
% code for that.
%    \begin{macrocode}

\hook_gput_code:nnn { cmd / selectfont / before } { . } {
  \tl_set:Ne \l__lngx_selectfont_tmp_tl { \f@encoding }
}

\hook_gput_code:nnn { cmd / selectfont / after } { . } {
  \tl_set_eq:NN \l_lngx_current_encoding_tl
                \l__lngx_selectfont_tmp_tl
  \tl_clear:N   \l__lngx_selectfont_tmp_tl
}
%    \end{macrocode}
% Now, after each |\XXfamily| commands, I save the family
% name in the respective |tl| for accessing later. All of
% these commands too reset the encoding. I repeat my trick
% for them too.
%    \begin{macrocode}

\hook_gput_code:nnn { cmd / rmfamily / before } { . } {
  \tl_set:Nn \l_lngx_current_meta_family_tl { rm }
  \tl_set:Ne \l__lngx_family_tmp_tl { \f@encoding }
}

\hook_gput_code:nnn { cmd / rmfamily / after } { . } {
  \tl_set:Nn \l_lngx_current_meta_family_tl { rm }
  \tl_set_eq:NN \l_lngx_current_encoding_tl
                \l__lngx_family_tmp_tl
  \tl_clear:N   \l__lngx_family_tmp_tl
}

\hook_gput_code:nnn { cmd / sffamily / before } { . } {
  \tl_set:Nn \l_lngx_current_meta_family_tl { sf }
  \tl_set:Ne \l__lngx_family_tmp_tl { \f@encoding }
}

\hook_gput_code:nnn { cmd / sffamily / after } { . } {
  \tl_set:Nn \l_lngx_current_meta_family_tl { sf }
  \tl_set_eq:NN \l_lngx_current_encoding_tl
                \l__lngx_family_tmp_tl
  \tl_clear:N   \l__lngx_family_tmp_tl
}

\hook_gput_code:nnn { cmd / ttfamily / before } { . } {
  \tl_set:Nn \l_lngx_current_meta_family_tl { tt }
  \tl_set:Ne \l__lngx_family_tmp_tl { \f@encoding }
}

\hook_gput_code:nnn { cmd / ttfamily / after } { . } {
  \tl_set:Nn \l_lngx_current_meta_family_tl { tt }
  \tl_set_eq:NN \l_lngx_current_encoding_tl
                \l__lngx_family_tmp_tl
  \tl_clear:N   \l__lngx_family_tmp_tl
}
%    \end{macrocode}
% After the series commands, I save the series name in the
% |tl|. Note that, I don’t use the traditional \LaTeX\
% labels |m|, |bx| etc. Using, |md| and |bx| is more
% intuitive, plus they also can be used in the argument of
% |\use:c| directly.
%    \begin{macrocode}

\hook_gput_code:nnn { cmd / mdseries / after } { . } {
  \tl_set:Nn \l_lngx_current_series_tl { md }
}

\hook_gput_code:nnn { cmd / bfseries / after } { . } {
  \tl_set:Nn \l_lngx_current_series_tl { bf }
}
%    \end{macrocode}
% For shape related commands too, I save the names that are
% more closer to their respective commands.
%    \begin{macrocode}

\hook_gput_code:nnn { cmd / upshape / after } { . } {
  \tl_set:Nn \l_lngx_current_shape_tl { up }
}

\hook_gput_code:nnn { cmd / itshape / after } { . } {
  \tl_set:Nn \l_lngx_current_shape_tl { it }
}

\hook_gput_code:nnn { cmd / scshape / after } { . } {
  \tl_set:Nn \l_lngx_current_shape_tl { sc }
}

\hook_gput_code:nnn { cmd / sscshape / after } { . } {
  \tl_set:Nn \l_lngx_current_shape_tl { ssc }
}

\hook_gput_code:nnn { cmd / slshape / after } { . } {
  \tl_set:Nn \l_lngx_current_shape_tl { sl }
}

\hook_gput_code:nnn { cmd / swshape / after } { . } {
  \tl_set:Nn \l_lngx_current_shape_tl { sw }
}

\hook_gput_code:nnn { cmd / ulcshape / after } { . } {
  \tl_set:Nn \l_lngx_current_shape_tl { ulc }
}

\hook_gput_code:nnn { cmd / ulcshape / after } { . } {
  \tl_set:Nn \l_lngx_current_shape_tl { #1 }
}
%    \end{macrocode}
% 
% \begin{macro}[pTF]{\lngx_if_encoding:n}
% I provide a conditional for checking the current encoding
% with the given argument.
%    \begin{macrocode}

\prg_new_conditional:Nnn \lngx_if_encoding:n {
  p,
  T,
  F,
  TF
} {
  \tl_if_eq:NnTF \l_lngx_current_encoding_tl { #1 } {
    \prg_return_true:
  } {
    \prg_return_false:
  }
}

%    \end{macrocode}
% \end{macro}
% \begin{macro}{\IfEncodingTF,\IfEncodingT,\IfEncodingF}
% For non-\LaTeX3 contexts, these simpler alternatives are
% provided.
%    \begin{macrocode}

\cs_new_eq:NN \IfEncodingTF \lngx_if_encoding:nTF
\cs_new_eq:NN \IfEncodingT  \lngx_if_encoding:nT
\cs_new_eq:NN \IfEncodingF  \lngx_if_encoding:nF
%    \end{macrocode}
% \end{macro}
% \begin{macro}[pTF]{\lngx_if_meta_family:n}
% A conditional for checking the meta family with the given
% argument.
%    \begin{macrocode}

\prg_new_conditional:Nnn \lngx_if_meta_family:n {
  p,
  T,
  F,
  TF
} {
  \tl_if_eq:NnTF \l_lngx_current_meta_family_tl { #1 } {
    \prg_return_true:
  } {
    \prg_return_false:
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{^^A
% \IfMetaFamilyTF,^^A
% \IfMetaFamilyT,^^A
% \IfMetaFamilyF
% }
% User-facing conditionals for meta family.
%    \begin{macrocode}

\cs_new_eq:NN \IfMetaFamilyTF \lngx_if_meta_family:nTF
\cs_new_eq:NN \IfMetaFamilyT  \lngx_if_meta_family:nT
\cs_new_eq:NN \IfMetaFamilyF  \lngx_if_meta_family:nF
%    \end{macrocode}
% \end{macro}
% \begin{macro}[pTF]{\lngx_if_super_family:n}
% A conditional for checking the super family with the given
% argument.
%    \begin{macrocode}

\prg_new_conditional:Nnn \lngx_if_super_family:n {
  p,
  T,
  F,
  TF
} {
  \tl_if_eq:NnTF \l_lngx_current_super_family_tl { #1 } {
    \prg_return_true:
  } {
    \prg_return_false:
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{^^A
% \IfSuperFamilyTF,^^A
% \IfSuperFamilyT,^^A
% \IfSuperFamilyF
% }
% User-facing conditionals for super family.
%    \begin{macrocode}

\cs_new_eq:NN \IfSuperFamilyTF \lngx_if_super_family:nTF
\cs_new_eq:NN \IfSuperFamilyT  \lngx_if_super_family:nT
\cs_new_eq:NN \IfSuperFamilyF  \lngx_if_super_family:nF
%    \end{macrocode}
% \end{macro}
% \begin{macro}[pTF]{\lngx_if_series:n}
% A conditional for checking the current series with the
% given argument.
%    \begin{macrocode}

\prg_new_conditional:Nnn \lngx_if_series:n {
  p,
  T,
  F,
  TF
} {
  \tl_if_eq:NnTF \l_lngx_current_series_tl { #1 } {
    \prg_return_true:
  } {
    \prg_return_false:
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\IfSeriesTF,\IfSeriesT,\IfSeriesF}
% Its user-side macros.
%    \begin{macrocode}

\cs_new_eq:NN \IfSeriesTF \lngx_if_series:nTF
\cs_new_eq:NN \IfSeriesT  \lngx_if_series:nT
\cs_new_eq:NN \IfSeriesF  \lngx_if_series:nF
%    \end{macrocode}
% \end{macro}
% \begin{macro}[pTF]{\lngx_if_shape:n}
% A conditional for checking the current shape with the
% current argument.
%    \begin{macrocode}

\prg_new_conditional:Nnn \lngx_if_shape:n {
  p,
  T,
  F,
  TF
} {
  \tl_if_eq:NnTF \l_lngx_current_shape_tl { #1 } {
    \prg_return_true:
  } {
    \prg_return_false:
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\IfShapeTF,\IfShapeT,\IfShapeF}
% User-side macros for the same.
%    \begin{macrocode}

\cs_new_eq:NN \IfShapeTF \lngx_if_shape:nTF
\cs_new_eq:NN \IfShapeT  \lngx_if_shape:nT
\cs_new_eq:NN \IfShapeF  \lngx_if_shape:nF
%    \end{macrocode}
% \end{macro}
% Now I will use the |\clist_map_inline:nn| technique for
% generating multiple conditionals of the same pattern. For
% that, I need a |cnn| variant of |\prg_new_conditional:Nnn|
% that I create with the following.
%    \begin{macrocode}

\cs_generate_variant:Nn \prg_new_conditional:Nnn { cnn }
%    \end{macrocode}
% 
% \begin{macro}[pTF]{^^A
% \lngx_if_meta_family_rm:,\lngx_if_meta_family_sf:,^^A
% \lngx_if_meta_family_tt:
% }
% These are separate conditionals for |rm|, |sf| and |tt|
% families. They don’t require arguments. No user side
% commands are provided for these.
%    \begin{macrocode}

\clist_map_inline:nn {
  rm,
  sf,
  tt
} {
  \prg_new_conditional:cnn {
    lngx _ if _ meta _ family _ #1 :
  } {
    p, T, F, TF
  } {
    \tl_if_eq:NnTF \l_lngx_current_meta_family_tl { #1 } {
      \prg_return_true:
    } {
      \prg_return_false:
    }
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}[pTF]{^^A
% \lngx_if_series_md:,\lngx_if_series_bf:
% }
% Separate conditionals for both the series.
%    \begin{macrocode}

\clist_map_inline:nn {
  md,
  bf
} {
  \prg_new_conditional:cnn { lngx _ if _ series _ #1 : } {
    p, T, F, TF
  } {
    \tl_if_eq:NnTF \l_lngx_current_series_tl { #1 } {
      \prg_return_true:
    } {
      \prg_return_false:
    }
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}[pTF]{^^A
% \lngx_if_shape_up:,\lngx_if_shape_it:,^^A
% \lngx_if_shape_sc:,\lngx_if_shape_ssc:,^^A
% \lngx_if_shape_sl:,\lngx_if_shape_sw:,^^A
% \lngx_if_shape_ulc:
% }
% Separate conditionals for all the shapes.
%    \begin{macrocode}

\clist_map_inline:nn {
  up,
  it,
  sc,
  ssc,
  sl,
  sw,
  ulc
} {
  \prg_new_conditional:cnn { lngx _ if _ shape _ #1 : } {
    p, T, F, TF
  } {
    \tl_if_eq:NnTF \l_lngx_current_shape_tl { #1 } {
      \prg_return_true:
    } {
      \prg_return_false:
    }
  }
}
%    \end{macrocode}
% \end{macro}
% These keys are used in the argument of
% |\lngx_super_font_family:nn|. This is why they are
% separated from the set |lngx_keys|. We create new |tl|s
% using these keys that save the |rm|, |sf| and |tt|
% defaults of the new super font family.
% |\l__lngx_nfss_tmp_tl| is defined by the command that
% creates the super font family.
%    \begin{macrocode}

\clist_map_inline:nn {
  rm,
  sf,
  tt
} {
  \keys_define:nn { lngx _ nfss } {
    #1
    .code:n                = {
      \tl_gclear_new:c {
        g _ lngx _ \l__lngx_nfss_tmp_tl _ #1 default _ tl
      }
      \tl_gset:cn {
        g _ lngx _ \l__lngx_nfss_tmp_tl _ #1 default _ tl
      } { ##1 }
    }
  }
}
%    \end{macrocode}
% \begin{macro}{^^A
% \lngx_super_font_family:nn,\superfontfamily^^A
% }
% I first set the temporary |tl| with the name of the super
% font family retrieved from the first argument.
%    \begin{macrocode}

\cs_new_protected:Npn \lngx_super_font_family:nn #1#2 {
  \tl_set:Ne \l__lngx_nfss_tmp_tl { #1 }
%    \end{macrocode}
% Now, I pass the second argument to the key-set I just
% defined. The temporary |tl| is cleared. This function
% comes with a user-side macro.
%    \begin{macrocode}
  \keys_set:nn { lngx _ nfss } { #2 }
  \tl_clear:N \l__lngx_nfss_tmp_tl
}

\cs_set_eq:NN \superfontfamily
              \lngx_super_font_family:nn
%    \end{macrocode}
% \end{macro}
% \begin{macro}{^^A
% \lngx_soft_super_font_family:nn,\softsuperfontfamily
% }
% I set the |tl| that saves the current font family to the
% first argument.
%    \begin{macrocode}

\cs_new_protected:Npn \lngx_soft_super_font_family:nn #1#2 {
  \tl_set:Ne \l_lngx_current_super_family_tl { #1 }
%    \end{macrocode}
% I first check if the |tl|s for rm, sf and tt are empty or
% not. Only if they are not, I use their content in the
% respective |\XXdefault|. This makes the use of all the
% keys optional. Only the keys that the user has used are
% processed here.
%    \begin{macrocode}
  \clist_map_inline:nn {
    rm,
    sf,
    tt
  } {
    \tl_if_empty:cF { g _ lngx _ #1 _ ##1 default _ tl } {
      \cs_set:cpe { ##1 default } {
        \tl_use:c { g _ lngx _ #1 _ ##1 default _ tl }
      }
    }
  }
%    \end{macrocode}
% After setting the |\XXdefault|, I use the |\normalfont| to
% initialise the super font family. 
%    \begin{macrocode}
  \normalfont
%    \end{macrocode}
% Now all the aspects are reset. But, we have them saved in
% our |tl|s. So now depending on the attributes that the
% user wants to retrieve, I call those attributes again. The
% second argument is (expected to be) a comma-separated list
% of all such attributes. Thus, we change the super font
% family, but retain the already active attributes. This
% command has a user-facing macro.
%    \begin{macrocode}
  \clist_map_inline:nn { #2 } {
    \str_case:nn { ##1 } {
      { encoding } {
        \exp_args:NV \fontencoding
                     \l_lngx_current_encoding_tl
      }
      { family } {
        \use:c {
          \l_lngx_current_meta_family_tl family
        }
        \exp_args:NV \fontencoding
                     \l_lngx_current_encoding_tl
        \selectfont
      }
      { series } {
        \use:c {
          \l_lngx_current_series_tl series
        }
      }
      { shape }  {
        \use:c {
          \l_lngx_current_shape_tl shape
        }
      }
    }
  }
}

\cs_set_eq:NN \softsuperfontfamily
              \lngx_soft_super_font_family:nn
%    \end{macrocode}
% \end{macro}
% \begin{macro}{^^A
% \lngx_softer_super_font_family:n,\softersuperfontfamily
% }
% This function excludes the encoding and resets all the
% other attributes. It comes with a user-side macro.
%    \begin{macrocode}

\cs_new_protected:Npn \lngx_softer_super_font_family:n #1 {
  \lngx_soft_super_font_family:nn { #1 } {
    family,
    series,
    shape
  }
}

\cs_set_eq:NN \softersuperfontfamily
              \lngx_softer_super_font_family:n
%    \end{macrocode}
% \end{macro}
% \begin{macro}{^^A
% \lngx_softest_super_font_family:n,\softestsuperfontfamily
% }
% This function resets all the attributes. It is available
% as a user-side macro.
%    \begin{macrocode}

\cs_new_protected:Npn \lngx_softest_super_font_family:n #1 {
  \lngx_soft_super_font_family:nn { #1 } {
    encoding,
    family,
    series,
    shape
  }
}

\cs_set_eq:NN \softestsuperfontfamily
              \lngx_softest_super_font_family:n
%    \end{macrocode}
% \end{macro}
% \begin{macro}{^^A
% \lngx_soft_normal_font:n,\softnormalfont
% }
% Following the same logic, I now provide the command for
% resetting to the default super family, but retaining the
% active attributes. I provide a user-side macro for this.
%    \begin{macrocode}

\cs_new_protected:Npn \lngx_soft_normal_font:n #1 {
  \tl_set:Ne \l_lngx_current_super_family_tl { default }
  \clist_map_inline:nn {
    rm,
    sf,
    tt
  } {
    \cs_set:cpe { ##1 default } {
      \tl_use:c { c _ lngx _ default _ ##1 default _ tl }
    }
  }
  \normalfont
  \clist_map_inline:nn { #1 } {
    \str_case:nn { ##1 } {
      { encoding } {
        \exp_args:NV \fontencoding
                     \l_lngx_current_encoding_tl
      }
      { family } {
        \use:c {
          \l_lngx_current_meta_family_tl family
        }
        \exp_args:NV \fontencoding
                     \l_lngx_current_encoding_tl
        \selectfont
      }
      { series } {
        \use:c {
          \l_lngx_current_series_tl series
        }
      }
      { shape }  {
        \use:c {
          \l_lngx_current_shape_tl shape
        }
      }
    }
  }
}

\cs_set_eq:NN \softnormalfont \lngx_soft_normal_font:n
%    \end{macrocode}
% \end{macro}
% \begin{macro}{^^A
% \lngx_softer_normal_font:,\softernormalfont
% }
% This is a parallel to the \enquote{softer} super family
% command for the default super family.
%    \begin{macrocode}

\cs_new_protected:Npn \lngx_softer_normal_font: {
  \lngx_soft_normal_font:n {
    family,
    series,
    shape
  }
}

\cs_set_eq:NN \softernormalfont \lngx_softer_normal_font:
%    \end{macrocode}
% \end{macro}
% \begin{macro}{^^A
% \lngx_softest_normal_font:,\softestnormalfont
% }
% This is a parallel to the \enquote{softest} super family
% command for the default super family.
%    \begin{macrocode}

\cs_new_protected:Npn \lngx_softest_normal_font: {
  \lngx_soft_normal_font:n {
    encoding,
    family,
    series,
    shape
  }
}

\cs_set_eq:NN \softestnormalfont \lngx_softest_normal_font:
%    \end{macrocode}
% \end{macro}
% \begin{macro}[EXP]{^^A
% \CurrentEncoding,\CurrentMetaFamily,\CurrentSeries,^^A
% \CurrentShape
% }
% Lastly, we create the commands that print the current
% values of the font attributes and end the package.
%    \begin{macrocode}
\cs_new:Npn \CurrentEncoding {
  \tl_use:N \l_lngx_current_encoding_tl
}
\cs_new:Npn \CurrentMetaFamily {
  \tl_use:N \l_lngx_current_meta_family_tl
}
\cs_new:Npn \CurrentSuperFamily {
  \tl_use:N \l_lngx_current_super_family_tl
}
\cs_new:Npn \CurrentSeries {
  \tl_use:N \l_lngx_current_series_tl
}
\cs_new:Npn \CurrentShape {
  \tl_use:N \l_lngx_current_shape_tl
}
%</nfss>
%    \end{macrocode}
% \end{macro}
% \end{implementation}
% \printbibliography
% ^^A \PrintIndex
% \Finale