3

In order to have this result

enter image description here

I wrote this command:

\newlength{\boldAcrwidth}
\setlength{\boldAcrwidth}{2cm}

\NewDocumentCommand{\boldAcr}{m >{\SplitList{ }}m}{%
    \makebox[\boldAcrwidth][l]{\bfseries\textit{\MakeUppercase{#1}}}%
    \ProcessList{#2}{\boldAcrFirst}%
    \unskip
}
\NewDocumentCommand{\boldAcrFirst}{m}{%
    \boldAcrFirstAux#1 % we want a space
}
\NewDocumentCommand{\boldAcrFirstAux}{m}{%
    \textbf{\MakeUppercase{#1}}%
}

and

\begin{flushleft}
        \boldAcr{owasp}{open web application security project} \\
        \boldAcr{asvs}{application security verification standard}\\
        \boldAcr{dbms}{database management system}\\
        \boldAcr{sqlia}{structured query language injection attack}\\
        \boldAcr{ldap}{lightweight directory access protocol}\\
\end{flushleft}

Is there a way to modify it in order to sort the elements alphabetically, based on the acronym?

ScTALE
  • 389
  • An option would be to have \addacr{owasp}{open web application security project} and add any acronym and then have a \printacrlist that automatically sorts them. But may be there's a package already made for acronyms? – Manuel Feb 13 '19 at 12:15
  • @Manuel There is the Acronym package, but it doesn't do (as I tried) the effect that i want – ScTALE Feb 13 '19 at 12:17

2 Answers2

5

Here's a way to do it. Each call to \boldAcr adds an item to a seq variable that contains the acronym and the meaning. At the \end of the defined environment the seq var is sorted (using code from this answer -- same caveats apply) then printed using \boldAcroPut, which is the same as you defined previously.

enter image description here

\documentclass{article}

\usepackage{xparse}

\newlength{\boldAcrwidth}
\setlength{\boldAcrwidth}{2cm}

\ExplSyntaxOn
\cs_if_exist:NTF \__str_if_eq:nn
  { \cs_new_eq:NN \sctale_str_if_eq:nn \__str_if_eq:nn } % TexLive 2018 onwards
  { \cs_new_eq:NN \sctale_str_if_eq:nn \__str_if_eq_x:nn } % Previous versions (TeXLive 2017 at least)
\cs_generate_variant:Nn \sctale_str_if_eq:nn { oo }
\cs_new:Npn \__sctale_acro:w #1 \q_mark #2 \q_stop {#1}
\seq_new:N \l__sctale_acro_seq
\NewDocumentEnvironment { acroenv } { }
  { \seq_clear:N \l__sctale_acro_seq }
  {
    \seq_sort:Nn \l__sctale_acro_seq
      {
        \int_compare:nNnTF
          {
            \sctale_str_if_eq:oo
              { \__sctale_acro:w ##1 \q_stop }
              { \__sctale_acro:w ##2 \q_stop }
          }
            < 0
          { \sort_return_same: }
          { \sort_return_swapped: }
      }
    \seq_map_function:NN \l__sctale_acro_seq \__sctale_put_acro:n
  }
\cs_new:Npn \__sctale_put_acro:n #1 { \__sctale_put_acro:w #1 \q_stop }
\cs_new:Npn \__sctale_put_acro:w #1 \q_mark #2 \q_stop
  { \boldAcroPut{#1}{#2} }
\NewDocumentCommand { \boldAcr }{ m >{\SplitList{~}} m }
  { \seq_put_right:Nn \l__sctale_acro_seq { #1 \q_mark {#2} } }
\ExplSyntaxOff

\NewDocumentCommand{\boldAcroPut}{mm}{%
  \noindent
  \makebox[\boldAcrwidth][l]{\bfseries\textit{\MakeUppercase{#1}}}%
  \ProcessList{#2}{\boldAcrFirst}%
  \unskip\par%
}
\NewDocumentCommand{\boldAcrFirst}{m}{%
  \boldAcrFirstAux#1 % we want a space
}
\NewDocumentCommand{\boldAcrFirstAux}{m}{%
  \textbf{\MakeUppercase{#1}}%
}

\begin{document}

\begin{acroenv}
  \boldAcr{owasp}{open web application security project}
  \boldAcr{asvs}{application security verification standard}
  \boldAcr{dbms}{database management system}
  \boldAcr{sqlia}{structured query language injection attack}
  \boldAcr{ldap}{lightweight directory access protocol}
\end{acroenv}

\end{document}

Replacing the definition of \boldAcr with this:

% \NewDocumentCommand { \boldAcr }{ m >{\SplitList{~}} m }
%   { \seq_put_right:Nn \l__sctale_acro_seq { #1 \q_mark {#2} } }
\cs_new_eq:NN \dont \prg_do_nothing:
\NewDocumentCommand { \boldAcr }{ >{\SplitList{~}} m }
  {
    \tl_set:Nx \l__sctale_tmpa_tl { \tl_map_function:nN {#1} \__sctale_make_acro:n }
    \seq_put_right:No \l__sctale_acro_seq { \l__sctale_tmpa_tl \q_mark {#1} }
  }
\cs_new:Npn \__sctale_make_acro:n #1 { \__sctale_make_acro:w #1 \q_nil }
\cs_new:Npn \__sctale_make_acro:w #1 #2 \q_nil
  { \token_if_eq_meaning:NNF #1 \dont { #1 } }

you spare yourself the hassle of writing the acronym. To avoid a word being used in the acronym you just tell it to \dont use it:

\begin{acroenv}
  \boldAcr{open web application security project}
  \boldAcr{application security verification standard}
  \boldAcr{database management system}
  \boldAcr{structured query language injection attack}
  \boldAcr{lightweight directory access protocol}
  \boldAcr{national oceanic \dont{and} atmospheric administration}
\end{acroenv}

enter image description here

  • It works with only one acronym, with 2 I have errors (Undefined control sequence. \end{acroenv}) – ScTALE Feb 13 '19 at 12:59
  • @ScTALE Sorry, I don't understand what you mean by “two acronyms”. Can you give an example for me to reproduce the error? – Phelype Oleinik Feb 13 '19 at 13:08
  • https://pastebin.com/LaqPM4QX With only one element, the acroenv environment works, with 2 no – ScTALE Feb 13 '19 at 13:13
  • @ScTALE Weird... The code you showed works for me (screenshot and output log). What LaTeX distribution/version you have. Can you upload the log so I can see? Perhaps it's an issue with the version of expl3. – Phelype Oleinik Feb 13 '19 at 13:20
  • At the moment I am writing from a different computer than before and unfortunately I will be not able to answer your question until tomorrow morning. In any case, I am using TexLive for Ubuntu 18 – ScTALE Feb 13 '19 at 13:58
  • @ScTALE No problem, I'll wait. I have a computer with Ubuntu 18 here somewhere. If I can I'll check that and update, otherwise I'll wait your feedback :) – Phelype Oleinik Feb 13 '19 at 14:02
  • @ScTALE Okay, I found the problem. Ubuntu 18's TeXLive is 2017, and mine is 2018. Between one version and another there was a large renaming of many of expl3 's internals. One of these is \__str_if_eq:nn which, in your version of expl3 is called \__str_if_eq_x:nn, thus the error. That's the price you pay for using expl3 internal commands :) I added a check for the existence of \__str_if_eq:nn and tested in an Ubuntu 18 and it works :) – Phelype Oleinik Feb 13 '19 at 15:46
  • With a lot of efford, I update my texlive version and now it works (I tried in another computer). Thank you! – ScTALE Feb 13 '19 at 18:39
  • @ScTALE You're welcome :) My 2 cents: after a couple of years using TeXLive from the Ubuntu repo I gave up and used the tug.org's installer. Never looked back. It's easy to install and to update, and it even works alongside Ubuntu's. Highly recommend :) – Phelype Oleinik Feb 13 '19 at 18:42
5

I just took the sorting algorithm from here.

\usepackage{xparse}

\ExplSyntaxOn

\seq_new:N \g_sctale_acr_seq
\prop_new:N \g_sctale_acr_prop

\NewDocumentCommand \addacr { m m }
 {
  \seq_put_right:Nn \g_sctale_acr_seq { #1 }
  \prop_put:Nnn \g_sctale_acr_prop { #1 } { #2 }
 }

\NewDocumentCommand \printacrlist { }
 {
  \seq_sort:Nn \g_sctale_acr_seq
   {
    \sctale_string_if_before_case_insensitive:nnTF { ##1 } { ##2 }
     { \sort_return_same:    }
     { \sort_return_swapped: }
   }
  \begin{flushleft}
   \seq_map_inline:Nn \g_sctale_acr_seq
    { \boldAcr{##1}{ \prop_item:Nn \g_sctale_acr_prop {##1} } \\ }
  \end{flushleft}
 }

\prg_new_conditional:Nnn \sctale_string_if_before_case_insensitive:nn { p, T, F, TF }
 {
  \int_compare:nNnTF { \pdftex_strcmp:D { \str_lowercase:n {#1} } { \str_lowercase:n {#2} } } < 0
   { \prg_return_true:  }
   { \prg_return_false: }
 }

\ExplSyntaxOff

This just uses \addacr{sql}{structured query language} before, and then \printacrlist, which in turn uses your \boldAcr for printing each one.

Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036
Manuel
  • 27,118