How to wrap LaTex command in new environment - latex

This question has already been answered once (wrap LaTeX command in environment), yet I still struggle to make my own rather simple new environment command work.
What I wanted to do is to convert the following LaTex block, which shows the output of some code, into a command I can reuse.
\fbox{\begin{minipage}{\textwidth}
\texttt{
>> CODE OUTPUT
\end{minipage}}
It is clear that in order to make a new environment command that replicates what I do above, I will have to make use of wrappers. (Because of the \fbox and the \texttt command.)
I would like to do this without having to download yet another package, or going into the secret realms of LaTex with some predefined \dir command that is only there to do the same job twice.
Checking the link from before, it seems that a productive solution is to use \bgroup and \egroup. I would therefore write something like this:
\newenvironment{CodeOutput}
{\fbox\bgroup\begin{minipage}{\textwidth}\texttt\bgroup}
{\egroup\end{minipage}\egroup}
Yet this will still not work. (On Overleaf at least.) It would be great if there was a straightforward way of making commands like these. Thanks for any useful suggestions!

If want to write a command that does what you're after, then the following would work:
\newcommand{\mycmd}[1]{%
\fbox{%
\begin{minipage}{\dimexpr\linewidth-2\fboxrule-2\fboxsep}
\ttfamily #1
\end{minipage}%
}%
}
The idea here works because the <arg>ument supplied to \mycmd{<arg>} is replaced by #1 in its entirety. If you want want to rewrite this as an environment, it's a little more difficult, purely because of \fbox. \fbox is doesn't have an environment-form equivalent the same way \texttt has \ttfamily (which is technically a font switch). There is a quick way around it provided by environ - it allows you to capture the contents of an environment in a macro \BODY:
\usepackage{environ}
\NewEnviron{myenvA}{%
\fbox{%
\begin{minipage}{\dimexpr\linewidth-2\fboxrule-2\fboxsep}
\ttfamily \BODY
\end{minipage}%
}%
}
However, you do have the option by capturing the content of an environment inside a box and then setting the box inside an \fbox:
\newsavebox{\codebox}% To store the content of myenvB
\newenvironment{myenvB}{%
\begin{lrbox}{\codebox}%
\ttfamily\ignorespaces
}{%
\end{lrbox}%
\fbox{\begin{minipage}{\dimexpr\linewidth-2\fboxrule-2\fboxsep}
\usebox{\codebox}%
\end{minipage}}%
}
The following minimal example shows all the above cases:
\documentclass{article}
\usepackage{environ}
\newcommand{\mycmd}[1]{%
\fbox{%
\begin{minipage}{\dimexpr\linewidth-2\fboxrule-2\fboxsep}
\ttfamily #1
\end{minipage}%
}%
}
\NewEnviron{myenvA}{%
\fbox{%
\begin{minipage}{\dimexpr\linewidth-2\fboxrule-2\fboxsep}
\ttfamily \BODY
\end{minipage}%
}%
}
\newsavebox{\codebox}
\newenvironment{myenvB}{%
\begin{lrbox}{\codebox}%
\ttfamily\ignorespaces
}{%
\end{lrbox}%
\fbox{\begin{minipage}{\dimexpr\linewidth-2\fboxrule-2\fboxsep}
\usebox{\codebox}%
\end{minipage}}%
}
\begin{document}
\noindent
\fbox{\begin{minipage}{\dimexpr\linewidth-2\fboxrule-2\fboxsep}
\ttfamily SoMe CoDe HeRe
\end{minipage}}
\bigskip
\noindent
\mycmd{SoMe CoDe HeRe}
\bigskip
\noindent
\begin{myenvA}
SoMe CoDe HeRe
\end{myenvA}
\bigskip
\begin{lrbox}{\codebox}
\ttfamily SoMe CoDe HeRe
\end{lrbox}
\noindent
\fbox{\begin{minipage}{\dimexpr\linewidth-2\fboxrule-2\fboxsep}
\usebox{\codebox}
\end{minipage}}
\bigskip
\noindent
\begin{myenvB}
SoMe CoDe HeRe
\end{myenvB}
\end{document}

Related

LaTeX - control textwidth within the music environment

I am typesetting an A5 document, which includes a music environment as provided by musixtex.
I would like to reduce the linewidth/textwidth of just the music.
Here are a few things, that I have tried:
Put the music inside a minipage. This works fine for short excerpts but for longer music there might be the necessity of a page break, which a minipage doesn't have.
Use the \newgeometry command and subsequently \restoregeometry. That works, but apparently inserts a \newpage, which I also would like to avoid.
Use the changepage package which provides the command \adjustwidth. This works on the left side of the page, but the music then doesn't produce the linebreak at the desired position, but shifted to the right. I provide a MWE of this below.
Use a list-like environment like trivlist or itemize. This works on the left side of the page, but the music then doesn't produce the linebreak at the desired position, but shifted to the right, basically the same as above.
\documentclass{article}
\author{Myself}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{geometry}
\geometry{a5paper}
\geometry{twoside}
\geometry{inner=1.375cm}
\geometry{outer=1.375cm}
\geometry{top=1.5cm}
\geometry{bottom=1.5cm}
\usepackage{changepage}
\usepackage{musixtex}
\usepackage{lipsum}
\begin{document}
\lipsum[1]
\begin{adjustwidth}{0.5cm}{0.5cm}
\begin{music}
\instrumentnumber{1}
\setstaffs1{1}
\generalmeter{\meterfrac{9}{4}}
\generalsignature{-1}
\nostartrule
\normalmusicsize
\nobarnumbers
\startpiece
\NOtes\qu{ff}\ql{j}\en\bar
\NOtes\qup{h}\cu{g}\qu{fedc}\en
\NOtes\qu{def}\en\bar
\NOtes\hup{gf}\en\rightrepeat
\NOtes\ql{jjj}\en\bar
\NOtes\hlp{k}\qu{h}\ql{ij}\en
\NOtes\qlp{j}\cl{i}\qu{h}\en\bar
\NOtes\hup{g}\qu{cdefgh}\en\bar
\NOtes\hup{gf}\en
\Endpiece
\end{music}
\end{adjustwidth}
\lipsum[2]
\end{document}
To me, both 3) and 4) seem to not work because musixtex doesn't understand/know the new settings for the linewidth etc.
More info: I am aware of the way that musixtex code has to be compiled, I am using a makefile that invokes pdflatex, musixflx and pdflatex again. This is not the cause of the problem.
Any help would be appreciated
You could use tcolorbox to create a breakable box:
\documentclass{article}
\author{Myself}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{geometry}
\geometry{a5paper}
\geometry{twoside}
\geometry{inner=1.375cm}
\geometry{outer=1.375cm}
\geometry{top=1.5cm}
\geometry{bottom=1.5cm}
\usepackage{changepage}
\usepackage{musixtex}
\usepackage{lipsum}
\usepackage[most]{tcolorbox}
\tcolorboxenvironment{music}{breakable,text width=\dimexpr\textwidth-2cm,enhanced,grow to left by=-1cm,colframe=white,colback=white}
\begin{document}
\lipsum[1]
\begin{music}
\instrumentnumber{1}
\setstaffs1{1}
\generalmeter{\meterfrac{9}{4}}
\generalsignature{-1}
\nostartrule
\normalmusicsize
\nobarnumbers
\startpiece
\NOtes\qu{ff}\ql{j}\en\bar
\NOtes\qup{h}\cu{g}\qu{fedc}\en
\NOtes\qu{def}\en\bar
\NOtes\hup{gf}\en\rightrepeat
\NOtes\ql{jjj}\en\bar
\NOtes\hlp{k}\qu{h}\ql{ij}\en
\NOtes\qlp{j}\cl{i}\qu{h}\en\bar
\NOtes\hup{g}\qu{cdefgh}\en\bar
\NOtes\hup{gf}\en
\Endpiece
\end{music}
\lipsum[2]
\end{document}

