1

I am trying to create a new environment for listing some achievements as follows:

\documentclass{article}

\begin{document}

\setlength{\tabcolsep}{0 pt}

\newenvironment{twentylong}{
    \begin{tabular*}{\textwidth}{l @{\extracolsep{\fill}}l}
}{
    \end{tabular*}
}

\newcommand{\twentyitemlong}[5]{
    #1 & \parbox[t]{0.8\textwidth}{\textbf{#2}\hfill
        #3\\
        #4\\
        #5\\
    }\\
}

\begin{twentylong}
    \twentyitemlong{since 2019}{Bachelor of Coding in LaTeX}{TimBukToo}{First-Class Honours}{TimBukToo University}
    %\twentyitemlong{<dates>}{<title>}{<location>}{<description1>}{<description2>}
\end{twentylong}

\end{document}

The desired output is basically a table (without borders) with three columns, where the first column only has the date, the second column has the title, description 1 and description 2, and the last column as the location.

However, I have some achievements that do not have some of the required arguments. For example, I may just want to input #1 and #3, with #2, #4 and #5 left blank.

I understand that the xparse package could possibly be used to do this, but I am unsure of how to proceed. I tried to read the documentation on my own as well as consult Professor Google, but to no avail.

In particular, I would like arguments #2 to #5 to all be optional and when they are not provided, then the output should be blank.

For example, I tried the following:

\documentclass{article}

\usepackage{xparse}

\begin{document}

\setlength{\tabcolsep}{0 pt}

\newenvironment{twenty}{
    \begin{tabular*}{\textwidth}{l @{\extracolsep{\fill}}l}
}{
    \end{tabular*}
}

\NewDocumentCommand{\twentyitem}{m O{} O{} O{} O{} O{}}{
    #1 & \parbox[t]{0.8\textwidth}{\textbf{#2}\hfill
        #3\\
        #4\\
        #5\\
    }\\
}

\begin{twenty}
    \twentyitem{since 2019}{Bachelor of Coding in LaTeX}{TimBukToo}{First-Class Honours}{TimBukToo University}
    %\twentyitem{<dates>}{<title>}{<location>}{<description1>}{<description2>}
\end{twenty}

\end{document}

However, the output is not like before and everything seems to be printed on one line i.e. the spaces and new lines between the arguments are not there.

What am I doing wrong?

Any intuitive explanations or suggestions will be greatly appreciated! Moreover, if there is a more succinct way to do this, then please feel free to chip in too!

6
  • 2
    Optional arguments should be delimited with [].
    – user202729
    Commented Dec 24, 2022 at 10:10
  • @user202729 do you mean to say that I should use O[] instead of O{}?
    – Ethan Mark
    Commented Dec 24, 2022 at 10:11
  • 3
    no, when you use the argument, you must use brackets (as you do with parbox and the [t], which is an optional argument). But five optional arguments are quite a nightmare, as they are used starting with the first, so if you want to set the last you would have to use something like \twentyitem{since 2019}[][][][][fifth opt] (and add to the code tests for empty optional arguments). Commented Dec 24, 2022 at 10:22
  • 1
    as Ulrik says, it is a bad design to have adjacent optional argument. Consider a single argument with a comma list \foo[date=..., dept=...,something=value]{main argument} Commented Dec 24, 2022 at 10:40
  • 1
    that is the point, don't use numbered arguments, look at \includegrahics where you can specify height width clip etc all as named keys Commented Dec 24, 2022 at 11:26

1 Answer 1

1

Here's slightly simplified code which I believe does what you want. I removed parbox and simply added p{}-type column with calculated remaining space for the middle column, although you could just add tabularx and use X column instead of p{\dimexpr ....} and simplify code even more.

The number of optional arguments is quite large. In this case I think, it is not too bad but if you had arguments somehow depending on one another, say the second argument depended on the first, the third on the second and so one, the number of tests would grow massively.

Regarding the tests, the following snippet

\IfValueT{#1}{\notblank{#1}{% Run this if not blank}{}}

does the following: with O{}, \IfValueT{#1}{% True} tests whether #1 has been used, then \notblank{#1}{% True}{% False} tests if #1 contains anything. \noblank{}{} is particularly useful because [] and [ ] will be tested negative and hence ignored in the code.

\documentclass{article}
\usepackage{etoolbox}

\NewDocumentEnvironment{twenty}{+b}{%
    \setlength{\tabcolsep}{3 pt}%
    \renewcommand{\arraystretch}{1.5}%
    \begin{tabular*}{\linewidth}{@{}
            p{2cm}
            p{\dimexpr\linewidth-4cm-4\tabcolsep-4\arrayrulewidth}
            p{2cm}
        @{}}
        #1
    \end{tabular*}}{}

\NewDocumentCommand{\twentyitem}{m O{} O{} O{} O{}}{%
    #1
    &
    \IfValueT{#2}{\notblank{#2}{\textbf{#2}}{}}%
    \IfValueT{#4}{\notblank{#4}{\par#4}{}}%
    \IfValueT{#5}{\notblank{#5}{\par#5}{}}
    &
    \IfValueT{#3}{\notblank{#3}{#3}{}}}


\begin{document}
\noindent
\begin{twenty}
    \twentyitem{since 2019}[Bachelor of Coding in LaTeX][TimBukToo][First-Class Honours][TimBukToo University] \\
    \twentyitem{since 2019}[Bachelor of Coding in LaTeX][TimBukToo] \\
    \twentyitem{since 2019}[Bachelor of Coding in LaTeX][][][TimBukToo University] \\
    \twentyitem{since 2019}[][][ ][TimBukToo University] \\
\end{twenty}
\end{document}

enter image description here

You must log in to answer this question.

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