
He escrito los siguientes comandos que primero dividen el texto de entrada ;
y luego crean "fracciones" a partir del texto separado por /
. Mi intención con esto es mostrar genotipos con el formato adecuado.
\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}
Ahora escribiendo el siguiente comando en el cuerpo del documento
\geno{y w ; ap$^{DG3}$ / CyO}
Producimos esta salida:
Sin embargo, cuando intento incluir comandos como \textsuperscript
, o símbolos como \Male
o \Female
en cualquier lugar de la cadena de entrada, me encuentro con el siguiente error:
Incomplete \iffalse; all text was ignored after line [line with \geno command].
Mi mejor suposición es que estoy teniendo problemas con la expansión de argumentos en una de las declaraciones if, así que intenté colocar algunos \protect
s en lugares que sospechaba que podrían causar problemas como cuándo \remainder
se define por primera vez en el \geno
comando y \IfSubStr
poco éxito. También intenté usar el \MakeRobust
comando así:
%definitions above here
\MakeRobust{\geno}
\MakeRobust{\genoHelper}
\MakeRobust{\genoSplitHelper}
Pero lamentablemente el problema persistió.
Otros disparos a ciegas en la oscuridad incluyen
- reemplazando el
\ifx
con\if\relax\detokenize{\remainder}\relax
(mismo error) \detokenize
enviar la entrada a\IfSubStr
(parece que todos devuelven un valor falso, ¿podría estar haciendo algo mal?)- Usar varias alternativas para el
\genoSplit
comando (mismo error, ahora estoy seguro de que no es el problema) - Reescribiendo todos los comandos para usar
\newcommand
y\renewcommand
(mismo error)
yo también he encontradoesta pregunta, pero no estoy seguro de que sea el mismo problema que estoy experimentando y la respuesta aceptada ( \begingroup\noexpandarg [...] \endgroup
) impide que la macro funcione.
Estoy agotado y agradecería mucho saber qué está causando este problema.
Respuesta1
xstrings
No le gustan los comandos frágiles en sus argumentos.
Aquí hay una expl3
implementación: primero dividimos en punto y coma; luego, cada elemento se pasa como argumento a una función que produce la fracción falsa, si /
está presente.
\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}
Respuesta2
Usando solo comandos primitivos TeX puedes definir tu \geno
macro de esta manera:
\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}
Respuesta3
Esto podría ser suficiente usando listofitems
el análisis. EDITADO para manejar la sintaxis más general especificada por el autor en el comentario.
\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}