% --------------------------------------------------------------------------
% the ACRO package
% 
%   Typeset Acronyms
% 
% --------------------------------------------------------------------------
% Clemens Niederberger
% Web:    https://bitbucket.org/cgnieder/acro/
% E-Mail: contact@mychemistry.eu
% --------------------------------------------------------------------------
% Copyright 2011-2013 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,xparse,l3keys2e,xtemplate}
\ProvidesExplPackage
  {acro}
  {2013/05/06}
  {1.3}
  {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:nnnn { acro } { undefined }
  { You've~requested~acronym~`#1'~but~it~seems~that~it~was~never~defined! }
  {
    You've~requested~acronym~`#1'~\msg_line_context: \c_space_tl but~you~
    apperantly~haven't~defined~it,~yet!~Maybe~you've~mispelled~it?
  }

\msg_new:nnnn { acro } { version }
  { You've~selected~the~version~option~`#1'~which~doesn't~exist. }
  {
    You've~selected~the~version~option~`#1'~which~doesn't~exist.~
    I'm~using~option~`#2'~instead.
  }

\msg_new:nnnn { acro } { replaced }
  { The~#1~`#2'~is~deprecated.~Use~`#3'~instead~\msg_line_context:. }
  {
    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:nnnn { acro } { deprecated }
  { The~#1~`#2'~is~deprecated.~\msg_line_context:. }
  {
    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.
  }

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

\cs_new:Npn \acro_command_deprecated:NN #1#2
  {
    \tl_if_blank:nTF { #2 }
      {
        \msg_warning:nnnnn { acro } { deprecated }
          { command }
          { \token_to_str:N #1 }
      }
      {
        \msg_warning: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      \l__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_version_selected_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

% --------------------------------------------------------------------------
% 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_active_version_tl
\tl_new:N   \l__acro_version_zero_tl
\tl_set:Nn  \l__acro_version_zero_tl { 0 }
\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

% --------------------------------------------------------------------------
% comma list variables
\clist_new:N \l__acro_versions_clist

% --------------------------------------------------------------------------
% property list variables:
\prop_new:N \l__acro_short_prop
\prop_new:N \l__acro_alt_prop
\prop_new:N \l__acro_sort_prop
\prop_new:N \l__acro_long_prop
\prop_new:N \l__acro_class_prop
\prop_new:N \l__acro_replace_plural_prop
\prop_new:N \l__acro_short_plural_prop
\prop_new:N \l__acro_long_plural_prop
\prop_new:N \l__acro_short_indefinite_prop
\prop_new:N \l__acro_long_indefinite_prop
\prop_new:N \l__acro_alt_indefinite_prop
\prop_new:N \l__acro_long_pre_prop
\prop_new:N \l__acro_long_post_prop
\prop_new:N \l__acro_extra_prop
\prop_new:N \l__acro_foreign_prop
\prop_new:N \l__acro_format_prop
\prop_new:N \l__acro_long_format_prop
\prop_new:N \l__acro_first_long_format_prop
\prop_new:N \l__acro_citation_prop
\prop_new:N \l__acro_citation_pre_prop
\prop_new:N \l__acro_citation_post_prop
\prop_new:N \l__acro_pdfstring_prop
\prop_new:N \l__acro_pdfstring_plural_prop
\prop_new:N \l__acro_acc_supp_prop
\prop_new:N \l__acro_index_prop
\prop_new:N \l__acro_index_sort_prop
\prop_new:N \l__acro_index_cmd_prop

% --------------------------------------------------------------------------
% 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:Npn \__acro_first_upper_case:n #1
  { \tl_expandable_uppercase:n { \tl_head:n { #1 } } \tl_tail:n { #1 } }
\cs_generate_variant:Nn \__acro_first_upper_case:n { x }

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

% --------------------------------------------------------------------------
% versioning:
\clist_put_right:Nn \l__acro_versions_clist { 0 }
\clist_put_right:Nn \l__acro_versions_clist { 1 }

\cs_new_protected:Npn \__acro_select_version:n #1
  {
    \clist_if_in:NnTF \l__acro_versions_clist { #1 }
      {
        \file_input:n { acro#1.def }
        \tl_set:Nn \l__acro_active_version_tl { #1 }
      }
      {
        \msg_warning:nnxx { acro } { version } { #1 } { 1 }
        \file_input:n { acro1.def }
        \tl_set:Nn \l__acro_active_version_tl { 1 }
      }
    \bool_set_true:N \l__acro_version_selected_bool
  }

% --------------------------------------------------------------------------
% options:
\keys_define:nn { acro }
  {
    version           .code:n     = \__acro_select_version:n { #1 } ,
    accsupp           .bool_set:N = \l__acro_acc_supp_bool          ,
    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      ,
    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_set_true:N \l__acro_mark_first_as_used_bool             ,
    mark-as-used / any   .code:n  =
      \bool_set_false:N \l__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-all          .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 }

% --------------------------------------------------------------------------
% 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 }
      { \hbox:n { #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
  {
    \tl_set:Nn #2
       {
         \acro_hyper_link:nn { #1 } { \phantom { #3 } }
         \__acro_is_single:nTF { #1 } { \hbox_overlap_left:n { #3 } }
           {
             \bool_if:nTF { \l__acro_use_hyperref_bool && \l__acro_hyperref_loaded_bool }
               { \acro_color_link:n { \hbox_overlap_left:n { #3 } } }
               { \hbox_overlap_left:n { #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 }

\AtBeginDocument
  {
    \tl_if_eq:NNT \l__acro_active_version_tl \l__acro_version_zero_tl
      {
        \cs_set:Npn \acro_print_page_numbers:n #1
          {
            \acro_no_break:
            \skip_horizontal:N \l__acro_page_space_dim
            \acro_no_break:
            \tl_use:N \l__acro_page_name_tl
            \pageref{ac:#1}
          }
      }
  }

% --------------------------------------------------------------------------
\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 } }

% --------------------------------------------------------------------------
% 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
          {
            ( \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
    \__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_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_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_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_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 { 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_if:n #1
  {
    \tl_if_blank:nTF { #1 }
      { \bool_set_true:N \l__acro_mark_as_used_bool }
      { \bool_set_false: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 }
      { \msg_error:nnx { acro } { undefined } { #1 } }
  }

\cs_new_protected:Npn \acro_get:n #1
  {
    \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_replace_plural_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 } &&
            \l__acro_mark_first_as_used_bool
          )
          ||
          ! \l__acro_mark_first_as_used_bool
        )
      }
      {
        \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 } {} {} {} }
          }
        \prg_return_true:
      }
      {
        \bool_if:NTF \l__acro_mark_as_used_bool
          {
            \iow_shipout_x:Nn \@auxout
              {
                \token_to_str:N \acro@used@once { #1 }
                  { \thepage }
                  { \arabic{page} }
                  { \arabic{abspage} }
              }
            \bool_if:nT
              {
                !\bool_if_p:c { g__acro_#1_label_bool } &&
                \tl_if_eq_p:NN \l__acro_active_version_tl \l__acro_version_zero_tl
              }
              {
                \bool_gset_true:c { g__acro_#1_label_bool }
                \label{ac:#1}
              }
            \bool_gset_true:c { g__acro_#1_used_bool }
          }
          {
            \iow_shipout_x:Nn \@auxout
             { \token_to_str:N \acro@used@once { #1 } {} {} {} }
          }
        \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
  {
    \expandafter\xdef\csname acro@#1@once \endcsname { #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@used@twice #1#2#3#4
  {
    \expandafter\xdef\csname acro@#1@twice \endcsname { #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 } }

\AtEndDocument
  {
    \cs_set_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
          { \@tempswatrue }
      }
    \prop_map_inline:Nn \l__acro_short_prop
      {
        \seq_if_empty:cF { g__acro_#1_pages_seq }
          {
            \iow_shipout_x:Nn \@auxout
              {
                \token_to_str:N \acro@pages { #1 }
                  { \seq_use:cnnn { g__acro_#1_pages_seq } { | } { | } { | } }
              }
          }
      }
  }

% if `acro' is deactivated prevent unnecessary errors from aux file:
\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] {}
      }
  }

% --------------------------------------------------------------------------
\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 } %{}

% #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: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_aux:nn #1#2
  {
    \BeginAccSupp { ActualText = #1 }
      #2
    \EndAccSupp { }
  }
\cs_generate_variant:Nn \__acro_acc_supp_aux:nn { V }

\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_aux:Vn \l__acro_acc_supp_tl { #2 }
          }
      }
  }

% --------------------------------------------------------------------------
% indefinite articles:
\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:
\AtBeginDocument
  {
    \bool_if:NT \l__acro_sort_bool
      {
        \RequirePackage { l3sort }
        \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 { \pdfstrcmp { ##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:
% automatic:
\NewDocumentCommand \ac { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \acro_use:n { #2 }
    \group_end:
  }

\NewDocumentCommand \iac { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_indefinite_bool
      \acro_use:n { #2 }
    \group_end:
  }

\NewDocumentCommand \Iac { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_upper_indefinite_bool
      \acro_use:n { #2 }
    \group_end:
  }

\NewDocumentCommand \Ac { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \acro_use_if:nn { #1 } { #2 }
      \bool_set_true:N \l__acro_first_upper_bool
      \acro_use:n { #2 }
    \group_end:
  }

\NewDocumentCommand \acp { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_use_plural_bool
      \acro_use:n { #2 }
    \group_end:
  }

\NewDocumentCommand \Acp { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_use_plural_bool
      \bool_set_true:N \l__acro_first_upper_bool
      \acro_use:n { #2 }
    \group_end:
  }

% short:
\NewDocumentCommand \acs { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \acro_short:n { #2 }
    \group_end:
  }

\NewDocumentCommand \iacs { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_indefinite_bool
      \acro_short:n { #2 }
    \group_end:
  }

\NewDocumentCommand \Iacs { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_upper_indefinite_bool
      \acro_short:n { #2 }
    \group_end:
  }

\NewDocumentCommand \acsp { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_use_plural_bool
      \acro_short:n { #2 }
    \group_end:
  }

% alt:
\NewDocumentCommand \aca { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \acro_alt:n { #2 }
    \group_end:
  }

\NewDocumentCommand \iaca { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_indefinite_bool
      \acro_alt:n { #2 }
    \group_end:
  }

\NewDocumentCommand \Iaca { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_upper_indefinite_bool
      \acro_alt:n { #2 }
    \group_end:
  }

\NewDocumentCommand \acap { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_use_plural_bool
      \acro_alt:n { #2 }
    \group_end:
  }

% long:
\NewDocumentCommand \acl { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \acro_long:n { #2 }
    \group_end:
  }

\NewDocumentCommand \iacl { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_indefinite_bool
      \acro_long:n { #2 }
    \group_end:
  }

\NewDocumentCommand \Iacl { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_upper_indefinite_bool
      \acro_long:n { #2 }
    \group_end:
  }

\NewDocumentCommand \Acl { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_first_upper_bool
      \acro_long:n { #2 }
    \group_end:
  }

\NewDocumentCommand \aclp { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_use_plural_bool
      \acro_long:n { #2 }
    \group_end:
  }

\NewDocumentCommand \Aclp { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_use_plural_bool
      \bool_set_true:N \l__acro_first_upper_bool
      \acro_long:n { #2 }
    \group_end:
  }

% first:
\NewDocumentCommand \acf { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \acro_first:n { #2 }
    \group_end:
  }

\NewDocumentCommand \iacf { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_indefinite_bool
      \acro_first:n { #2 }
    \group_end:
  }

\NewDocumentCommand \Iacf { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_upper_indefinite_bool
      \acro_first:n { #2 }
    \group_end:
  }

\NewDocumentCommand \Acf { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_first_upper_bool
      \acro_first:n { #2 }
    \group_end:
  }

\NewDocumentCommand \acfp { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_use_plural_bool
      \acro_first:n { #2 }
    \group_end:
  }

\NewDocumentCommand \Acfp { sm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_use_plural_bool
      \bool_set_true:N \l__acro_first_upper_bool
      \acro_first:n { #2 }
    \group_end:
  }

% first-like:
\NewDocumentCommand \acflike { smm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \acro_first_like:nn { #2 } { #3 }
    \group_end:
  }

\NewDocumentCommand \iacflike { smm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_indefinite_bool
      \acro_first_like:nn { #2 } { #3 }
    \group_end:
  }

\NewDocumentCommand \Iacflike { smm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_upper_indefinite_bool
      \acro_first_like:nn { #2 } { #3 }
    \group_end:
  }

\NewDocumentCommand \acfplike { smm }
  {
    \group_begin:
      \acro_defined:n { #2 }
      \IfBooleanTF { #1 }
        { \acro_use_if:n { * } }
        { \acro_use_if:n {   } }
      \bool_set_true:N \l__acro_use_plural_bool
      \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 }
    \cs_if_exist:cTF { acro@#1@once }
      { \cs_gset:cpn { acro@#1@twice } { #1 } }
      { \cs_gset:cpn { acro@#1@once  } { #1 } }
  }

\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 } } }

\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 }

% TODO: why did I do this instead of \tl_if_eq:nnTF ?
\cs_new:Npn \acro_tl_if_eq:nnTF #1#2
  { \ifx#1#2\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi }

\cs_new:Npn \acro_pdf_string:n #1
  {
    \acro_tl_if_eq:nnTF {*} {#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_tl_if_eq:nnTF {*} {#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 } }
      } {}
  }

% --------------------------------------------------------------------------
% 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 }\@ }

% --------------------------------------------------------------------------
% load default version
\bool_if:NF \l__acro_version_selected_bool
  { \__acro_select_version:n { 1 } }

\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

% --------------------------------------------------------------------------
% TODO:
- 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