# Write a macro which is called with \begin and \end

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)?

-
Use the command \newenvironment. Look here for previous answer. tex.stackexchange.com/questions/60079/… –  R. Schumacher Aug 19 '12 at 20:38
I think \newenvironment is yourt friend. –  knut Aug 19 '12 at 20:39
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 '12 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 –  David Carlisle Aug 19 '12 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 '12 at 6:00

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}}

-
I think it's a beamer block. –  percusse Aug 19 '12 at 20:45
You cannot directly use # in the ending part of a \newenvironment. –  Gonzalo Medina Aug 19 '12 at 20:49
@GonzaloMedina: Ah, thank you for the correction. –  canaaerus Aug 19 '12 at 20:51

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}}

-

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}


-
Where do those macros \krdmakekeys and \krdusekeys come from? –  canaaerus Aug 22 '12 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 '12 at 4:04