
Eu escrevi os seguintes comandos que primeiro fragmentam o texto de entrada ;
e depois criam "frações" do texto separado por /
. Minha intenção com isso é exibir genótipos com formatação adequada.
\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}
Agora, digitando o seguinte comando no corpo do documento
\geno{y w ; ap$^{DG3}$ / CyO}
Produzimos esta saída:
No entanto, quando tento incluir comandos como \textsuperscript
ou símbolos como \Male
ou \Female
em qualquer lugar da string de entrada, encontro o seguinte erro:
Incomplete \iffalse; all text was ignored after line [line with \geno command].
Meu melhor palpite é que estou tendo problemas com a expansão de argumentos em uma das instruções if, então tentei colocar alguns \protect
s em lugares que suspeitava que poderiam causar problemas como quando \remainder
é definido pela primeira vez no \geno
comando e com \IfSubStr
pouco sucesso. Eu também tentei usar o \MakeRobust
comando assim:
%definitions above here
\MakeRobust{\geno}
\MakeRobust{\genoHelper}
\MakeRobust{\genoSplitHelper}
Mas infelizmente o problema persistiu.
Outros tiros cegos no escuro incluem
- substituindo o
\ifx
por\if\relax\detokenize{\remainder}\relax
(mesmo erro) \detokenize
inserindo a entrada para\IfSubStr
(parece que todos eles retornam um falso, pode estar fazendo algo errado?)- Usando várias alternativas para o
\genoSplit
comando (mesmo erro, agora tenho certeza de que não é o problema) - Reescrevendo todos os comandos para usar
\newcommand
e\renewcommand
(mesmo erro)
Eu também encontreiessa questão, mas não tenho certeza se este é o mesmo problema que estou enfrentando, e a resposta aceita ( \begingroup\noexpandarg [...] \endgroup
) impede que a macro funcione.
Estou perdendo o juízo e gostaria muito de receber algumas dicas sobre o que está causando esse problema.
Responder1
xstrings
não gosta de comandos frágeis em seus argumentos.
Aqui está uma expl3
implementação: primeiro dividimos em ponto e vírgula; então cada item é passado como argumento para uma função que produz a fração falsa, se /
estiver 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}
Responder2
Usando apenas comandos primitivos do TeX você pode definir sua \geno
macro assim:
\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}
Responder3
Isso pode ser suficiente, usando listofitems
análise. EDITADO para lidar com a sintaxe mais geral especificada pelo autor no comentário.
\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}