% \iffalse meta-comment % % File: linguistix.dtx % % ---------------------------------------------------------- % The LaTeX bundle linguistix v0.1b % 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 % . % ---------------------------------------------------------- % % \fi % \iffalse %<*internal> \iffalse % %<*readme> ------------------------------------------------------------ Bundle: linguistix Version: v0.1b Author: निरंजन Description: Enhanced support for linguistics. Repository: puszcza.gnu.org.ua/projects/linguistix License: GPLv3+, GFDLv1.3+ ------------------------------------------------------------ % %<*internal> \fi % %<*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} } \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}% } \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% } \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} % % \fi % \title{^^A % \phantomsection\label{lngx}^^A % The \lngxpkg\ bundle^^A % } % \author{{\mrfnt निरंजन}} % \date{^^A % \today\ (v0.1b)\\[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. % % \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! % % \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{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. Let’s 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} % \cs{lngx_keys_set:n} \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{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} % \cs{lngx_set_main_font:nn} \marg{features} \marg{font} % \cs{lngx_set_sans_font:nn} \marg{features} \marg{font} % \cs{lngx_set_mono_font:nn} \marg{features} \marg{font} % \cs{lngx_set_math_font:nn} \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} % \cs{lngx_set_main_ipa_font:nn} \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} % \cs{lngx_set_sans_ipa_font:nn} \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} % \cs{lngx_set_mono_ipa_font:nn} \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-05-20} {v0.1b} {% 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 } } % % \end{macrocode} % \newpage % % \lngximplementation{base} % % Set the essentials of the package. % \begin{macrocode} %<*base> \ProvidesExplPackage{linguistix-base} {2025-05-20} {v0.1b} {% 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 % % \end{macrocode} % \end{macro} % \newpage % \lngximplementation{fonts} % Package essentials first. % \begin{macrocode} %<*font> \ProvidesExplPackage{linguistix-fonts} {2025-05-20} {v0.1b} {% 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 } } % \end{macrocode} % \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 = { NewCM08-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 = { NewCMSans08-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 } } % % \end{macrocode} % \newpage % \lngximplementation{ipa} % \begin{macrocode} %<*ipa> \ProvidesExplPackage{linguistix-ipa} {2025-05-20} {v0.1b} {% 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 } } % \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 = { NewCM08-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 = { NewCMSans08-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_bold_upright_tl }, UprightFeatures = { \g_lngx_ipa_mono_bold_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 } } % % \end{macrocode} % \newpage % \lngximplementation{logos} % \begin{macrocode} %<*logos> \ProvidesExplPackage{linguistix-logos} {2025-05-20} {v0.1b} {% 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} % \begin{macrocode} \color_set:nn { lngx _ purple _ color } { blue ! 50 ! red } % \end{macrocode} % \end{macro} % \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} % \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 % } % \begin{macrocode} \clist_map_inline:nn { base, examples, fonts, ipa, logos, nfss } { \cs_new:cpn { lngx #1 logo } { \texorpdfstring { \lngxlogo [ #1 ] } { LinguisTiX - #1 } } } % % \end{macrocode} % \end{macro} % \lngximplementation{nfss} % \begin{macrocode} %<*nfss> \ProvidesExplPackage{linguistix-nfss} {2025-05-20} {v0.1b} {% 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 } % % \end{macrocode} % \end{macro} % \end{implementation} % \printbibliography % ^^A \PrintIndex % \Finale