토큰별로 토큰을 처리할 때 명령이 중단됨

토큰별로 토큰을 처리할 때 명령이 중단됨

\everymath특정 특정 문자의 형식을 지정하는(자동으로 입력 v\mathbf) 명령을 만들려고 합니다 . 그 부분은 사실 이미 알아냈는데, 문제를 일으키는 것은 처리 자체입니다. 수학 모드 내에서 명령을 분리하여 잘못 표시되거나 완전히 중단되는 것 같습니다.

이것은 이론적으로 아무것도 변경하지 않고 단계적으로 진행하는 최소한의 버전입니다.

\ExplSyntaxOn
\NewDocumentCommand{\mformat}{+m}{%
  \exp_after:wN #1 \mode_if_math:TF { \mformat } { }
}
\ExplSyntaxOff

다음과 같이 사용됩니다:

\everymath{\mformat}

다음은 깨지는 방법에 대한 몇 가지 예입니다.

\(\vec{v}\)

예상되는:예상 Vec

실제:실제Vec(와 동일 \vec{}v)

\(\mathbf{v}\) % Just gives "Missing } inserted." error

이 문제를 해결하는 방법에 대한 아이디어가 있습니까?

편집: 내가 발견한 새로운 것; 문제 명령을 중괄호(예: with mathbf, 잘 작동함) 로 묶으면 \({\mathbf{v}}\)갑자기 완벽하게 작동합니다. 왜 이런 일이 발생하는지 모르겠습니다.


나는 egreg의 대답을 내가 묻는 질문에 대답했기 때문에 해결책으로 표시했지만, 후손을 위해 여기에 내가 물어봤어야 했던 질문에 대한 해결책이 있습니다(PhelypeOleinik의 의견에 기초).

\ExplSyntaxOn

% Used to keep track of already active characters
\tl_new:N \g__mformat_mathactive_tl
% Used to figure out which characters need to be made normal again
\tl_new:N \l__mformat_remove_mathactive_tl
% Used to keep track of added characters from *this* iteration
\tl_new:N \l__mformat_used_tl

