将参数传递给标题内的嵌套宏

将参数传递给标题内的嵌套宏

我真的很难理解这个庞大文档中的错误。我花了一些时间找出一个“最小示例”,以便能够准确地发布错误。请在尝试回答时不要更改结构,假设这个“玩具示例”可以轻松重新排列。非常感谢。这是示例。下面我将更详细地解释这些尝试。

% By Dr. Beco - 60 games
\documentclass[a4paper,12pt]{article}

\usepackage[utf8]{inputenc} % accented chars
\usepackage[english]{babel} % translations
\usepackage{graphicx} % includegraphics
\usepackage[ps]{skak} % chess
\usepackage{float} % figure[H]
\usepackage{xstring} % get tokens

%%%%%%%%%%%%%%%%%%%%% define \variable = value
\newcommand{\setvalue}[2]
{
    \ifdefined #1
        \renewcommand{#1}{#2}
    \else
        \newcommand{#1}{#2}
    \fi
}

%%%%%%%%%%%%%%%%%%%%% fill all needed variables for a section
\newcommand{\setsec}[6]
{
  \setvalue{\gnumber}{#1}
  \setvalue{\gcolor}{#2}
  \setvalue{\gdate}{#3}
  \setvalue{\gresult}{#4}
  \setvalue{\gopening}{#5}
  \setvalue{\gfirstmoves}{#6}
  \mysec{\gnumber}{\gcolor}{\gdate}{\gresult}{\gopening}{#6}
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%% inicia seção
% parâmetros:
% #1 num. jogo
% #2 minha cor (W ou B)
% #3 Data
% #4 resultado (1:brancas, 0:pretas, 2:empate)
% #5 ECO code seguido do nome da abertura
% #6 Linha principal para mostrar a abertura
\newcommand{\mysec}[6]
{
  \section*{Code #1#2, date: #3 result: #4 opening: #5}
  \mygamesi{#1}{#2}{#5}{#6}
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \mygamesi{Game Number}{Color}{Opening}{Moves}
\newcommand{\mygamesi}[4]
{
  \newgame
  \mainline{#4}
  \begin{figure}[H]
  \centering
  \showboard
  \caption{#1#2, #3}
  \label{g1}
  \end{figure}
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% show some variation on board
% #1 game number \gnumber
% #2 my color \gcolor
% #3 #2 label key for \ref{}
% #4 #3 variation to show (board and caption)
% optional #1 : s=show full var in caption, h=hide, only last move in caption
\newcommand{\myvar}[3][h]
{
  \storegame{mainline}
  \hidemoves{#3}
  \begin{figure}[H]
  \centering
  \showboard

  \ifthenelse{\equal{#1}{s}}{\caption{opt S:position after variation \protect\movecomment{#3}}}{}
  \ifthenelse{\equal{#1}{h}}{\caption{opt H:position after variation \protect\movecomment{\protect\StrBefore[2]{#3}{ }} ... \lastmove{}}}{} %<<<<<<<<<<<<<<<<<

  \label{gv}
  \end{figure}
  \restoregame{mainline}
}

%%%%%%%%%%%%%%%%%%%%%%%%%% fim de seção
% #1 num. jogo \gnumber
% #2 minha cor (W ou B) \gcolor
\newcommand{\myend}
{
  \begin{figure}[H]
%   \includegraphics{\gnumber-graph.png}
[altern. text: evaluation graph]
  \caption{\gnumber\gcolor, evaluation graph}
  \label{ge}
  \end{figure}
}

\tinyboard

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}

\setsec{1}{B}{2017.17.17}{0}{B00 Strange Defense}{1. e3 e5 2. d3 d4 3. Nc3 Bb4}

It was a serious game.

\mainline{4. a3 Bxc3+ 5. bxc3 dxe4 6. Qg4 Nf6 7. Qxg7
Rg8 8. Qh6 c5 9. Bg5 Ng4 }

after \variationcurrent{10. Qxh7 Qxg5 11. Qxe4 Nf6 12. Bb5+ Nbd7} you can see:

my var show:

\myvar[s]{v1}{10. Qxh7 Qxg5 11. Qxe4 Nf6 12. Bb5+ Nbd7}

my var hide:

\myvar[h]{v1}{10. Qxh7 Qxg5 11. Qxe4 Nf6 12. Bb5+ Nbd7}

White resigns

\myend

\end{document}
  • 注意:我们使用 PDFLatex
  • 有错误的行标记为%<<<<<<<<<<<<<<<<<

我期望它能做什么

  • \myvar[s]将在标题中显示所有棋步。效果很好。
  • \myvar[h]只会显示字符串的第一步、3 个点和最后一步。这是无法实现的。

问题是我无法给skak命令的\movecomment{}标题内添加变量。

我尝试过\def和的所有组合\edef,但我不太理解这些组合,所以我更喜欢一种LaTeX方法。我尝试过\newcommand和,以及在很多地方DeclareRobustCommand添加和删除。\protect

这个想法很简单:给定一个带有走法的字符串,比如“1. e4 e5 2. d4 d5”,我想要“第一步”,也就是“1. e4”。skak包中提供了一个lastmove可以在 captions 中运行的函数,我甚至读过它的代码。但我无法理解它并进行调整。

我的简单解决方案是:

例如:

  • \StrBefore[2]{#1}{ }[\firstmove]

进而

  • \movecomment{\firstmove}

但谁说这有效?我已经尝试并阅读了有关此扩展和宏的资料一段时间了,但我无法解决。

谢谢任何帮助。


編輯:

还有一些不起作用的东西:

\newcommand{\setsec}[6]
{
  \setvalue{\gnumber}{#1}
  \setvalue{\gcolor}{#2}
  \setvalue{\gdate}{#3}
  \setvalue{\gresult}{#4}
  \setvalue{\gopening}{#5}
  \setvalue{\gfirstmoves}{#6}
  \mysec{\gnumber}{\gcolor}{\gdate}{\gresult}{\gopening}{#6}
}

最后一行实际上应该是:

  \mysec{\gnumber}{\gcolor}{\gdate}{\gresult}{\gopening}{\gfirstmoves}

可惜...


当前解决方案(解决方法)

  • 内部命令\myvar

       \ifthenelse{\equal{#1}{s}}{\caption{THEN: position after variation \protect\movecomment{#3}}}{\caption{ELSE: position after variation \protect\movecomment{#1} \ldots\ \lastmove{}}}
    
  • 如果整行都作为标题:

        \myvar[s]{v1}{10. Qc4+ Kb8 11. Qd3 Qf6 12. Rd1 Qxf2}
         % or
         \myvar{v1}{10. Qc4+ Kb8 11. Qd3 Qf6 12. Rd1 Qxf2}
    
  • 如果只有第一个和最后一个动作在标题中:

        \myvar[22. Qc4+]{v1}{10. Qc4+ Kb8 11. Qd3 Qf6 12. Rd1 Qxf2}
    

编辑:删除了包多列 - 毕竟不是一个最小示例。;)

答案1

这是该问题的更好的 MWE。

\documentclass[a4paper,12pt]{article}

\usepackage[ps]{skak} % chess
\usepackage{xstring} % get tokens

\begin{document}

Extracted String: \StrBefore[2]{10. Qxh7 Qxg5 11. Qxe4 Nf6 12. Bb5+ Nbd7}{ }

Move Comment: \movecomment{10. Qxh7 Qxg5 11. Qxe4 Nf6 12. Bb5+ Nbd7}

Reduced Move Comment: \movecomment{\StrBefore[2]{10. Qxh7 Qxg5 11. Qxe4 Nf6 12. Bb5+ Nbd7}{ }}

\end{document}

我认为这可能表明 存在根本问题\movecomment。可能需要巧妙地使用\expandafter。我试图解决它,但失败了。

一旦上述方法奏效,您就会想将其放入另一个宏中并使用位置参数。然后将其放入传递这些参数的另一个宏调用中。老实说,我看不出您所做的真的是最好的方法。相反,我看到了一种过度设计的方法,它不能在最低级别直接工作,需要尚未知晓的 TeX 级原始命令来强制它即使在最低级别也能工作,并且一旦将其封装在另一层带有位置参数的宏中(宏之上的宏之上的宏),可能会带来更多问题。

啊!

这是一个更简洁方法的起点。首先,我避免在宏中调用宏,也避免将参数从一个宏传递到另一个宏,然后再传递到另一个宏。我只需指定始终需要的内容和可以选择隐藏的内容,而不是费力地搜索字符串以删除空格后的部分。诚然,您说后一种方法是一种“变通方法”。然而,我诚实地选择这种“变通方法”而不是您每天尝试的方法,即使您拥有的方法可行。今天,您要跳过的空格的位置值为 [2]。明天,您可能会决定第三个示例的跳过值应为 [3]。然后,您必须重新硬编码 LaTeX 文档以仅在该点处理这种情况。在下面的方法中,您只需更改传递给宏的第二个和第三个参数的内容\myvar

\documentclass[a4paper,12pt]{article}

\usepackage{graphicx} % includegraphics
\usepackage[ps]{skak} % chess
\usepackage{float} % figure[H]

\setlength{\parindent}{0em}

\newcommand{\setvalue}[2]
{
    \ifdefined #1
        \renewcommand{#1}{#2}
    \else
        \newcommand{#1}{#2}
    \fi
}

\newcommand{\setsec}[5]
{
  \setvalue{\gnumber}{#1}
  \setvalue{\gcolor}{#2}
  \setvalue{\gdate}{#3}
  \setvalue{\gresult}{#4}
  \setvalue{\gopening}{#5}
  \section*{Code \gnumber\gcolor, date: \gdate result: \gresult opening: \gopening}
}

\newcommand{\mygamesi}[1]
{
  \setvalue{\gfirstmoves}{#1}
  \newgame
  \mainline{#1}
  \begin{figure}[H]
  \centering
  \showboard
  \caption{\gnumber{}\gcolor{}\gdate{}}
  \label{g1}
  \end{figure}
}

\newcommand{\myvar}[3][h]
{
  \storegame{mainline}
  \hidemoves{#2 #3}
  \begin{figure}[H]
  \centering
  \showboard
  \ifthenelse{\equal{#1}{s}}
  {\caption{opt S:position after variation \protect\movecomment{#2\ #3}}}
  {\caption{opt H:position after variation \protect\movecomment{#3}} ... \lastmove{}}
  \label{gv}
  \end{figure}
  \restoregame{mainline}
}

\newcommand{\myend}
{
  \begin{figure}[H]
%   \includegraphics{\gnumber-graph.png}[altern. text: evaluation graph]
  \caption{\gnumber\gcolor, evaluation graph}
  \label{ge}
  \end{figure}
}

\tinyboard

\begin{document}

\setsec{1}{B}{2017.17.17}{0}{B00 Strange Defense}

\mygamesi{1. e3 e5 2. d3 d4 3. Nc3 Bb4}

It was a serious game.

\mainline{4. a3 Bxc3+ 5. bxc3 dxe4 6. Qg4 Nf6 7. Qxg7
Rg8 8. Qh6 c5 9. Bg5 Ng4 }

after \variationcurrent{10. Qxh7 Qxg5 11. Qxe4 Nf6 12. Bb5+ Nbd7} you can see:

my var show:

\myvar[s]{10. Qxh7 Qxg5}{11. Qxe4 Nf6 12. Bb5+ Nbd7}

my var hide:

\myvar[h]{10. Qxh7 Qxg5}{11. Qxe4 Nf6 12. Bb5+ Nbd7}

White resigns
%
%\myend

\end{document}

我仍然很好奇,有人会发布我发布的 MWE 的解决方案。但我并不抱太大希望。

相关内容