1

I'm trying to make code formatting a conversation between two ends with boxes left and right respectively. So far i have seen examples in which two \NewEnviron were used respectively for left side boxes and right ones.

I'd like to make a single \newcommand that will decide on the basis of a parameter value whether it should be \begin{flushleft} or \begin{flushright}

here is my non-working try:

\documentclass{article}
\usepackage{tcolorbox}}
\usepackage{ifthen}
\usepackage{varwidth}

\newcommand{\bubble}[3]{%
  \ifthenelse{\equal{#1}{\flushright}}{\begin{\flushright}}{\begin{\flushleft}}
    \begin{tcolorbox}[width=0.5\textwidth, title=#2]
       #3
    \end{tcolorbox}
  \ifthenelse{\equal{#1}{\flushright}}{\end{\flushright}}{\end{\flushleft}}

% use it like this:
\bubble{flushleft}{friend}{hello, what's your plan today?}
\bubble{flushright}{me}{nothing!}
2
  • There are a few issues in your code. With \newcommand you have to give the name of the macro with a leading backslash, so it should be \newcommand\bubbles.... Whereas in \begin you should not use a leading backslash, so correct would be \begin{flushright} or \begin{flushleft}, same for \end. Is the title in #2 to be always the same for the same alignment? How do you intend to use \bubbles? Can you show a (non-)working minimal example how you intend to use it?
    – Skillmon
    Commented Feb 23, 2021 at 11:44
  • for the backslash before "bubbles" it's a typo Commented Feb 23, 2021 at 11:59

3 Answers 3

0

If you give the first parameter to \bubbles without backslash, you can just use it as parameter to \begin. This simplifies the command a lot, with no test being necessary.

I suppose varwidth is to be used somewhere else, because for this simple example it isn't necessary.

\documentclass{article}
\usepackage{tcolorbox}
\usepackage{varwidth}
\usepackage{lipsum}

\newcommand{\bubbles}[3]{%
  \begin{#1}
    \begin{tcolorbox}[width=0.5\textwidth, title=#2]
       #3
    \end{tcolorbox}
  \end{#1}
}

\begin{document}

Test

\bubbles{flushleft}{Title Left}{Contents left\\\lipsum[1][1-2]}

\bubbles{flushright}{Title Right}{Contents right\\\lipsum[1][3-4]}

More text

\end{document}

enter image description here

3
  • i left \usepackage{varwidth} in the example here because i was not sure whether \textwidth was part of it. Commented Feb 23, 2021 at 12:26
  • \textwidth is standard LaTeX. Commented Feb 23, 2021 at 12:42
  • without additional options what would be the simplest way to make left boxes with title and content right aligned, and right boxes left aligned? Nothing justified! Commented Feb 23, 2021 at 14:57
0

You can achieve a much simpler syntax:

\documentclass{article}
\usepackage[many]{tcolorbox}

\newcommand{\bubble}[3]{%
  \begin{flushleft}
  \if>#1\hspace*{\fill}\fi
  \mbox{\begin{tcolorbox}[width=0.5\textwidth, title=#2]
    #3
  \end{tcolorbox}}%
  \end{flushleft}
}

\begin{document}

\bubble{<}{friend}{hello, what's your plan today?}
\bubble{>}{me}{nothing!}

\end{document}

enter image description here

0

If you want to use the same title and alignment for each speaker, it might be a better idea to store that information inside a key you can use as the first mandatory argument to \bubble. I added an optional argument to \bubble with which individual customizations can be made.

The following does so using expkv-def for a key=value interface (of course other packages could be used for this as well).

The box key can be used to forward additional keys to the tcolorbox environment (in the example I use this to specify colours for each speaker).

The align key might take the value center in which case a center environment is used, else the used environment will be flush<align>, so right and left are possible values.

\documentclass[]{article}

\usepackage{tcolorbox}
\usepackage{expkv-def}

\makeatletter
% we define new keys here. The `store' type of keys will store the value during
% its usage inside the macros. The `code' type allows own definitions. We use it
% to define a key that will add additional contents to an existing macro
% (\bubble@box) with a comma between the old and new material.
% With `initial' we set initial values for the keys `width` and `align`, all
% other macros are initially empty (title and box).
% The `BOX' key will overwrite any other option passed to `tcolorbox', whereas
% the `box' key will add to the list of options.
\ekvdefinekeys{bubbles}
  {
     store title = \bubble@title
    ,store align = \bubble@align
    ,store BOX   = \bubble@box
    ,code  box   = \edef\bubble@box{\unexpanded\expandafter{\bubble@box,#1}}
    ,store width = \bubble@wd
    ,initial width = .5\textwidth
    ,initial align = left
  }
% we define a shorthand macro to set options of bubbles.
\ekvsetdef\bubbleoptions{bubbles}
% the real macro
\newcommand\bubble[3][]
  {%
    % contain the definitions done by the key=value interface inside a group so
    % that one call can't affect another one.
    \begingroup
      % test if the macro holding defaults exists, if so call it 
      \ifcsname bubble@defaults@\detokenize{#2}\endcsname
        \csname bubble@defaults@\detokenize{#2}\endcsname
      \fi
      % parse the additional options with our key=value interface
      \bubbleoptions{#1}%
      % handle the `center' alignment by comparing the current alignment with a
      % temporary macro
      \def\bubble@tmp{center}%
      \begin{\ifx\bubble@tmp\bubble@align\else flush\fi\bubble@align}
        % expand the contents of `\bubble@box' so that the key=value interface
        % of tcolorbox can do its job
        \expandafter\bubble@startbox\expandafter{\bubble@box}%
          #3%
        \end{tcolorbox}%
      \end{\ifx\bubble@tmp\bubble@align\else flush\fi\bubble@align}
    \endgroup
  }
% helper macro to expand the contents of `\bubble@box' before calling
% `tcolorbox'.
\newcommand\bubble@startbox[1]
  {%
    % check if the title is empty, if so, don't use the title key of tcolorbox.
    \ifx\bubble@title\@empty
      \begin{tcolorbox}[width=\bubble@wd, #1]
    \else
      \begin{tcolorbox}[width=\bubble@wd, title=\bubble@title, #1]
    \fi
  }
% define a default option list. The optional argument is used as is for the
% `tcolorbox' options, the rest is parsed by our key=value interface. Since we
% use it inside of `\edef' the values passed to the keys here are fully
% expanded. This shouldn't be an issue normally.
\newcommand\bubbledef[3][]
  {%
    \expandafter\edef\csname bubble@defaults@\detokenize{#2}\endcsname
      {\unexpanded{\def\bubble@box{#1}}\bubbleoptions{#3}}%
  }
\makeatother

% define the two speakers (with short name A and B)
\bubbledef[colframe=red!50!black]{A}{title=Speaker A, align=left}
\bubbledef[colframe=green!50!black]{B}{title=Speaker B, align=right}

\usepackage{duckuments} % just for some dummy text

\begin{document}
\bubble{A}{\blindduck[-]}
\bubble{B}{\blindduck[-]}
\bubble[title=New Speaker]{}{A new speaker shows up.}
\bubble[align=center, width=.7\textwidth]{}{Another fat speaker is here.}
\end{document}

enter image description here


Changes:

2021-02-23, 18:38 (UTC+1)

  • added a lot of comments
  • added an optional argument to \bubbledef to set the default tcolorbox options in an, imho, nicer way.
  • changed the box key to add additional options instead of clearing the list
  • added the BOX key (does what the box key did previously)
2
  • the end result looks really nice, but i don't know as much of latex. Most of your code would require a lot of homework. Commented Feb 23, 2021 at 14:50
  • @user1850133 just ask what you don't understand and I'll try to explain... :)
    – Skillmon
    Commented Feb 23, 2021 at 17:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .