David has given a simple, commonsense solution, but your question has led to a package called newenviron, which may be used without a trick on the part of the user. \envbody and \<env name>body can be used to apply some code to the body of an environment.
\begin{filecontents*}{newenviron.sty}
% Collect environment body in macros \envbody and \<env name>body.
\@ifpackageloaded{catoptions}{}{\RequirePackage{catoptions}[2011/12/12]}
\UseNormalCatcodes
\StyleFilePurpose{Collect and execute environment body (AM)}
\StyleFileRCSInfo
$Id: newenviron.sty,v 1.0 2013/03/08 09:00:00 Ahmed Musa Exp $
\ProvidesPackage{newenviron}[\StyleFileInfo]
\NeedsTeXFormat{LaTeX2e}[2011/06/27]
\cptnewvariables{toks}[nenv@]{temptoks}
\new@def\nenv@gobbletomarker#1\nenv@endmarker{}
\new@def*\nevn@quark{}
\new@def*\AlwaysTrimEnvEntries{\global\nenv@alwaystrimtrue}
\new@def*\nenv@trimspace{%
\ifdefboolTF{nenv@alwaystrim}\cpttrimspace\unexpanded
}
\new@def*\nenv@everybegin@hook{}
\robust@def*\EveryBeginOfEnvironment#1{%
\xifinsetTF
{\detokenize{\nevn@quark#1\nevn@quark}}
{\cptoxdetok\nenv@everybegin@hook}{}{%
\edef\nenv@everybegin@hook{%
\expandcsonce\nenv@everybegin@hook
\noexpand\nevn@quark\unexpanded{#1}\noexpand\nevn@quark
}%
}%
}
\new@def*\nenv@everyend@hook{}
\robust@def*\EveryEndOfEnvironment#1{%
\xifinsetTF
{\detokenize{\nevn@quark#1\nevn@quark}}
{\cptoxdetok\nenv@everyend@hook}{}{%
\edef\nenv@everyend@hook{%
\expandcsonce\nenv@everyend@hook
\noexpand\nevn@quark\unexpanded{#1}\noexpand\nevn@quark
}%
}%
}
\EveryEndOfEnvironment{\@ignoretrue}
\robust@def*\nenv@appto#1#2{%
\ifdefTF#1{%
\edef#1{\expandcsonce#1\unexpanded{#2}}%
}{%
\edef#1{\unexpanded{#2}}%
}%
}
%
% \newenviron<optional *>
% {<name>}[<narg>][<default of 1st arg>]{<start-code>}{<end-code>}
%
% \renewenviron<optional *>
% {<name>}[<narg>][<default of 1st arg>]{<start-code>}{<end-code>}
%
\robust@def*\newenviron{\cpt@starorlong\nenv@newenviron}
\robust@def*\nenv@newenviron#1{%
\edef\cpt@tempa{\nenv@trimspace{#1}}%
\cptexpandarg\cpt@testopt
{\nenv@newenviron@a{\expandcsonce\cpt@tempa}}{0}%
}
\robust@def*\nenv@newenviron@a#1[#2]{%
\cpt@ifbrack{\nenv@newenviron@b#1[#2]}{\nenv@newenviron@c{#1}{[#2]}}%
}
\robust@def*\nenv@newenviron@b#1[#2][#3]{\nenv@newenviron@c{#1}{[#2][{#3}]}}
\robust@def\nenv@newenviron@c#1#2#3#4{%
\ifcsndefTF{#1}{}{\letcsntocsn{#1}{end#1}}%
\aftercsname\new@command{#1}#2{%
\edef\nenv@beforebody{\nenv@trimspace{#3}}%
\nenv@everybegin@hook
\nenv@collectbody
}%
\l@ngrel@x\csn@edef{end#1}{%
\def\noexpand\cpt@prova{\nenv@trimspace{#4}}\noexpand\cpt@prova
\noexpand\nenv@everyend@hook
}%
}
\robust@def*\nenv@collectbody{%
\begingroup
\toks@{}%
\everyeof{\end{EOF}\relax}%
\nenv@collectbody@a
}
\robust@def\nenv@collectbody@a#1\end#2{%
\nenv@temptoks{%
\cptexpanded{%
\toks@{%
\the\toks@\nenv@trimspace{#1}%
\noexpand\end{\expandcsonce\cpt@argofend}%
}%
}%
\nenv@collectbody@a
}%
\edef\cpt@argofend{\cpttrimspace{#2}}%
\ifcseqTF\cpt@argofend\@currenvir{%
\def\cpt@tempa{}%
\nenv@pushbegin#1\begin\end\nenv@endmarker
\ifcsemptyTF\cpt@tempa{%
\cptexpanded{\endgroup
\csn@edef{\@currenvir body}{%
\noexpand\unexpanded{\the\toks@\nenv@trimspace{#1}}%
}%
\letcstocsn\noexpand\envbody{\@currenvir body}%
\unexpanded{%
\nenv@beforebody\relax
\ifdefboolTF{nenv@alwaystrim}\@ignoretrue\relax
}%
\noexpand\end{\cpt@argofend}%
}%
}{%
\the\nenv@temptoks
}%
}{%
\oifstrcmpTF{\cpt@argofend}{document}{%
\expandafter\endgroup\expandafter
\@checkend\expandafter{\cpt@argofend}%
}{%
\oifstrcmpTF{\cpt@argofend}{EOF}{%
\expandafter\endgroup\expandafter
\@checkend\expandafter{\cpt@argofend}%
}{%
\the\nenv@temptoks
}%
}%
}%
}
\new@def\nenv@pushbegin#1\begin#2{%
\expandafter\ifx\cpt@car#2x\car@nil\end
\expandafter\@gobble
\else
\edef\cpt@prova{\cpttrimspace{#2}}%
\ifx\cpt@prova\cpt@argofend
\def\cpt@tempa{x}%
\expandafter\expandafter\expandafter\nenv@gobbletomarker
\else
\expandafter\expandafter\expandafter\nenv@pushbegin
\fi
\fi
}
\robust@def*\renewenviron{\cpt@starorlong\nenv@renewenviron}
\robust@def*\nenv@renewenviron#1{%
\edef\cpt@tempa{\nenv@trimspace{#1}}%
\ifcsndefTF\cpt@tempa
{}
{\@latex@error{Environment #1 is undefined}\@ehd}%
\letcsntocs\cpt@tempa\relax
\letcsntocs{end\cpt@tempa}\relax
\expandafter\nenv@newenviron\expandafter{\cpt@tempa}%
}
\XDeclareBooleanOption{alwaystrim}[true](nenv@){}{}
\XDeclareOption*{\@@warning{Unknown option '\CurrentOption' ignored}}
\XExecuteOptions{alwaystrim}
\XProcessOptions*\relax
\endinput
\end{filecontents*}
Example:
\documentclass{article}
\usepackage{newenviron,xcolor}
% \envbody will always work for 'unnested' environments:
% \newenviron{assertion}{}{Assertion: \envbody}
% But if you intend to nest the environment, it will be safer to use \assertionbody:
\newenviron{assertion}{%
\def\acmd##1{##1}% test <start-code>.
}{%
\def\bcmd##1{##1}% test <end-code>.
Assertion: \assertionbody
}
\newenviron{outerassertion}{%
% Put any start code here.
}{%
\textcolor{blue}{Outer assertion:} %
\begin{assertion}\outerassertionbody\end{assertion}%
}
\begin{document}
% Just for testing:
\EveryEndOfEnvironment{\def\ccmd#1{#1}}
\begin{assertion}
test
\end{assertion}
\endgraf\bigskip
\begin{outerassertion}
test2
\end{outerassertion}
\endgraf\bigskip
\begin{assertion}
Level-1 test.
\begin{assertion}
Another level-1 test.
\end{assertion}
\end{assertion}
\endgraf\bigskip
% Another test. Note the use of \usename{env-1body} and \usename{env-2body}:
\newenviron{env-1}[2][blue]{%
\fboxrule=#2\relax
\cptdimdef\temp{.5\textwidth}%
\endgraf\noindent
\fcolorbox{#1}{gray!10}{\parbox{\temp}{\textcolor{#1}{\usename{env-1body}}}}%
}{}
\newenviron*{env-2}[1][black]{%
\noindent
\fcolorbox{#1}{gray!30}{%
\parbox{.7\textwidth}{%
\leftskip=1cm
\textcolor{#1}{\usename{env-2body}}%
}%
}%
}{%
\def\testcmd##1{##1}% test <end-code>.
}
\begin{env-2}[red]
Outer box\endgraf
\def\tempa#1{***#1***}\tempa{aa}%
\endgraf\vspace*{5mm}%
\begin{env-1}[blue]{1pt}%
Inner box\endgraf\vspace*{5mm}%
\def\tempa#1{+++#1+++}\tempa{bb}%
\end{env-1}%
\begin{env-1}[brown]{4pt}%
Inner box\endgraf\vspace*{5mm}%
\def\tempa#1{---#1---}\tempa{cc}%
\end{env-1}%
\end{env-2}
\end{document}
