% --------------------------------------------------------------------------
% the ACRO package
% 
%   Typeset Acronyms
% 
% --------------------------------------------------------------------------
% Clemens Niederberger
% Web:    https://bitbucket.org/cgnieder/acro/
% E-Mail: contact@mychemistry.eu
% --------------------------------------------------------------------------
% Copyright 2011-2015 Clemens Niederberger
% 
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
% 
% This work has the LPPL maintenance status `maintained'.
% 
% The Current Maintainer of this work is Clemens Niederberger.
% --------------------------------------------------------------------------
% The acro package consists of the files
%  - acro.sty, acro0.def, acro1.def, acro_en.tex, acro_en.pdf, README
% --------------------------------------------------------------------------
% If you have any ideas, questions, suggestions or bugs to report, please
% feel free to contact me.
% --------------------------------------------------------------------------
\RequirePackage{expl3,l3sort,xparse,l3keys2e,xtemplate}
\ProvidesExplPackage
  {acro}
  {2015/04/08}
  {1.6a}
  {Typeset Acronyms}

% --------------------------------------------------------------------------
% check expl3 version:
\@ifpackagelater { expl3 } { 2012/11/21 }
  { }
  {
    \PackageError {acro} { Support~package~expl3~too~old }
      {
        You~need~to~update~your~installation~of~the~bundles~'l3kernel'~and~
        'l3packages'.\MessageBreak
        Loading~acro~will~abort!
      }
    \tex_endinput:D
  }

% --------------------------------------------------------------------------
% warning and error messages:
\msg_new:nnn {acro} {undefined}
  {
    You've~requested~acronym~`#1'~\msg_line_context: \c_space_tl but~you~
    apparently~haven't~defined~it,~yet!~Maybe~you've~misspelled~it?
  }

\msg_new:nnn {acro} {macro}
  {
    A~macro~with~the~csname~`#1'~already~exists.~Unless~you~set~acro's~option~
    `strict'~I~won't~redefine~it~\msg_line_context: .
  } 

\msg_new:nnn {acro} {replaced}
  {
    The~#1~`#2'~you~used~\msg_line_context: \c_space_tl is~deprecated~and~has~
    been~replaced~by~`#3'.~Since~I~will~not~guarantee~that~#1~will~be~kept~
    forever~I~encourage~you~to~switch.
  }

\msg_new:nnn {acro} {deprecated}
  {
    The~#1~`#2'~you~used~\msg_line_context: \c_space_tl is~deprecated~and~there~
    is~no~replacement.~Since~I~will~not~guarantee~that~#1~will~be~kept~forever~
    I~encourage~you~to~remove~it~from~your~document.
  }

% message macros:
\bool_new:N \l__acro_silence_bool

\cs_new_protected:Npn \acro_serious_message:nn
  {
    \bool_if:NTF \l__acro_silence_bool
      { \msg_warning:nn }
      { \msg_error:nn }
  }

\cs_new_protected:Npn \acro_serious_message:nnn
  {
    \bool_if:NTF \l__acro_silence_bool
      { \msg_warning:nnn }
      { \msg_error:nnn }
  }

\cs_new_protected:Npn \acro_serious_message:nnnn
  {
    \bool_if:NTF \l__acro_silence_bool
      { \msg_warning:nnnn }
      { \msg_error:nnnn }
  }

\cs_new_protected:Npn \acro_harmless_message:nnn
  {
    \bool_if:NTF \l__acro_silence_bool
      { \msg_info:nnn }
      { \msg_warning:nnn }
  }

\cs_new_protected:Npn \acro_harmless_message:nnnn
  {
    \bool_if:NTF \l__acro_silence_bool
      { \msg_info:nnnn }
      { \msg_warning:nnnn }
  }

\cs_new_protected:Npn \acro_harmless_message:nnnnn
  {
    \bool_if:NTF \l__acro_silence_bool
      { \msg_info:nnnnn }
      { \msg_warning:nnnnn }
  }

