There doesn’t seem to be a way of defining procedures in algorithms
but you can use an algorithm
environment with an appropriate \caption
that names your algorithm.
Personally, though, I would switch to the superior algorithmicx
package that defines a \Procedure
macro:
\begin{algorithm}
\Procedure{recurse}{$x$}
\If{$x=1$}
\State\Return{$1$}
\Else
\State\Return{\Call{recurse}{$x-1$}}
\EndIf
\EndProcedure
\end{algorithm}
Here are some more natural (automatic and better-behaved) implementations of the vertical lines, where I have used Werner's answer to the linked question as a starting point.
Version 1: Draw a fixed-height rule for each line and each indent level
This version does not work well if the line height and depths differ; see below for attempted update to solve this.
This works for the noend
case too, but there is a fudge factor of \addvspace{-3pt}
in the printing code to prevent unwanted gaps in lines that don't get printed. This is not very robust but I can't do any better currently as I haven't identified the space (seems to come from \item[]
).
\documentclass{article}
\usepackage{algorithm}% http://ctan.org/pkg/algorithm
\PassOptionsToPackage{noend}{algpseudocode}% comment out if want end's to show
\usepackage{algpseudocode}% http://ctan.org/pkg/algorithmicx
\errorcontextlines\maxdimen
% begin vertical rule patch for algorithmicx (http://tex.stackexchange.com/questions/144840/vertical-loop-block-lines-in-algorithmicx-with-noend-option)
\makeatletter
% start with some helper code
% This is the vertical rule that is inserted
\newcommand*{\algrule}[1][\algorithmicindent]{\makebox[#1][l]{\hspace*{.5em}\vrule height .75\baselineskip depth .25\baselineskip}}%
\newcount\ALG@printindent@tempcnta
\def\ALG@printindent{%
\ifnum \theALG@nested>0% is there anything to print
\ifx\ALG@text\ALG@x@notext% is this an end group without any text?
% do nothing
\addvspace{-3pt}% FUDGE for cases where no text is shown, to make the rules line up
\else
\unskip
% draw a rule for each indent level
\ALG@printindent@tempcnta=1
\loop
\algrule[\csname ALG@ind@\the\ALG@printindent@tempcnta\endcsname]%
\advance \ALG@printindent@tempcnta 1
\ifnum \ALG@printindent@tempcnta<\numexpr\theALG@nested+1\relax% can't do <=, so add one to RHS and use < instead
\repeat
\fi
\fi
}%
\usepackage{etoolbox}
% the following line injects our new indent handling code in place of the default spacing
\patchcmd{\ALG@doentity}{\noindent\hskip\ALG@tlm}{\ALG@printindent}{}{\errmessage{failed to patch}}
\makeatother
% end vertical rule patch for algorithmicx
\begin{document}
\begin{algorithm}
\caption{Euclid’s algorithm}\label{euclid}
\begin{algorithmic}[1]
\Procedure{Euclid}{$a,b$}\Comment{The g.c.d.\ of a and b}
\State $r\gets a\bmod b$
\While{$r\not=0$}\Comment{We have the answer if r is 0}
\State $a\gets b$
\State $b\gets r$
\State $r\gets a\bmod b$
\EndWhile\label{euclidendwhile}
\State \Return $b$\Comment{The gcd is b}
\EndProcedure
\end{algorithmic}
\end{algorithm}
\end{document}
Version 2: process boxes twice in attempt to measure heights
The following is a version that attempts to take better care of the line heights, by passing states to \myState
wrapped in braces instead of \State
directly, which measures the line heights before reprocessing the content. As it has a different interface, and may be even less robust (I am not yet sure), I am leaving the original answer above rather than replacing it.
\documentclass{article}
\usepackage{algorithm}% http://ctan.org/pkg/algorithm
%\PassOptionsToPackage{noend}{algpseudocode}% comment out if want end's to show
\usepackage{algpseudocode}% http://ctan.org/pkg/algorithmicx
\errorcontextlines\maxdimen
% begin vertical rule patch for algorithmicx (http://tex.stackexchange.com/questions/144840/vertical-loop-block-lines-in-algorithmicx-with-noend-option)
\makeatletter
% start with some helper code
% This is the vertical rule that is inserted
\newcommand*{\algrule}[1][\algorithmicindent]{\makebox[#1][l]{\hspace*{.5em}\thealgruleextra\vrule height \thealgruleheight depth \thealgruledepth}}%
% its height and depth need to be adjustable
\newcommand*{\thealgruleextra}{}
\newcommand*{\thealgruleheight}{.75\baselineskip}
\newcommand*{\thealgruledepth}{.25\baselineskip}
\newcount\ALG@printindent@tempcnta
\def\ALG@printindent{%
\ifnum \theALG@nested>0% is there anything to print
\ifx\ALG@text\ALG@x@notext% is this an end group without any text?
% do nothing
\else
\unskip
\addvspace{-1pt}% FUDGE to make the rules line up
% draw a rule for each indent level
\ALG@printindent@tempcnta=1
\loop
\algrule[\csname ALG@ind@\the\ALG@printindent@tempcnta\endcsname]%
\advance \ALG@printindent@tempcnta 1
\ifnum \ALG@printindent@tempcnta<\numexpr\theALG@nested+1\relax% can't do <=, so add one to RHS and use < instead
\repeat
\fi
\fi
}%
\usepackage{etoolbox}
% the following line injects our new indent handling code in place of the default spacing
\patchcmd{\ALG@doentity}{\noindent\hskip\ALG@tlm}{\ALG@printindent}{}{\errmessage{failed to patch}}
\makeatother
% the required height and depth are set by measuring the content to be shown
% this means that the content is processed twice
\newbox\statebox
\newcommand{\myState}[1]{%
\setbox\statebox=\vbox{#1}%
\edef\thealgruleheight{\dimexpr \the\ht\statebox+1pt\relax}%
\edef\thealgruledepth{\dimexpr \the\dp\statebox+1pt\relax}%
\ifdim\thealgruleheight<.75\baselineskip
\def\thealgruleheight{\dimexpr .75\baselineskip+1pt\relax}%
\fi
\ifdim\thealgruledepth<.25\baselineskip
\def\thealgruledepth{\dimexpr .25\baselineskip+1pt\relax}%
\fi
%\showboxdepth=100
%\showboxbreadth=100
%\showbox\statebox
\State #1%
%\State \usebox\statebox
%\State \unvbox\statebox
%reset in case the next command is not wrapped in \myState
\def\thealgruleheight{\dimexpr .75\baselineskip+1pt\relax}%
\def\thealgruledepth{\dimexpr .25\baselineskip+1pt\relax}%
}
% end vertical rule patch for algorithmicx
\begin{document}
\begin{algorithm}
\caption{Euclid’s algorithm}\label{euclid}
\begin{algorithmic}[1]
\Procedure{Euclid}{$a,b$}\Comment{The g.c.d.\ of a and b}
\myState{$r\gets a\bmod b$}
\While{$r\not=0$}\Comment{We have the answer if r is 0}
\myState{$a\gets\displaystyle\sum_{i=1}^n x_i$}\Comment{Nonsense to show that tall lines might work}
\myState{$a\gets b$}
\myState{$b\gets r$}
\myState{$r\gets a\bmod b$}
\EndWhile\label{euclidendwhile}
\myState{\Return $b$\Comment{The gcd is b}}
\EndProcedure
\end{algorithmic}
\end{algorithm}
\end{document}
Version 3: use tikzmark at start and end of each block
@desa pointed out that version 2 doesn't work when there are displayed equations in the algorithm. Here is a new implementation that attempts to fix that (I couldn't see how to correct the height guessing algorithm for this case).
This code uses tikz's remember picture
feature so requires multiple runs to stabilise (the lines will not appear in the correct place in the first run, or in the first run following other changes on the page). Again, this may be disadvantageous in some cases (or for other reasons not yet identified), so I am also leaving the previous two approaches above.
\documentclass{article}
\usepackage{algorithm}% http://ctan.org/pkg/algorithm
%\PassOptionsToPackage{noend}{algpseudocode}% comment/uncomment depending on whether want ends to show
\usepackage{algpseudocode}% http://ctan.org/pkg/algorithmicx
\usepackage{etoolbox}
\usepackage{tikz}
\usetikzlibrary{tikzmark}
\usetikzlibrary{calc}
\errorcontextlines\maxdimen
% begin vertical rule patch for algorithmicx (http://tex.stackexchange.com/questions/144840/vertical-loop-block-lines-in-algorithmicx-with-noend-option)
% note that some of the packages above are also needed
\newcommand{\ALGtikzmarkcolor}{black}% customise this, if you want
\newcommand{\ALGtikzmarkextraindent}{4pt}% customise this, if you want
\newcommand{\ALGtikzmarkverticaloffsetstart}{-.5ex}% customise this, if you want
\newcommand{\ALGtikzmarkverticaloffsetend}{-.5ex}% customise this, if you want
\makeatletter
\newcounter{ALG@tikzmark@tempcnta}
\newcommand\ALG@tikzmark@start{%
\global\let\ALG@tikzmark@last\ALG@tikzmark@starttext%
\expandafter\edef\csname ALG@tikzmark@\theALG@nested\endcsname{\theALG@tikzmark@tempcnta}%
\tikzmark{ALG@tikzmark@start@\csname ALG@tikzmark@\theALG@nested\endcsname}%
\addtocounter{ALG@tikzmark@tempcnta}{1}%
}
\def\ALG@tikzmark@starttext{start}
\newcommand\ALG@tikzmark@end{%
\ifx\ALG@tikzmark@last\ALG@tikzmark@starttext
% ignore this, the block was opened then closed directly without any other blocks in between (so just a \State basically)
% don't draw a vertical line here
\else
\tikzmark{ALG@tikzmark@end@\csname ALG@tikzmark@\theALG@nested\endcsname}%
\tikz[overlay,remember picture] \draw[\ALGtikzmarkcolor] let \p{S}=($(pic cs:ALG@tikzmark@start@\csname ALG@tikzmark@\theALG@nested\endcsname)+(\ALGtikzmarkextraindent,\ALGtikzmarkverticaloffsetstart)$), \p{E}=($(pic cs:ALG@tikzmark@end@\csname ALG@tikzmark@\theALG@nested\endcsname)+(\ALGtikzmarkextraindent,\ALGtikzmarkverticaloffsetend)$) in (\x{S},\y{S})--(\x{S},\y{E});%
\fi
\gdef\ALG@tikzmark@last{end}%
}
% the following line injects our new tikzmarking code
\apptocmd{\ALG@beginblock}{\ALG@tikzmark@start}{}{\errmessage{failed to patch}}
\pretocmd{\ALG@endblock}{\ALG@tikzmark@end}{}{\errmessage{failed to patch}}
\makeatother
% end vertical rule patch for algorithmicx
\begin{document}
\begin{algorithm}
\caption{Euclid's algorithm}\label{euclid}
\begin{algorithmic}[1]%
\Procedure{Euclid}{$a,b$}\Comment{The g.c.d.\ of a and b}%
\State $r\gets a\bmod b$%
\While{$r\not=0$}\Comment{We have the answer if r is 0}%
\State $a\gets\displaystyle\sum_{i=1}^n x_i$\Comment{Nonsense to show that tall lines might work}%
\State $a\gets b$%
\State $b\gets r$%
\State \begin{equation} y = mx + c \end{equation}%
\State $r\gets a\bmod b$%
\EndWhile\label{euclidendwhile}%
\State \Return $b$\Comment{The gcd is b}%
\EndProcedure%
\end{algorithmic}
\end{algorithm}
\end{document}
Best Answer
Use
and
This way you're passing these macros a non-empty, non-printing argument. Here is a mock example taken from the
algorithmicx
documentation: