9

I would like to have something like this in LaTex:

indented text

Is there a function that does that? Otherwise I would like to have a command that I can pass an array of strings, separated by a comma/semicolon, which then generates the above output; e.g. \createindentedtext(string1, string2, string3).

Output:

string1
    string2
        string3

Is that even possible?

Using egreg's solution almost works. The code I used is

\documentclass{article}
\usepackage{xparse}

\setlength{\parindent}{0cm}
\setlength{\parskip}{8pt}

\ExplSyntaxOn
\NewDocumentCommand{\createindentedlist}{m}
{
    \group_begin:
    \skip_zero:N \parskip
    \skip_set:Nn \parindent { 1.5em }
    \par\medskip
    \cil_iterate:n { #1 }
    \medskip
    \group_end:
}
\cs_new_protected:Npn \cil_iterate:n #1
 {
  \int_set:Nn \cil_iteration_int { 0 } % 0 = first line gets indented; -1 = skip first line
  \clist_map_inline:nn { #1 }
   {
    \hspace*{\cil_iteration_int \parindent} \textsf{##1}
    \int_incr:N \cil_iteration_int
    \par\nobreak
   }
 }
\int_new:N \cil_iteration_int
\ExplSyntaxOff

\begin{document}
\section*{Section}
\createindentedlist{string1,string2,string3}
\end{document}

The indentation is a little off, no matter if I ignore the first string or not (0 or -1).

wrong indentation

Is it further possible to insert a symbol for all strings, except the first one? So it looks like this:

enter image description here

3
  • 1
    Please, try making that code into a compilable example (with your setting of parskip and parindent).
    – egreg
    Jun 10, 2012 at 21:47
  • The first paragraph of a section has a special treatment with respect to indentation. Do you really need the command at the start of a section?
    – egreg
    Jun 10, 2012 at 22:04
  • As a matter of fact, I ONLY need it at the start of a section. As mentioned I want to achieve a JavaDoc look&feel: docs.oracle.com/javase/7/docs/api/javax/swing/JPanel.html
    – cherrung
    Jun 11, 2012 at 5:47

3 Answers 3

9

Here's one way:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\createindentedlist}{m}
 {
  \par\medskip
  \cil_iterate:n { #1 }
  \medskip
 }
\cs_new_protected:Npn \cil_iterate:n #1
 {
  \int_set:Nn \cil_iteration_int { -1 }
  \clist_map_inline:nn { #1 }
   {
    \hspace*{\cil_iteration_int \parindent} \textsf{##1}
    \int_incr:N \cil_iteration_int
    \par\nobreak
   }
 }
\int_new:N \cil_iteration_int
\ExplSyntaxOff

\usepackage{lipsum}

\begin{document}

\lipsum[1]

\createindentedlist{string1,string2,string3}

\lipsum[2]

\end{document}

The first item will not be indented; change -1 to 0 if you prefer to indent it. I've added \textsf around the entry to be typeset to show were acting for setting the format.


enter image description here


In case you're using the parskip package (or set manually the \parskip and use a zero \parindent) change the first definition into

\NewDocumentCommand{\createindentedlist}{m}
 {
  \group_begin:
  \skip_zero:N \parskip
  \skip_set:Nn \parindent { 1.5em }
  \par\medskip
  \cil_iterate:n { #1 }
  \medskip
  \group_end:
 }

Using this command at the start of a section is different, because the first paragraph is treated somewhat specially: you can try

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\createindentedlist}{m}
 {
  \parbox{\textwidth}{
    \skip_zero:N \parskip
    \skip_set:Nn \parindent { 1.5em }
    \cil_iterate:n { #1 }
    \medskip
  }
 }
\cs_new_protected:Npn \cil_iterate:n #1
 {
  \int_set:Nn \cil_iteration_int { -1 }
  \clist_map_inline:nn { #1 }
   {
    \hspace*{\cil_iteration_int \parindent} \textsf{##1}
    \int_incr:N \cil_iteration_int
    \par\nobreak
   }
 }
\int_new:N \cil_iteration_int
\ExplSyntaxOff

\usepackage{lipsum}

\begin{document}

\section{Title}    
\createindentedlist{string1,string2,string3}

\lipsum[2]

\end{document}
11
  • Can you tell me what the dependencies are? It works fine as a standalone document, but when I copy it to my working project it just displays the three strings below each other without identation.
    – cherrung
    Jun 10, 2012 at 14:10
  • @cherrung You probably are setting the parindent to zero, which is something I can't recommend. I've added a workaround.
    – egreg
    Jun 10, 2012 at 14:20
  • Yes, you were right. Agh. I changed the indentation to zero, because I didn't like the way paragraphs looked. Is there a workaround?
    – cherrung
    Jun 10, 2012 at 14:22
  • @cherrung I've added the workaround. But, frankly, the indentation has been in use for five centuries (in movable type printing) and it's hard to believe that people did badly for such a long time. :)
    – egreg
    Jun 10, 2012 at 14:24
  • 1
    @cherrung That's controlled by the \medskip; you can try with \bigskip or with \vspace{...} where you can set any space you want.
    – egreg
    Jun 11, 2012 at 16:34
6

You can also use pgf's \foreach macro to iterate over the list and increase the horizontal indent at each iteration, and use tikz to add the lines.

To make it easier to control the formatting for each of the list members, I have defined three different commands for the first, middle, and last list members:

\newcommand*{\FormatFirstListMember}[1]{\textcolor{magenta}{\texttt{#1}}}%
\newcommand*{\FormatMiddleListMember}[1]{\textcolor{blue}{\texttt{#1}}}%
\newcommand*{\FormatLastListMember}[1]{\texttt{#1}}%

With the above settings, here are the result of using:

\createindentedtext{java.lang.Object, java.awt.Component3, java.awt.Container, javax.swing.JComponent}

\createindentedtext[50pt]{java.lang.Object, java.awt.Component3, java.awt.Container, javax.swing.JComponent}

enter image description here

Notes:

  • The optional first parameter to \createindentedtext can be used to override the default setting of the indent amount. Default value is the value specified in \DefaultIndentSize.
  • The \FormatFirstListMember, \FormatMiddleListMember, \FormatLastListMember can be modified to tweak the desired formatting to be applied to the list members.
  • You can adjust the settings in \ConnectIndentedText to tweak the formatting of the lines.
  • The current setting of the vertical bar joining the elements is set to half the indent size. This can be tweaked as desired by changing the 0.5 constant in the definition of \ConnectIndentedText. It can also be adjusted to always be under a specific letter (such as v in java) by replacing -0.5*#1 in this macro with an appropriate expression using \widthof{} from the the calc package (which is different than what \usetikzlibrary{calc} loads).
  • The showframe package was used to show the position of the text relative to the margins. The \noindent ensures that your text is shifted relative to the margin.
  • This requires two runs. Once to determine the end point of the lines, and the second to draw them.

Code:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{tikz}
\usepackage{xstring}
\usepackage{showframe}
\usetikzlibrary{calc}


\newlength{\DefaultIndentSize}%
\setlength{\DefaultIndentSize}{25pt}% adjust to suit

% Specify the formatting of each of the list members
\newcommand*{\FormatFirstListMember}[1]{\textcolor{magenta}{\texttt{#1}}}%
\newcommand*{\FormatMiddleListMember}[1]{\textcolor{blue}{\texttt{#1}}}%
\newcommand*{\FormatLastListMember}[1]{\texttt{#1}}%


\newcommand{\tikzmark}[1]{\tikz[overlay,remember picture] \node (#1) {};}

\newcommand*{\ConnectIndentedText}[2][\DefaultIndentSize]{%
    \begin{tikzpicture}[overlay, remember picture]
        \draw [thick, blue]
            ($(#2)+(0,0.5ex)$) --
            ($(#2)+(-0.5*#1,0.5ex)$) --
            ($(#2)+(-0.5*#1,2.0ex)$) 
        ;
    \end{tikzpicture}
}%

\newcounter{TotalNumberOfListMembers}%
\newcommand{\SetTotalNumberOfListMembers}[1]{%
    \setcounter{TotalNumberOfListMembers}{0}%
    \foreach \member in {#1} {%
        \stepcounter{TotalNumberOfListMembers}%
    }%
}%


\newlength{\IndentLength}%
\newcounter{CurrentListMemberCount}%
\newtoggle{FirstIndentedText}%
\newcommand*{\createindentedtext}[2][\DefaultIndentSize]{%
    \setlength{\IndentLength}{0pt}%
    \SetTotalNumberOfListMembers{#2}%
    \setcounter{CurrentListMemberCount}{0}%
    \global\toggletrue{FirstIndentedText}%
    \foreach \member in {#2} {%
        \stepcounter{CurrentListMemberCount}%
        \par\noindent\hspace*{\IndentLength}%
        \tikzmark{start}%
        \iftoggle{FirstIndentedText}{%
            \FormatFirstListMember{\member}%
        }{%
            \IfEq{\the\value{CurrentListMemberCount}}{\the\value{TotalNumberOfListMembers}}{%
                \FormatLastListMember{\member}%
            }{%
                \FormatMiddleListMember{\member}%
            }%
            \ConnectIndentedText[#1]{start}%
        }%
        \global\addtolength{\IndentLength}{#1}%
        \global\togglefalse{FirstIndentedText}%
    }%
}%

\begin{document}
    \createindentedtext{java.lang.Object, java.awt.Component3,  java.awt.Container, javax.swing.JComponent}

    \bigskip
    \createindentedtext[50pt]{java.lang.Object, java.awt.Component3, java.awt.Container, javax.swing.JComponent}
\end{document}
5

A possible solution would be:

\documentclass{article}
\makeatletter
\newlength\CurrIndent
\newcommand\IndentedList[1]{\setlength\CurrIndent{0cm}\par\noindent%
  \expandafter\Indented@List#1,,\@nil}
\def\Indented@List#1,#2,#3\@nil{%
  \hspace*{\CurrIndent}\texttt{#1}%
  \ifx\relax#2\relax\par\else\newline
    \addtolength\CurrIndent{1cm}\Indented@List#2,#3\@nil\fi}
\makeatother
\usepackage{lipsum}

\begin{document}

\lipsum[1]
\IndentedList{string1,string2,string3}
\lipsum[2]

\end{document}

which yields:

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .