假设我有一个带有\title
命令的类文件,我想检查标题是否以字母开头,而不是以数学或数字或符号开头。我该怎么做?
这是我的 MnWE,的语法\@iffirstnotletter
当然可以进行合理的修改。如果它也能识别重音字符,那就更好了,但这不是必需的。
\documentclass{article}
\makeatletter
\newcommand\@iffirstnotletter[3]{#2} % <-- should be modified
\renewcommand\title[1]{\@iffirstnotletter{#1}{%
\GenericWarning{}{Please start the title with a letter!}%
}{}%
\def\@title{#1}%
}%
\makeatother
\title{Ahoj}
\begin{document}
\maketitle
\end{document}
编辑:
我的第一个想法是这样的:
\def\ONETWO#1#2\ENDONETWO{#1} % strips the 1st token of
% whatever is between `\ONETWO...\ENDONETWO`
\def\@iffirstnotletter#1#2#3{%
% checks the \catcode of the 1st token of #1
\expandafter\ifnum\expandafter\the\expandafter\catcode
\expandafter`\csname\ONETWO#1\ENDONETWO\endcsname=11\relax
#3\else#2
\fi}
但它有一个疯狂的行为,例如,当第一件事是\(
作为数学模式的开始时:然后它给出! Missing \endcsname inserted.
答案1
用 进行长检查\futurelet
;这涵盖了 UTF-8 多字节字符,但如果参数中的第一个项是多字节字符,它无论如何都会给出“好”,因为“UTF-8 字母”的概念没有明确定义。另一方面,在“\'{U}jezd”等情况下,这将失败。可以添加可接受的控制序列列表来应对这种情况。
\documentclass{article}
\usepackage[utf8]{inputenc}
\makeatletter
\newcommand\ifletter[1]{%
\futurelet\letter@token\checknextletter#1\relax\@nil
}
\def\checknextletter{%
\ifcat\noexpand\letter@token a%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\@gobbleto@nil{good}}%
{\checknextutfii}%
}
\def\checknextutfii{%
\expandafter\ifx\expandafter\UTFviii@two@octets\letter@token
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\@gobbleto@nil{good}}%
{\checknextutfiii}%
}
\def\checknextutfiii{%
\expandafter\ifx\expandafter\UTFviii@three@octets\letter@token
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\@gobbleto@nil{good}}%
{\checknextutfiv}%
}
\def\checknextutfiv{%
\expandafter\ifx\expandafter\UTFviii@four@octets\letter@token
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\@gobbleto@nil{good}}%
{\GenericWarning{}{Please start the title with a letter}%
\@gobbleto@nil{bad}}%
}
\long\def\@gobbleto@nil#1#2\@nil{#1}
\makeatother
\begin{document}
\verb*'foo': \ifletter{foo} = good
\verb*' foo': \ifletter{ foo} = bad
\verb*'f12': \ifletter{f12} = good
\verb*'1oo': \ifletter{1oo} = bad
\verb*'$math$': \ifletter{$math$} = bad
\verb*'\(math\)': \ifletter{\(math\)} = bad
\verb*'äoo': \ifletter{äoo} = good
\verb*'\relax': \ifletter{\relax} = bad
\verb*'': \ifletter{} = bad
\end{document}
答案2
这是我的尝试似乎涵盖基础知识:
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{etoolbox}% I don't want to define \ifdefmacro
\makeatletter
\newcommand\ifletter[1]{%
\ifcat#1a\@empty
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
\newcommand\iffirstletter[1]{\@iffirstletter#1\@empty\q@stop}
\def\@iffirstletter#1#2\q@stop{%
\ifdefmacro{#1} % to prevent error messages from accented letters, they're false
{\@secondoftwo}% starts with macro...
{\ifletter{#1}}%
}
\makeatother
\begin{document}
!\iffirstletter{foo}{true}{false}! = true
!\iffirstletter{ foo}{true}{false}! = true
!\iffirstletter{f12}{true}{false}! = true
!\iffirstletter{1oo}{true}{false}! = false
!\iffirstletter{$math$}{true}{false}! = false
!\iffirstletter{\(math\)}{true}{false}! = false
!\iffirstletter{äoo}{true}{false}! = false % this may be misleading
!\iffirstletter{\relax}{true}{false}! = false
!\iffirstletter{}{true}{false}! = false
\end{document}