% ^package_name="xsipa"_version="1.0" % ^desc A LaTeX package for phonetic transcription inspired by XSAMPA, mapping custom XSAMPA-like input into IPA using TIPA or xunicode depending on engine. _desc % ^author Akpoué Kouamé Josué _author % ^contact djosuebetsaleelakpoue@gmail.com _contact % ^license LaTeX Project Public License v1.3c _license \ProvidesPackage{xsipa}[2025/05/16 v1.0 XSAMPA-inspired input to IPA transcription] % ^action_name="Loading Required Packages" \RequirePackage{iftex} \ifXeTeX \RequirePackage{xunicode} \else \ifLuaTeX \RequirePackage{xunicode} \else \ifPDFTeX \RequirePackage{tipa} \fi \fi \fi \RequirePackage{xparse} % _action % ^action_name="Setting default transcription engine" % This can be expanded later to allow user-defined options like [xunicode] or [tipa] \newcommand{\xs@engine}{} \ifXeTeX \renewcommand{\xs@engine}{xunicode} \else \ifLuaTeX \renewcommand{\xs@engine}{xunicode} \else \renewcommand{\xs@engine}{tipa} \fi \fi % _action % ^action_name="Defining Utilities" \ExplSyntaxOn \NewDocumentCommand{\ifNextCharTF}{m m m}{% \tl_if_eq:NnTF \c_token_next_token% {#1} {#2} {#3}% } \ExplSyntaxOff % _action % ^action_name="Declaring xipa Symbols" % ^- --- CONSONANTS --- _- % ^- Eng _- \DeclareTextSymbol{\tipaEngChar}{T3}{78} \NewDocumentCommand{\xsipaEng}{}{{\tipaencoding\tipaEngChar}} % ^- --- SUPRASEGMENTALS --- _- \NewDocumentCommand{\xsipaExtraShort}{m}% {\tipaupperaccent{'010}{\xsipaProcess{#1}}} % ^- --- TONE DIACRITICS --- _- \NewDocumentCommand{\xsipaExtraHighTone}{m}% {\tipaupperaccent{'005}{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaHighTone}{m}% {\tipaupperaccent{'001}{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaMidTone}{m}% {\tipaupperaccent{'011}{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaLowTone}{m}% {\tipaupperaccent{'000}{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaExtraLowTone}{m}% {\tipaupperaccent{'015}{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaRisingTone}{m}% {\tipaupperaccent{'007}{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaFallingTone}{m}% {\tipaupperaccent{'002}{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaLowRisingTone}{m}% {\tipaupperaccent{'231}{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaHighRisingTone}{m}% {\tipaupperaccent{'230}{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaFallingRisingTone}{m}% {\tipaupperaccent{'233}{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaRisingFallingTone}{m}% {\tipaupperaccent{'232}{\xsipaProcess{#1}}} % ^- --- OTHER DIACRITICS --- _- % ^- Nasalized _- \NewDocumentCommand{\xsipaNasalized}{m}% {\tipaupperaccent{'003}{\xsipaProcess{#1}}} % ^- Linking _- \NewDocumentCommand{\xsipaLinking}{m}% {\textipa{\textbottomtiebar{\xsipaProcess{#1}}}} \NewDocumentCommand{\xsipaVoiceless}{m}% {\textsubring{*#1}} \NewDocumentCommand{\xsipaVoiced}{m}% {\textsubwedge{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaAspirated}{m}{#1\textipa{\super h}} \NewDocumentCommand{\xsipaMoreRounded}{m}{\textsubrhalfring{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaLessRounded}{m}{\textsublhalfring{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaAdvanced}{m}{\textsubplus{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaRetracted}{m}{\textsubbar{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaCentralized}{m}% {\tipaupperaccent{'004}{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaMidCentralized}{m}{\textovercross{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaSyllabic}{m}{\textsyllabic{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaNonSyllabic}{m}{\textsubarch{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaRhoticity}{m}{\xsipaProcess{\xsipaProcess{#1}}\textrhoticity} \NewDocumentCommand{\xsipaBreathyVoiced}{m}{\textsubumlaut{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaCreackyVoiced}{m}{\textsubtilde{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaLinguolabial}{m}{\textseagull{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaLabialized}{m}{#1\textipa{\super w}} \NewDocumentCommand{\xsipaPalatalized}{m}{#1\textipa{\super j}} \NewDocumentCommand{\xsipaVelarized}{m}{#1\textipa{\super G}} \NewDocumentCommand{\xsipaPharyngealized}{m}{#1\textipa{\super Q}} \NewDocumentCommand{\xsipaDental}{m}{\textsubbridge{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaApical}{m}{\textinvsubbridge{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaLaminal}{m}{\textsubsquare{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaNasalRelease}{m}{#1\textipa{\super n}} \NewDocumentCommand{\xsipaLateralRelease}{m}{#1\textipa{\super l}} \NewDocumentCommand{\xsipaNoAudibleRelease}{m}{#1\textcorner} \NewDocumentCommand{\xsipaVelarizedOrPharyngealized}{m}{\textsuperimposetilde{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaRaised}{m}{\textraising{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaLowered}{m}{\textlowering{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaATR}{m}{\textadvancing{\xsipaProcess{#1}}} \NewDocumentCommand{\xsipaRTR}{m}{\textretracting{\xsipaProcess{#1}}} % _action % ^action_name="Définition de la macro \xs" \NewDocumentCommand{\xs}{t* t; t? t| t: t~ t\@}{% \IfBooleanTF{#1}{% \IfBooleanT{#2}{\relax}% \IfBooleanT{#3}{\relax}% \IfBooleanT{#4}{\relax}% \IfBooleanT{#5}{\relax}% \IfBooleanT{#6}{\relax}% \xsipaParse}{% \IfBooleanTF{#2}{\xsipaDiacritiques}{% \IfBooleanTF{#3}{\xsipaGlottalConsonant}{% \IfBooleanTF{#4}{\xsipaDentalClick}{% \IfBooleanTF{#5}{\xsipatestvlength}{% \IfBooleanTF{#6}{\xsipaNasalized}{% \IfBooleanTF{#7}{\xsipatestat}{% \xsipaSpecChars}}}}}}}% } \NewDocumentCommand{\xsipaParse}{u*}% {% \xsipaProcess{#1}% } % ^action_name="Disabling LaTeX3 syntax" \ExplSyntaxOn % _action \NewDocumentCommand{\xsipaProcess}{ m } {% \group_begin:% \char_set_catcode_other:N \~% \xs_process:n { #1 }% \group_end: }% % ^action_name="Configuration de la Fonction principale de traitement" \cs_new_protected:Nn \xs_process:n {% \xs_replace:n { #1 }% }% % _action % ^action_name="Configuration de la Fonction de remplacement" \cs_new:Npn \xs_replace:n #1% {% \tl_set:Nn \l_tmpa_tl { #1 }% % ^action_name="Configuring replacements" \tl_replace_all:Nnn \l_tmpa_tl { z` } { \textrtailz }% \tl_replace_all:Nnn \l_tmpa_tl { z/ } { \textctz }% \tl_replace_all:Nnn \l_tmpa_tl { Z } { \textipa{Z} }% \tl_replace_all:Nnn \l_tmpa_tl { Y } { \textscy }% \tl_replace_all:Nnn \l_tmpa_tl { x/ } { \texththeng }% \tl_replace_all:Nnn \l_tmpa_tl { X/ } { \textcrh }% \tl_replace_all:Nnn \l_tmpa_tl { X } { \textipa{X} }% \tl_replace_all:Nnn \l_tmpa_tl { W } { \textipa{\*w} }% \tl_replace_all:Nnn \l_tmpa_tl { v/ } { \textipa{V} }% \tl_replace_all:Nnn \l_tmpa_tl { V } { \textipa{2} }% \tl_replace_all:Nnn \l_tmpa_tl { U } { \textipa{U} }% \tl_replace_all:Nnn \l_tmpa_tl { t` } { \textrtailt }% \tl_replace_all:Nnn \l_tmpa_tl { t;S } { \textteshlig }% \tl_replace_all:Nnn \l_tmpa_tl { t;s } { \textipa{\t{ts}} }% \tl_replace_all:Nnn \l_tmpa_tl { t;> } { t' }% \tl_replace_all:Nnn \l_tmpa_tl { t;) } { t' }% \tl_replace_all:Nnn \l_tmpa_tl { s` } { \textrtails }% \tl_replace_all:Nnn \l_tmpa_tl { s/ } { \textipa{C} }% \tl_replace_all:Nnn \l_tmpa_tl { s;> } { s' }% \tl_replace_all:Nnn \l_tmpa_tl { s;) } { s' }% \tl_replace_all:Nnn \l_tmpa_tl { S } { \textipa{S} }% \tl_replace_all:Nnn \l_tmpa_tl { r` } { \textrtailr }% \tl_replace_all:Nnn \l_tmpa_tl { r/` } { \textturnrrtail }% \tl_replace_all:Nnn \l_tmpa_tl { r/ } { \textipa{\*r} }% \tl_replace_all:Nnn \l_tmpa_tl { R/ } { \textscr }% \tl_replace_all:Nnn \l_tmpa_tl { 4 } { \textipa{R} }% \tl_replace_all:Nnn \l_tmpa_tl { Q } { \textipa{6} }% \tl_replace_all:Nnn \l_tmpa_tl { p/ } { \textipa{F} }% \tl_replace_all:Nnn \l_tmpa_tl { p;> } { p' }% \tl_replace_all:Nnn \l_tmpa_tl { p;) } { p' }% \tl_replace_all:Nnn \l_tmpa_tl { P } { \textipa{V} }% \tl_replace_all:Nnn \l_tmpa_tl { O/ } { \textbullseye }% \tl_replace_all:Nnn \l_tmpa_tl { O } { \textipa{O} }% \tl_replace_all:Nnn \l_tmpa_tl { n` } { \textrtailn }% \tl_replace_all:Nnn \l_tmpa_tl { N/ } { \textscn }% \tl_replace_all:Nnn \l_tmpa_tl { N } { \textipa{N} }% \tl_replace_all:Nnn \l_tmpa_tl { M/ } { \textturnmrleg }% \tl_replace_all:Nnn \l_tmpa_tl { l` } { \textrtaill }% \tl_replace_all:Nnn \l_tmpa_tl { l/ } { \textturnlonglegr }% \tl_replace_all:Nnn \l_tmpa_tl { L/ } { \textipa{\;L} }% \tl_replace_all:Nnn \l_tmpa_tl { K/ } { \textlyoghlig }% \tl_replace_all:Nnn \l_tmpa_tl { k;p } { \textipa{\t{kp}} }% \tl_replace_all:Nnn \l_tmpa_tl { k;> } { k' }% \tl_replace_all:Nnn \l_tmpa_tl { k;) } { k' }% \tl_replace_all:Nnn \l_tmpa_tl { K } { \textbeltl }% \tl_replace_all:Nnn \l_tmpa_tl { J/;< } { \texthtbardotlessj }% \tl_replace_all:Nnn \l_tmpa_tl { J/;( } { \texthtbardotlessj }% \tl_replace_all:Nnn \l_tmpa_tl { j/ } { \textipa{J} }% \tl_replace_all:Nnn \l_tmpa_tl { J/ } { \textbardotlessj }% \tl_replace_all:Nnn \l_tmpa_tl { J } { \textltailn }% \tl_replace_all:Nnn \l_tmpa_tl { I } { \textipa{I} }% \tl_replace_all:Nnn \l_tmpa_tl { h/ } { \textipa{H} }% \tl_replace_all:Nnn \l_tmpa_tl { H/ } { \textipa{\;H} }% \tl_replace_all:Nnn \l_tmpa_tl { G/;< } { \texthtscg }% \tl_replace_all:Nnn \l_tmpa_tl { G/;( } { \texthtscg }% \tl_replace_all:Nnn \l_tmpa_tl { G/ } { \textscg }% \tl_replace_all:Nnn \l_tmpa_tl { g;< } { \texthtg }% \tl_replace_all:Nnn \l_tmpa_tl { g;( } { \texthtg }% \tl_replace_all:Nnn \l_tmpa_tl { G } { \textipa{G} }% \tl_replace_all:Nnn \l_tmpa_tl { g } { \textipa{g} }% \tl_replace_all:Nnn \l_tmpa_tl { E } { \textipa{E} }% \tl_replace_all:Nnn \l_tmpa_tl { d` } { \textrtaild }% \tl_replace_all:Nnn \l_tmpa_tl { d;Z } { \textdyoghlig }% \tl_replace_all:Nnn \l_tmpa_tl { d;< } { \texthtd }% \tl_replace_all:Nnn \l_tmpa_tl { d;( } { \texthtd }% \tl_replace_all:Nnn \l_tmpa_tl { D } { \textipa{D} }% \tl_replace_all:Nnn \l_tmpa_tl { C } { \textipa{\c{c}} }% \tl_replace_all:Nnn \l_tmpa_tl { B/ } { \textscb }% \tl_replace_all:Nnn \l_tmpa_tl { b;< } { \texthtb }% \tl_replace_all:Nnn \l_tmpa_tl { b;( } { \texthtb }% \tl_replace_all:Nnn \l_tmpa_tl { A } { \textipa{A} }% \tl_replace_all:Nnn \l_tmpa_tl { 8 } { \textipa{8} }% \tl_replace_all:Nnn \l_tmpa_tl { 7 } { \textipa{7} }% \tl_replace_all:Nnn \l_tmpa_tl { 6 } { \textipa{5} }% \tl_replace_all:Nnn \l_tmpa_tl { 3/ } { \textcloseepsilon }% \tl_replace_all:Nnn \l_tmpa_tl { 3 } { \textipa{3} }% \tl_replace_all:Nnn \l_tmpa_tl { 2 } { \textipa{\o} }% \tl_replace_all:Nnn \l_tmpa_tl { 1 } { \textipa{1} }% \tl_replace_all:Nnn \l_tmpa_tl { || } { \textdoublevertline }% \tl_replace_all:Nnn \l_tmpa_tl { |/|/ } { \textipa{||} }% \tl_replace_all:Nnn \l_tmpa_tl { |/ } { \textipa{|} }% \tl_replace_all:Nnn \l_tmpa_tl { | } { \textvertline }% \tl_replace_all:Nnn \l_tmpa_tl { >/ } { \textbarglotstop }% \tl_replace_all:Nnn \l_tmpa_tl { =/ } { \textdoublebarpipe }% \tl_replace_all:Nnn \l_tmpa_tl { = } { \xsipaSyllabic }% \tl_replace_all:Nnn \l_tmpa_tl { } { \textglobrise }% \tl_replace_all:Nnn \l_tmpa_tl { } { \textglobfall }% \tl_replace_all:Nnn \l_tmpa_tl { t)}{% \IfBooleanTF{#1}{p'}{% \IfBooleanTF{#2}{p'}{\PackageWarning{xipa}{Perhaps you mean \xsp;> or \xsp;)}}}} %\xsp;> \xsp;) \xsp_ \xsp/ \xsp{} \NewDocumentCommand{\xsipatcmd}{m}{% \ifvalueTF{#1}{;}{\xsipatestejectivet}{% \ifvalueTF{#1}{`}{\textipa{\:t}}{t}}} \NewDocumentCommand{\xsipatestejectivet}{t> t)}{% \IfBooleanTF{#1}{t'}{% \IfBooleanTF{#2}{t'}{\PackageWarning{xipa}{Perhaps you mean \xst;> or \xst;)}}}} %\xst;> \xst;) \xst; \xst` \xst{} \NewDocumentCommand{\xsk}{t;}{% \IfBooleanTF{#1}{\xsipatestejectivek}{k}} \NewDocumentCommand{\xsipatestejectivek}{t> t)}{% \IfBooleanTF{#1}{k'}{% \IfBooleanTF{#2}{k'}{\PackageWarning{xipa}{Perhaps you mean \xsk;> or \xsk;)}}}} %\xsk_ \xsk;> \xsk;) \xsk% \NewDocumentCommand{\xsipascmd}{m}{% \ifvalueTF{#1}{;}{\xsipatestejectives}{% \ifvalueTF{#1}{`}{\textipa{\:s}}{s}}} \NewDocumentCommand{\xsipatestejectives}{t> t)}{% \IfBooleanTF{#1}{s'}{% \IfBooleanTF{#2}{s'}{\PackageWarning{xipa}{Perhaps you mean \xss;> or \xss;)}}}} %\xss;> \xss;) \xss; \xss` \xss{} % ^- --- VOYELLES --- _- \NewDocumentCommand{\xsi}{s}{\IfBooleanTF{#1}{\i}{i}} \NewDocumentCommand{\xsy}{}{y} \NewDocumentCommand{\xsu}{}{u} \NewDocumentCommand{\xsI}{}{\textipa{I}}%\xsI \NewDocumentCommand{\xsY}{}{\textipa{Y}}%\xsY \NewDocumentCommand{\xsU}{}{\textipa{U}}%\xsU \NewDocumentCommand{\xse}{}{e}% %\xs2 \NewDocumentCommand{\xsipatestat}{t/}{% \IfBooleanTF{#1}{\textipa{9}}{\textipa{@}}} \NewDocumentCommand{\xso}{}{o} \NewDocumentCommand{\xsipathreecmd}{t/}{% \IfBooleanTF{#1}{\textcloseepsilon}{\textipa{3}}} %\xs9 \xs3 \xs3/ \NewDocumentCommand{\xsE}{}{\textepsilon}%\xsE \NewDocumentCommand{\xsV}{}{\textipa{2}}%\xsV %\xsO %\xs( \xs6 %\xs& \NewDocumentCommand{\xsA}{}{\textipa{A}}%\xsA \NewDocumentCommand{\xsQ}{}{\textipa{6}}%\xsQ % ^- --- SUPRASEGMENTS --- _- \NewDocumentCommand{\xsipatestvlength}{t/}{% \IfBooleanTF{#1}{\textipa{;}}{\textipa{:}}} %a\xs:bi\xs:/ %\xs_Xe \xs| \xs|| \NewDocumentCommand{\xsipalinking}{t/ m}{% \IfBooleanTF{#1}{\textipa{\t*{#2}}}{\PackageWarning{xipa}{Perhaps you mean \xs-/}}} \makeatother% % _code % ^- end of WRIML markup _- % ^_* % _package \endinput