
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:
Wenn ich jedoch versuche, Befehle wie \textsuperscript
oder Symbole wie \Male
oder \Female
an 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 \protect
s an Stellen zu platzieren, von denen ich vermutete, dass sie Probleme verursachen könnten, wie beispielsweise wenn \remainder
sie zum ersten Mal im \geno
Befehl definiert werden und das, allerdings mit wenig Erfolg. Ich habe auch versucht, den Befehl folgendermaßen \IfSubStr
zu 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
\ifx
durch\if\relax\detokenize{\remainder}\relax
(gleicher Fehler) \detokenize
ing 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
\genoSplit
Befehl (derselbe Fehler, ich bin jetzt sicher, dass es nicht das Problem ist) - Alle Befehle neu schreiben, um
\newcommand
und 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
xstrings
mag keine fragilen Befehle in seinen Argumenten.
Hier ist eine expl3
Implementierung: 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}
Antwort2
Indem Sie ausschließlich einfache TeX-Befehle verwenden, können Sie Ihr \geno
Makro 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 listofitems
der 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}