Объединить последовательные переносы строк

Объединить последовательные переносы строк

У меня что-то вроде этого:

%\newcommand{\maybehide}[1]{#1}
\newcommand{\maybehide}[1]{}
\newcommand{\thing}[1]{#1}
\newcommand{\bigthing}[1]{#1}

\bigthing{  
\thing{1}\\
  \maybehide{\thing{2}}\\
  \thing{3}
}

и я бы хотел, чтобы он вел себя так,

\bigthing{
  \thing{1}\\
  \thing{3}
}

но он ведет себя как

  \bigthing{
    \thing{1}\\
    \\
    \thing{3}
  }

Есть ли способ это сделать?

Единственный способ сделать это, который я смог придумать, — это переопределить его \\так, чтобы он переопределялся \\как ничего не делающий, а затем в \thing, переопределить его \\как то, чем он должен быть.

  \let\mylinebreak\\
  \let\mything\thing

  \def\mynewlinebreak{
    \def\\{}
    \mylinebreak  
  }
  \def\mynewthing{
    \def\\{\mynewlinebreak}
    \mything
  }

  \def\\{\mynewlinebreak}
  \def\thing{\mynewthing}

  \bigthing{
    \thing{1}\\
    \maybehide{\thing{2}}\\
    \thing{3}
  }

Но это действительно похоже на хак, который в конечном итоге что-то сломает, поэтому я бы предпочел другой метод. И есть еще тот факт, что это зависит от того, знаю ли я, что там будет \things. Если бы было \thing1и \thing2это могло бы чередоваться, мне пришлось бы добавить еще немного кода, и если я не знаю, что там может быть, это вообще не сработает...

Заранее спасибо за вашу помощь.

решение1

Ваш хак не так уж плох. Но вы можете сделать это быстрее и без необходимости переопределения \\.

Следующее решение определяет gobble-версию \maybehide(ту, которую вы активируете, если хотите скрыть содержимое) с двумя аргументами и проверяет, равен ли второй аргумент \\. Если true, он будет съеден, если false, он выводит то, что было вторым аргументом:

\newcommand{\maybehide}[2]{\ifx\\#2\else#2\fi}

Например: \maybehide{xyz}abcидентифицирует 'xyz' как первый аргумент, который в любом случае забыт (он не присутствует в тексте замены), а 'a' как второй аргумент. Таким образом, первое расширение — это , \ifx\\a\else a\fiкоторое затем, очевидно, расширяется до случая else, т. е. a; следовательно: \maybehide{xyz}abc--> "abc". В реальном варианте использования ' \maybehide{xyz}\\...' \maybehideбудет найден \\как второй аргумент, поэтому тест расширяется до случая true, который пуст; это означает, \\что он отбрасывается и \maybehide{xyz}\\просто ничего не выводит.

Полный пример:

\documentclass{article}

\parindent0pt

\makeatletter
%\newcommand{\maybehide}[1]{#1}
\newcommand{\maybehide}[2]{\ifx#2\\\else#2\fi}% in case you wanna hide
\newcommand{\thing}[1]{#1}
\newcommand{\bigthing}[1]{#1}
\makeatother

\begin{document}
\bigthing{%
  \thing{1}\\
  \maybehide{\thing{2}}\\
  \thing{3}
}
\end{document}

затем компилируется в нечто вроде

1
3

вместо

1

3

Для более общего решения, которое не зависит от ваших конкретных макросов, вы, конечно, можете также переопределить \\. Что-то вроде

\def\\#1{\ifx\\#1\newline\else\newline#1\fi}

по сути то, что нужно (и оно использует тот же подход, что и специальное решение выше). Теперь есть два предостережения: (1) \\может означать разные вещи в зависимости от своего окружения и (2) необязательный аргумент теряется.

  • ad (1): Сначала легкие вещи. Сохраните исходное значение, \let\ltx@nl=\\и\def\\#1{\ifx\\#1\ltx@nl\else\ltx@nl#1\fi}
  • ad (2): Необязательный аргумент, который по умолчанию равен '0pt', в принципе достаточен: \renewcommand{\\}[2][0pt]{\ifx\\#2\expandafter\ltx@nl\else\ltx@nl[#1]#2\fi}. Это также гарантирует, что любой необязательный аргумент superflous \\не будет выведен на выход, напримерsome text\\ \\[3pt] some other text не будетбыть преобразован в

какой-то текст

[3pt] какой-то другой текст

Последнее замечание: второй пункт можно было бы сделать еще лучше. В нынешнем виде будет использоваться необязательный аргумент сожранной строки. Но я бы сказал, что желательно забыть и необязательный аргумент. Для этого вам понадобится еще один вспомогательный макрос, который вызывает сохраненную версию \\с необязательным аргументом исходного вызова \\:

\newcommand{\ltx@nl@}[1][]{\ltx@nl[\@tempa]}% \@tempa will hold the optional argument of \\
\renewcommand{\\}[2][0pt]{%
  \def\@tempa{#1}%
  \ifx\\#2
    \expandafter\ltx@nl@
  \else
    \ltx@nl[#1]#2
  \fi}

Полный пример для проверки всех случаев:

\documentclass{article}

\parindent0pt

\makeatletter
\let\ltx@nl=\\
\renewcommand{\\}[2][0pt]{%
  \def\@tempa{#1}%
  \ifx\\#2
    \expandafter\ltx@nl@
  \else
    \ltx@nl[#1]#2
  \fi}
\newcommand{\ltx@nl@}[1][]{\ltx@nl[\@tempa]}
\makeatother

\begin{document}
some text\\[16pt]  %linebreak with 16pt vertical offset
\\[4pt]            %will be forgotten completely
someother text\\   %regular forced linebreak
hello world
\end{document}

Связанный контент