Problem mit der Befehlserweiterung im XString-Makro? „Unvollständiges \iffalse“

Problem mit der Befehlserweiterung im XString-Makro? „Unvollständiges \iffalse“

Ich habe die folgenden Befehle geschrieben, die den Eingabetext zunächst in Abschnitte aufteilen ;und dann aus dem durch getrennten Text „Brüche“ machen /. Damit möchte ich Genotypen mit der richtigen Formatierung anzeigen.

\documentclass{article}

\usepackage{amsmath}
\usepackage{xstring}

\newcommand\genoLineDist{.2mm}
\newcommand{\genoSplit}[2]{%
    $\begin{array}{@{}c@{}}
    \text{\protect#1} \\
    \noalign{\vskip\genoLineDist}
    \hline
    \noalign{\vskip\genoLineDist}
    \text{\protect#2}
    \end{array}$%
}

\newcommand{\geno}[1]{%
    \def\remainder{#1}%
    \def\splitchar{;}%
    \genoHelper
}
\newcommand{\genoHelper}{%
    \IfSubStr{\remainder}{\splitchar}{%
        \StrBefore{\remainder}{\splitchar}[\firstpart]%
        \StrBehind{\remainder}{\splitchar}[\remainder]%
        \genoSplitHelper
        \ifx\remainder\empty
        \else
        \ ;\ \genoHelper
        \fi
    }{%
        \def\firstpart{\remainder}%
        \genoSplitHelper
    }%
}
\newcommand{\genoSplitHelper}{%
    \IfSubStr{\firstpart}{/}{%
        \StrBefore{\firstpart}{/}[\upperGeno]%
        \StrBehind{\firstpart}{/}[\lowerGenoTemp]%
        \IfSubStr{\lowerGenoTemp}{\splitchar}{%
            \StrBefore{\lowerGenoTemp}{\splitchar}[\lowerGeno]%
            \StrBehind{\lowerGenoTemp}{\splitchar}[\remainder]%
        }{\def\lowerGeno{\lowerGenoTemp}}%
        \genoSplit{\upperGeno}{\lowerGeno}%
    }{%
        \firstpart\unskip%
    }%
}

\begin{document}

%working
\geno{y w ; ap$^{DG3}$ / CyO}
%breaks
%\geno{ y w ; ap\textsuperscript{DG3} / CyO}

\end{document}

Geben Sie nun den folgenden Befehl in den Dokumenttext ein

\geno{y w ; ap$^{DG3}$ / CyO}

Wir erzeugen diese Ausgabe:

Genotyp

Wenn ich jedoch versuche, Befehle wie \textsuperscriptoder Symbole wie \Maleoder \Femalean beliebiger Stelle in die Eingabezeichenfolge einzufügen, tritt der folgende Fehler auf:

Incomplete \iffalse; all text was ignored after line [line with \geno command].

Meine beste Vermutung ist, dass ich in einer der if-Anweisungen auf Probleme mit der Argumenterweiterung stoße. Daher habe ich versucht, einige \protects an Stellen zu platzieren, von denen ich vermutete, dass sie Probleme verursachen könnten, wie beispielsweise wenn \remaindersie zum ersten Mal im \genoBefehl definiert werden und das, allerdings mit wenig Erfolg. Ich habe auch versucht, den Befehl folgendermaßen \IfSubStrzu verwenden :\MakeRobust

%definitions above here
\MakeRobust{\geno}
\MakeRobust{\genoHelper}
\MakeRobust{\genoSplitHelper}

Aber leider bestand das Problem weiterhin.

Weitere blinde Schüsse im Dunkeln sind

  • Ersetzen \ifxdurch \if\relax\detokenize{\remainder}\relax(gleicher Fehler)
  • \detokenizeing die Eingabe an \IfSubStr(scheint, als würden sie alle „false“ zurückgeben, könnte etwas falsch gemacht werden?)
  • Verwenden verschiedener Alternativen für den \genoSplitBefehl (derselbe Fehler, ich bin jetzt sicher, dass es nicht das Problem ist)
  • Alle Befehle neu schreiben, um \newcommandund zu verwenden \renewcommand(derselbe Fehler)

Ich habe auch gefundendiese Frage, aber ich bin nicht sicher, ob es sich um dasselbe Problem handelt, das ich habe, und die akzeptierte Antwort ( \begingroup\noexpandarg [...] \endgroup) verhindert, dass das Makro funktioniert.

Ich bin mit meinem Latein am Ende und wäre für einige Erkenntnisse zur Ursache dieses Problems sehr dankbar.

Antwort1

xstringsmag keine fragilen Befehle in seinen Argumenten.

Hier ist eine expl3Implementierung: Zuerst teilen wir an den Semikolons; dann wird jedes Element als Argument an eine Funktion übergeben, die den falschen Bruch erzeugt, falls /vorhanden.

\documentclass{article}

\usepackage{amsmath}

\newcommand\genoLineDist{.2mm}

\ExplSyntaxOn
\NewDocumentCommand{\geno}{m}
 {
  \tired_geno:n { #1 }
 }

\seq_new:N \l__tired_geno_parts_in_seq
\seq_new:N \l__tired_geno_parts_out_seq
\seq_new:N \l__tired_geno_temp_seq

\cs_new_protected:Nn \tired_geno:n
 {
  \seq_set_split:Nnn \l__tired_geno_parts_in_seq { ; } { #1 }
  \seq_set_map:NNn \l__tired_geno_parts_out_seq \l__tired_geno_parts_in_seq
   {
    \__tired_geno_split:n { ##1 }
   }
  \seq_use:Nn \l__tired_geno_parts_out_seq { \ ; \  }
 }

\cs_new_protected:Nn \__tired_geno_split:n
 {
  \seq_set_split:Nnn \l__tired_geno_temp_seq { / } { #1 }
  \int_compare:nTF { \seq_count:N \l__tired_geno_temp_seq == 1 }
   {
    #1 % no /
   }
   {
    \begin{tabular}{@{}c@{}}
    \seq_item:Nn \l__tired_geno_temp_seq { 1 } \\
    \noalign{\vskip\genoLineDist}
    \hline
    \noalign{\vskip\genoLineDist}
    \seq_item:Nn \l__tired_geno_temp_seq { 2 } \\ 
    \end{tabular}
   }
 }

\ExplSyntaxOff

\begin{document}

\geno{y w ; ap$^{DG3}$ / CyO}

\geno{ y w ; ap\textsuperscript{DG3} / CyO}

\geno{y/w ; ap$^{DG3}$ / CyO}

\end{document}

Bildbeschreibung hier eingeben

Antwort2

Indem Sie ausschließlich einfache TeX-Befehle verwenden, können Sie Ihr \genoMakro folgendermaßen definieren:

\def\geno#1{\def\genoS{\def\genoS{; }}\genoA #1; \end; }
\def\genoA#1; {\ifx\end#1\else
      \genoS 
      \isinslash#1/\iffalse #1\else \genoB #1/\fi
      \expandafter\genoA
   \fi
} 
\def\genoB #1/#2/{$\displaystyle{\hbox{#1\unskip}\over\hbox{\ignorespaces#2\unskip}}$ }
\def\isinslash #1/#2\iffalse{\ifx/#2/} 

\geno{y w ; ap$^{DG3}$ / CyO ; next ; A/B}

Antwort3

Dies könnte mithilfe listofitemsder Analyse ausreichen. BEARBEITET, um die allgemeinere Syntax zu verarbeiten, die vom Autor im Kommentar angegeben wurde.

\documentclass{article}
\usepackage{amsmath}
\usepackage{listofitems}
\newcommand\geno[1]{%
  \setsepchar[&]{;&/}%
  \readlist*\myterm{#1}%
  \foreachitem\z\in\myterm[]{%
    \ifnum\zcnt=1 \else \ ;\ \fi
    \ifnum\listlen\myterm[\zcnt]=1
      \myterm[\zcnt]%
    \else
      $\displaystyle
        \frac{\text{\myterm[\zcnt,1]}}{\text{\myterm[\zcnt,2]}}$%
    \fi
  }%
}
\begin{document}
\geno{y w ; ap$^{DG3}$ / CyO}

\bigskip
\geno{ y w ; ap\textsuperscript{DG3} / CyO}

\bigskip
\geno{ y w ; ap\textsuperscript{DG3} / CyO ;
   bp\textsuperscript{DG0} / CzO ; z x}
\end{document}

Bildbeschreibung hier eingeben

verwandte Informationen