xstring 매크로의 명령 확장에 문제가 있습니까? "불완전\iffalse"

xstring 매크로의 명령 확장에 문제가 있습니까? "불완전\iffalse"

;먼저 입력 텍스트를 으로 청크 한 다음 로 구분된 텍스트에서 "분수"를 만드는 다음 명령을 작성했습니다 /. 나의 의도는 적절한 형식으로 유전자형을 표시하는 것입니다.

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

이제 문서 본문에 다음 명령을 입력하면 됩니다.

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

우리는 다음과 같은 출력을 생성합니다.

유전자형

\textsuperscript그러나 입력 문자열에 와 같은 명령 이나 기호 \Male또는 같은 기호 를 포함하려고 하면 \Female다음 오류가 발생합니다.

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

내 추측으로는 if 문 중 하나에서 인수 확장과 관련된 문제가 발생했기 때문에 명령 에서 가 처음 정의된 시기 와 거의 성공하지 못하는 \protect등의 문제를 일으킬 수 있다고 의심되는 위치에 일부 를 배치해 보았습니다. 또한 다음과 같은 명령을 사용하려고 시도했습니다 .\remainder\geno\IfSubStr\MakeRobust

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

그러나 불행하게도 문제는 계속되었습니다.

어둠 속에서의 다른 블라인드 샷에는 다음이 포함됩니다.

  • \ifx다음으로 교체 \if\relax\detokenize{\remainder}\relax(동일한 오류)
  • \detokenize입력을 입력합니다 \IfSubStr(모두 false를 반환하는 것 같습니다. 뭔가 잘못하고 있는 것 같나요?).
  • 명령 에 대한 다양한 대안 사용 \genoSplit(동일한 오류, 이제는 문제가 아니라고 확신합니다)
  • 사용할 모든 명령을 다시 작성 \newcommand하고 \renewcommand(동일 오류)

나도 찾았어이 질문, 그러나 이것이 제가 겪고 있는 문제와 동일한지 확신할 수 없으며 허용된 답변( \begingroup\noexpandarg [...] \endgroup)으로 인해 매크로가 작동하지 않습니다.

어찌할 바를 모르겠습니다. 이 문제의 원인이 무엇인지 알려주시면 대단히 감사하겠습니다.

답변1

xstrings인수에서 깨지기 쉬운 명령을 좋아하지 않습니다.

구현 은 다음과 같습니다 expl3. 먼저 세미콜론으로 분할합니다. 그런 다음 각 항목이 /존재 하는 경우 가짜 분수를 생성하는 함수에 인수로 전달됩니다 .

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

여기에 이미지 설명을 입력하세요

답변2

TeX 기본 명령만 사용하면 \geno다음과 같이 매크로를 정의할 수 있습니다.

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

답변3

구문 분석을 사용하면 충분할 수 있습니다 listofitems. 주석에서 작성자가 지정한 보다 일반적인 구문을 처리하도록 편집되었습니다.

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

여기에 이미지 설명을 입력하세요

관련 정보