중첩된 \def로 인해 \inaccessible 오류 발생

중첩된 \def로 인해 \inaccessible 오류 발생

나는 적어도 내 눈에는 단어를 대문자로 표기하는 아주 간단한 방법을 시도해 보았습니다.

\documentclass{article}

\begin{document}
\begingroup%
\obeyspaces%\catcode`\ \active
\def {\space\MakeUppercase}%
Hello world
\endgroup
\end{document}

말할 필요도 없이 나는 이것을 다음과 같은 매크로로 포장하려고 했습니다.

\documentclass{article}

\newcommand{\capitalize}[1]{\begingroup\obeyspaces\def {\space\MakeUppercase}#1\endgroup}

\begin{document}
\capitalize{Hello world}
\end{document}

이는 TeX가 내부 구문에 대해 불평하게 만들고 \def그것을 \inaccessible.

정확히 무엇이 잘못되고 있으며 이 문제를 해결할 수 있는 방법이 있습니까?

답변1

\verb이것은 논쟁 문제에서 작동하지 않는 일반적인 현상입니다 .

\obeyspacesspace의 catcode를 변경합니다. 이는 space를 의미합니다.성격안에파일활성 토큰으로 변환됩니다. catcode 변경 사항이 있습니다아니요이미 생성된 토큰에 영향을 미칩니다. 귀하의 경우 전체 인수가 \newcommand토큰화되었으므로 이후에는 공간 토큰이 전혀 \def없습니다 \def{.

인수 이전에 space의 catcode를 변경해야 하며 \newcommand인수 \capitalize를 취하기 전에 space의 catcode를 변경해야 합니다. (이러한 이유와 다른 이유로 나는 이에 대해 catcode 변경을 사용하지 않고 대신 일반 공백을 찾기 위해 구분된 인수를 사용합니다)

\documentclass{article}

\newcommand{\capitalize}[1]{\xcapitalize#1 \relax}
\def\xcapitalize#1 #2{%
#1%
\ifx\relax#2%
\else
\space\MakeUppercase{#2}%
\expandafter\xcapitalize
\fi}

\begin{document}
\capitalize{Hello world and this}
\end{document}

첫 글자도 대문자로 표시하고 인수가 매크로가 되도록 허용하는 주석에서 요청된 버전입니다.

\documentclass{article}

\newcommand{\capitalize}[1]{\ignorespaces
\expandafter\expandafter\expandafter
\xcapitalize\expandafter\space #1 \relax}
\def\xcapitalize#1 #2{%
#1%
\ifx\relax#2%
\else
\space\MakeUppercase{#2}%
\expandafter\xcapitalize
\fi}

\begin{document}
\capitalize{hello world and this}

\newcommand\zzz{hello world and this}
\capitalize{\zzz}
\end{document}

답변2

이 솔루션에는 최근 업데이트된 TeX 배포판이 필요합니다. 을 사용한 접근 방식에 비해 \obeyspaces범주 코드가 변경되지 않으므로 매크로가 다른 명령에 대한 인수로 포함될 수도 있다는 이점이 있습니다 .

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\capitalize}{m}
 {
  \ruben_capitalize:n { #1 }
 }

\seq_new:N \l__ruben_capitalize_words_seq
\seq_new:N \l__ruben_capitalize_out_seq

\cs_new_protected:Npn \ruben_capitalize:n #1
 {
  \seq_set_split:Nnn \l__ruben_capitalize_words_seq { ~ } { #1 }
  \seq_set_map:NNn \l__ruben_capitalize_out_seq \l__ruben_capitalize_words_seq
   {
    \tl_mixed_case:n { ##1 }
   }
  \seq_use:Nn \l__ruben_capitalize_out_seq { ~ }
 }
\ExplSyntaxOff

\begin{document}
\capitalize{Hello world}
\end{document}

매크로로 전달된 문자열을 대문자로 표시하려면 \capitalize다음 과 같이 정의를 변경하면 됩니다.

\NewDocumentCommand{\capitalize}{m}
 {
  \ruben_capitalize:o { #1 }
 }

그리고 추가하세요

\cs_generate_variant:Nn \ruben_capitalize:n { o }

의 정의 뒤 \ruben_capitalize:n(즉, 바로 앞 \ExplSyntaxOff).

완전한 예:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\capitalize}{m}
 {
  \ruben_capitalize:o { #1 }
 }

\seq_new:N \l__ruben_capitalize_words_seq
\seq_new:N \l__ruben_capitalize_out_seq

\cs_new_protected:Npn \ruben_capitalize:n #1
 {
  \seq_set_split:Nnn \l__ruben_capitalize_words_seq { ~ } { #1 }
  \seq_set_map:NNn \l__ruben_capitalize_out_seq \l__ruben_capitalize_words_seq
   {
    \tl_mixed_case:n { ##1 }
   }
  \seq_use:Nn \l__ruben_capitalize_out_seq { ~ }
 }
\cs_generate_variant:Nn \ruben_capitalize:n { o }
\ExplSyntaxOff

\newcommand{\myhello}{hello world}

\begin{document}
\capitalize{Hello world}

\capitalize{hello world}

\capitalize{\myhello}

\capitalize\myhello
\end{document}

여기에 이미지 설명을 입력하세요


고전적인 접근 방식에서는 \obeylines이를 발행해야 합니다.~ 전에주장을 흡수 :

% First setup obeyspace and give a meaning to active space
\newcommand{\capitalize}{\begingroup\obeyspaces\setupcapspace\docapitalize}
% Just absorb the argument and end the group
\newcommand{\docapitalize}[1]{#1\endgroup}
% Define (locally) the behavior of active space
\begingroup\lccode`~=`\ % <--- don't forget this one
  \lowercase{\endgroup\newcommand\setupcapspace{\def~{\space\MakeUppercase}}}

마지막 두 줄도 가능합니다.

{\obeyspaces\gdef\setupcapspace{\def {\space\MakeUppercase}}}

그러나 이 접근 방식은 가짜 공간으로 인한 문제를 \lowercase방지 하고 발생할 수 있는 문제를 방지합니다.\obeyspaces

그러나 구분된 인수 접근 방식은 \capitalize다른 명령에 대한 인수를 허용하므로 확실히 더 좋습니다.

답변3

LuaLaTeX 기반 솔루션입니다. 우리는 \capitalizeLua 함수 string.uppertex.sprint. 인수는 \capitalize하드 코딩된 문자열이거나 아마도 문자열을 생성하는 매크로일 수 있습니다.

여기에 이미지 설명을 입력하세요

% !TEX TS-program = lualatex
\documentclass{article}
{\catcode\%=12 
 \gdef\capitalize#1{
   \directlua{ str="#1"; 
               tex.sprint ( string.gsub(" "..str, "%W%l",
                string.upper):sub(2)) } }
} 
\begin{document}

\capitalize{Once upon a time there was a princess
  who lived in a great palace that was close to the 
  edge of a dark and mysterious forest.}
\end{document}

답변4

귀하의 질문은 중첩에 관한 것이지만 \def응용 프로그램은 단어를 대문자로 사용합니다. 패키지 는 매크로를 titlecaps사용하여 이 작업을 수행합니다 \titlecap. 글꼴 스타일 및 크기 변경을 포함하여 인수에 폭넓은 유연성을 허용합니다. 또한 대문자로 시작하지 않도록 제외 단어를 설정할 수도 있습니다(선택적으로 인수의 첫 번째 단어 제외). 단어 등을 대문자로 표기할 때 선행 구두점(괄호 및 대괄호 등)을 상당 부분 극복할 수 있습니다. 발음 구별 부호 등을 대문자로 표기할 수 있습니다.

MWE에서는 "hello world" 예제를 보여주고 패키지 설명서의 최신 샘플을 사용합니다.

\documentclass{article}
\usepackage{titlecaps}
\def\bs{$\backslash$}

\begin{document}
\titlecap{hello world}

\Addlcwords{for a is but and with of in as the etc on to if}
\titlecap{% 
to know that none of the words typed in this paragraph were initially
upper cased might be of interest to you.  it is done to demonstrate the
behavioral features of this package.  first, you should know the words
that i have pre-designated as lower case.  they are:  ``for a is but and
with of in as the etc on to if.''  you can define your own list.  note
that punctuation, like the period following the word ``if'' did not mess
up the search for lower case (nor did the quotation marks just now).
punctuation which is screened out of the lower-cased word search pattern
include . , : ; ( ) [ ] ? ! ` ' however, I cannot screen text braces;
\{for example in\} is titled, versus (for example in), since the braces
are not screened out in the search for pre-designated lower-case words
like for and in.  However, \texttt{\bs textnc} provides a workaround:
\{\textnc{for example in}\}.  titlecap will consider capitalizing
following a (, [, \{, or - symbol, such as (abc-def).  you can use your
text\textit{\relax xx} commands, like i just did here with the prior xx,
but if you want the argument of that command to not be titled, you
either need, in this example, to add \textit{xx} to the lowercase word
list, which you can see i did not.  instead, i put ``\bs relax~xx'' as
the argument, so that, in essence, the \bs relax was capitalized, not
the x.  Or you could use \texttt{\bs textnc} .  here i demonstrate that
text boldface, \textbf{as in the \bs textbf command}, also works fine,
as do \texttt{texttt}, \textsl{textsl}, \textsc{textsc},
\textsf{textsf}, \textit{etc}.  titlecap will work on diacritical marks,
such as \"apfel, \c cacao \textit{etc.}, \scriptsize fontsize \LARGE
changing commands\normalsize\unskip, as well as national symbols such as
\o laf, \ae gis, and \oe dipus.  unfortunately, i could not get it to
work on the \aa~nor the \l~symbols. the method will work with some
things in math mode, capitalizing symbols if there is a leading space,
$x^2$ can become $ x^2$, and it can process but it will not capitalize
the greek symbols, such as $\alpha$, and will choke on most macros, if
they are not direct character expansions.  Additionally,
\textsf{titlecaps} also works with font changing declarations, for
example, \bs itshape\bs sffamily. \itshape\sffamily you can see that it
works fine.  likewise, any subsequent \bs textxx command will, upon
completion, return the font to its prior state, such as this
\textbf{textbf of some text}.  you can see that i have returned to the
prior font, which was italic sans-serif. now I will return to upright
roman\upshape\rmfamily.  a condition that will not behave well is inner
braces, such as \ttfamily \bs titlecap\{blah \{inner brace material\}
blah-blah\}. \rmfamily see the section on quirks and limitations for a
workaround involving \texttt{\bs textnc}.  titlecap will always
capitalize the first word of the argument (\textbf{even if it is on the
lower-case word list}), unless \texttt{\bs titlecap} is invoked with an
optional argument that is anything other than a capital p.  in that case,
the first word will be titled \textit{unless} it is on the lowercase
word list.  for example, i will do a \bs titlecap[\relax s]\{\relax
a~big~man\} and get ``\titlecap[s]\textnc{a big man}'' with the ``a''
not titled.  i hope this package is useful to you, but as far as using
\textsf{titlecaps} on such large paragraphs\ldots \textbf{do not try
this at home!}}
\end{document}

여기에 이미지 설명을 입력하세요

관련 정보