Можно ли создавать имена макросов, содержащие специальные символы?
Я хотел бы создать несколько макросов с именами вроде\с1.4а также иметь возможность использовать их, например, \s1.4Test
когда Test не рассматривается как часть имени макроса (по сути, все, что находится после float, исключается как часть имени макроса)
По сути, это делается для того, чтобы избежать необходимости делать \s{1.4}Text
то, что добавляет два дополнительных символа, и для моих целей \s1.4
не представляет никаких проблем (я никогда не буду делать что-то вроде \s1.x
и ожидаю, что x не будет частью макроса, поэтому никогда не возникнет никакой двусмысленности).
Кстати, я определяю их с помощью foreach:
\makeatletter
\foreach \m in {1.1, 2.2}
{
\expandafter\protected@xdef\csname s\m\endcsname{$_\mathbf{\m}$}
}
\makeatother
решение1
Пример простого TeX, но он будет работать в latex, \s
он проще, но требует .
\t
более сложен, но принимает целое число.
\def\s#1.{%
\def\tmp{#1.}%
\afterassignment\xxs\count0= }
\def\xxs{\csname s\tmp\the\count0\endcsname}
%%%%%%%%%%%%%%%%%%%
\def\t{\afterassignment\xxt\count0= }
\def\xxt{\futurelet\tmp\xxxt}
\def\xxxt{%
\if.\noexpand\tmp
\expandafter\xxxxt
\else
\csname s\the\count0\expandafter\endcsname
\fi}
\def\xxxxt.{\afterassignment\xtx\count2= }
\def\xtx{\csname s\the\count0.\the\count2\endcsname}
%%%%%%%%%%%%%%%%%%%
\expandafter\def\csname s1.4\endcsname{one point four }
\expandafter\def\csname s2.6\endcsname{ten point six }
\expandafter\def\csname s5\endcsname{five }
%%%%%%%%%%%%%%%%%%%
\s1.4more text \s2.6 and more
\t1.4more text \t2.6 and more and \t5 yet more
\bye
решение2
В следующем примере макрос \s
просто собирает цифры и точки и набирает их, как показано в вопросе, как жирные нижние индексы. LaTeX's \@ifnextchar
использовать нельзя, потому что он поглощает пробелы, когда ищет следующий токен.
\documentclass{article}
\usepackage{ltxcmds}[2011/04/14]
\makeatletter
\newcommand*{\s}{%
\begingroup
\let\tmp\ltx@empty
\s@aux
}
\newcommand*{\s@aux}{%
\ltx@ifnextchar@nospace{.}{%
\edef\tmp{\tmp.}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{0}{%
\edef\tmp{\tmp0}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{1}{%
\edef\tmp{\tmp1}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{2}{%
\edef\tmp{\tmp2}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{3}{%
\edef\tmp{\tmp3}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{4}{%
\edef\tmp{\tmp4}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{5}{%
\edef\tmp{\tmp5}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{6}{%
\edef\tmp{\tmp6}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{7}{%
\edef\tmp{\tmp7}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{8}{%
\edef\tmp{\tmp8}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{9}{%
\edef\tmp{\tmp9}%
\expandafter\s@aux\ltx@gobble
}{%
\expandafter\s@end\expandafter{\tmp}%
}}}}}}}}}}}%
}
\newcommand*{\s@end}[1]{%
\endgroup
\ensuremath{_\mathbf{#1}}%
}
\makeatother
\begin{document}
\s1.4Test and \s2more.
\end{document}
Обновлять
Легко добавить слой сопоставления, включая сообщения об ошибках, если \s
за ним не следуют цифры и точки или строка цифр/точек не определена.
\documentclass{article}
\usepackage{pgffor}
\usepackage{ltxcmds}[2011/04/14]
\makeatletter
\foreach \m in {1.1, 1.4, 2, 2.2}{%
\expandafter\protected@xdef\csname s\m\endcsname{$_\mathbf{\m}$}%
}
\newcommand*{\s}{%
\begingroup
\let\tmp\ltx@empty
\s@aux
}
\newcommand*{\s@aux}{%
\ltx@ifnextchar@nospace{.}{%
\edef\tmp{\tmp.}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{0}{%
\edef\tmp{\tmp0}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{1}{%
\edef\tmp{\tmp1}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{2}{%
\edef\tmp{\tmp2}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{3}{%
\edef\tmp{\tmp3}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{4}{%
\edef\tmp{\tmp4}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{5}{%
\edef\tmp{\tmp5}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{6}{%
\edef\tmp{\tmp6}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{7}{%
\edef\tmp{\tmp7}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{8}{%
\edef\tmp{\tmp8}%
\expandafter\s@aux\ltx@gobble
}{\ltx@ifnextchar@nospace{9}{%
\edef\tmp{\tmp9}%
\expandafter\s@aux\ltx@gobble
}{%
\ifx\tmp\@empty
\@latex@error{\string\s: no digits/dots found}\@ehc
\else
\@ifundefined{s\tmp}{%
\@latex@error{\string\s: Undefined `\tmp'}\@ehc
}{%
\@nameuse{s\tmp}%
}%
\fi
\endgroup
}}}}}}}}}}}%
}
\makeatother
\begin{document}
\s1.4Test and \s2more.
\end{document}
В следующем примере анализируемый аргумент \s
представляет собой строку, которая начинается с одной или нескольких цифр, необязательных точек и необязательных цифр.
\documentclass{article}
\usepackage{pgffor}
\usepackage{ltxcmds}[2011/04/14]
\makeatletter
\foreach \m in {1.1, 1.4, 2, 2.2}{%
\expandafter\protected@xdef\csname s\m\endcsname{$_\mathbf{\m}$}%
}
\newcommand*{\s}{%
\begingroup
\let\s@tmp\ltx@empty
\futurelet\s@tok\s@startnum
}
\newcommand*{\s@startnum}{%
\s@digit\s@digitordot
\s@next
}
\newcommand*{\s@digit}[1]{%
\def\s@next{\s@add#1}%
\ifx0\s@tok
\else\ifx1\s@tok
\else\ifx2\s@tok
\else\ifx3\s@tok
\else\ifx4\s@tok
\else\ifx5\s@tok
\else\ifx6\s@tok
\else\ifx7\s@tok
\else\ifx8\s@tok
\else\ifx9\s@tok
\else
\let\s@next\s@end
\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
}
\newcommand*{\s@add}[2]{%
\edef\s@tmp{\s@tmp#2}%
\futurelet\s@tok
#1%
}
\newcommand*{\s@digitordot}{%
\let\s@next\s@end
\ifx.\s@tok
\def\s@next{\s@add\s@endnum}%
\else
\s@digit\s@digitordot
\fi
\s@next
}
\newcommand*{\s@endnum}{%
\s@digit\s@endnum
\s@next
}
\newcommand*{\s@end}{%
\ifx\s@tmp\@empty
\@latex@error{\string\s: no digits/dots found}\@ehc
\else
\@ifundefined{s\s@tmp}{%
\@latex@error{\string\s: Undefined `\s@tmp'}\@ehc
}{%
\@nameuse{s\s@tmp}%
}%
\fi
\endgroup
}
\makeatother
\begin{document}
\s1.4Test and \s2more.
\end{document}
решение3
Если второе число после точки состоит только из одной цифры, вы можете использовать следующее:
\def\s#1.#2{$_\mathbf{#1.#2}$}