[Beamer/Latex]: Getting \part name from different part

Hi I would like to create some sort of my own table of content in beamer presentation where there will be all parts with all sections listed.
To this moment I came up with this solution to list all \tableofcontents in one slide
\begin{frame}
\begin{multicols}{2}
\setcounter{tocdepth}{1}
\foreach\x in {1,...,\totvalue{part}}{%
\vskip 0.4cm
\tableofcontents[part=\x]%
}%
\setcounter{tocdepth}{2}
\end{multicols}
\end{frame}
Problem here is that I get section of each part but there is not partname listed.
Is there way how to access name of part by index \x of for-cycle? Something like \insertpart[\x]?
Ok with help of one co-student of mine I came up with solution to my problem.
\makeatletter
\AtBeginPart{
\write\#auxout{%
\noexpand\expandafter\noexpand\gdef\noexpand\csname
part\thepart name\noexpand\endcsname{\beamer#partname}}
}
\makeatother
\begin{document}
\frame{\maketitle}
\section*{Outline}
\begin{frame}{Outline of Presentation}
\begin{multicols}{2}
\setcounter{tocdepth}{1}
\foreach\x in {1,...,\totvalue{part}}{%
\medskip\expandafter\let\expandafter\partname
\csname part\x name\endcsname
\penalty-999
\textit{\partname}
\medskip
{\let\vfill=\relax\tableofcontents[part=\x]}\vfill
\penalty-999
}%
\setcounter{tocdepth}{2}
\end{multicols}
\end{frame}
Unfortunately I cannot write down deep description of how exactly it works but basically it takes names of parts during first run of pdflatex and saves them into .aux file. Then during second run of pdflatex it will correctly print them out. Then negative penalty is added to each block so partname is not splitted out of rest of part-toc.
So two runs of pdflatex are needed to work it correctly but it should work quite nicely. I managed to create table of content with 4 parts.
example
Hopefully it will help someone.

Environment inside a longtable with LaTeX

I would like to create a new environment to print a header and a footer between sections of a table.
I did this:
\documentclass{article}
\usepackage{longtable}
\newenvironment{env}{Heading&&& \\}{\hline \\}
\begin{document}
\begin{longtable}{p{7cm}lrr}
\begin{env}
Content&b&c&d
\end{env}
\end{longtable}
\end{document}
but I get insulted by the compiler. See here for the complete output.
Does someone see the problem?
There are two problems here. First, you need an \\ at the end of the "Content&b&c&d" line. Second, environments don't work inside tabular/longtable — that's where most of your error messages are coming from. It may be possible to diddle them into working, but it's way beyond my TeX-fu. This is the best I can come up with:
\documentclass{article}
\usepackage{longtable}
\newcommand{\startenv}{Heading\tabularnewline}
\newcommand{\stopenv}{\hline\tabularnewline}
\begin{document}
\begin{longtable}{p{7cm}lrr}
\startenv
Content&b&c&d \\
\stopenv
\end{longtable}
(It is not strictly necessary to use \tabularnewline instead of \\, but it will avoid headaches if you ever mix this with other environments that use \\ for their own purposes.)

Suppress indentation after environment in LaTeX

I'm trying to create a new environment in my LaTeX document where indentation in the next paragraph following the environment is suppressed.
I have been told (TeXbook and LaTeX source) that by setting \everypar to {\setbox0\lastbox}, the TeX typesetter will execute this at the beginning of the next paragraph and thus remove the indentation:
\everypar{\setbox0\lastbox}
So this is what I do, but to no effect (following paragraph is still indented):
\newenvironment{example}
{\begin{list}
{}
{\setlength\leftmargin{2em}}}
{\end{list}\everypar{\setbox0\lastbox}}
I have studied LaTeX's internals as well as I could manage. It seems that the \end routine says \endgroup and \par at some point, which may be the reason LaTeX ignores my \everypar setting. \global doesn't help either. I know about \noindent but want to do this automatically.
Example document fragment:
This is paragraph text. This is paragraph text, too.
\begin{example}
\item This is the first item in the list.
\item This is the second item in the list.
\end{example}
This is more paragraph text. I don't want this indented, please.
Internal routines and switches of interest seem to be \#endpetrue, \#endparenv and others. Thanks for your help.
I couldn't get anything to work without redefining \end, but I'm certainly no expert.
The following is quite hacky, but worked in my limited testing. Of course this will interfere with nested environments (you should be able to redefine \begin to restore the old \end if you have problems).
\newenvironment{example}{%
\bgroup
\let\oldend=\end
\def\end##1{\oldend{##1}\csname #afterindentfalse\endcsname
\csname #afterheading\endcsname}
\begin{list}{}
{\setlength\leftmargin{2em}}
}{%
\end{list}
\egroup
}
Can't you avoid this by not having a blank line between your environment and the next line?
This is paragraph text. This is paragraph text, too.
\begin{example}
\item This is the first item in the list.
\item This is the second item in the list.
\end{example}
% (No blank line)
This is more paragraph text. I don't want this indented, please.
Something as simple as this works for me:
\makeatletter
\newenvironment{example}{%
\bgroup
\list{}{}
}{%
\endlist
\#afterindentfalse
\#afterheading
\egroup
}
\makeatother
But, it doesn't work before the first \section (or \chapter, in the case of classes "book" and "report") is called. I don't know why.
I tried the Ivan's answer, but it wasn't working for me. But I did get it working! Here's what I did:
\makeatletter
\renewenvironment{quotation}{%
\bgroup%
\let\oldend=\end%
\def\end##1{\oldend{##1}\csname #afterindentfalse\endcsname%
\csname #afterheading\endcsname}%
\list{}{\listparindent 1.5em%
\itemindent \listparindent%
\leftmargin 1.5em% This controls the size of the indentation
\rightmargin \leftmargin
\parsep \z# \#plus\p#}% This line reduces inter-paragraph space to normal values.
\item\relax%
}{%
\endlist%%
\egroup%
}
\makeatother
The advantage to this is that it typesets your blockquotes very nicely, and removes the indentation from paragraph after the blockquote.
You can do this without redefining \end
\makeatletter
\newenvironment{example}
{\begin{list}
{}
{\setlength\leftmargin{2em}}}
{\end{list}%
\def\if#endpe{%
\#doendpe
\let\par\##par
\iffalse}}
\makeatother
Explanation
\end changes \everypar after expanding \endexample. To make things even more complicated it sets \par to restore \everypar{}. Appearently \#doendpe is ment to make sure that there is no indentation if the paragraph continues after the environment, but to restore normal behavior if there is a \par (or empty line) after the environment.
You may want to avoid changing \end because it would have to be changed at the begining of the environment and may therefore disturb nested environments. Luckily the definition of \end contains \expandafter\endgroup\if#endpe. We can use \if#endpe as a hook to inject our code to the outer scope. After the \endgroup \if#endpe is automatically restored.
Include \#afterindentfalse\#afterheading at the end of your definition.
I had the same problem. I just used this:
\noindent \newenvironment
You should not mess with the \everypar token list, unless you know exactly what you are doing. Use
\setlength{\parindent}{0pt}
to get rid of indenting in the whole document.
ending your environment with \noindent could help you

How to create own and fancy \sub<float> command

I'm using packages subfigure and float to create figures and tables that I want to create and I'm trying to create my own environment graph with its own counter and caption (solved there, thanks to dmckee). Now I'd like to create \subgraph command which will do exactly the same as \subfigure command.
I tried create my own command with propreate counter (Assisted here, thanks to Alexey). But problem appears with using \ref command. Reference to \subfigure returns 2.1(a) but reference to \subgraph returns 1.
As I tried to find out how to solve this I read subfig manual, where I've found \newsubfloat command with an example. First error was in use of subfig's commands in subfigure and I got stuck there. If I use subfigure I can access \subfigure but can't force \subgraph working, when I use subfig I can acces \subfloat in graph but not in figure and \ref returns 1.0a instead of 1.1 (a).
definition by subfig package:
\newfloat{graph2}{tbph}{lom}[chapter]
\restylefloat*{graph2}
\floatstyle{plain}
\floatname{grap2}{Graph2}
\captionsetup[graph2]{position=top}
\newcommand{\listofGraphs}{\listof{Graph2}{List of Graphs}}
\newsubfloat[position=bottom,listofformat=subsimple]{graph2}
definition my own \subgraph
\newfloat{graph1}{H}{lop}[chapter]
\floatname{graph1}{Graph1}
\newcounter{GraphOne}[graph1]
\def\theGraphOne{\alph{GraphOne}}
\newcommand{\subgraph}[2][]{
\captionof{subGraph}{#1} #2
}
\newfloat{subGraph}{H}{lop}[graph1]
\floatname{subGraph}{}
Please help me with understanding how \label and \ref commands work (I think my solution collapses because \label is before \caption) and/or with forcing subfig package to work as I want.
Thank you for any idea and be merciful to my english.
Crowley
Improvement:
By using caption package I can create new counter (subGraph) and use it outside its environment. Only way how to have both counter (subgraph and graph) correcly referred is using \captionof{graph} before \subgraph.
So, my new question is: How to execute \captionof{graph} before subgraphs and typeset in below them? And how to force \ref to show 1.1-a instead of 1.1.1
Atachements:
Code for subfigure: (Returns <chapter>.<figure> (<subfigure>) correct.
\begin{figure}
\subfigure[sub-caption]{\includegraphics{fig1}\label{fig:1}}
\caption{main caption}
\end{figure}
\ref{fig:1}
Code for subfig: (Returns <chapter>.<graph2>-1<subfigure>) incorrect.
\begin{graph2}
\subfloat[sub-caption]{\includegraphics{fig1}\label{fig:2}}
\caption{main caption}
\end{graph2}
\ref{fig:2}
My code: (Returns <chapter>.<graph1>.<subgraph> but caption shows the same "adress")
\begin{graph1}
\captionof{graph1}{main caption}
\subgraph[sub-caption]{\includegraphics{fig1}\label{fig:3}}
\end{graph1}
\ref{fig:3}
I think your subfig solution should work (subfigure is deprecated anyway). The issue with the wrong references might have to do with you using \label incorrectly. You must have the \label command after the \caption, or as a part of it:
\begin{figure}
\caption{A Figure}
\label{fig}
\end{figure}
or
\begin{figure}
\caption{A Figure%
\label{fig}}
\end{figure}
Edit: the following "works for me". As I said, the \label is after the \caption:
\documentclass{report}
\usepackage{float}
\usepackage{subfig}
\newfloat{graph2}{tbph}{lom}[chapter]
\restylefloat*{graph2}
\floatstyle{plain}
\floatname{grap2}{Graph2}
\captionsetup[graph2]{position=top}
\newcommand{\listofGraphs}{\listof{Graph2}{List of Graphs}}
\newsubfloat[position=bottom,listofformat=subsimple]{graph2}
\begin{document}
\chapter{Test}
\section{Test s}
\begin{graph2}
\subfloat[sub-caption]{\fbox{Fig 1}}
\caption{main caption}
\label{fig:1}
\end{graph2}
\begin{graph2}
\subfloat[sub-caption]{\fbox{Fig 2}}
\caption{main caption}
\label{fig:2}
\end{graph2}
Graph~\ref{fig:1} is the first graph, and~\ref{fig:2} is the second.
\end{document}
This produces:
Graph 1.1 is the first graph, and 1.2 is the second.
I can't elaborate right now, but you want to use \refstepcounter instead of \addtocounter.

Resources