% Using https://tex.stackexchange.com/a/611898/261875
% and https://tex.stackexchange.com/a/299805/261875
\NewDocumentCommand{\mformat}{m}{
  % By default remove all previous active characters
  \tl_set_eq:NN \l__mformat_remove_mathactive_tl \g__mformat_mathactive_tl
  \tl_set:Nn \l__mformat_used_tl {}

  \tl_if_empty:nTF { #1 } {} {
    % Parse the formatting
    \cs_set:Npn \__mformat_parse:w ##1[##2]##3\relax {
      % Process each character in the set
      \tl_map_inline:nn { ##2 } {
        \tl_if_in:NnTF \g__mformat_mathactive_tl { ####1 } {
          % If this character is already active, keep it active
          \tl_remove_once:Nn \l__mformat_remove_mathactive_tl { ####1 }

          % Check if the character has been used this iteration
          \tl_if_in:NnTF \l__mformat_used_tl {####1} {
            % Helper needed to have something expandable once
            \cs_set_eq:Nc \__mformat_letter_helper: 
            { __mformat_letter_new_####1: }
            % Add a formatting option to the letter
            \cs_set:cx { __mformat_letter_new_####1: }  { 
              \exp_not:N ##1 { \exp_not:o \__mformat_letter_helper: } 
            }
          } {
            % Record that this has been used
            \tl_put_right:Nn \l__mformat_used_tl { ####1 }
            % Define what the letter will now resolve to
            \cs_set:cx { __mformat_letter_new_####1: }  { 
              \exp_not:N ##1 {\mathchar\use:c { __mformat_mathcode_####1: }} 
            }
          }
          
          \char_gset_active_eq:nc { `####1 } { __mformat_letter_new_####1: }
        } {
          % Record that this is now an active character
          \tl_gput_right:Nn \g__mformat_mathactive_tl { ####1 }
          % Record that this has been used
          \tl_put_right:Nn \l__mformat_used_tl { ####1 }
          
          % Record the normal character so it can be used later
          \cs_new:cx { __mformat_mathcode_####1: } 
          { \the\mathcode`####1 }
          
          % Define what the letter will now resolve to
          \cs_new:cx { __mformat_letter_new_####1: }  { 
            \exp_not:N ##1 {\mathchar\use:c { __mformat_mathcode_####1: }} 
          }
          \char_gset_active_eq:nc { `####1 } { __mformat_letter_new_####1: }
          
          % Set the character to be active in math mode
          \char_set_mathcode:nn { `####1 } { "8000 }
        }
      }

      % If there's no more character sets, finish, otherwise recurse
      \tl_if_empty:nTF { ##3 } { } { \__mformat_parse:w ##3\relax }
    }

    % Begin recursive parsing
    \__mformat_parse:w #1\relax
  }

  % \tl_show:N \l__mformat_remove_mathactive_tl
  % Remove the active status from the characters that need it
  \tl_map_inline:Nn \l__mformat_remove_mathactive_tl {
    \tl_gremove_once:Nn \g__mformat_mathactive_tl {##1}
    
    % Reset the math code
    \char_set_mathcode:nn { `##1 } { \use:c { __mformat_mathcode_##1: } }

    % Deregister functions
    \cs_undefine:c { __mformat_letter_new_##1: }
    \cs_undefine:c { __mformat_mathcode_##1: }
  }
}

\NewDocumentCommand{\std}{m}{ \mathchar\use:c { __mformat_mathcode_#1: } }

\ExplSyntaxOff

다음과 같이 사용됩니다.

\mformat{\mathbb[R]\mathbf[vw]}

답변1

이것은 XY 문제와 매우 유사해 보입니다. 당신은 말한다

(이론적으로) 아무것도 변경하지 않습니다.

죄송합니다. 사실이 아닙니다. 첫 번째 레벨 확장

\mode_if_math:TF { \mformat } { }

~이다

\if_mode_math: \__prg_TF_true:w \fi: \use_ii:nn {\mformat}{}

가지고 계시다면 $\vec{v}$획득하세요

\vec\if_mode_math: \__prg_TF_true:w \fi: \use_ii:nn {\mformat}{}

그래서 에 대한 주장은 \vec입니다 \if_mode_math:. 예:

\documentclass{article}

\ExplSyntaxOn
\NewDocumentCommand{\mformat}{+m}{%
  \exp_after:wN #1 \mode_if_math:TF { \mformat } { }
}
\ExplSyntaxOff

\everymath{\mformat}

\renewcommand{\vec}[1]{\showtokens{#1}}

\begin{document}

$\vec{v}$

\end{document}

내가 얻는 콘솔에서

No file mform.aux.
> \if_mode_math: .
\vec #1->\showtokens {#1}

l.13 $\vec

그것은 더 좋을 것입니다\exp_last_unbraced:Nf

\documentclass{article}

\ExplSyntaxOn
\NewDocumentCommand{\mformat}{+m}{%
  \exp_last_unbraced:Nf #1 { \mode_if_math:TF { \mformat } { } }
}
\ExplSyntaxOff

\everymath{\mformat}

\renewcommand{\vec}[1]{\showtokens{#1}}

\begin{document}

$\vec{v}$

\end{document}

콘솔이 인쇄되는 곳

> v.
\vec #1->\showtokens {#1}

하지만 그것도 별로 좋지는 않습니다.

\mathrm{x}

그 결과 긴 일련의 오류가 발생합니다. 그리고 다음과 같은 긴 사례 목록을 작성하여 문제를 해결한다고 해도

\mathrm{abc}

로 변할 것이다

\exp_last_unbraced:Nf abc { \mode_if_math:TF { \mformat } { } }

그것은 확실히 당신이 보고 싶은 것이 아닙니다.

답변2

수학 모드의 모든 문자에 대한 기본 글꼴은 이미 명시적으로 선언되어 있으므로 v에 대한 선언만 조정하면 됩니다. \mathbf"예상" 이미지가 기울임꼴로 표시되었지만 여기서는 굵은 로마자를 사용합니다(일치).

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

\documentclass{article}

\DeclareSymbolFont{boldrm}     {OT1}{cmr}{bx}{n}
\DeclareSymbolFontAlphabet{\mathbf}   {boldrm}
\DeclareMathSymbol{v}{\mathalpha}{boldrm}{`v}

\begin{document}

$\vec{v} + \vec{w}$


\end{document}

관련 정보