I would like to define nested environments that have the same nested definitions of sub-commands and sub-environments. This is how it would be used:
\begin{myenva}
\begin{myenvx}
\begin{myenvz}
\mycmdz{}
\end{myenvz}
\end{myenvx}
\end{myenva}
\begin{myenvb}
\begin{myenvx}
\begin{myenvz}
\mycmdz{}
\end{myenvz}
\end{myenvx}
\end{myenvb}
I would like for myenvx
to be a totally different environment with different functionality when used under myenva
vs. myenvb
. Likewise, I would like myenvz
underneath myenva/myenvx
to be totally different than myenvz
under myenvb/myenvx
.
I have the following MWE demonstrating how I tried getting it to work:
\documentclass[a4paper]{article}
\usepackage{expl3}
\usepackage{xparse}
\ExplSyntaxOn
\begin{document}
\NewDocumentEnvironment{myenva}{} {
\NewDocumentEnvironment{myenvx}{} {
\NewDocumentEnvironment{myenvz}{} {
\NewDocumentCommand{mycmdz} {
\mycmda{}
\mycmdx{}
\typeout{mycmdz}
}
}{}
\NewDocumentCommand{mycmdx} {
\typeout{mycmdx}
}
}{}
\NewDocumentCommand{mycmda} {
\typeout{mycmda}
}
}{}
\NewDocumentEnvironment{myenvb}{} {
\NewDocumentEnvironment{myenvx}{} {
\NewDocumentEnvironment{myenvz}{} {
\NewDocumentCommand{mycmdz} {
\mycmdb{}
\mycmdx{}
\typeout{mycmdz}
}
}{}
\NewDocumentCommand{mycmdx} {
\typeout{mycmdx}
}
}{}
\NewDocumentCommand{mycmdb} {
\typeout{mycmdb}
}
}{}
\begin{myenva}
\begin{myenvx}
\begin{myenvz}
\mycmdz{}
\end{myenvz}
\end{myenvx}
\end{myenva}
\begin{myenvb}
\begin{myenvx}
\begin{myenvz}
\mycmdz{}
\end{myenvz}
\end{myenvx}
\end{myenvb}
\end{document}
But I get this error when trying to compile:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! LaTeX error: "xparse/command-already-defined"
!
! Command 'mycmda' already defined!
!
! See the LaTeX3 documentation for further information.
!
! For immediate help type H <return>.
!...............................................
l.51 \begin
{myenvx}
I am not sure how exactly to define nested environments. It used to work in LaTeX2 with \newenvironment
, but it doesn't seem to be working with LaTeX3. Not sure what might be going wrong, seems like there could be several things. The goal is to be able to define nested environments and commands where the name is the same in subcommands in different environments.
(I would like for the environments to be scoped like this, so they can be handled differently.)
I don't think I should be using \DeclareDocumentCommand
anywhere. Maybe this is where I should be using the new LaTeX3 functions, but not sure. I am able to get a little further by using \cs_new:Npn
, as in this MWE:
\documentclass[a4paper]{article}
\usepackage{expl3}
\usepackage{xparse}
\ExplSyntaxOn
\begin{document}
\NewDocumentEnvironment{myenva}{} {
\NewDocumentEnvironment{myenvx}{} {
\NewDocumentEnvironment{myenvz}{} {
\cs_new:Npn \mycmdz {
\mycmda{}
\mycmdx{}
\typeout{mycmdz}
}
}{}
\cs_new:Npn \mycmdx {
\typeout{mycmdx}
}
}{}
\cs_new:Npn \mycmda {
\typeout{mycmda}
}
}{}
\NewDocumentEnvironment{myenvb}{} {
\NewDocumentEnvironment{myenvx}{} {
\NewDocumentEnvironment{myenvz}{} {
\cs_new:Npn \mycmdz {
\mycmda{}
\mycmdx{}
\typeout{mycmdz}
}
}{}
\cs_new:Npn \mycmdx {
\typeout{mycmdx}
}
}{}
\cs_new:Npn \mycmdb {
\typeout{mycmdb}
}
}{}
\begin{myenva}
\begin{myenvx}
\begin{myenvz}
\mycmdz{}
\end{myenvz}
\end{myenvx}
\end{myenva}
\begin{myenvb}
\begin{myenvx}
\begin{myenvz}
\mycmdz{}
\end{myenvz}
\end{myenvx}
\end{myenvb}
\end{document}
But it still errors with:
mycmda
mycmdx
mycmdz
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! LaTeX error: "kernel/command-already-defined"
!
! Control sequence \mycmdx already defined.
!
! See the LaTeX3 documentation for further information.
!
! For immediate help type H <return>.
!...............................................
I am able to accomplish the desired behavior when using LaTeX2 functionality, demonstrated in the following MWE:
\documentclass[a4paper]{article}
\usepackage{expl3}
\usepackage{xparse}
\begin{document}
\newenvironment{myenva} {
\newenvironment{myenvx} {
\newenvironment{myenvz} {
\newcommand{\mycmdz} {
\mycmda{}
\mycmdx{}
\typeout{mycmdz}
}
}{}
\newcommand{\mycmdx} {
\typeout{mycmdx}
}
}{}
\newcommand{\mycmda} {
\typeout{mycmda}
}
}{}
\newenvironment{myenvb} {
\newenvironment{myenvx} {
\newenvironment{myenvz} {
\newcommand{\mycmdz} {
\mycmdb{}
\mycmdx{}
\typeout{mycmdz}
}
}{}
\newcommand{\mycmdx} {
\typeout{mycmdx}
}
}{}
\newcommand{\mycmdb} {
\typeout{mycmdb}
}
}{}
\begin{myenva}
\begin{myenvx}
\begin{myenvz}
\mycmdz{}
\end{myenvz}
\end{myenvx}
\end{myenva}
\begin{myenvb}
\begin{myenvx}
\begin{myenvz}
\mycmdz{}
\end{myenvz}
\end{myenvx}
\end{myenvb}
\end{document}
However, I would like to take advantage of the following features while accomplishing the nested environments/commands:
- Use LaTeX3 features.
- Have dynamic/overloaded argument parsing thanks to
xparse
.
Update
I tried some more permutations to make sure it covered the cases I was looking for and it all seems to work, yay!
\documentclass[a4paper]{article}
\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{expl3}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentEnvironment{myenvx}{}{}{}
\NewDocumentEnvironment{myenvz}{}{}{}
\NewDocumentCommand{\mycmdz}{}{}
\NewDocumentEnvironment{myenva}{}{%
\NewDocumentCommand{\mycmda}{mm}{%
\typeout{mycmda}
\typeout{##1}
\typeout{##2}
}%
\RenewDocumentEnvironment{myenvx}{}{%
\NewDocumentCommand{\mycmdx}{mm}{%
\typeout{mycmdx}
\typeout{####1}
\typeout{####2}
}%
\RenewDocumentEnvironment{myenvz}{}{%
\RenewDocumentCommand{\mycmdz}{mm}{%
\mycmda{mycmda:a}{mycmda:b}
\mycmdx{mycmda:mycmdx:a}{mycmda:mycmdx:b}
\typeout{mycmdz}
\typeout{########1}
\typeout{########2}
}%
}{}%
%
}{}%
%
}{}
\NewDocumentEnvironment{myenvb}{} {%
\NewDocumentCommand{\mycmdb}{}{%
\typeout{mycmdb}
}%
\RenewDocumentEnvironment{myenvx}{} {%
\NewDocumentCommand{\mycmdx}{mmm}{%
\typeout{mycmdx}
\typeout{####1}
\typeout{####2}
\typeout{####3}
}%
\RenewDocumentEnvironment{myenvz}{} {%
\RenewDocumentCommand{\mycmdz}{mmm}{%
\mycmdb{}
\mycmdx{mycmdb:mycmdx:a}{mycmdb:mycmdx:b}{mycmdb:mycmdx:c}
\typeout{mycmdz}
\typeout{########1}
\typeout{########2}
\typeout{########3}
}%
}{}%
%
}{}%
%
}{}
\begin{document}
\begin{myenva}
\begin{myenvx}
\begin{myenvz}
\mycmdz{mycmda:mycmdx:mycmdz:a}{mycmda:mycmdx:mycmdz:b}
\end{myenvz}
\end{myenvx}
\end{myenva}
\begin{myenvb}
\begin{myenvx}
\begin{myenvz}
\mycmdz{mycmdb:mycmdx:mycmdz:a}{mycmdb:mycmdx:mycmdz:b}{mycmdb:mycmdx:mycmdz:c}
\end{myenvz}
\end{myenvx}
\end{myenvb}
\begin{myenva}
\begin{myenvx}
\begin{myenvz}
\mycmdz{mycmda:mycmdx:mycmdz:a}{mycmda:mycmdx:mycmdz:b}
\end{myenvz}
\end{myenvx}
\end{myenva}
\end{document}
Outputs:
mycmda
mycmda:a
mycmda:b
mycmdx
mycmda:mycmdx:a
mycmda:mycmdx:b
mycmdz
mycmda:mycmdx:mycmdz:a
mycmda:mycmdx:mycmdz:b
mycmdb
mycmdx
mycmdb:mycmdx:a
mycmdb:mycmdx:b
mycmdb:mycmdx:c
mycmdz
mycmdb:mycmdx:mycmdz:a
mycmdb:mycmdx:mycmdz:b
mycmdb:mycmdx:mycmdz:c
mycmda
mycmda:a
mycmda:b
mycmdx
mycmda:mycmdx:a
mycmda:mycmdx:b
mycmdz
mycmda:mycmdx:mycmdz:a
mycmda:mycmdx:mycmdz:b
Update 2
It seems to work without RenewDocumentCommand
and RenewDocumentEnvironment
.
\documentclass[a4paper]{article}
\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{expl3}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentEnvironment{myenva}{}{
\NewDocumentCommand{\mycmda}{mm}{
\typeout{mycmda}
\typeout{##1}
\typeout{##2}
}
\NewDocumentEnvironment{myenvx}{}{
\NewDocumentCommand{\mycmdx}{mm}{
\typeout{mycmdx}
\typeout{####1}
\typeout{####2}
}
\NewDocumentEnvironment{myenvz}{}{
\NewDocumentCommand{\mycmdz}{mm}{
\mycmda{mycmda:a}{mycmda:b}
\mycmdx{mycmda:mycmdx:a}{mycmda:mycmdx:b}
\typeout{mycmdz}
\typeout{########1}
\typeout{########2}
}
}{}
}{}
}{}
\NewDocumentEnvironment{myenvb}{} {
\NewDocumentCommand{\mycmdb}{}{
\typeout{mycmdb}
}
\NewDocumentEnvironment{myenvx}{} {
\NewDocumentCommand{\mycmdx}{mmm}{
\typeout{mycmdx}
\typeout{####1}
\typeout{####2}
\typeout{####3}
}
\NewDocumentEnvironment{myenvz}{} {
\NewDocumentCommand{\mycmdz}{mmm}{
\mycmdb{}
\mycmdx{mycmdb:mycmdx:a}{mycmdb:mycmdx:b}{mycmdb:mycmdx:c}
\typeout{mycmdz}
\typeout{########1}
\typeout{########2}
\typeout{########3}
}
}{}
}{}
}{}
\begin{document}
\begin{myenva}
\begin{myenvx}
\begin{myenvz}
\mycmdz{mycmda:mycmdx:mycmdz:a}{mycmda:mycmdx:mycmdz:b}
\end{myenvz}
\end{myenvx}
\end{myenva}
\begin{myenvb}
\begin{myenvx}
\begin{myenvz}
\mycmdz{mycmdb:mycmdx:mycmdz:a}{mycmdb:mycmdx:mycmdz:b}{mycmdb:mycmdx:mycmdz:c}
\end{myenvz}
\end{myenvx}
\end{myenvb}
\begin{myenva}
\begin{myenvx}
\begin{myenvz}
\mycmdz{mycmda:mycmdx:mycmdz:a}{mycmda:mycmdx:mycmdz:b}
\end{myenvz}
\end{myenvx}
\end{myenva}
\end{document}
\RenewDocumentCommand
and\RenewDocumentEnvironment
within your environments to redefine them with the desired definitions.tabbing
(the one place there is some 'leakage' in the kernel) ...