Befehle werden unterbrochen, wenn Token für Token verarbeitet werden

Befehle werden unterbrochen, wenn Token für Token verarbeitet werden

Ich versuche, einen Befehl zu erstellen, der \everymathbestimmte angegebene Zeichen formatiert (automatisch einfügt vusw. \mathbf). Diesen Teil habe ich eigentlich schon herausgefunden, aber was mir Probleme bereitet, ist die Verarbeitung selbst. Es scheint, als würden Befehle im Mathematikmodus getrennt, entweder werden sie falsch angezeigt oder sie brechen einfach komplett ab.

Dies ist eine Minimalversion davon, die nur durchgeht und (theoretisch) nichts ändert:

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

Es wird folgendermaßen verwendet:

\everymath{\mformat}

Hier sind einige Beispiele, wie es kaputt geht:

\(\vec{v}\)

Erwartet:ErwarteterVec

Tatsächlich:TatsächlicherVec(gleichwertig \vec{}v)

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

Irgendwelche Ideen, wie man das beheben kann?

Bearbeiten: Mir ist etwas Neues aufgefallen; wenn ich die Problembefehle mit Klammern umschließe (wie mit mathbf, \({\mathbf{v}}\)funktioniert einwandfrei), funktionieren sie plötzlich einwandfrei. Keine Ahnung, warum das passiert.


Ich habe die Antwort von egreg als Lösung markiert, da sie die von mir gestellte Frage beantwortet hat, aber für die Nachwelt ist hier die Lösung für die Frage, die ich hätte stellen sollen (basierend auf den Kommentaren von 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

Was verwendet wird wie

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

Antwort1

Das sieht sehr nach einem XY-Problem aus. Sie sagen

und ändert nichts (theoretisch)

Tut mir leid, das stimmt nicht. Die erste Level-Erweiterung von

\mode_if_math:TF { \mformat } { }

Ist

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

Wenn Sie haben, $\vec{v}$erhalten Sie

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

\vecund daher ist das Argument für \if_mode_math:. Beispiel:

\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}

Auf der Konsole bekomme ich

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

l.13 $\vec

Besser wäre es mit\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}

wo die Konsole druckt

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

Aber das ist auch nicht wirklich gut: mit so etwas wie

\mathrm{x}

Das Ergebnis ist eine lange Reihe von Fehlern. Und selbst wenn Sie sie beheben, indem Sie eine lange Liste von Fällen durchführen, so etwas wie

\mathrm{abc}

würde sich verwandeln in

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

und das ist definitiv nicht das, was Sie sehen möchten.

Antwort2

Die Standardschriftart für jedes Zeichen im Mathematikmodus ist bereits explizit deklariert, Sie müssen also nur die Deklarationen für v anpassen. Ich verwende hier Fettdruck Roman (entsprechend \mathbf), obwohl Ihr „erwartetes“ Bild Kursivdruck zeigte.

Bildbeschreibung hier eingeben

\documentclass{article}

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

\begin{document}

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


\end{document}

verwandte Informationen