ifdefstring + lstinline = 文字をエスケープする必要がある

ifdefstring + lstinline = 文字をエスケープする必要がある

\ifdefstring環境変数に依存する条件付き定義の一部として使用しています。この質問では

ほぼ正常に動作しますが、 で定義されたブロック内にバックスラッシュが含まれて\ifdefstringいる場合は\lstinline、それをエスケープする必要があります。そうしないと動作しません。

特にエラー メッセージが明確ではないため、内部の内容をエスケープ/アンエスケープせずにブロックを追加できるようにしたいと思います\ifdefstring。バックスラッシュがないと、ブロックの最後に不可解なエラー メッセージが表示されます。これを行う方法はありますか?

これは MVE です。各ケース ( の内側と外側の両方\ifdefstring) で 1 つのバックスラッシュを印刷する必要があります。

\documentclass{article}
\usepackage{listings}
\usepackage{etoolbox}
% catchfile block copied from other question
\usepackage{catchfile}
\newcommand{\getenv}[2][]{%
  \CatchFileEdef{\temp}{"|kpsewhich --var-value #2"}{\endlinechar=-1\relax}%
  \if\relax\detokenize{#1}\relax\temp\else\edef#1{\temp}\fi}
\getenv[\VAR]{VAR}%

\begin{document}
\ifdefstring{\VAR}{yes}{
  \lstinline|\\must_be_escaped_yes|
}{
  \lstinline|\\must_be_escaped_not_yes|
}

\lstinline|\must_not_be_escaped|

\end{document}

出力(ここではVAR != yes)は次のようになります。

lstinline を内部に含む ifdefstring の MVE

しかし、解析可能にするには、ブロック内のパーツ\内に手動で余分なものを追加する必要があり、これは避けたいと思いました。\lstinline\ifdefstring

答え1

\lstinline他の逐語的コマンドとは少し異なるので、できる別のコマンドの引数として使用できますが、制限があります。

\else–形式を定義すると、エスケープされていないバージョンを使用できます。\fi\ifdefstring

\documentclass{article}
\usepackage{listings}
\usepackage{etoolbox}
% catchfile block copied from other question
\usepackage{catchfile}
\newcommand{\getenv}[2][]{%
  \CatchFileEdef{\temp}{"|kpsewhich --var-value #2"}{\endlinechar=-1\relax}%
  \if\relax\detokenize{#1}\relax\temp\else\edef#1{\temp}\fi}

\newcommand{\defstring}[2]{%
  TT\fi
  \ifdefstring{#1}{#2}{\iftrue}{\iffalse}%
  \ignorespaces
}

\getenv[\VAR]{VAR}

\begin{document}
\if\defstring{\VAR}{yes}
  \lstinline|\must_be_escaped_yes|
\else
  \lstinline|\must_be_escaped_not_yes|
\fi

\lstinline|\must_not_be_escaped|

\end{document}

VAR設定されていない出力

ここに画像の説明を入力してください

VARに設定して出力yes

ここに画像の説明を入力してください

関連情報