1

As continuation for answer on this question: Kerning with xcolor

There is first attempting define kerning macros for whole word with colored first letter, without parenthesis:
(in more programmer-style than TeX-style, using pgf parser). I set only several accents for first time.
(This macros I use for church-slavonic language)

And I don't know how use macros as argument in this case:
\cuParse \SomeMacros don't work correctly, m.b. whole argument-macros treat as first letter?
Anybody help with this?

MWE:

\documentclass{article}
\usepackage{polyglossia}
\usepackage{fontspec}
\setmainfont{CMU Serif}
\usepackage{xcolor}
\usepackage{pgf}
\usepgfmodule{parser}

% from egreg's answer
% https://tex.stackexchange.com/questions/567220/kerning-with-xcolor
\newcommand{\kerncolor}[4]{%
  % #1 = color, #2 = before, #3 = colored part, #4 = after
  \sbox0{#2#3}\sbox2{\mbox{#2}\mbox{#3}}%
  \dimen0=\dimexpr\wd0-\wd2\relax
  \sbox0{#3#4}\sbox2{\mbox{#3}\mbox{#4}}%
  \dimen2=\dimexpr\wd0-\wd2\relax
  #2\kern\dimen0 \textcolor{#1}{#3}\kern\dimen2 #4%
}
%------------------------------------------
\def\cuFirstLetter{}
\def\cuFirstSub{}
\def\cuSndSub{}
\def\cuSndLetter{}
\def\cuTail{}
\def\TailFinal{}

\futurelet\pgfspace{ }
%------------------------------------------
\pgfparserdefunknown{cuw}{initial}{%
  \edef\cuFirstLetter{\pgfparserletter}%
  \pgfparserswitch{second symbol}}
%------------------------------------------
\pgfparserdefunknown{cuw}{second symbol}{%
  \edef\cuSndLetter{\pgfparserletter}%
  \pgfparserswitch{letters}}
\newcommand{\SetCUWFirstCuAccent}[1]{%
  \pgfparserdef{cuw}{second symbol}{the letter #1}{%
    \edef\cuFirstSub{#1}%
    \pgfparserswitch{subs}}}
%Some general accents
\SetCUWFirstCuAccent{̀}% COMBINING GRAVE ACCENT (U+0300) /вария
\SetCUWFirstCuAccent{́}% COMBINING ACUTE ACCENT (U+0301) /оксия 
\SetCUWFirstCuAccent{̈}% Combining Diaeresis (U+0308)
\SetCUWFirstCuAccent{̋}% Combining Double Acute Accent (U+030B)
\SetCUWFirstCuAccent{̏}% Combining Double Grave Accent (U+030F)
%Some church-slavonic accents:    
\SetCUWFirstCuAccent{҃}% Combining Cyrillic Titlo (U+0483) /титло 
\SetCUWFirstCuAccent{҆}% Combining Cyrillic Psili Pneumata (U+0486) /звательце
\SetCUWFirstCuAccent{ⷭ}% с под покрытие
\SetCUWFirstCuAccent{ⷣ}% д-титло 
%------------------------------------------
\pgfparserdef{cuw}{subs}{\meaning\pgfspace}{%
  \edef\TailFinal{\ }
  \pgfparserswitch{final}}
\pgfparserdefunknown{cuw}{subs}{%
  \edef\cuSndLetter{\pgfparserletter}%
  \pgfparserswitch{letters}}
\newcommand{\SetCUWSecondCuAccent}[1]{%
  \pgfparserdef{cuw}{subs}{the letter #1}{%
    \edef\cuSndSub{#1}}}
%Some general accents
\SetCUWSecondCuAccent{́}% COMBINING ACUTE ACCENT (U+0301) /оксия
\SetCUWSecondCuAccent{̀}% COMBINING GRAVE ACCENT (U+0300) /вария 
%Some church-slavonic accents:
\SetCUWSecondCuAccent{҇}% Combining Cyrillic Pokrytie (U+0487) /покрытие
%------------------------------------------
\pgfparserdefunknown{cuw}{letters}{%
  \let\savedTail\cuTail%
  \edef\cuTail{\savedTail\pgfparserletter}}
\pgfparserdef{cuw}{letters}{\meaning\pgfspace}{%
  \edef\TailFinal{\ }
  \pgfparserswitch{final}}
%------------------------------------------
\pgfparserdeffinal{cuw}{\kerncolor{red}{}{\cuFirstLetter\cuFirstSub\cuSndSub}{\cuSndLetter}\cuTail\TailFinal}%
\pgfparserset{cuw/silent=true}%
%------------------------------------------
\newcommand{\cuParse}[1]{%
  \def\cuFirstLetter{}%
  \def\cuFirstSub{}%
  \def\cuSndSub{}%
  \def\cuSndLetter{}%
  \def\cuTail{}%
  \def\cuTailFinal{}%
  \pgfparserparse{cuw}#1%
}

\newcommand{\TEST}{VAR}

\begin{document}

\textcolor{red}{Á}VE <- \textit{without kerning}

\cuParse ÁVE 

\cuParse ÀVE

\cuParse Ä́h

\cuParse \TEST test

\end{document}

enter image description here

1
  • This reminds me that the documentation of \pgfparserreinsert should be improved to make it clear that the contents of \pgfparserletter get reinserted...
    – Skillmon
    Oct 19, 2020 at 13:01

1 Answer 1

2

The following changes your code such that for the initial state of your parser it is checked whether the first token is a macro that doesn't take an argument. If that is the case that macro is expanded and the result stored into \pgfparserletter, the contents of which get reinserted by \pgfparserreinsert.

This way the first token will be expanded and the result examined by the parser. The test for a macro without a parameter will fail if the first token is a macro that includes macro:-> in its replacement (that seems unlikely, so the test should be fine, but one could create a more robust test).

The only things changed from your original code is the added \CuIfMacro and \CuIfMacroHelper (which does the test), and the changed definition of \pgfparserunknown{cuw}{initial}.

\documentclass{article}
\usepackage{polyglossia}
\usepackage{fontspec}
\setmainfont{CMU Serif}
\usepackage{xcolor}
\usepackage{pgf}
\usepgfmodule{parser}

% from egreg's answer
% https://tex.stackexchange.com/questions/567220/kerning-with-xcolor
\newcommand{\kerncolor}[4]{%
  % #1 = color, #2 = before, #3 = colored part, #4 = after
  \sbox0{#2#3}\sbox2{\mbox{#2}\mbox{#3}}%
  \dimen0=\dimexpr\wd0-\wd2\relax
  \sbox0{#3#4}\sbox2{\mbox{#3}\mbox{#4}}%
  \dimen2=\dimexpr\wd0-\wd2\relax
  #2\kern\dimen0 \textcolor{#1}{#3}\kern\dimen2 #4%
}
%------------------------------------------
\def\cuFirstLetter{}
\def\cuFirstSub{}
\def\cuSndSub{}
\def\cuSndLetter{}
\def\cuTail{}
\def\TailFinal{}

\futurelet\pgfspace{ }
\makeatletter
\edef\CuIfMacro
  {%
    \unexpanded{\expandafter\CuIfMacroHelper\meaning\pgfparsertoken}%
    \unexpanded{\CuMark\@firstoftwo}%
    \detokenize{macro:->}%
    \unexpanded{\CuMark\@secondoftwo\CuStop}%
  }
\edef\CuIfMacroHelper{\unexpanded{\def\CuIfMacroHelper#1}\detokenize{macro:->}}%
\CuIfMacroHelper#2\CuMark#3#4\CuStop{#3}%
\makeatother
%------------------------------------------
\pgfparserdefunknown{cuw}{initial}{%
  \CuIfMacro
    {%
      \edef\pgfparserletter
        {\unexpanded\expandafter\expandafter\expandafter{\pgfparserletter}}%
      \pgfparserreinsert
    }%
    {\edef\cuFirstLetter{\pgfparserletter}\pgfparserswitch{second symbol}}%
  }
%------------------------------------------
\pgfparserdefunknown{cuw}{second symbol}{%
  \edef\cuSndLetter{\pgfparserletter}%
  \pgfparserswitch{letters}}
\newcommand{\SetCUWFirstCuAccent}[1]{%
  \pgfparserdef{cuw}{second symbol}{the letter #1}{%
    \edef\cuFirstSub{#1}%
    \pgfparserswitch{subs}}}
%Some general accents
\SetCUWFirstCuAccent{̀}% COMBINING GRAVE ACCENT (U+0300) /вария
\SetCUWFirstCuAccent{́}% COMBINING ACUTE ACCENT (U+0301) /оксия 
\SetCUWFirstCuAccent{̈}% Combining Diaeresis (U+0308)
\SetCUWFirstCuAccent{̋}% Combining Double Acute Accent (U+030B)
\SetCUWFirstCuAccent{̏}% Combining Double Grave Accent (U+030F)
%Some church-slavonic accents:    
\SetCUWFirstCuAccent{҃}% Combining Cyrillic Titlo (U+0483) /титло 
\SetCUWFirstCuAccent{҆}% Combining Cyrillic Psili Pneumata (U+0486) /звательце
\SetCUWFirstCuAccent{ⷭ}% с под покрытие
\SetCUWFirstCuAccent{ⷣ}% д-титло 
%------------------------------------------
\pgfparserdef{cuw}{subs}{\meaning\pgfspace}{%
  \edef\TailFinal{\ }
  \pgfparserswitch{final}}
\pgfparserdefunknown{cuw}{subs}{%
  \edef\cuSndLetter{\pgfparserletter}%
  \pgfparserswitch{letters}}
\newcommand{\SetCUWSecondCuAccent}[1]{%
  \pgfparserdef{cuw}{subs}{the letter #1}{%
    \edef\cuSndSub{#1}}}
%Some general accents
\SetCUWSecondCuAccent{́}% COMBINING ACUTE ACCENT (U+0301) /оксия
\SetCUWSecondCuAccent{̀}% COMBINING GRAVE ACCENT (U+0300) /вария 
%Some church-slavonic accents:
\SetCUWSecondCuAccent{҇}% Combining Cyrillic Pokrytie (U+0487) /покрытие
%------------------------------------------
\pgfparserdefunknown{cuw}{letters}{%
  \let\savedTail\cuTail%
  \edef\cuTail{\savedTail\pgfparserletter}}
\pgfparserdef{cuw}{letters}{\meaning\pgfspace}{%
  \edef\TailFinal{\ }
  \pgfparserswitch{final}}
%------------------------------------------
\pgfparserdeffinal{cuw}{\kerncolor{red}{}{\cuFirstLetter\cuFirstSub\cuSndSub}{\cuSndLetter}\cuTail\TailFinal}%
\pgfparserset{cuw/silent=true}%
%------------------------------------------
\newcommand{\cuParse}[1]{%
  \def\cuFirstLetter{}%
  \def\cuFirstSub{}%
  \def\cuSndSub{}%
  \def\cuSndLetter{}%
  \def\cuTail{}%
  \def\cuTailFinal{}%
  \pgfparserparse{cuw}#1%
}

\newcommand{\TEST}{VAR}

\begin{document}

\textcolor{red}{Á}VE <- \textit{without kerning}

\cuParse ÁVE 

\cuParse ÀVE

\cuParse Ä́h

\cuParse \TEST test 

\end{document}

enter image description here

5
  • Thank you! Can you help with space in last string (with macro) between VAR and test?
    – Elisey
    Oct 19, 2020 at 13:25
  • @Elisey That space doesn't exist as far as TeX is concerned, and automatically adding it could again result in unwanted behaviour. My suggestion would be to not use a space as the end delimiter of your parser, but instead let \cuParse take an argument and placing some other token (e.g., \cuParse itself) as the end token, then doing a \pgfparserdef{cuw}{all}\cuParse{\pgfparserswitch{final}}.
    – Skillmon
    Oct 19, 2020 at 13:32
  • @Elisey and your parser would also work for \cuParse\TEST\ test there (though the \ doesn't end the parser, but still gets output as a space, the parser would then be ended by the space after test).
    – Skillmon
    Oct 19, 2020 at 13:33
  • Macro \cuParse can be end token? Thank you! (In similar case i insert into handler macros something non-text string like ==END==) - there is few info in pgf-documentation about this.
    – Elisey
    Oct 19, 2020 at 13:41
  • @Elisey everything can be used as an end token by using \pgfparserswitch{final}, you just have to know its \meaning (and make sure that it doesn't change). Feel free to make suggestions on how the documentation of pgfparser could be improved.
    – Skillmon
    Oct 19, 2020 at 18:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .