Escreva uma macro que seja chamada com \begin e \end

Escreva uma macro que seja chamada com \begin e \end

Eu gostaria de escrever uma macro scaleblockque receba 2 argumentos titlee content. Pode ser chamado como:

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

E é equivalente ao seguinte:

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

Alguém sabe como escrever esse tipo de macro (com \begine \end)?

Responder1

Você pode definir um ambiente da mesma forma que definiria uma macro. Só que em vez de dizer que \newcommand\mycmd[1]{...#1...}você deve escrever

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

Aqui os dois últimos parâmetros dizem o que deve ser colocado antes e depois do conteúdo.

Isso significa que a primeira tentativa seria escrever

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

Mas isso não reflete o aninhamento pretendido de parâmetros e, na verdade, você fornece apenas a parte inicial do seu ambiente, enquanto a parte final é o caractere de nova linha na quarta linha.

Portanto, no seu caso, provavelmente é melhor primeiro coletar tudo dentro do corpo do ambiente e depois usá-lo. Isso pode ser feito com o environpacote. Ele fornece o comando \NewEnvironque você pode usar \BODYpara acessar esse conteúdo. Supondo blockque seja o de beamer, você pode fazer o seguinte:

\usepackage{environ}
\NewEnviron{scaleblock}[1]{\begin{block}{\scalebox{0.8}{#1}}
  \scalebox{0.8}{\vbox{\BODY}}
\end{block}}

Responder2

Aqui está uma versão "puro LaTeX":

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

Responder3

Você tem maior controle com as teclas:

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

Isso pode ser usado como:

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

EDITAR (23/08/2012)

O código acima é baseado em uma versão doleitor de chavespacote que não está no CTAN. Aqui está uma solução baseada emteclas pgf.

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

insira a descrição da imagem aqui

informação relacionada