14

I would like to write a macro scaleblock which takes 2 arguments title and content. It can be called like:

\begin{scaleblock}{a_title}
   a_content
\end{scaleblock}

And it is equivalent to the follows:

\begin{block}{\scalebox{0.8}{a_title}}
  \scalebox{0.8}{\vbox{a_content}}
\end{block}

Does anyone know how to write this kind of macro (with \begin and \end)?

5
  • 3
    Use the command \newenvironment. Look here for previous answer. tex.stackexchange.com/questions/60079/… Aug 19, 2012 at 20:38
  • 1
    I think \newenvironment is yourt friend.
    – knut
    Aug 19, 2012 at 20:39
  • 1
    I don't think that \newenvironment can suffice. I believe that \NewEnviron from environ package is needed, as suggested in cannaerus'es answer.
    – yo'
    Aug 19, 2012 at 21:22
  • @tohez since the body is to be boxed anyway using newenvironment and newenvironment with lrbox as in egreg's answer would have several benefits, especially allowing verb and friends to work Aug 19, 2012 at 21:54
  • @DavidCarlisle Ok, another approach, but still, the solely link provided by R. Schumacher would not help, you need to add information "... and use lrbox. Other than that, I agree that egreg's solution is elegant and efficient!
    – yo'
    Aug 20, 2012 at 6:00

3 Answers 3

12

You can define an environment just as you would define a macro. Only instead of saying \newcommand\mycmd[1]{...#1...} you must write

\newenvironment{myenv}[1]{Begin...#1...}{End}

Here the last two parameters say what should be put before and after the contents.

This means the first try would be to write

\newenvironment{scaleblock}[1]{\begin{block}{\scalebox{0.4}{#1}}
    \scalebox{0.4}{\vbox{}%
  {}}
\end{block}}

But this does not reflect the intended nesting of parameters and you actually only give the begin part of your environment, while the end part is the newline character in the fourth line.

So in your case it is probably better to first collect everything inside the environments body and then use it. This can be done with the environ package. It provides the command \NewEnviron where you can use \BODY to access those content. Assuming block is the one from beamer, you can do the following:

\usepackage{environ}
\NewEnviron{scaleblock}[1]{\begin{block}{\scalebox{0.8}{#1}}
  \scalebox{0.8}{\vbox{\BODY}}
\end{block}}
3
  • 1
    I think it's a beamer block.
    – percusse
    Aug 19, 2012 at 20:45
  • 1
    You cannot directly use # in the ending part of a \newenvironment. Aug 19, 2012 at 20:49
  • @GonzaloMedina: Ah, thank you for the correction.
    – bodo
    Aug 19, 2012 at 20:51
13

Here's a "pure LaTeX" version:

\newsavebox{\scaleblockbox}
\newenvironment{scaleblock}[1]
  {\begin{block}{\scalebox{0.8}{#1}
   \begin{lrbox}{\scaleblockbox}
   \begin{minipage}{\textwidth}}
  {\end{minipage}
   \end{lrbox}
   \scalebox{0.8}{\usebox{\scaleblockbox}}
   \end{block}}
1

You have greater control with keys:

\krdmakekeys[
  prefix=KV,
  family=collectbody,
  hp=mp,
  initialize,
  endlinechar=-1
]{%
  cmd/title//,
  zcmd/title scale/1,
  zcmd/body scale/1,
  cmd/width/\textwidth,
  zcmd/title text style//,
  zcmd/body text style//,
  cmd/action//
}

\newsavebox{\boxbody}
\newenvironment{collectbody}[1][]{%
  \krdusekeys[prefix=KV,family=collectbody]{#1}%
  \ifx\mptitle\@empty\else\krdafterfi
    \begin{center}%
    \scalebox{\mptitlescale}{\mptitletextstyle\mptitle}%
    \end{center}%
  \fi
  \begin{lrbox}{\boxbody}%
  \begin{minipage}{\mpwidth}%
  \mpbodytextstyle\mpaction
}{%
  \end{minipage}%
  \end{lrbox}%
  \scalebox{\mpbodyscale}{\usebox{\boxbody}}%
}

This may be used as:

\documentclass{article}
\usepackage[dvipsname]{xcolor}
\usepackage{graphicx}
\usepackage{lipsum}
\begin{collectbody}[
  title=Example of collect body,
  title scale=.8,
  title text style=\ttfamily\color{red}
]
\lipsum[1]
\end{collectbody}
\end{document} 

EDIT (2012/08/23)

The above code is based on a version of keyreader package that isn't on CTAN. Here is a solution based on pgfkeys.

\documentclass{standalone}
\usepackage[dvipsname]{xcolor}
\usepackage{graphicx}
\usepackage{pgfkeys}
\usepackage{lipsum}
\makeatletter
\def\pgfkeysafterfi#1\fi{\fi#1}
\def\pgfkeysafterelse@i#1\else#2\fi{\fi#1}
\def\pgfkeysifkeydefined#1#2#3{%
  \ifcsname pgfk@#1/.@cmd\endcsname
    \pgfkeysafterelse@i{#2}\else\pgfkeysafterfi{#3}\fi
}
\pgfkeys{
  /handlers/.protected estore in/.code=
    \pgfkeys{
      \pgfkeyscurrentpath/.code=\protected@edef#1{##1}
    },
  /handlers/.default and initial/.code=
    \pgfkeys{
      \pgfkeyscurrentpath/.initial=#1,
      \pgfkeyscurrentpath/.default=#1,
      \pgfkeyscurrentpath=#1%
    },
  /handlers/.new key/.code 2 args=
    \pgfkeysifkeydefined{\pgfkeyscurrentpath}{%
      \@latexerr{Key '\pgfkeyscurrentpath' already exists}\@ehd
    }{%
      \pgfkeys{
        \pgfkeyscurrentpath/.store in=#1,
        \pgfkeyscurrentpath/.default and initial=#2%
      }%
    }%
}
\pgfkeys{%
  /collectbody/.is family,/collectbody/.cd,
  title/.new key=\mptitle\@empty,
  title scale/.new key=\mptitlescale{1},
  body scale/.new key=\mpbodyscale{1},
  width/.new key=\mpwidth\textwidth,
  title text style/.new key=\mptitletextstyle\@empty,
  body text style/.new key=\mpbodytextstyle\@empty,
  action/.new key=\mpaction\@empty
}
\def\@@empty{\@empty}
\newsavebox{\boxbody}
\newenvironment{collectbody}[1][]{%
  \pgfkeys{/collectbody/.cd,#1}%
  \ifx\mptitle\@@empty\else\pgfkeysafterfi
    \begin{center}%
    \scalebox{\mptitlescale}{\mptitletextstyle\mptitle}%
    \end{center}%
  \fi
  \begin{lrbox}{\boxbody}%
  \begin{minipage}{\mpwidth}%
  \mpbodytextstyle\mpaction
}{%
  \end{minipage}%
  \end{lrbox}%
  \scalebox{\mpbodyscale}{\usebox{\boxbody}}%
}
\makeatother

% Example:
\begin{document}
\begin{collectbody}[
  title=Example of \texttt{collect body} environment,
  title scale=.8,
  title text style=\scshape\color{red}
]
\lipsum[1]
\end{collectbody}
\end{document}

enter image description here

2
  • Where do those macros \krdmakekeys and \krdusekeys come from?
    – bodo
    Aug 22, 2012 at 5:26
  • Oops, I am sorry. The package that authored the macros isn't on CTAN. I will change the code soon.
    – Ahmed Musa
    Aug 24, 2012 at 4:04

You must log in to answer this question.

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