\cs_new_protected:Npn \acro_option_deprecated:nn #1#2
  {
    \tl_if_blank:nTF {#2}
      { \acro_harmless_message:nnnn  {acro} {deprecated} {option} {#1 } }
      { \acro_harmless_message:nnnnn {acro} {replaced}   {option} {#1} {#2} }
  }

\cs_new_protected:Npn \acro_command_deprecated:NN #1#2
  {
    \tl_if_blank:nTF {#2}
      {
        \acro_harmless_message:nnnnn {acro} {deprecated}
          {command}
          { \token_to_str:N #1 }
      }
      {
        \acro_harmless_message:nnnnn {acro} {replaced}
          {command}
          { \token_to_str:N #1 }
          { \token_to_str:N #2 }
      }
  }

% --------------------------------------------------------------------------
% temporary variables
\tl_new:N   \l__acro_tmpa_tl
\tl_new:N   \l__acro_tmpb_tl
\tl_new:N   \l__acro_tmpc_tl
\prop_new:N \l__acro_tmpa_prop
\prop_new:N \l__acro_tmpb_prop
\seq_new:N  \l__acro_tmpa_seq
\seq_new:N  \l__acro_tmpb_seq
\int_new:N  \l__acro_tmpa_int
\int_new:N  \l__acro_tmpb_int
\int_new:N  \l__acro_tmpc_int
\int_new:N  \l__acro_tmpd_int

% --------------------------------------------------------------------------
% variants of kernel commands
\cs_generate_variant:Nn \quark_if_no_value:nTF { V }
\cs_generate_variant:Nn \tl_put_right:Nn       { NV }
\cs_generate_variant:Nn \tl_if_eq:nnT          { V }
\cs_generate_variant:Nn \tl_if_eq:nnF          { V }
\cs_generate_variant:Nn \seq_use:Nnnn          { c }
\cs_generate_variant:Nn \seq_gset_split:Nnn    { c }

% --------------------------------------------------------------------------
% boolean variables:
\bool_new:N      \l__acro_mark_as_used_bool
\bool_new:N      \g__acro_mark_first_as_used_bool
\bool_new:N      \l__acro_use_single_bool
\bool_new:N      \l__acro_print_only_used_bool
\bool_set_true:N \l__acro_print_only_used_bool
\bool_new:N      \l__acro_use_plural_bool
\bool_new:N      \l__acro_hyperref_loaded_bool
\bool_new:N      \l__acro_use_hyperref_bool
\bool_new:N      \l__acro_custom_format_bool
\bool_new:N      \l__acro_strict_bool
\bool_new:N      \l__acro_create_macros_bool
\bool_new:N      \l__acro_xspace_bool
\bool_new:N      \l__acro_first_upper_bool
\bool_new:N      \l__acro_indefinite_bool
\bool_new:N      \l__acro_upper_indefinite_bool
\bool_new:N      \l__acro_foreign_bool
\bool_set_true:N \l__acro_foreign_bool
\bool_new:N      \l__acro_sort_bool
\bool_set_true:N \l__acro_sort_bool
\bool_new:N      \l__acro_capitalize_list_bool
\bool_new:N      \l__acro_citation_all_bool
\bool_new:N      \l__acro_citation_first_bool
\bool_set_true:N \l__acro_citation_first_bool
\bool_new:N      \l__acro_acc_supp_bool
\bool_new:N      \l__acro_following_page_bool
\bool_new:N      \l__acro_following_pages_bool
\bool_new:N      \l__acro_record_pages_bool
\bool_set_true:N \l__acro_record_pages_bool
\bool_new:N      \l__acro_addto_index_bool
\bool_new:N      \l__acro_is_excluded_bool
\bool_new:N      \l__acro_page_punct_bool
\bool_new:N      \l__acro_page_brackets_bool
\bool_new:N      \l__acro_page_display_bool
\bool_new:N      \l__acro_new_page_numbering_bool
\bool_new:N      \l__acro_first_use_brackets_bool
\bool_new:N      \l__acro_first_only_short_bool
\bool_new:N      \l__acro_first_reversed_bool
\bool_new:N      \l__acro_use_note_bool
\bool_new:N      \l__acro_extra_punct_bool
\bool_new:N      \l__acro_extra_use_brackets_bool
\bool_new:N      \l__acro_in_list_bool
\bool_new:N      \l__acro_place_label_bool
\bool_new:N      \l__acro_list_all_pages_bool
\bool_set_true:N \l__acro_list_all_pages_bool

% --------------------------------------------------------------------------
% token list variables:
\tl_new:N   \l__acro_ignore_tl
\tl_new:N   \l__acro_short_format_tl
\tl_new:N   \l__acro_list_short_format_tl
\tl_new:N   \l__acro_long_format_tl
\tl_new:N   \l__acro_first_long_format_tl
\tl_new:N   \l__acro_list_long_format_tl
\tl_new:N   \l__acro_default_indefinite_tl
\tl_set:Nn  \l__acro_default_indefinite_tl { a }
\tl_new:N   \l__acro_extra_format_tl
\tl_new:N   \l__acro_foreign_tl
\tl_new:N   \l__acro_foreign_sep_tl
\tl_new:N   \l__acro_foreign_format_tl
\tl_new:N   \l__acro_foreign_list_format_tl
\tl_set:Nn  \l__acro_foreign_list_format_tl { \acroenparen }
\tl_new:N   \l__acro_first_instance_tl
\tl_set:Nn  \l__acro_first_instance_tl { default }
\tl_new:N   \l__acro_extra_instance_tl
\tl_set:Nn  \l__acro_extra_instance_tl { default }
\tl_new:N   \l__acro_page_instance_tl
\tl_set:Nn  \l__acro_page_instance_tl  { none }
\tl_new:N   \l__acro_page_name_tl
\tl_set:Nn  \l__acro_page_name_tl      { p.\@\, }
\tl_new:N   \l__acro_pages_name_tl
\tl_set:Nn  \l__acro_pages_name_tl     { pp.\@\, }
\tl_new:N   \l__acro_next_page_tl
\tl_set:Nn  \l__acro_next_page_tl      { \,f.\@ }
\tl_new:N   \l__acro_next_pages_tl
\tl_set:Nn  \l__acro_next_pages_tl     { \,ff.\@ }
\tl_new:N   \l__acro_list_instance_tl
\tl_set:Nn  \l__acro_list_instance_tl  { list }
\tl_new:N   \l__acro_list_type_tl
\tl_set:Nn  \l__acro_list_type_tl      { description }
\tl_new:N   \l__acro_list_title_tl
\tl_set:Nn  \l__acro_list_title_tl     { section* }
\tl_new:N   \l__acro_list_name_tl
\tl_set:Nn  \l__acro_list_name_tl      { Acronyms }
\tl_new:N   \l__acro_short_tl
\tl_new:N   \l__acro_short_plural_tl
\tl_new:N   \l__acro_default_plural_tl
\tl_set:Nn  \l__acro_default_plural_tl { s }
\tl_new:N   \l__acro_alt_tl
\tl_new:N   \l__acro_long_tl
\tl_new:N   \l__acro_long_pre_tl
\tl_new:N   \l__acro_long_post_tl
\tl_new:N   \l__acro_custom_format_tl
\tl_new:N   \l__acro_first_between_tl
\tl_new:N   \l__acro_citation_space_tl
\tl_set:Nn  \l__acro_citation_space_tl { \nobreakspace }
\tl_new:N   \l__acro_extra_brackets_tl
\tl_new:N   \l__acro_extra_punct_tl
\tl_new:N   \l__acro_first_brackets_tl
\tl_new:N   \l__acro_page_punct_tl
\tl_new:N   \l__acro_page_brackets_tl
\tl_new:N   \l__acro_last_page_tl
\tl_new:N   \l__acro_current_page_tl
\tl_new:N   \l__acro_list_table_tl
\tl_new:N   \l__acro_list_table_spec_tl
\tl_new:N   \l__acro_index_short_tl
\tl_new:N   \l__acro_index_format_tl
\tl_new:N   \l__acro_acc_supp_tl
\tl_new:N   \l__acro_acc_supp_options_tl
\tl_new:N   \l__acro_label_prefix_tl
\tl_set:Nn  \l__acro_label_prefix_tl { ac: }

% --------------------------------------------------------------------------
% length variables:
\dim_new:N  \l__acro_table_width_dim
\dim_set:Nn \l__acro_table_width_dim { .7\linewidth }
\dim_new:N  \l__acro_page_space_dim

% --------------------------------------------------------------------------
% small commands for use at various places
\cs_new:Npn \acro_no_break: { \tex_penalty:D \c_ten_thousand }

\cs_new_protected:Npn \__acro_first_upper_case:n #1
  { \tl_mixed_case:n {#1} }
\cs_generate_variant:Nn \__acro_first_upper_case:n { x }
\cs_generate_variant:Nn \tl_mixed_case:n { x }

\cs_new_eq:NN \acro_first_upper_case:n \__acro_first_upper_case:n

\NewDocumentCommand \acfirstupper { m }
  { \acro_first_upper_case:n {#1} }

% --------------------------------------------------------------------------
% options:
\keys_define:nn {acro}
  {
    version           .code:n     = 
      \acro_option_deprecated:nn { version } { }               ,
    messages          .choice: ,
    messages / silent .code:n     =
      \bool_set_true:N \l__acro_silence_bool ,
    messages / loud .code:n     =
      \bool_set_false:N \l__acro_silence_bool ,
    accsupp           .bool_set:N = \l__acro_acc_supp_bool          ,
    accsupp-options   .tl_set:N   = \l__acro_acc_supp_options_tl    ,
    macros            .bool_set:N = \l__acro_create_macros_bool     ,
    xspace            .bool_set:N = \l__acro_xspace_bool            ,
    strict            .bool_set:N = \l__acro_strict_bool            ,
    sort              .bool_set:N = \l__acro_sort_bool              ,
    short-format      .code:n     =
      \tl_set:Nn \l__acro_short_format_tl {#1}
      \tl_set:Nn \l__acro_list_short_format_tl {#1}                 ,
    long-format       .code:n     =
      \tl_set:Nn \l__acro_long_format_tl {#1}
      \tl_set:Nn \l__acro_first_long_format_tl {#1}
      \tl_set:Nn \l__acro_list_long_format_tl {#1}                  ,
    first-long-format .code:n     =
      \tl_set:Nn \l__acro_first_long_format_tl {#1}                 ,
    display-foreign   .bool_set:N = \l__acro_foreign_bool           ,
    foreign-format    .tl_set:N   = \l__acro_foreign_format_tl      ,
    list-short-format .tl_set:N   = \l__acro_list_short_format_tl   ,
    list-long-format  .tl_set:N   = \l__acro_list_long_format_tl    ,
    list-foreign-format .tl_set:N = \l__acro_foreign_list_format_tl ,
    extra-format      .tl_set:N   = \l__acro_extra_format_tl        ,
    single            .bool_set:N = \l__acro_use_single_bool        ,
    first-style       .tl_set:N   = \l__acro_first_instance_tl      ,
    extra-style       .tl_set:N   = \l__acro_extra_instance_tl      ,
    label             .bool_set:N = \l__acro_place_label_bool       ,
    label-prefix      .tl_set:N   = \l__acro_label_prefix_tl        ,
    pages             .choice: ,
    pages / all       .code:n     =
      \bool_set_true:N \l__acro_list_all_pages_bool                 ,
    pages / first     .code:n     =
      \bool_set_true:N \l__acro_place_label_bool
      \bool_set_false:N \l__acro_list_all_pages_bool                ,
    page-ref          .tl_set:N   = \l__acro_page_instance_tl       ,
    page-name         .tl_set:N   = \l__acro_page_name_tl           ,
    pages-name        .tl_set:N   = \l__acro_pages_name_tl          ,
    page-ranges       .code:n     =
      \bool_set_false:N \l__acro_following_page_bool
      \bool_set_false:N \l__acro_following_pages_bool
      \acro_option_deprecated:nn { pages-ranges } { }               ,
    following-page    .bool_set:N = \l__acro_following_page_bool    ,
    following-pages   .bool_set:N = \l__acro_following_pages_bool   ,
    record-pages      .code:n     = 
      \acro_option_deprecated:nn { record-pages } { }               ,
    next-page         .tl_set:N   = \l__acro_next_page_tl           ,
    next-pages        .tl_set:N   = \l__acro_next_pages_tl          ,
    list-style        .tl_set:N   = \l__acro_list_instance_tl       ,
    list-type         .tl_set:N   = \l__acro_list_type_tl           ,
    list-header       .code:n     =
      \acro_option_deprecated:nn { list-header } { list-heading }
      \tl_set:Nn \l__acro_list_title_tl {#1}                      ,
    list-heading      .tl_set:N   = \l__acro_list_title_tl          ,
    list-name         .tl_set:N   = \l__acro_list_name_tl           ,
    list-table-width  .dim_set:N  = \l__acro_table_width_dim        ,
    hyperref          .bool_set:N = \l__acro_use_hyperref_bool      ,
    only-used         .bool_set:N = \l__acro_print_only_used_bool   ,
    mark-as-used      .choice: ,
    mark-as-used / first .code:n  =
      \bool_gset_true:N \g__acro_mark_first_as_used_bool            ,
    mark-as-used / any   .code:n  =
      \bool_gset_false:N \g__acro_mark_first_as_used_bool           ,
    plural-ending     .tl_set:N   = \l__acro_default_plural_tl      ,
    list-caps         .bool_set:N = \l__acro_capitalize_list_bool   ,
    cite              .choice:                                      ,
    cite / all        .code:n     =
      \bool_set_true:N \l__acro_citation_all_bool
      \bool_set_true:N \l__acro_citation_first_bool                 ,
    cite / none       .code:n     =
      \bool_set_false:N \l__acro_citation_all_bool
      \bool_set_false:N \l__acro_citation_first_bool                ,
    cite / first      .code:n     =
      \bool_set_false:N \l__acro_citation_all_bool
      \bool_set_true:N  \l__acro_citation_first_bool                ,
%     cite              .default:n  = all                             ,
    cite-cmd          .code:n     =
      \cs_set:Npn \__acro_citation_cmd:w {#1}                     ,
    cite-space        .tl_set:N   = \l__acro_citation_space_tl      ,
    index             .bool_set:N = \l__acro_addto_index_bool       ,
    index-cmd         .code:n     =
      \cs_set:Npn \__acro_index_cmd:n {#1} ,
    uc-cmd            .code:n     =
      \cs_set_eq:NN \__acro_first_upper_case:n #1
  }

\AtBeginDocument
  {
    \bool_if:NTF \l__acro_xspace_bool
      {
        \@ifpackageloaded {xspace}
          { }
          { \RequirePackage {xspace} }
        \cs_new_eq:NN \acro_xspace: \xspace
      }
      { \cs_new:Npn \acro_xspace: {} }
    \bool_if:NF \l__acro_record_pages_bool
      { \cs_set_eq:NN \acro_record_page_number:n \use_none:n }
  }

% --------------------------------------------------------------------------
% setup command:
\NewDocumentCommand \acsetup { m }
  { \keys_set:nn {acro} {#1} \ignorespaces }

% --------------------------------------------------------------------------
\cs_new_protected:Npn \acro_plural:
  { \bool_set_true:N \l__acro_use_plural_bool }

\cs_new_protected:Npn \acro_upper:
  { \bool_set_true:N \l__acro_first_upper_bool }

% typeset the short form:
\cs_new:Npn \__acro_write_short:n #1
  {
    \mode_if_horizontal:F { \leavevmode }
    \group_begin:
      \bool_if:NTF \l__acro_custom_format_bool
        { \l__acro_custom_format_tl }
        { \l__acro_short_format_tl }
      {  #1 }
    \group_end:
    \bool_if:NT \l__acro_use_plural_bool
      { \tl_use:N \l__acro_short_plural_tl }
  }
\cs_generate_variant:Nn \__acro_write_short:n { V }

% typeset the longform,...:
% TODO: rethink the formatting mechanism
% right now a custom format gets applied additionally to the global one
% although before it
\cs_new_protected:Npn \__acro_write_long:Nn #1#2
  {
    \mode_if_horizontal:F { \leavevmode }
    \group_begin:
      \bool_if:NTF \l__acro_custom_long_format_bool
        { \l__acro_custom_long_format_tl }
        { \use:n }
      {
        \exp_args:Nx #1
          {
            \bool_if:NTF \l__acro_first_upper_bool
              { \exp_not:N \__acro_first_upper_case:n { \exp_not:n {#2} } }
              { \exp_not:n {#2} }
          }
      }
    \group_end:
  }
\cs_generate_variant:Nn \__acro_write_long:Nn { NV,No,Nf }

% --------------------------------------------------------------------------
% hyperref support
\cs_new_eq:NN \acro_hyper_target:nn \use_ii:nn
\cs_new_eq:NN \acro_hyper_link:nn   \use_ii:nn

\cs_new_protected:Npn \__acro_activate_hyperref_support:
  {
    \bool_if:nT { \l__acro_hyperref_loaded_bool && \l__acro_use_hyperref_bool }
      {
        \cs_set_eq:NN \acro_hyper_link:nn \hyperlink
        \cs_set:Npn \acro_hyper_target:nn ##1##2
          { \raisebox { 3ex } [ 0pt ] { \hypertarget {##1} { } } ##2 }
      }
  }

\cs_new_protected:Npn \__acro_make_link:nNN #1#2#3
  {
    \bool_if:nTF
      { \l__acro_use_hyperref_bool && \l__acro_hyperref_loaded_bool }
      {
        \tl_set:Nn #2
           {
             \acro_hyper_link:nn {#1} { \phantom {#3} }
             \__acro_is_single:nTF {#1}
               { \hbox_overlap_left:n {#3} }
               { \acro_color_link:n { \hbox_overlap_left:n {#3} } }
           }
       }
       { \tl_set:Nn #2 {#3} }
  }

\cs_new:Npn \acro_color_link:n #1
  {
    \cs_if_exist:NTF \hypersetup
      {
        \ifHy@colorlinks
          \exp_after:wN \use_i:nn
        \else
          \ifHy@ocgcolorlinks
            \exp_after:wN \use_i:nn
          \else
            \exp_after:wN \exp_after:wN \exp_after:wN \use_ii:nn
          \fi
        \fi
        { \textcolor { \@linkcolor } {#1} }
        {#1}
      }
      {#1}
  }

\AtBeginDocument{
  \cs_if_exist:NF \textcolor { \cs_new_eq:NN \textcolor \use_ii:nn }
}

% --------------------------------------------------------------------------
% output style of the first time an acronym is used
\cs_new:Npn \__acro_note_command:n #1 {#1}

% #1: id
% #2: short
% #3: long
\DeclareObjectType { acro-first } { 3 }

% template for inline appearance:
\DeclareTemplateInterface { acro-first } { inline } { 3 }
  {
    brackets      : boolean   = true  ,
    brackets-type : tokenlist = ()    ,
    only-short    : boolean   = false ,
    reversed      : boolean   = false ,
    between       : tokenlist         ,
    foreign-sep   : tokenlist = { , ~ }
  }
\DeclareTemplateCode { acro-first } { inline } { 3 }
  {
    brackets      = \l__acro_first_use_brackets_bool ,
    brackets-type = \l__acro_first_brackets_tl       ,
    only-short    = \l__acro_first_only_short_bool   ,
    reversed      = \l__acro_first_reversed_bool     ,
    between       = \l__acro_first_between_tl        ,
    foreign-sep   = \l__acro_foreign_sep_tl
  }
  {
    \AssignTemplateKeys
    \bool_if:nT { !\l__acro_first_only_short_bool && !\l__acro_first_reversed_bool }
      {
        \__acro_indefinite:nn {#1} { long }
        \__acro_write_long:No \l__acro_first_long_format_tl {#3}
        \tl_use:N \c_space_tl
        \tl_if_blank:VF \l__acro_first_between_tl
          {
            \tl_use:N \l__acro_first_between_tl
            \tl_use:N \c_space_tl
          }
      }
    \bool_if:nT
      { \l__acro_first_use_brackets_bool && !\l__acro_first_reversed_bool }
      { \tl_head:N \l__acro_first_brackets_tl }
    \bool_if:nT
      {
         \l__acro_foreign_bool &&
        !\l__acro_first_reversed_bool &&
        !\l__acro_first_only_short_bool
      }
      {
        \prop_get:NnNT \l__acro_foreign_prop {#1} \l__acro_foreign_tl
          {
            \group_begin:
              \tl_use:N \l__acro_foreign_format_tl
              \tl_use:N \l__acro_foreign_tl
            \group_end:
            \tl_use:N \l__acro_foreign_sep_tl
          }
      }
    \bool_if:nT
      { \l__acro_first_reversed_bool || \l__acro_first_only_short_bool }
      { \__acro_indefinite:nn {#1} { short } }
    \__acro_acc_supp:nn {#1} { \__acro_write_short:n {#2} }
    \bool_if:nT
      { \l__acro_first_use_brackets_bool && !\l__acro_first_reversed_bool }
      { \tl_tail:N \l__acro_first_brackets_tl }
    \bool_if:nT
      { !\l__acro_first_only_short_bool && \l__acro_first_reversed_bool }
      {
        \tl_if_blank:VF \l__acro_first_between_tl
          {
            \tl_use:N \c_space_tl
            \tl_use:N \l__acro_first_between_tl
          }
        \tl_use:N \c_space_tl
        \bool_if:nT
          { \l__acro_first_use_brackets_bool && \l__acro_first_reversed_bool }
          { \tl_head:N \l__acro_first_brackets_tl }
        \__acro_write_long:No \l__acro_first_long_format_tl {#3}
        \bool_if:nT { \l__acro_foreign_bool && \l__acro_first_reversed_bool }
          {
            \prop_get:NnNT \l__acro_foreign_prop {#1} \l__acro_foreign_tl
              {
                \tl_use:N \l__acro_foreign_sep_tl
                \group_begin:
                  \tl_use:N \l__acro_foreign_format_tl
                  \tl_use:N \l__acro_foreign_tl
                \group_end:
              }
          }
        \bool_if:nT
          { \l__acro_first_use_brackets_bool && \l__acro_first_reversed_bool }
          { \tl_tail:N \l__acro_first_brackets_tl }
      }
    \__acro_cite_if:Nn \l__acro_citation_first_bool {#1}
    \__acro_index_if:Nn \l__acro_addto_index_bool {#1}
  }

% template for footnotes, sidenotes, ...
\DeclareTemplateInterface { acro-first } { note } { 3 }
  {
    use-note     : boolean    = true ,
    note-command : function 1 = \footnote {#1} ,
    foreign-sep  : tokenlist  = ~
  }

\DeclareTemplateCode { acro-first } { note } { 3 }
  {
    use-note     = \l__acro_use_note_bool ,
    note-command = \__acro_note_command:n ,
    foreign-sep  = \l__acro_foreign_sep_tl
  }
  {
    \AssignTemplateKeys
    \__acro_indefinite:nn {#1} { short }
    \__acro_acc_supp:nn {#1} { \__acro_write_short:n {#2} }
    \bool_if:NT \l__acro_use_note_bool
      {
        \__acro_note_command:n
          {
            \__acro_write_long:No \l__acro_first_long_format_tl {#3}
            \bool_if:NT \l__acro_foreign_bool
              {
                \prop_get:NnNT \l__acro_foreign_prop {#1} \l__acro_foreign_tl
                  {
                    \tl_use:N \l__acro_foreign_sep_tl
                    (
                    \group_begin:
                      \tl_use:N \l__acro_foreign_format_tl
                      \tl_use:N \l__acro_foreign_tl
                    \group_end:
                    )
                  }
              }
            \__acro_cite_if:Nn \l__acro_citation_first_bool {#1}
            \__acro_index_if:Nn \l__acro_addto_index_bool {#1}
          }
      }
  }

% the different styles:
\DeclareInstance { acro-first }
  { default }
  { inline }
  { }
\DeclareInstance { acro-first }
  { square }
  { inline }
  { brackets-type = [] }
\DeclareInstance { acro-first }
  { plain }
  { inline }
  {
    brackets = false ,
    between = --
  }
\DeclareInstance { acro-first }
  { plain-reversed }
  { inline }
  { 
    brackets = false ,
    between = -- ,
    reversed = true
  }
\DeclareInstance { acro-first }
  { footnote }
  { note }
  { }
\DeclareInstance { acro-first }
  { sidenote }
  { note }
  { note-command = \sidenote {#1} }
\DeclareInstance { acro-first }
  { empty }
  { note }
  { use-note = false }
\DeclareInstance { acro-first }
  { short }
  { inline }
  {
    only-short = true ,
    brackets = false
  }
\DeclareInstance { acro-first }
  { reversed }
  { inline }
  { reversed = true }

% --------------------------------------------------------------------------
% formatting the extras information:
\DeclareObjectType { acro-extra } { 1 }

\DeclareTemplateInterface { acro-extra } { default } { 1 }
  {
    punct         : boolean   = false ,
    punct-symbol  : tokenlist = {,}   ,
    brackets      : boolean   = true  ,
    brackets-type : tokenlist = ()
  }

\DeclareTemplateCode { acro-extra } { default } { 1 }
  {
    punct         = \l__acro_extra_punct_bool        ,
    punct-symbol  = \l__acro_extra_punct_tl          ,
    brackets      = \l__acro_extra_use_brackets_bool ,
    brackets-type = \l__acro_extra_brackets_tl
  }
  {
    \AssignTemplateKeys
    \bool_if:NT \l__acro_extra_punct_bool
      { \tl_use:N \l__acro_extra_punct_tl \tl_use:N \c_space_tl }
    \bool_if:NT \l__acro_extra_use_brackets_bool
      { \tl_head:N \l__acro_extra_brackets_tl }
    \__acro_write_long:Nn \l__acro_extra_format_tl {#1}
    \bool_if:NT \l__acro_extra_use_brackets_bool
      { \tl_tail:N \l__acro_extra_brackets_tl }
  }

% the different styles:
\DeclareInstance { acro-extra } { default } { default }
  { brackets = false , punct = true , punct-symbol = . }
\DeclareInstance { acro-extra } { plain   } { default }
  { brackets = false , punct = false }
\DeclareInstance { acro-extra } { paren   } { default }
  { punct = true , punct-symbol =  }
\DeclareInstance { acro-extra } { bracket } { default }
  {  punct = true , punct-symbol = , brackets-type=[] }
\DeclareInstance { acro-extra } { comma   } { default }
  { punct = true, brackets = false }

% --------------------------------------------------------------------------
% outputting the page numbers:
\RequirePackage { zref-abspage }

\cs_new_protected:Npn \acro_create_page_records:n #1
  {
    \seq_new:c { g__acro_#1_pages_seq }
    \tl_new:c  { g__acro_#1_recorded_pages_tl }
  }

\cs_new_protected:Npn \acro_hyper_page:n #1 { \use:n {#1} }

\cs_new:Npn \acro_get_thepage:nnn #1#2#3 { \acro_hyper_page:n {#1} }
\cs_new:Npn \acro_get_thepage_from:N #1
  { \exp_after:wN \acro_get_thepage:nnn #1 }

\cs_new:Npn \acro_get_page_number:nnn #1#2#3 {#2}
\cs_new:Npn \acro_get_page_number_from:N #1
  { \exp_after:wN \acro_get_page_number:nnn #1 }

\cs_new:Npn \acro_get_abspage:nnn #1#2#3 {#3}
\cs_new:Npn \acro_get_abspage_from:N #1
  { \exp_after:wN \acro_get_abspage:nnn #1 }

\cs_new:Npn \acro_page_range_comma: {}

\cs_new_protected:Npn \acro_print_page_numbers:n #1
  {
    \seq_if_empty:cF { g__acro_#1_pages_seq }
      {
        % have the numbers changed?
        \tl_set:Nx \l__acro_tmpa_tl
          { \seq_use:cnnn { g__acro_#1_pages_seq } { | } { | } { | } }
        \tl_if_eq:cNF { g__acro_#1_recorded_pages_tl } \l__acro_tmpa_tl
          {
            \@latex@warning@no@line
              {Rerun~to~get~page~numbers~of~acronym~#1~in~acronym~list~right}
          }
        \tl_clear:N \l__acro_write_pages_tl
        \tl_clear:N \l__acro_last_page_tl
        \tl_clear:N \l__acro_current_page_tl
        \seq_set_eq:Nc \l__acro_tmpb_seq { g__acro_#1_pages_seq }
        \seq_remove_duplicates:N \l__acro_tmpb_seq
        \seq_clear:N \l__acro_tmpa_seq
        \cs_set_protected:Npn \acro_page_range_comma:
          { \cs_set:Npn \acro_page_range_comma: { ,~ } }
        % get the numbers:
        \int_compare:nNnTF { \seq_count:N \l__acro_tmpb_seq } = { 1 }
          {
            \l__acro_page_name_tl
            \seq_get_right:cN { g__acro_#1_pages_seq } \l__acro_tmpa_tl
            \acro_get_thepage_from:N \l__acro_tmpa_tl
          }
          { \l__acro_pages_name_tl
            \seq_map_inline:cn { g__acro_#1_pages_seq }
              {
                \tl_if_blank:VTF \l__acro_last_page_tl
                  {% we're at the beginning
                    \seq_put_right:Nn \l__acro_tmpa_seq {##1}
                    \tl_set:Nn \l__acro_last_page_tl {##1}
                  }
                  {% we'at least at the second page
                     % current page:
                     \tl_set:Nn  \l__acro_current_page_tl {##1}
                     % last page:
                     \seq_get_right:NN \l__acro_tmpa_seq \l__acro_last_page_tl
                     \tl_if_eq:NNTF \l__acro_current_page_tl \l__acro_last_page_tl
                       {% there were more than one appearance on the current page
                         \seq_put_right:Nn \l__acro_tmpa_seq {##1}
                       }
                       {% new page
                         \acro_determine_page_ranges:NNn
                           \l__acro_tmpa_seq
                           \l__acro_write_pages_tl
                           {##1}
                       }
                  }
              }
            \seq_if_empty:NF \l__acro_tmpa_seq
              {
                \acro_determine_page_ranges:NNV
                  \l__acro_tmpa_seq
                  \l__acro_write_pages_tl
                  \l__acro_current_page_tl
              }
            \tl_use:N \l__acro_write_pages_tl
            \tl_clear:N \l__acro_write_pages_tl
          }
      }
    \seq_clear:N \l__acro_tmpa_seq
    \seq_clear:N \l__acro_tmpb_seq
  }

\cs_new:Npn \acro_determine_page_ranges:NNn #1#2#3
  {
    \seq_remove_duplicates:N #1
    % current page:
    \int_set:Nn \l__acro_tmpa_int { \acro_get_abspage:nnn #3 }
    \int_set:Nn \l__acro_tmpb_int { \acro_get_page_number:nnn #3 }
    % last page:
    \seq_get_right:NN #1 \l__acro_last_page_tl
    \int_set:Nn \l__acro_tmpc_int
      { \acro_get_abspage_from:N \l__acro_last_page_tl }
    \int_set:Nn \l__acro_tmpd_int
      { \acro_get_page_number_from:N \l__acro_last_page_tl }
    \bool_if:nTF
      {
        \int_compare_p:nNn
          { \l__acro_tmpa_int - \l__acro_tmpc_int }
           =
          { \l__acro_tmpb_int - \l__acro_tmpd_int }
        &&
        \int_compare_p:nNn
        { \l__acro_tmpb_int - \l__acro_tmpd_int } = {1}
      }
      {% same kind of page numbering, one page ahead
       % => possible range
         \seq_put_right:Nn #1 {#3}
      }
      {% any possible range ended
        \tl_put_right:Nn #2 { \acro_page_range_comma: }
        \int_compare:nNnTF
          { \seq_count:N #1 } > {2}
          {% real range
            \seq_get_left:NN #1 \l__acro_tmpa_tl
            \tl_put_right:Nx #2 { \acro_get_thepage_from:N \l__acro_tmpa_tl }
            \bool_if:NTF \l__acro_following_pages_bool
              { \tl_put_right:Nn #2 { \l__acro_next_pages_tl } }
              {
                \tl_put_right:Nn #2 { -- }
                \seq_get_right:NN #1 \l__acro_tmpa_tl
                \tl_put_right:Nx #2 { \acro_get_thepage_from:N \l__acro_tmpa_tl }
              }
          }
          {
            \int_compare:nNnTF
              { \seq_count:N #1 } = {2}
              {% range of two pages
                \seq_get_left:NN #1 \l__acro_tmpa_tl
                \tl_put_right:Nx #2 { \acro_get_thepage_from:N \l__acro_tmpa_tl }
                \bool_if:NTF \l__acro_following_page_bool
                  { \tl_put_right:Nn #2 { \l__acro_next_page_tl } }
                  {
                    \tl_put_right:Nn #2 { ,~ }
                    \seq_get_right:NN #1 \l__acro_tmpa_tl
                    \tl_put_right:Nx #2 { \acro_get_thepage_from:N \l__acro_tmpa_tl }
                  }
              }
              {% no range at all
                \seq_get_right:NN #1 \l__acro_tmpa_tl
                \tl_put_right:Nx #2 { \acro_get_thepage_from:N \l__acro_tmpa_tl }
              }
          }
        \seq_clear:N #1
        \seq_put_right:Nn #1 {#3}
      }
  }
\cs_generate_variant:Nn \acro_determine_page_ranges:NNn { NNV }

% --------------------------------------------------------------------------
\DeclareObjectType { acro-page-number } { 1 }

\DeclareTemplateInterface { acro-page-number } { default } { 1 }
  {
    display       : boolean   = true  ,
    punct         : boolean   = false ,
    punct-symbol  : tokenlist = {,}   ,
    brackets      : boolean   = false ,
    brackets-type : tokenlist = ()    ,
    space         : length    = .3ex
  }

\DeclareTemplateCode { acro-page-number } { default } { 1 }
  {
    display       = \l__acro_page_display_bool  ,
    punct         = \l__acro_page_punct_bool    ,
    punct-symbol  = \l__acro_page_punct_tl      ,
    brackets      = \l__acro_page_brackets_bool ,
    brackets-type = \l__acro_page_brackets_tl   ,
    space         = \l__acro_page_space_dim
  }
  {
    \AssignTemplateKeys
    \bool_if:NT \l__acro_page_display_bool
      {
        \bool_if:NT \l__acro_page_punct_bool
          { \tl_use:N \l__acro_page_punct_tl }
        \tl_use:N \c_space_tl
        \bool_if:NT \l__acro_page_brackets_bool
          { \tl_head:N \l__acro_page_brackets_tl }
        \acro_print_page_numbers:n {#1}
        \bool_if:NT \l__acro_page_brackets_bool
          { \tl_tail:N \l__acro_page_brackets_tl }
      }
  }

% the different styles:
\DeclareInstance { acro-page-number } { default } { default }
  { punct = true , punct-symbol = . }
\DeclareInstance { acro-page-number } { plain   } { default }
  { punct = false }
\DeclareInstance { acro-page-number } { comma   } { default } { punct = true }
\DeclareInstance { acro-page-number } { paren   } { default }
  { brackets=true , punct-symbol = ~ }
\DeclareInstance { acro-page-number } { none    } { default }
  { display = false }

% --------------------------------------------------------------------------
% the title of the list:
\cs_new:Npn \acro_list_title_format:n #1 {#1}

\DeclareObjectType { acro-title } { 1 }

\DeclareTemplateInterface { acro-title } { sectioning } { 1 }
  { name-format : function 1 = #1 }

\DeclareTemplateCode { acro-title } { sectioning } { 1 }
  { name-format = \acro_list_title_format:n }
  {
    \AssignTemplateKeys
    \acro_list_title_format:n {#1}
  }

% the different styles:
\DeclareInstance { acro-title } { chapter*    } { sectioning }
  { name-format = \chapter* {#1} }
\DeclareInstance { acro-title } { part*       } { sectioning }
  { name-format = \part* {#1} }
\DeclareInstance { acro-title } { section*    } { sectioning }
  { name-format = \section* {#1} }
\DeclareInstance { acro-title } { subsection* } { sectioning }
  { name-format = \subsection* {#1} }
\DeclareInstance { acro-title } { chapter     } { sectioning }
  { name-format = \chapter {#1} }
\DeclareInstance { acro-title } { part        } { sectioning }
  { name-format = \part {#1} }
\DeclareInstance { acro-title } { section     } { sectioning }
  { name-format = \section {#1} }
\DeclareInstance { acro-title } { subsection  } { sectioning }
  { name-format = \subsection {#1} }
\DeclareInstance { acro-title } { addchap     } { sectioning }
  { name-format = \addchap {#1} }
\DeclareInstance { acro-title } { addsec      } { sectioning }
  { name-format = \addsec {#1} }
\DeclareInstance { acro-title } { none        } { sectioning }
  { name-format = \use_none:n {#1} }

% --------------------------------------------------------------------------
% outputting the whole list
\DeclareObjectType { acro-list } { 3 }

% #1: id
% #2: excluded classes
% #3: continue if not excluded
\cs_new_protected:Npn \acro_is_excluded:nnF #1#2#3
  {
    \bool_set_false:N \l__acro_is_excluded_bool
    \tl_if_empty:nTF {#2}
      {#3}
      {
        \clist_map_inline:nn {#2}
          {
            \prop_get:NnNF \l__acro_class_prop {#1} \l__acro_tmpa_tl {}
            \tl_if_eq:VnT \l__acro_tmpa_tl {##1}
              { \bool_set_true:N \l__acro_is_excluded_bool }
          }
        \bool_if:NF \l__acro_is_excluded_bool {#3}
      }
  }

% build the list, dummy functions to be redefined in the template code:
\cs_new:Npn \acro_print_list_short:nn #1#2 { }
\cs_new:Npn \acro_print_list_long:n   #1   { }
\cs_new:Npn \acro_print_list_extra:n  #1   { }
\cs_new:Npn \acro_print_list_page:n   #1   { }

\cs_new:Npn \acroenparen #1 { ( #1 ) }

\cs_new_protected:Npn \acro_get_foreign:n #1
  {
    \prop_get:NnNT \l__acro_foreign_prop {#1} \l__acro_foreign_tl
      {
        \tl_use:N \l__acro_foreign_sep_tl
        \group_begin:
          \tl_use:N \l__acro_foreign_list_format_tl
          { \tl_use:N \l__acro_foreign_tl }
        \group_end:
      }
  }

% Test, if acronyms should be printed or not; needs testing for in/excluded
% classes and options `only-used' and `single':
\cs_new_protected:Npn \acro_list_allow_items:nn #1#2
  {
    \prop_map_inline:Nn \l__acro_short_prop
      {
        \acro_get:n {##1}
        \bool_if:nT
          {
            \bool_if_p:c { g__acro_##1_in_list_bool } &&
            (
              ( \l__acro_use_single_bool && \cs_if_exist_p:c { acro@##1@twice } )
              ||
              (
                !\l__acro_use_single_bool &&
                \cs_if_exist_p:c { acro@##1@once } &&
                \l__acro_print_only_used_bool
              )
            )
            ||
            ( !\l__acro_use_single_bool && !\l__acro_print_only_used_bool )
          }
          {
            \acro_is_excluded:nnF {##1} {#2}
              {
                \tl_if_blank:nTF {#1}
                  {
                    \acro_print_list_short:nn {##1} {##2}
                    \bool_if:NT \l__acro_capitalize_list_bool
                      { \bool_set_true:N \l__acro_first_upper_bool }
                    \acro_print_list_long:n {##1}
                    \bool_set_false:N \l__acro_first_upper_bool
                    \bool_if:NT \l__acro_foreign_bool
                      { \acro_get_foreign:n {##1} }
                    \acro_print_list_extra:n {##1}
                    \acro_print_list_page:n {##1}
                  }
                  {
                    \clist_map_inline:nn {#1}
                      {
                        \prop_get:NnNT \l__acro_class_prop {##1} \l__acro_tmpa_tl
                          {
                            \tl_set:Nn \l__acro_tmpb_tl { ####1 }
                            \tl_trim_spaces:N \l__acro_tmpa_tl
                            \tl_trim_spaces:N \l__acro_tmpb_tl
                            \tl_if_eq:NNT \l__acro_tmpa_tl \l__acro_tmpb_tl
                              {
                                \acro_print_list_short:nn {##1} { ##2 }
                                \bool_if:NT \l__acro_capitalize_list_bool
                                  { \bool_set_true:N \l__acro_first_upper_bool }
                                \acro_print_list_long:n {##1}
                                \bool_set_false:N \l__acro_first_upper_bool
                                \bool_if:NT \l__acro_foreign_bool
                                  { \acro_get_foreign:n {##1} }
                                \acro_print_list_extra:n {##1}
                                \acro_print_list_page:n {##1}
                              }
                          }
                      }
                  }
              }
          }
      }
  }

% list template:
\DeclareTemplateInterface {acro-list} {list} {3}
  { foreign-sep : tokenlist = { ~ } }

\DeclareTemplateCode {acro-list} {list} {3}
  { foreign-sep = \l__acro_foreign_sep_tl }
  {
    \AssignTemplateKeys
    \bool_set_true:N \l__acro_in_list_bool
    \__acro_activate_hyperref_support:
    \cs_set:Npn \acro_print_list_short:nn ##1##2
      {
        \item
          [
            \acro_hyper_target:nn
              {##1}
              {
                \__acro_acc_supp:nn
                  {##1}
                  { \__acro_write_short:n { \l__acro_list_short_format_tl { ##2 } } }
              }
          ]
      }
    \cs_set:Npn \acro_print_list_long:n ##1
      {
        \__acro_write_long:Nf \l__acro_list_long_format_tl
          {
            \prop_if_in:NnTF \l__acro_list_prop {##1}
              { \prop_get:Nn \l__acro_list_prop {##1} }
              { \prop_get:Nn \l__acro_long_prop {##1} }
          }
        \__acro_cite_if:Nn \l__acro_citation_all_bool {##1}
      }
    \cs_set_protected:Npn \acro_print_list_extra:n ##1
      {
        \prop_get:NnNT \l__acro_extra_prop {##1} \l__acro_tmpa_tl
          {
            \UseInstance { acro-extra } { \l__acro_extra_instance_tl }
              { \l__acro_tmpa_tl }
          }
      }
    \cs_set:Npn \acro_print_list_page:n ##1
      {
        \bool_if:nT { \cs_if_exist_p:c { acro@##1@once } }
          { \UseInstance { acro-page-number } { \l__acro_page_instance_tl } {##1} }
      }
    \begin {#1}
      \acro_list_allow_items:nn {#2} {#3}
    \end {#1}
  }

% table template:
\DeclareTemplateInterface {acro-list} {table} {3}
  {
    table       : tokenlist = longtable         ,
    table-spec  : tokenlist = lp{\l__acro_table_width_dim} ,
    foreign-sep : tokenlist = { ~ }
  }

\DeclareTemplateCode { acro-list } { table } { 3 }
  {
    table       = \l__acro_list_table_tl      ,
    table-spec  = \l__acro_list_table_spec_tl ,
    foreign-sep = \l__acro_foreign_sep_tl
  }
  {
    \AssignTemplateKeys
    \__acro_activate_hyperref_support:
    \cs_set:Npn \acro_print_list_short:nn ##1##2
      {
        \acro_hyper_target:nn
          {##1}
          {
            \__acro_acc_supp:nn
              {##1}
              { \__acro_write_short:n { \l__acro_list_short_format_tl { ##2 } } }
          }
        &
      }
    \cs_set:Npn \acro_print_list_long:n ##1
      {
        \__acro_write_long:Nf \l__acro_list_long_format_tl
          {
            \prop_if_in:NnTF \l__acro_list_prop {##1}
              { \prop_get:Nn \l__acro_list_prop {##1} }
              { \prop_get:Nn \l__acro_long_prop {##1} }
          }
        \__acro_cite_if:Nn \l__acro_citation_all_bool {##1}
      }
    \cs_set_protected:Npn \acro_print_list_extra:n ##1
      {
        \prop_get:NnNT \l__acro_extra_prop {##1} \l__acro_tmpa_tl
          {
            \UseInstance { acro-extra } { \l__acro_extra_instance_tl }
              { \l__acro_tmpa_tl }
          }
      }
    \cs_set:Npn \acro_print_list_page:n ##1
      {
        \bool_if:nT { \cs_if_exist_p:c { acro@##1@once } }
          { \UseInstance { acro-page-number } { \l__acro_page_instance_tl } {##1} }
        \tabularnewline
      }
    \exp_args:Noo \begin { \l__acro_list_table_tl } { \l__acro_list_table_spec_tl }
      \acro_list_allow_items:nn {#2} {#3}
    \exp_args:No \end { \l__acro_list_table_tl }
  }

% extra-table template:
\DeclareTemplateInterface { acro-list } { extra-table } { 3 }
  {
    table      : tokenlist = longtable         ,
    table-spec : tokenlist = lp{\l__acro_table_width_dim}ll
  }

\DeclareTemplateCode { acro-list } { extra-table } { 3 }
  {
    table      = \l__acro_list_table_tl      ,
    table-spec = \l__acro_list_table_spec_tl
  }
  {
    \AssignTemplateKeys
    \__acro_activate_hyperref_support:
    \cs_set:Npn \acro_print_list_short:nn ##1##2
      {
        \acro_hyper_target:nn
          {##1}
          {
            \__acro_acc_supp:nn
              {##1}
              { \__acro_write_short:n { \l__acro_list_short_format_tl { ##2 } } }
          }
        &
      }
    \cs_set:Npn \acro_print_list_long:n ##1
      {
        \__acro_write_long:Nf \l__acro_list_long_format_tl
          {
            \prop_if_in:NnTF \l__acro_list_prop {##1}
              { \prop_get:Nn \l__acro_list_prop {##1} }
              { \prop_get:Nn \l__acro_long_prop {##1} }
          }
        \__acro_cite_if:Nn \l__acro_citation_all_bool {##1}
        &
      }
    \cs_set_protected:Npn \acro_print_list_extra:n ##1
      {
        \prop_get:NnNT \l__acro_extra_prop {##1} \l__acro_tmpa_tl
          {
            \UseInstance { acro-extra } { \l__acro_extra_instance_tl }
              { \l__acro_tmpa_tl }
          }
        &
      }
    \cs_set:Npn \acro_print_list_page:n ##1
      {
        \bool_if:nT { \cs_if_exist_p:c { acro@##1@once } }
          { \UseInstance { acro-page-number } { \l__acro_page_instance_tl } {##1} }
        \tabularnewline
      }
    \exp_args:Noo \begin { \l__acro_list_table_tl } { \l__acro_list_table_spec_tl }
      \acro_list_allow_items:nn {#2} {#3}
    \exp_args:No \end { \l__acro_list_table_tl }
  }

% extra-table-rev template:
\DeclareTemplateInterface { acro-list } { extra-table-rev } { 3 }
  {
    table      : tokenlist = longtable         ,
    table-spec : tokenlist = llp{\l__acro_table_width_dim}l
  }

\DeclareTemplateCode { acro-list } { extra-table-rev } { 3 }
  {
    table      = \l__acro_list_table_tl      ,
    table-spec = \l__acro_list_table_spec_tl
  }
  {
    \AssignTemplateKeys
    \__acro_activate_hyperref_support:
    \cs_set:Npn \acro_print_list_short:nn ##1##2
      {
        \acro_hyper_target:nn
          {##1}
          { \__acro_acc_supp:nn {##1} { \__acro_write_short:n { ##2 } } }
        &
      }
    \cs_set_protected:Npn \acro_print_list_extra:n ##1
      {
        \bool_if:NT \l__acro_capitalize_list_bool
          { \bool_set_true:N \l__acro_first_upper_bool }
        \__acro_write_long:Nf \l__acro_long_format_tl
          {
            \prop_if_in:NnTF \l__acro_list_prop {##1}
              { \prop_get:Nn \l__acro_list_prop {##1} }
              { \prop_get:Nn \l__acro_long_prop {##1} }
          }
        \__acro_cite_if:Nn \l__acro_citation_all_bool {##1}
        &
      }
    \cs_set_protected:Npn \acro_print_list_long:n ##1
      {
        \prop_get:NnNT \l__acro_extra_prop {##1} \l__acro_tmpa_tl
          {
            \UseInstance { acro-extra } { \l__acro_extra_instance_tl }
              { \l__acro_tmpa_tl }
          }
        &
      }
    \cs_set:Npn \acro_print_list_page:n ##1
      {
        \bool_if:nT { \cs_if_exist_p:c { acro@##1@once } }
          { \UseInstance { acro-page-number } { \l__acro_page_instance_tl } {##1} }
        \tabularnewline
      }
    \exp_args:Noo \begin { \l__acro_list_table_tl } { \l__acro_list_table_spec_tl }
      \acro_list_allow_items:nn {#2} {#3}
    \exp_args:No \end { \l__acro_list_table_tl }
  }

% the different styles:
\DeclareInstance {acro-list} {list}
  { list }
  { }
\DeclareInstance { acro-list } { tabular }
  { table }
  { table = tabular }
\DeclareInstance { acro-list } { longtable }
  { table }
  { table = longtable }
\DeclareInstance { acro-list } { extra-longtable }
  { extra-table }
  { table = longtable }
\DeclareInstance { acro-list } { extra-tabular }
  { extra-table }
  { table = tabular }
\DeclareInstance { acro-list } { extra-longtable-rev }
  { extra-table-rev }
  { table = longtable }
\DeclareInstance { acro-list } { extra-tabular-rev }
  { extra-table-rev }
  { table = tabular }

% --------------------------------------------------------------------------
% automatic typesetting, the internals of \ac:
% #1: id
\cs_new_protected:Npn \acro_use:n #1
  {
    % get the acronym and the plural settings:
    \acro_get:n {#1}
    \acro_is_used:nTF {#1}
      {
        % this is not the first time
        \__acro_indefinite:nn {#1} {short}
        \__acro_acc_supp:nn
          {#1}
          { \__acro_write_short:V \l__acro_short_tl }
        \acro_after:n {#1}
      }
      {
        % this is the first time
        \bool_gset_true:c { g__acro_#1_first_use_bool }
        \__acro_is_single:nTF {#1}
          {
            \__acro_indefinite:nn {#1} {long}
            \__acro_write_long:NV \l__acro_long_format_tl \l__acro_long_tl
          }
          { 
            \UseInstance {acro-first} { \l__acro_first_instance_tl }
              {#1}
              { \l__acro_short_tl }
              { \l__acro_long_tl }
          }
      }
  }

\prg_new_conditional:Npnn \__acro_is_single:n #1 { p,T,TF }
  {
    \bool_if:nTF { !\l__acro_use_single_bool || \cs_if_exist_p:c { acro@#1@twice } }
      { \prg_return_false: } { \prg_return_true: }
  }

\cs_new_protected:Npn \acro_use_acronym:n #1
  { \use:c {bool_set_#1:N} \l__acro_mark_as_used_bool }

% --------------------------------------------------------------------------
% some helpers we'll need more often:
\cs_new_protected:Npn \acro_defined:n #1
  {
    \prop_if_in:NnF \l__acro_short_prop {#1}
      { \acro_serious_message:nnn {acro} {undefined} {#1} }
  }

\cs_new_protected:Npn \acro_get:n #1
  {
    \bool_if:NF \l__acro_in_list_bool
      { \leavevmode }
    % \acro_defined:n {#1}
    \__acro_activate_hyperref_support:
    \prop_get:NnNF \l__acro_short_prop {#1} \l__acro_tmpa_tl {}
    \__acro_make_link:nNN {#1} \l__acro_short_tl \l__acro_tmpa_tl
    \prop_get:NnNF \l__acro_short_plural_prop {#1} \l__acro_short_plural_tl {}
    \prop_get:NnNF \l__acro_long_prop {#1} \l__acro_long_tl {}
    \prop_get:NnNTF \l__acro_long_format_prop {#1}
      \l__acro_custom_long_format_tl
      { \bool_set_true:N  \l__acro_custom_long_format_bool }
      { \bool_set_false:N \l__acro_custom_long_format_bool }
    \prop_get:NnNF \l__acro_first_long_format_prop {#1}
      \l__acro_first_long_format_tl
      {}% to avoid hanging compilation if first-long-format hasn't been set
    \prop_get:NnNT \l__acro_long_pre_prop {#1} \l__acro_long_pre_tl
      { \tl_put_left:NV \l__acro_long_tl \l__acro_long_pre_tl }
    \prop_get:NnNF \l__acro_alt_prop {#1} \l__acro_tmpb_tl {}
    \__acro_make_link:nNN {#1} \l__acro_alt_tl \l__acro_tmpb_tl
    \prop_get:NnNTF \l__acro_format_prop {#1} \l__acro_custom_format_tl
      { \bool_set_true:N \l__acro_custom_format_bool }
      { \bool_set_false:N \l__acro_custom_format_bool }
    \__acro_set_plural:n {#1}
    \prop_get:NnNT \l__acro_long_post_prop {#1} \l__acro_long_post_tl
      { \tl_put_right:NV \l__acro_long_tl \l__acro_long_post_tl }
  }

\cs_new_protected:Npn \__acro_set_plural:n #1
  {
    \bool_if:NT \l__acro_use_plural_bool
      {
        \bool_if:nTF { \prop_get:Nn \l__acro_long_plural_form_prop {#1} }
          { \prop_get:NnNF \l__acro_long_plural_prop {#1} \l__acro_long_tl {} }
          {
            \tl_put_right:Nn \l__acro_long_tl
              { \prop_get:Nn \l__acro_long_plural_prop {#1} }
          }
      }
  }

% --------------------------------------------------------------------------
% enable us to know if the acronym is used only once and provide a different
% style for that:
\prg_new_protected_conditional:Npnn \acro_is_used:n #1 { TF }
  {
    \bool_if:nTF
      {
        \bool_if_p:c { g__acro_#1_used_bool } &&
        (
          (
            \bool_if_p:c { g__acro_#1_first_use_bool } &&
            \g__acro_mark_first_as_used_bool
          )
          ||
          ! \g__acro_mark_first_as_used_bool
        )
      }
      {
        \if@filesw
          \bool_if:NTF \l__acro_mark_as_used_bool
            {
              \iow_shipout_x:Nn \@auxout
                {
                  \token_to_str:N \acro@used@twice {#1}
                    { \thepage }
                    { \arabic{page} }
                    { \arabic{abspage} }
                }
            }
            {
              \iow_shipout_x:Nn \@auxout
                { \token_to_str:N \acro@used@twice {#1} {} {} {} }
            }
        \fi
        \prg_return_true:
      }
      {
        \bool_if:NTF \l__acro_mark_as_used_bool
          {
%            \if@filesw
              \iow_shipout_x:Nn \@auxout
                {
                  \token_to_str:N \acro@used@once {#1}
                    { \thepage }
                    { \arabic{page} }
                    { \arabic{abspage} }
                }

%             \fi
            \bool_if:nT
              {
                !\bool_if_p:c { g__acro_#1_label_bool } &&
                \l__acro_place_label_bool
              }
              {
                \bool_gset_true:c { g__acro_#1_label_bool }
                \label{\l__acro_label_prefix_tl #1}
              }
            \bool_gset_true:c { g__acro_#1_used_bool }
          }
          {
            \if@filesw
              \iow_shipout_x:Nn \@auxout
                { \token_to_str:N \acro@used@once {#1} {} {} {} }
            \fi
          }
        \prg_return_false:
      }
  }

\cs_new:Npn \acro_is_used:n #1
  { \acro_is_used:nTF {#1} { } { } }

% --------------------------------------------------------------------------
% the commands for the auxiliary file:
\cs_new_protected:Npn \acro@used@once #1#2#3#4
  {
    \cs_gset_nopar:cpn { acro@#1@once } {#1}
    \bool_gset_true:c { g__acro_#1_in_list_bool }
    \tl_if_empty:nF { #2#3#4 }
      { \seq_gput_right:cn { g__acro_#1_pages_seq } { {#2}{#3}{#4} } }
  }
\cs_new_protected:Npn \acro@used@twice #1#2#3#4
  {
    \cs_gset_nopar:cpn { acro@#1@twice } {#1}
    \tl_if_empty:nF { #2#3#4 }
      { \seq_gput_right:cn { g__acro_#1_pages_seq } { {#2}{#3}{#4} } }
  }

\cs_new_protected:Npn \acro@pages #1#2
  { \tl_gset:cn { g__acro_#1_recorded_pages_tl } {#2} }

\bool_new:N \g__acro_rerun_bool

\cs_new_protected:Npn \acro@rerun@check
  {
    \bool_if:NT \g__acro_rerun_bool
      {
        \@latex@warning@no@line
          {Acronyms~ may~ have~ changed.~ Please~ rerun~ LaTeX}
      }
  }

\AtEndDocument
  {
    \bool_gset_false:N \g__acro_rerun_bool
    \cs_gset_protected:Npn \acro@used@once #1#2#3#4
      {
        \tl_set:Nn \l__acro_tmpa_tl {#1}
        \tl_if_eq:cNF { acro@#1@once } \l__acro_tmpa_tl
          { \bool_gset_true:N \g__acro_rerun_bool }
      }
    \cs_gset_protected:Npn \acro@used@twice #1#2#3#4
      {
        \tl_set:Nn \l__acro_tmpa_tl {#1}
        \tl_if_eq:cNF { acro@#1@twice } \l__acro_tmpa_tl
          { \bool_gset_true:N \g__acro_rerun_bool }
      }
    \prop_map_inline:Nn \l__acro_short_prop
      {
        \seq_if_empty:cF { g__acro_#1_pages_seq }
          {
            \if@filesw
              \iow_shipout_x:Nn \@auxout
                {
                  \token_to_str:N \acro@pages {#1}
                    { \seq_use:cnnn { g__acro_#1_pages_seq } { | } { | } { | } }
                }
            \fi
          }
      }
    \iow_shipout_x:Nn \@auxout { \acro@rerun@check }
  }

% if `acro' is deactivated prevent unnecessary errors from aux file:
\if@filesw
\AtBeginDocument
  {
    \iow_now:Nx \@auxout
      {
        \token_to_str:N \providecommand \token_to_str:N \acro@used@once [4] {} ^^J
        \token_to_str:N \providecommand \token_to_str:N \acro@used@twice [4] {} ^^J
        \token_to_str:N \providecommand \token_to_str:N \acro@pages [2] {} ^^J
        \token_to_str:N \providecommand \token_to_str:N \acro@rerun@check {}
      }
  }
\fi

% --------------------------------------------------------------------------
\cs_new:Npn \acro_after:n #1
  {
    \__acro_cite_if:Nn \l__acro_citation_all_bool {#1}
    \__acro_index_if:Nn \l__acro_addto_index_bool {#1}
  }

% the standard internals:
\cs_new_protected:Npn \acro_short:n #1
  {
    \acro_get:n {#1}
    \acro_is_used:n {#1}
    \__acro_indefinite:nn {#1} { short }
    \__acro_is_single:nT {#1}
      { \cs_set_eq:NN \acro_hyper_link:nn \use_ii:nn }
    \__acro_acc_supp:nn
      {#1}
      { \__acro_write_short:V \l__acro_short_tl }
    \acro_after:n {#1}
  }

% get alternative entry:
\cs_new_protected:Npn \acro_alt:n #1
  {
    \acro_get:n {#1}
    \acro_is_used:n {#1}
    \__acro_indefinite:nn {#1} { alt }
    \__acro_is_single:nT {#1}
      { \cs_set_eq:NN \acro_hyper_link:nn \use_ii:nn }
    \__acro_acc_supp:nn
      {#1}
      { \__acro_write_short:V \l__acro_alt_tl }
    \acro_after:n {#1}
  }

% get long entry:
\cs_new_protected:Npn \acro_long:n #1
  {
    \acro_get:n {#1}
    \acro_is_used:n {#1}
    \__acro_indefinite:nn {#1} { long }
    \__acro_is_single:nT {#1}
      { \cs_set_eq:NN \acro_hyper_link:nn \use_ii:nn }
    \__acro_write_long:NV \l__acro_long_format_tl \l__acro_long_tl
    \acro_after:n {#1}
  }

% output like the first time:
\cs_new_protected:Npn \acro_first:n #1
  {
    \bool_gset_true:c { g__acro_#1_first_use_bool }
    \acro_get:n {#1}
    \acro_is_used:n {#1}
    \__acro_is_single:nT {#1}
      { \cs_set_eq:NN \acro_hyper_link:nn \use_ii:nn }
    \UseInstance { acro-first } { \l__acro_first_instance_tl }
      {#1}
      { \l__acro_short_tl }
      { \l__acro_long_tl }
  }

% output like the first time with own long version:
\cs_new_protected:Npn \acro_first_like:nn #1#2
  {
    \bool_gset_true:c { g__acro_#1_first_use_bool }
    \acro_get:n {#1}
    \acro_is_used:n {#1}
    \__acro_is_single:nT {#1}
      { \cs_set_eq:NN \acro_hyper_link:nn \use_ii:nn }
    \UseInstance { acro-first } { \l__acro_first_instance_tl }
      {#1}
      { \l__acro_short_tl }
      {#2}
  }

% ----------------------------------------------------------------------------
% citations:
\cs_new:Npn \__acro_citation_cmd:w { \cite } %{}

\cs_new_protected:Npn \acro_cite:
  { \bool_set_true:N \l__acro_citation_all_bool }

% #1 pre
% #2 post
% #3 key
\cs_new:Npn \__acro_cite:nnn #1#2#3
  {
    \quark_if_no_value:nTF {#1}
      { \__acro_citation_cmd:w {#3} }
      {
        \quark_if_no_value:nTF {#2}
          { \__acro_citation_cmd:w [ #1 ] {#3} }
          { \__acro_citation_cmd:w [ #1 ] [ #2 ] {#3} }
      }
  }
\cs_generate_variant:Nn \__acro_cite:nnn { VVV }

\cs_new_protected:Npn \__acro_cite_if:Nn #1#2
  {
    \bool_if:NT #1
      {
        \prop_get:NnNT \l__acro_citation_prop {#2} \l__acro_tmpa_tl
          {
            \prop_get:NnN \l__acro_citation_pre_prop {#2} \l__acro_tmpb_tl
            \prop_get:NnN \l__acro_citation_post_prop {#2} \l__acro_tmpc_tl
            \acro_no_break:
            \tl_use:N \l__acro_citation_space_tl
            \__acro_cite:VVV
              \l__acro_tmpb_tl
              \l__acro_tmpc_tl
              \l__acro_tmpa_tl
          }
      }
  }

% ----------------------------------------------------------------------------
% indexing:
\cs_new_protected:Npn \__acro_index_if:Nn #1#2
  {
    \bool_if:nT { #1 && \l__acro_mark_as_used_bool }
      {
        \prop_get:NnN \l__acro_index_cmd_prop  {#2} \l__acro_tmpa_tl
        \prop_get:NnN \l__acro_index_sort_prop {#2} \l__acro_tmpb_tl
        \prop_get:NnN \l__acro_index_prop      {#2} \l__acro_tmpc_tl
        \__acro_index:VnVV
          \l__acro_tmpa_tl
          {#2}
          \l__acro_tmpb_tl
          \l__acro_tmpc_tl
      }
  }

\cs_new_protected:Npn \acro_index:
  { \bool_set_true:N \l__acro_addto_index_bool }

\cs_new:Npn \__acro_index_cmd:n { \index }

% #1: cmd
% #2: key
% #3: sort
% #4: replace
\cs_new_protected:Npn \__acro_index:nnnn #1#2#3#4
  {
    \prop_get:NnNF \l__acro_short_prop  {#2} \l__acro_index_short_tl {}
    \prop_get:NnNF \l__acro_format_prop {#2} \l__acro_index_format_tl {}
    \quark_if_no_value:VTF \l__acro_index_format_tl
      { \tl_set:Nn \l__acro_tmpa_tl { \l__acro_short_format_tl \l__acro_index_short_tl } }
      { \tl_set:Nn \l__acro_tmpa_tl { \l__acro_index_format_tl \l__acro_index_short_tl } }
    \quark_if_no_value:nF {#1}
      { \cs_set:Npn \__acro_index_cmd:n {#1} }
    \quark_if_no_value:nTF { #4 }
      {
        \quark_if_no_value:nTF {#3}
          { \__acro_index_cmd:n { #2 @ { \l__acro_tmpa_tl } } }
          { \__acro_index_cmd:n { #3 @ { \l__acro_tmpa_tl } } }
      }
      { \__acro_index_cmd:n { #4 } }
  }
\cs_generate_variant:Nn \__acro_index:nnnn { VnVV }

% ----------------------------------------------------------------------------
% accessability support
\cs_new_eq:NN \__acro_acc_supp:nn \use_ii:nn

\cs_new:Npn \acro_acc_supp:nnn #1#2#3
  {
    \BeginAccSupp { ActualText = #1 , #2 }
      #3
    \EndAccSupp { }
  }
\cs_generate_variant:Nn \acro_acc_supp:nnn { VV }

\AtBeginDocument
  {
    \bool_if:NT \l__acro_acc_supp_bool
      {
        \RequirePackage { accsupp }
        \cs_set_protected:Npn \__acro_acc_supp:nn #1#2
          {
            \prop_get:NnNF \l__acro_acc_supp_prop {#1} \l__acro_acc_supp_tl
              { \prop_get:NnNF \l__acro_short_prop {#1} \l__acro_acc_supp_tl {} }
            \bool_if:NT \l__acro_use_plural_bool
              { \tl_put_right:NV \l__acro_acc_supp_tl \l__acro_short_plural_tl }
            \acro_acc_supp:VVn
              \l__acro_acc_supp_tl
              \l__acro_acc_supp_options_tl
              {#2}
          }
      }
  }

% --------------------------------------------------------------------------
% indefinite articles:
\cs_new_protected:Npn \acro_indefinite:
  {
    \bool_if:NTF \l__acro_first_upper_bool
      { \bool_set_true:N \l__acro_upper_indefinite_bool }
      { \bool_set_true:N \l__acro_indefinite_bool }
  }

\cs_new_protected:Npn \__acro_indefinite:nn #1#2
  {
    \bool_if:NT \l__acro_indefinite_bool
      { \prop_get:cn { l__acro_#2_indefinite_prop } {#1} ~ }
    \bool_if:NT \l__acro_upper_indefinite_bool
      {
         \__acro_first_upper_case:x
           { \prop_get:cn { l__acro_#2_indefinite_prop } {#1} } ~
      }
  }

% --------------------------------------------------------------------------
% experimental sorting feature:

% the following code is an adaption of expl3 code used for \str_if_eq:NN(TF)
\luatex_if_engine:TF
  {
    \tl_set:Nn \l__acro_tmpa_tl
      {
        acro ~ = ~ acro ~ or ~ { ~ } ~
        function ~ acro.strcmp ~ (A, B) ~
          if ~ A ~ == ~ B ~ then ~
            tex.write ("0") ~
          elseif ~ A ~ < ~ B ~ then ~
            tex.write ("-1") ~
          else ~
            tex.write ("1") ~
          end ~
        end
      }
    \luatex_directlua:D { \l__acro_tmpa_tl }
    \cs_new_protected:Npn \acro_strcmp:nn #1#2
      {
        \luatex_directlua:D
          {
            acro.strcmp
              (
                " \__acro_escape_x:n {#1} " ,
                " \__acro_escape_x:n {#2} "
              )
          }
      }
    \cs_new:Npn \__acro_escape_x:n #1
      {
        \luatex_luaescapestring:D
          { \etex_detokenize:D \exp_after:wN { \luatex_expanded:D {#1} } }
      }
  }
  { \cs_new_eq:NN \acro_strcmp:nn \pdftex_strcmp:D }

\AtBeginDocument
  {
    \bool_if:NT \l__acro_sort_bool
      {
        \cs_new_protected:Npn \acro_sort_prop:N #1
          {
            \seq_clear:N  \l__acro_tmpa_seq
            \prop_clear:N \l__acro_tmpa_prop
            \prop_clear:N \l__acro_tmpb_prop
            \prop_map_inline:Nn \l__acro_sort_prop
              {
                \seq_put_right:Nn \l__acro_tmpa_seq { ##2 }
                \prop_put:Nnn \l__acro_tmpa_prop { ##2 } {##1}
              }
            \seq_sort:Nn \l__acro_tmpa_seq
              {
                \tl_to_lowercase:n {
                  \int_compare:nTF { \acro_strcmp:nn {##1} { ##2 } = -1 }
                    { \sort_ordered: }
                    { \sort_reversed: }
                }
              }
            \seq_map_inline:Nn \l__acro_tmpa_seq
              {
                % get ID:
                \prop_get:NnNF \l__acro_tmpa_prop {##1} \l__acro_tmpa_tl {}
                % get prop entry of ID in #1:
                \prop_get:NVNT #1 \l__acro_tmpa_tl \l__acro_tmpb_tl
                  {
                    \prop_put:NVV \l__acro_tmpb_prop
                      \l__acro_tmpa_tl
                      \l__acro_tmpb_tl
                  }
              }
            \prop_set_eq:NN #1 \l__acro_tmpb_prop
          }
      }
  }

% --------------------------------------------------------------------------
% regarding list printing:
% this command ensures that a rerun warning is given when \printacronyms
% is set the first time. This mechanism doesn't make very much sense,
% should be replaced by a different and more efficient one
%
\cs_new_protected:Npn \acro@print@list
  { \cs_if_exist:NF \acro@printed@list { \cs_new:Npn \acro@printed@list { printed } } }

% --------------------------------------------------------------------------
% the user commands:
% #1: ID
% #2: true|false
\cs_new_protected:Npn \acro_check_acronym:nn #1#2
  {
    \acro_defined:n {#1}
    \acro_use_acronym:n {#2}
  }

% automatic:
\NewDocumentCommand \ac { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_use:n {#2}
    \group_end:
  }

\NewDocumentCommand \iac { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_indefinite:
      \acro_use:n {#2}
    \group_end:
  }

\NewDocumentCommand \Iac { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_upper:
      \acro_indefinite:
      \acro_use:n {#2}
    \group_end:
  }

\NewDocumentCommand \Ac { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_upper:
      \acro_use:n {#2}
    \group_end:
  }

\NewDocumentCommand \acp { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_plural:
      \acro_use:n {#2}
    \group_end:
  }

\NewDocumentCommand \Acp { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_plural:
      \acro_upper:
      \acro_use:n {#2}
    \group_end:
  }

% short:
\NewDocumentCommand \acs { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_short:n {#2}
    \group_end:
  }

\NewDocumentCommand \iacs { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_indefinite:
      \acro_short:n {#2}
    \group_end:
  }

\NewDocumentCommand \Iacs { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_upper:
      \acro_indefinite:
      \acro_short:n {#2}
    \group_end:
  }

\NewDocumentCommand \acsp { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_plural:
      \acro_short:n {#2}
    \group_end:
  }

% alt:
\NewDocumentCommand \aca { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_alt:n {#2}
    \group_end:
  }

\NewDocumentCommand \iaca { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_indefinite:
      \acro_alt:n {#2}
    \group_end:
  }

\NewDocumentCommand \Iaca { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_upper:
      \acro_indefinite:
      \acro_alt:n {#2}
    \group_end:
  }

\NewDocumentCommand \acap { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_plural:
      \acro_alt:n {#2}
    \group_end:
  }

% long:
\NewDocumentCommand \acl { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_long:n {#2}
    \group_end:
  }

\NewDocumentCommand \iacl { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_indefinite:
      \acro_long:n {#2}
    \group_end:
  }

\NewDocumentCommand \Iacl { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_upper:
      \acro_indefinite:
      \acro_long:n {#2}
    \group_end:
  }

\NewDocumentCommand \Acl { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_upper:
      \acro_long:n {#2}
    \group_end:
  }

\NewDocumentCommand \aclp { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_plural:
      \acro_long:n {#2}
    \group_end:
  }

\NewDocumentCommand \Aclp { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_plural:
      \acro_upper:
      \acro_long:n {#2}
    \group_end:
  }

% first:
\NewDocumentCommand \acf { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_first:n {#2}
    \group_end:
  }

\NewDocumentCommand \iacf { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_indefinite:
      \acro_first:n {#2}
    \group_end:
  }

\NewDocumentCommand \Iacf { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_upper:
      \acro_indefinite:
      \acro_first:n {#2}
    \group_end:
  }

\NewDocumentCommand \Acf { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_upper:
      \acro_first:n {#2}
    \group_end:
  }

\NewDocumentCommand \acfp { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_plural:
      \acro_first:n {#2}
    \group_end:
  }

\NewDocumentCommand \Acfp { sm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_plural:
      \acro_upper:
      \acro_first:n {#2}
    \group_end:
  }

% first-like:
\NewDocumentCommand \acflike { smm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_first_like:nn {#2} {#3}
    \group_end:
  }

\NewDocumentCommand \iacflike { smm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_indefinite:
      \acro_first_like:nn {#2} {#3}
    \group_end:
  }

\NewDocumentCommand \Iacflike { smm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_upper:
      \acro_indefinite:
      \acro_first_like:nn {#2} {#3}
    \group_end:
  }

\NewDocumentCommand \acfplike { smm }
  {
    \group_begin:
      \IfBooleanTF #1
        { \acro_check_acronym:nn {#2} {false} }
        { \acro_check_acronym:nn {#2} {true} }
      \acro_plural:
      \acro_first_like:nn {#2} {#3}
    \group_end:
  }

% reset outputs, they'll behave like the first time again (!not like the _only_
% time!):
\cs_new_protected:Npn \acro_reset:n #1
  {
    \bool_gset_false:c { g__acro_#1_used_bool }
    \bool_gset_false:c { g__acro_#1_first_use_bool }
  }

\cs_new_protected:Npn \acro_mark_as_used:n #1
  {
    \bool_gset_true:c { g__acro_#1_used_bool }
    \bool_gset_true:c { g__acro_#1_first_use_bool }
    \bool_gset_true:c { g__acro_#1_in_list_bool }
    \if@filesw
      \iow_shipout_x:Nn \@auxout
        { \token_to_str:N \acro@used@once {#1} {} {} {} }
      \iow_shipout_x:Nn \@auxout
        { \token_to_str:N \acro@used@twice {#1} {} {} {} }
    \fi
  }


\cs_new_protected:Npn \acro_reset_all:
  { \prop_map_inline:Nn \l__acro_short_prop { \acro_reset:n {##1} } }

\cs_new_protected:Npn \acro_mark_all_as_used:
  { \prop_map_inline:Nn \l__acro_short_prop { \acro_mark_as_used:n {##1} } }

\DeclareExpandableDocumentCommand \acifused { m }
  { \acro_if_acronym_used:nTF {#1} }

\prg_new_conditional:Npnn \acro_if_acronym_used:n #1 { TF }
  {
    \bool_if:nTF
      {
        \bool_if_p:c { g__acro_#1_used_bool } &&
        ( !\__acro_is_single_p:n {#1} )
      }
      { \prg_return_true: }
      { \prg_return_false: }
  }

\NewDocumentCommand \acresetall {}
  { \acro_reset_all: }

\NewDocumentCommand \acuseall {}
  { \acro_mark_all_as_used: }

\NewDocumentCommand \acreset { > { \SplitList { , } } m }
  { \ProcessList {#1} { \acro_reset:n } \ignorespaces }

\NewDocumentCommand \acuse { > { \SplitList { , } } m }
  { \ProcessList {#1} { \acro_mark_as_used:n } \ignorespaces }

% ---------------------------------------------------------------------------
% process options:
\ProcessKeysOptions {acro}

% ---------------------------------------------------------------------------
% PDF bookmark support
\cs_new:Npn \acpdfstring
  { \acro_pdf_string:n }

\cs_new:Npn \acpdfstringplural
  { \acro_pdf_string_plural:n }

\prg_new_conditional:Npnn \acro_if_star_gobble:n #1 {TF}
  {
    \if_meaning:w *#1
      \prg_return_true:
    \else:
      \prg_return_false:
    \fi:
  }

\cs_new:Npn \acro_pdf_string:n #1
  {
    \acro_if_star_gobble:nTF {#1}
      { \prop_get:Nn \l__acro_pdfstring_prop }
      { \prop_get:Nn \l__acro_pdfstring_prop {#1} }
  }

\cs_new:Npn \acro_pdf_string_plural:n #1
  {
    \acro_if_star_gobble:nTF {#1}
      { \prop_get:Nn \l__acro_pdfstring_plural_prop }
      { \prop_get:Nn \l__acro_pdfstring_plural_prop {#1} }
  }

\AtBeginDocument
  {
    \@ifpackageloaded { hyperref }
      {
        \bool_set_true:N \l__acro_hyperref_loaded_bool
        \pdfstringdefDisableCommands
          {
            \cs_set_eq:NN \ac   \acpdfstring
            \cs_set_eq:NN \Ac   \acpdfstring
            \cs_set_eq:NN \acs  \acpdfstring
            \cs_set_eq:NN \acl  \acpdfstring
            \cs_set_eq:NN \Acl  \acpdfstring
            \cs_set_eq:NN \acf  \acpdfstring
            \cs_set_eq:NN \Acf  \acpdfstring
            \cs_set_eq:NN \aca  \acpdfstring
            \cs_set_eq:NN \acp  \acpdfstringplural
            \cs_set_eq:NN \Acp  \acpdfstringplural
            \cs_set_eq:NN \acsp \acpdfstringplural
            \cs_set_eq:NN \aclp \acpdfstringplural
            \cs_set_eq:NN \Aclp \acpdfstringplural
            \cs_set_eq:NN \acfp \acpdfstringplural
            \cs_set_eq:NN \Acfp \acpdfstringplural
            \cs_set_eq:NN \acap \acpdfstringplural
          }
        \cs_set_protected:Npn \acro_hyper_page:n #1 { \hyperpage {#1} }
      } {}
  }

% --------------------------------------------------------------------------
% additional variables:
\tl_new:N \l__acro_current_key_tl

% --------------------------------------------------------------------------
% key and order checking
\msg_new:nnn {acro} {no-id}
  { Something~has~gone~wrong,~you've~probably~forgotten~to~set~the~acronym~ID. }

\msg_new:nnn {acro} {before-short}
  {
    You've~set~The~key~`#2'~before~the~`short'~key~for~acronym~`#1'~but~
    needs~to~be~set~after~it.
  }

\msg_new:nnn {acro} {missing}
  { The~`#2'~key~for~acronym~`#1'~is~missing. }

\msg_new:nnn {acro} {doubled-key}
  {
    It~seems~to~me~you~have~used~the~`#1'~key~before.~If~you~haven't~there's~
    something~different~wrong~and~I'm~lost.~You~'re~on~your~own~now.
  }

\cs_new_protected:Npn \__acro_key_check:nn #1#2
  {
    \tl_if_blank:VT \l__acro_current_key_tl
      { \acro_serious_message:nn {acro} {no-id} }
    \bool_if:cF { l__acro_#1_short_set_bool }
      { \acro_serious_message:nnnn {acro} {before-short} {#1} {#2} }
    \bool_new:c { l__acro_#1_#2_set_bool }
    \bool_set_true:c { l__acro_#1_#2_set_bool }
  }

\cs_new_protected:Npn \__acro_first_key_check:n #1
  {
    \cs_if_exist:cTF { l__acro_#1_short_set_bool }
      {
         \bool_if:cT { l__acro_#1_short_set_bool }
           { \acro_serious_message:nnn {acro} {doubled-key} {#1} }
      }
      {
        \bool_new:c { l__acro_#1_short_set_bool }
        \bool_set_true:c { l__acro_#1_short_set_bool }
      }
  }

% --------------------------------------------------------------------------
% the internal key selection functions for \DeclareAcronym:

% #1: name in associated cs
% #2: key name
% #3: action
\cs_new_protected:Npn \acro_declare_key_generic:nnn #1#2#3
  {
    \prop_new:c { l__acro_#1_prop }
    \cs_new_protected:cpn { __acro_declare_#1:nn } ##1##2
      {
        #3
      }
    \cs_generate_variant:cn { __acro_declare_#1:nn } { V }
    \keys_define:nn { acro / declare-acronym }
      {
        #2 .code:n =
          \use:c {__acro_declare_#1:Vn} \l__acro_current_key_tl {##1}
      }
  }
\cs_generate_variant:Nn \cs_generate_variant:Nn {c}

% #1: name in associated cs
% #2: key name
% #3: action
\cs_new_protected:Npn \acro_declare_key:nnn #1#2#3
  {
    \acro_declare_key_generic:nnn {#1} {#2}
      {
        \__acro_key_check:nn {##1} {#2}
        \prop_put:cnn { l__acro_#1_prop } {##1} {##2}
        #3
      }
  }

% #1: name in associated cs
% #2: key name
\cs_new_protected:Npn \acro_declare_key:nn #1#2
  { \acro_declare_key:nnn {#1} {#2} {} }
\cs_generate_variant:Nn \acro_declare_key:nn { V }

\cs_new_protected:Npn \acro_declare_simple_key:n #1
  {
    \tl_set:Nn \l__acro_tmpa_tl {#1}
    \tl_replace_all:Nnn \l__acro_tmpa_tl {-} {_}
    \acro_declare_key:Vn \l__acro_tmpa_tl {#1}
  }

% #1: new alias key
% #2: old key
\cs_new_protected:Npn \acro_declare_key_alias:nn #1#2
  {
    \keys_define:nn { acro / declare-acronym }
      { #1 .meta:n = { #2 = {##1} } }
  }

% --------------------------------------------------------------------------
% declare the keys for \DeclareAcronym:
% short:
\acro_declare_key_generic:nnn {short} {short}
  {
    \__acro_first_key_check:n {#1}
    \prop_put:Nnn \l__acro_short_prop      {#1} {#2}
    \prop_put:Nnn \l__acro_sort_prop       {#1} {#1}
    \prop_put:Nnn \l__acro_index_sort_prop {#1} {#1}
    \prop_put:Nnn \l__acro_alt_prop        {#1} {#2}
    \prop_put:Nnx \l__acro_pdfstring_prop  {#1} { \exp_not:n {#2} }
    \prop_put:Nnn \l__acro_short_plural_prop
      {#1} { \l__acro_default_plural_tl }
    \prop_put:Nnx \l__acro_short_indefinite_prop
      {#1} { \l__acro_default_indefinite_tl }
    \prop_put:Nnx \l__acro_alt_indefinite_prop
      {#1} { \l__acro_default_indefinite_tl }
    \prop_put:Nnx \l__acro_pdfstring_plural_prop
      {#1} { \exp_not:n {#2} \exp_not:V \l__acro_default_plural_tl }
  }

% short plural:
\acro_declare_simple_key:n {short-plural}

% long:
\acro_declare_key:nnn {long} {long}
  {
    \prop_put:Nnn \l__acro_long_plural_form_prop {#1} { \c_false_bool }
    \prop_put:Nnx \l__acro_long_indefinite_prop
      {#1} { \l__acro_default_indefinite_tl }
    \bool_if:cF { l__acro_#1_long-plural_set_bool }
      {
        \prop_put:Nnn \l__acro_long_plural_prop
          {#1} { \l__acro_default_plural_tl }
      }
  }

% list:
\acro_declare_simple_key:n {list}

% long plural:
\acro_declare_key:nnn {long_plural} {long-plural}
  { \prop_put:Nnn \l__acro_long_plural_form_prop {#1} { \c_false_bool } }

% long plural form:
\acro_declare_key_generic:nnn {long_plural_form} {long-plural-form}
  {
    \__acro_key_check:nn {#1} { long-plural-form }
    \prop_put:Nnn \l__acro_long_plural_form_prop {#1} { \c_true_bool }
    \prop_put:Nnn \l__acro_long_plural_prop {#1} {#2}
  }

% short indefinite article:
\acro_declare_simple_key:n {short-indefinite}

% long indefinite article:
\acro_declare_simple_key:n {long-indefinite}

% pre long:
\acro_declare_simple_key:n {long-pre}

% post long:
\acro_declare_simple_key:n {long-post}

% sort:
\acro_declare_key:nnn {sort} {sort}
  {
    \bool_if:cF { l__acro_#1_index-sort_set_bool }
      { \prop_put:Nnn \l__acro_index_sort_prop {#1} {#2} }
  }

% alternative:
\acro_declare_key:nnn {alt} {alt}
  {
    \prop_put:Nnx \l__acro_alt_indefinite_prop
      {#1} { \l__acro_default_indefinite_tl }
  }

% alt. indefinite article:
\acro_declare_simple_key:n {alt-indefinite}

% foreign:
\acro_declare_simple_key:n {foreign}

% format:
\acro_declare_simple_key:n {format}

% short format:
\acro_declare_key_alias:nn {short-format} {format}

% long format:
\acro_declare_simple_key:n {long-format}

% first long format:
\acro_declare_simple_key:n {first-long-format}

% pdfstring:
\prop_new:N \l__acro_pdfstring_prop
\prop_new:N \l__acro_pdfstring_plural_prop
\cs_new_protected:Npn \__acro_declare_pdfstring:nw #1#2/#3/#4 \acro_stop:
  {
    \__acro_key_check:nn {#1} { pdfstring }
    \prop_put:Nnx \l__acro_pdfstring_prop {#1} {#2}
    \tl_if_empty:nTF { #3 }
      {
        \prop_put:Nnx \l__acro_pdfstring_plural_prop
          {#1} { \exp_not:n {#2} \exp_not:V \l__acro_default_plural_tl }
      }
      {
        \prop_put:Nnx \l__acro_pdfstring_plural_prop
          {#1} { \exp_not:n { #2#3 } }
      }
  }
\cs_generate_variant:Nn \__acro_declare_pdfstring:nw { V }
\keys_define:nn { acro / declare-acronym }
  {
    pdfstring    .code:n =
      \__acro_declare_pdfstring:Vw \l__acro_current_key_tl #1 // \acro_stop: ,
  }

% class:
\acro_declare_simple_key:n {class}

% extra information:
\acro_declare_simple_key:n {extra}

% acc supp:
\acro_declare_key:nn {acc_supp} {accsupp}

% citation:
\prop_new:N \l__acro_citation_prop
\prop_new:N \l__acro_citation_pre_prop
\prop_new:N \l__acro_citation_post_prop
\cs_new_protected:Npn \__acro_declare_citation:nw #1#2[#3]#4[#5]#6#7 \acro_stop:
  {
    % no options: #1: ID, #2: key, #3 is blank
    % 1 option:   #1: ID, #4: key, #3: option, #5 is blank
    % 2 options:  #1: ID: #6: key, #3: first option, #5: second option
    \tl_if_blank:nF { #2#4#6 }
      {
        \tl_if_empty:nTF { #3 }
          { \__acro_declare_citation_aux:nnnn {#1} { } { } {#2} }
          {
            \tl_if_empty:nTF { #5 }
              { \__acro_declare_citation_aux:nnnn {#1} { #3 } {    } { #4 } }
              { \__acro_declare_citation_aux:nnnn {#1} { #3 } { #5 } { #6 } }
          }
      }
  }
\cs_generate_variant:Nn \__acro_declare_citation:nw { V }

\keys_define:nn { acro / declare-acronym }
  {
    cite .code:n =
      \__acro_declare_citation:Vw
        \l__acro_current_key_tl #1 [][] \scan_stop: \acro_stop:
  }

\cs_new_protected:Npn \__acro_declare_citation_aux:nnnn #1#2#3#4
  {
    \__acro_key_check:nn {#1} { cite }
    \prop_put:Nnn \l__acro_citation_prop {#1} { #4 }
    \tl_if_empty:nF {#2}
      { \prop_put:Nnn \l__acro_citation_pre_prop {#1} {#2} }
    \tl_if_empty:nF { #3 }
      { \prop_put:Nnn \l__acro_citation_post_prop {#1} { #3 } }
  }

% TODO:
% add index entries, by default \index{<sort>@<short>}
% index: overwrite default <sort>@<short> entry completely
% index-sort: overwrite the <sort> part of <sort>@<short> entry

% need to take care of custom index cmd, at least
%  - \index{}
%  - \index[]{}
% question is, though, if it should be the same one for all acronyms?
% I go for yes but would also add a `post' key that allows to add arbitrary
% TeX code after an acronym is typeset

% index:
\acro_declare_simple_key:n {index}

% index-sort:
\acro_declare_simple_key:n {index-sort}

% index-cmd:
\acro_declare_simple_key:n {index-cmd}

% --------------------------------------------------------------------------
% acronym macros:
\cs_new_protected:Npn \acro_define_acronym_macro:n #1
  {
    \bool_if:NT \l__acro_create_macros_bool
      {
        \cs_if_exist:cTF {#1}
          {
            \bool_if:NTF \l__acro_strict_bool
              { \cs_set:cpn {#1} { \ac {#1} \acro_xspace: } }
              { \acro_serious_message:nnn {acro} {macro} {#1} }
          }
          { \cs_new:cpn {#1} { \ac {#1} \acro_xspace: } }
      }
  }

% --------------------------------------------------------------------------
% internal acronym declaring function:
\cs_new_protected:Npn \acro_declare_acronym:nn #1#2
  {
    \tl_set:Nn \l__acro_current_key_tl {#1}
    \keys_set:nn { acro / declare-acronym } {#2}
    \bool_new:c { g__acro_#1_first_use_bool }
    \bool_new:c { g__acro_#1_used_bool }
    \bool_new:c { g__acro_#1_label_bool }
    \bool_new:c { g__acro_#1_in_list_bool }
    \bool_if:NF \l__acro_print_only_used_bool
      { \bool_gset_true:c { g__acro_#1_in_list_bool } }
    \acro_create_page_records:n {#1}
    \acro_define_acronym_macro:n {#1}
    \tl_clear:N \l__acro_current_key_tl
    \bool_if:cF { l__acro_#1_short_set_bool }
      { \acro_serious_message:nnnn {acro} {missing} {#1} {short} }
    \bool_if:cF { l__acro_#1_long_set_bool }
      { \acro_serious_message:nnnn {acro} {missing} {#1} {long} }
  }

% --------------------------------------------------------------------------
% the user command:
\NewDocumentCommand \DeclareAcronym { mm }
  { \acro_declare_acronym:nn {#1} {#2} }

% --------------------------------------------------------------------------
% print the list:
% #1: list of classes
% #2: list of excluded classes
\tl_new:N \l__acro_included_classes_tl
\tl_new:N \l__acro_excluded_classes_tl

\cs_new_protected:Npn \acro_use_list_instance:nn #1#2
  {
    \UseInstance { acro-list } { \l__acro_list_instance_tl }
      { \l__acro_list_type_tl } {#1} {#2}
  }
\cs_generate_variant:Nn \acro_use_list_instance:nn { VV }

\keys_define:nn { acro / print-acronyms }
  {
    include-classes .tl_set:N   = \l__acro_included_classes_tl ,
    exclude-classes .tl_set:N   = \l__acro_excluded_classes_tl ,
    name            .tl_set:N   = \l__acro_list_name_tl ,
    header          .code:n     =
      \acro_option_deprecated:nn { header } { heading }
      \tl_set:Nn \l__acro_list_title_tl {#1} ,
    heading         .tl_set:N   = \l__acro_list_title_tl ,
    sort            .bool_set:N = \l__acro_sort_bool
  }

\cs_new_protected:Npn \acro_print_acronyms:n #1
  {
    \group_begin:
      % this is a cheap trick to prevent the \@noitemerr
      % if one forgot to delete either the aux file or
      % remove \printacronyms -- but it's local:
      \cs_set:Npn \@noitemerr {}
      \tl_clear:N \l__acro_included_classes_tl
      \tl_clear:N \l__acro_excluded_classes_tl
      \keys_set:nn { acro / print-acronyms } {#1}
      \iow_now:Nx \@auxout { \string \acro@print@list }
      \bool_if:NT \l__acro_sort_bool
        { \acro_sort_prop:N \l__acro_short_prop }
      \UseInstance { acro-title } { \l__acro_list_title_tl }
        { \l__acro_list_name_tl }
      \cs_if_exist:NTF \acro@printed@list
        {
          \acro_use_list_instance:VV
            \l__acro_included_classes_tl
            \l__acro_excluded_classes_tl
        }
        { \@latex@warning@no@line {Rerun~to~get~acronym~list~right} }
    \group_end:
  }

\NewDocumentCommand \printacronyms { O{} }
  { \acro_print_acronyms:n {#1} }

% --------------------------------------------------------------------------
% language support
\RequirePackage { translations }
% Listenname
\DeclareTranslationFallback        { acronym-list-name } { Acronyms }
\DeclareTranslation { English    } { acronym-list-name } { Acronyms }
\DeclareTranslation { American   } { acronym-list-name } { Acronyms }
\DeclareTranslation { British    } { acronym-list-name } { Acronyms }
\DeclareTranslation { French     } { acronym-list-name } { Acronymes }
\DeclareTranslation { German     } { acronym-list-name } { Abk\"urzungen }
\DeclareTranslation { Italian    } { acronym-list-name } { Acronimi }
\DeclareTranslation { Portuguese } { acronym-list-name } { Acr\'onimos }
\DeclareTranslation { Spanish    } { acronym-list-name } { Siglas }
\DeclareTranslation { Catalan    } { acronym-list-name } { Sigles }
\DeclareTranslation { Turkish    } { acronym-list-name } { K\i saltmalar }
\tl_set:Nn \l__acro_list_name_tl { \GetTranslation { acronym-list-name } }
% Seitenname
\DeclareTranslationFallback        { acronym-page-name } { p. }
\DeclareTranslation { English    } { acronym-page-name } { p. }
\DeclareTranslation { German     } { acronym-page-name } { S. }
\DeclareTranslation { Portuguese } { acronym-page-name } { p. }
\tl_set:Nn \l__acro_page_name_tl { \GetTranslation { acronym-page-name }\@\, }
% Seitenname - Plural
\DeclareTranslationFallback        { acronym-pages-name } { pp. }
\DeclareTranslation { English    } { acronym-pages-name } { pp. }
\DeclareTranslation { German     } { acronym-pages-name } { S. }
\DeclareTranslation { Portuguese } { acronym-pages-name } { pp. }
\tl_set:Nn \l__acro_pages_name_tl { \GetTranslation { acronym-pages-name }\@\, }
% einzelne folgende Seite
\DeclareTranslationFallback        { acronym-next-page } { f. }
\DeclareTranslation { English    } { acronym-next-page } { f. }
\DeclareTranslation { German     } { acronym-next-page } { f. }
\DeclareTranslation { Portuguese } { acronym-next-page } { s. }
\tl_set:Nn \l__acro_next_page_tl { \,\GetTranslation {acronym-next-page }\@ }
% mehrere folgende Seiten
\DeclareTranslationFallback        { acronym-next-pages } { ff. }
\DeclareTranslation { English    } { acronym-next-pages } { ff. }
\DeclareTranslation { German     } { acronym-next-pages } { ff. }
\DeclareTranslation { Portuguese } { acronym-next-pages } { ss. }
\tl_set:Nn \l__acro_next_pages_tl { \,\GetTranslation {acronym-next-pages }\@ }

\tex_endinput:D
% --------------------------------------------------------------------------
% HISTORY:
2012/06/22 v0.1  - first public release
2012/06/23 v0.1a - bug fix, added `strict' and `macros' option and creation of
                   shortcut macros
                 - added capitalized version of long forms
                 - added `sort' option
2012/06/24 v0.1b - added \Acf and \Acfp, added option `plural-ending'
2012/06/24 v0.1c - added excluded argument to \printacronyms
2012/06/24 v0.2  - renamed \NewAcronym => \DeclareAcronym
                   \AcronymFormat => \DeclareAcronymFormat
2012/06/25 v0.2a - new first-style's: `short' and `reversed'
2012/06/25 v0.3  - new list formats: extra-tabular, extra-longtable,
                   extra-tabular-rev, extra-longtable-rev
                 - extra precaution when using \printacronyms to avoid errors.
2012/06/27 v0.3a - new option `list-caps', \Acp added
2012/06/29 v0.3b - extended the `text' template to the `acro-first' object
                 - added `acro-first' instances `plain' and `plain-reversed'
2012/07/16 v0.3c - small adjustments to the documentation
2012/07/23 v0.3d - first CTAN version
2012/07/24 v0.3e - adapted to updated l3kernel
2012/09/28 v0.4  - added means to add citations to acronyms
2012/10/07 v0.4a - new options: "uc-cmd", "list-long-format"
                 - preliminary language support, needs package `translations'
2012/11/30 v0.5  - added starred variants of the commands that won't mark an
                   acronym as used
                 - added \acreset{<id>}
                 - added preliminary support for pdf strings: in pdf strings
                   always the singular lowercase short version is inserted
                   (the equivalent of \acs)
2012/12/14 v0.6  - bug with not-colored links resolved
                 - bug introduced with the last update (full expansion of the
                   short entry) resolved
                 - option `xspace' added
2013/01/02 v0.6a - \acuseall
2013/01/16 v1.0  - new syntax of \DeclareAcronym
                 - new option `version'
                 - new `accsupp' acronym property
                 - new `sort' acronym property
                 - new syntax of \printacronyms
                 - new default: `sort=true' 
                 - new options `page-ranges', `next-page', `next-pages',
                   `pages-name', `record-pages'
                 - no automatic label placement for page number referencing
                   any more
2013/01/26 v1.1  - bug fix in the plural detection
                 - new keys `long-pre' and `long-post'
                 - new keys `index', `index-sort' and `index-cmd'
                 - new options `index' and `index-cmd'
2013/01/29 v1.1a - added `long-format' key
                 - renamed `format' key into `short-format', kept `format' for
                   compatibility reasons
2013/02/09 v1.2  - error message instead of hanging when an undefined acronym
                   is used
                 - added `first-long-format' key and `first-long-format' option
                 - added \acflike and \acfplike
                 - improvements and bug fixes to the page recording mechanism
                 - new option `mark-as-used'
                 - new keys: `short-indefinite', `alt-indefinite' and
                   `long-indefinite'
                 - new commands: \iac, \Iac, \iacs, \Iacs, \iaca, \Iaca, \iacl,
                   \Iacl, \iacf, \Iacf, \iacflike and \Iacflike
2013/04/04 v1.2a - added Portuguese translations
2013/05/06 v1.3  - protected internal commands where appropriate
                 - new option `sort' to \printacronyms
                 - renamed options `print-acronyms/header' and `list-header'
                   into `print-acronyms/heading' and `list-heading'
                 - fix: added missing group to \printacronyms
                 - add key `foreign'
                 - rewritten page-recording:
                   * most importantly: record them at shipout; this is done
                     when \acro@used@once or \acro@used@twice are written to
                     the aux file
                   * no restrictions regarding \pagenumbering
                   * options `page-ranges' and `record-pages' are deprecated
                   * new options `following-page' and `following-pages'
                 - disable \@noitemerr in the list of acronyms: we don't need
                   it there but there are occasions when it is annoying
                 - cleaned the sty file, added a few more comments
2013/05/09 v1.3a - Bug fix: corrected wrong argument checking in \Ac, thanks
                   to Michel Voßkuhle
2013/05/30 v1.3b - obey \if@filesw
2013/06/16 v1.3c - added \leavevmode to \acro_get:n
2013/07/08 v1.3d - corrected wrong call of \leavevmode in the list
                   (list-type=list)
2013/08/07 v1.3e - bug fix in the list when testing for used acronyms
                 - new commands \acifused, \acfirstupper
2013/08/27 v1.4  - new property `list'
2013/09/02 v1.4a - bug fix: used acronyms are added to the list when the list
                   is printed before the use
                 - \DeclareAcronym may now be used after \begin{document}
2013/09/24 v1.4b - bug fix: only-used=false works again for only declared but
                   unused acronyms (only if option single is not used)
2013/11/04 v1.4c - remove \hbox from the written short form
                 - changed \__acro_make_link:nNN in a way that it doesn't box
                   its when links are deactivated
2013/11/22 v1.4d - require `l3sort' independently from the `sort' option
                   instead of at begin document in order to avoid conflicts
                   with `babel' and `french'
2013/12/18 v1.5  - new option `label=true|false' that
                   places \label{<prefix>:<id>} the first time an acronym is
                   used
                 - new option `pages=first|all' that determines if in the list
                   of acronyms all appearances are listed or only the first
                   time; implicitly sets `label=true'
2015/02/26 v1.6  - new `acro-title' instance `none'
                 - change of expl3's tl uppercasing function (adapt to updates
                   of l3kernel and friends
                 - new package option `messages=silent|loud'
                 - fix issue https://bitbucket.org/cgnieder/acro/issue/23/
                 - fix issue https://bitbucket.org/cgnieder/acro/issue/24/
                 - fix issue https://bitbucket.org/cgnieder/acro/issue/28/
                 - drop support for version 0
2015/04/08 v1.6a - more generalized user command definitions, see
                   http://tex.stackexchange.com/q/236362/ for an application

% --------------------------------------------------------------------------
% TODO:
- extend option `macros' to also define uppercase macros, possibly as a choice
- https://bitbucket.org/cgnieder/acro/issue/18
- options user1, user2, user3? (Genitiv lang, Akkusativ lang,...) Bsp: ``des
  Bundesinstituts für Risikobewertung''
- Option `totoc'!?
- revise list styles to allow _full_ customization by creating own instances!
  this probably needs a handfull of macros that give access to the entries
  without worrying about internals
- add \ACF, \ACFP, \ACL and \ACLP that will print all words of the long form
  capitalized
