% --------------------------------------------------------------------------
% 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.
% --------------------------------------------------------------------------
\ProvidesFile{acro1.def}

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

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

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

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

\msg_new:nnnn { acro } { doubled-key }
  { It~seems~to~me~you~have~used~the~`#1'~key~before. }
  {
    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:Npn \__acro_key_check:nn #1#2
  {
    \tl_if_blank:VT \l__acro_current_key_tl
      { \msg_error:nn { acro } { no-id } }
    \bool_if:cF { l__acro_#1_short_set_bool }
      { \msg_error:nnxx { 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: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 }
           { \msg_error:nnx { 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 selection functions:
% short:
\cs_new:Npn \__acro_declare_short:nn #1#2
  {
    \__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 }
  }
\cs_generate_variant:Nn \__acro_declare_short:nn { V }

\cs_new:Npn \__acro_declare_short_plural:nn #1#2
  {
    \__acro_key_check:nn { #1 } { short-plural }
    \prop_put:Nnn \l__acro_short_plural_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_short_plural:nn { V }

% long:
\cs_new:Npn \__acro_declare_long:nn #1#2
  {
    \__acro_key_check:nn { #1 } { long }
    \prop_put:Nnn \l__acro_replace_plural_prop { #1 } { \c_false_bool }
    \prop_put:Nnn \l__acro_long_prop { #1 } { #2 }
    \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 }
      }
  }
\cs_generate_variant:Nn \__acro_declare_long:nn { V }

% long plural:
\cs_new:Npn \__acro_declare_long_plural:nn #1#2
  {
    \__acro_key_check:nn { #1 } { long-plural }
    \prop_put:Nnn \l__acro_replace_plural_prop { #1 } { \c_false_bool }
    \prop_put:Nnn \l__acro_long_plural_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_long_plural:nn { V }

% long plural form:
\cs_new:Npn \__acro_declare_long_plural_form:nn #1#2
  {
    \__acro_key_check:nn { #1 } { long-plural-form }
    \prop_put:Nnn \l__acro_replace_plural_prop { #1 } { \c_true_bool }
    \prop_put:Nnn \l__acro_long_plural_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_long_plural_form:nn { V }

% short indefinite article:
\cs_new:Npn \__acro_declare_short_indefinite:nn #1#2
  {
    \__acro_key_check:nn { #1 } { short-indefinite }
    \prop_put:Nnn \l__acro_short_indefinite_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_short_indefinite:nn { V }

% long indefinite article:
\cs_new:Npn \__acro_declare_long_indefinite:nn #1#2
  {
    \__acro_key_check:nn { #1 } { long-indefinite }
    \prop_put:Nnn \l__acro_long_indefinite_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_long_indefinite:nn { V }

% pre long:
\cs_new:Npn \__acro_declare_long_pre:nn #1#2
  {
    \__acro_key_check:nn { #1 } { long-pre }
    \prop_put:Nnn \l__acro_long_pre_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_long_pre:nn { V }

% post long:
\cs_new:Npn \__acro_declare_long_post:nn #1#2
  {
    \__acro_key_check:nn { #1 } { long-post }
    \prop_put:Nnn \l__acro_long_post_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_long_post:nn { V }

% sort:
\cs_new:Npn \__acro_declare_sort:nn #1#2
  {
    \__acro_key_check:nn { #1 } { sort }
    \prop_put:Nnn \l__acro_sort_prop { #1 } { #2 }
    \bool_if:cF { l__acro_#1_index-sort_set_bool }
      { \prop_put:Nnn \l__acro_index_sort_prop { #1 } { #2 } }
  }
\cs_generate_variant:Nn \__acro_declare_sort:nn { V }

% alternative:
\cs_new:Npn \__acro_declare_alt:nn #1#2
  {
    \__acro_key_check:nn { #1 } { alt }
    \prop_put:Nnn \l__acro_alt_prop { #1 } { #2 }
    \prop_put:Nnx \l__acro_alt_indefinite_prop
      { #1 } { \l__acro_default_indefinite_tl }
  }
\cs_generate_variant:Nn \__acro_declare_alt:nn { V }

% alt. indefinite article:
\cs_new:Npn \__acro_declare_alt_indefinite:nn #1#2
  {
    \__acro_key_check:nn { #1 } { alt-indefinite }
    \prop_put:Nnn \l__acro_alt_indefinite_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_alt_indefinite:nn { V }

% format:
\cs_new:Npn \__acro_declare_format:nn #1#2
  {
    \__acro_key_check:nn { #1 } { format }
    \prop_put:Nnn \l__acro_format_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_format:nn { V }

% long format:
\cs_new:Npn \__acro_declare_long_format:nn #1#2
  {
    \__acro_key_check:nn { #1 } { long-format }
    \prop_put:Nnn \l__acro_long_format_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_long_format:nn { V }

% first long format:
\cs_new:Npn \__acro_declare_first_long_format:nn #1#2
  {
    \__acro_key_check:nn { #1 } { first-long-format }
    \prop_put:Nnn \l__acro_first_long_format_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_first_long_format:nn { V }

% pdfstring:
\cs_new: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 }

% class:
\cs_new:Npn \__acro_declare_class:nn #1#2
  {
    \__acro_key_check:nn { #1 } { class }
    \prop_put:Nnn \l__acro_class_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_class:nn { V }

% extra information:
\cs_new:Npn \__acro_declare_extra:nn #1#2
  {
    \__acro_key_check:nn { #1 } { extra }
    \prop_put:Nnn \l__acro_extra_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_extra:nn { V }

% acc supp:
\cs_new:Npn \__acro_declare_acc_supp:nn #1#2
  {
    \__acro_key_check:nn { #1 } { accsupp }
    \prop_put:Nnn \l__acro_acc_supp_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_acc_supp:nn { V }

% citation:
\cs_new: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 }

\cs_new: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:
\cs_new:Npn \__acro_declare_index:nn #1#2
  {
    \__acro_key_check:nn { #1 } { index }
    \prop_put:Nnn \l__acro_index_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_index:nn { V }

% index-sort:
\cs_new:Npn \__acro_declare_index_sort:nn #1#2
  {
    \__acro_key_check:nn { #1 } { index-sort }
    \prop_put:Nnn \l__acro_index_sort_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_index_sort:nn { V }

% index-cmd:
\cs_new:Npn \__acro_declare_index_cmd:nn #1#2
  {
    \__acro_key_check:nn { #1 } { index-cmd }
    \prop_put:Nnn \l__acro_index_cmd_prop { #1 } { #2 }
  }
\cs_generate_variant:Nn \__acro_declare_index_cmd:nn { V }

% --------------------------------------------------------------------------
% the keys of \DeclareAcronym
\keys_define:nn { acro / declare-acronym }
  {
    short        .code:n =
      \__acro_declare_short:Vn \l__acro_current_key_tl { #1 } ,
    short-plural .code:n =
      \__acro_declare_short_plural:Vn \l__acro_current_key_tl { #1 } ,
    alt          .code:n =
      \__acro_declare_alt:Vn \l__acro_current_key_tl { #1 } ,
    long         .code:n =
      \__acro_declare_long:Vn \l__acro_current_key_tl { #1 } ,
    long-plural  .code:n =
      \__acro_declare_long_plural:Vn \l__acro_current_key_tl { #1 } ,
    long-plural-form .code:n =
      \__acro_declare_long_plural_form:Vn \l__acro_current_key_tl { #1 } ,
    short-indefinite .code:n =
      \__acro_declare_short_indefinite:Vn \l__acro_current_key_tl { #1 } ,
    alt-indefinite .code:n =
      \__acro_declare_alt_indefinite:Vn \l__acro_current_key_tl { #1 } ,
    long-indefinite .code:n =
      \__acro_declare_long_indefinite:Vn \l__acro_current_key_tl { #1 } ,
    long-pre     .code:n =
      \__acro_declare_long_pre:Vn \l__acro_current_key_tl { #1 } ,
    long-post    .code:n =
      \__acro_declare_long_post:Vn \l__acro_current_key_tl { #1 } ,
    sort         .code:n =
      \__acro_declare_sort:Vn \l__acro_current_key_tl { #1 } ,
    extra        .code:n =
      \__acro_declare_extra:Vn \l__acro_current_key_tl { #1 } ,
    format       .code:n =
      \__acro_declare_format:Vn \l__acro_current_key_tl { #1 } ,
    short-format .code:n =
      \__acro_declare_format:Vn \l__acro_current_key_tl { #1 } ,
    long-format  .code:n =
      \__acro_declare_long_format:Vn \l__acro_current_key_tl { #1 } ,
    first-long-format .code:n =
      \__acro_declare_first_long_format:Vn \l__acro_current_key_tl { #1 } ,
    class        .code:n =
      \__acro_declare_class:Vn \l__acro_current_key_tl { #1 } ,
    cite         .code:n =
      \__acro_declare_citation:Vw \l__acro_current_key_tl #1 [][] \scan_stop: \acro_stop: ,
    pdfstring    .code:n =
      \__acro_declare_pdfstring:Vw \l__acro_current_key_tl #1 // \acro_stop: ,
    accsupp      .code:n =
      \__acro_declare_acc_supp:Vn \l__acro_current_key_tl { #1 } ,
    index        .code:n =
      \__acro_declare_index:Vn \l__acro_current_key_tl { #1 } ,
    index-sort   .code:n =
      \__acro_declare_index_sort:Vn \l__acro_current_key_tl { #1 } ,
    index-cmd    .code:n =
      \__acro_declare_index_cmd:Vn \l__acro_current_key_tl { #1 }
  }

\cs_new:Npn \acro_define_acronym_macro:n #1
  {
    \bool_if:NT \l__acro_create_macros_bool
      {
        \cs_if_exist:cTF { #1 }
          {
            \bool_if:NT \l__acro_strict_bool
              { \cs_set:cpn { #1 } { \ac { #1 } \acro_xspace: } }
          }
          { \cs_new:cpn { #1 } { \ac { #1 } \acro_xspace: } }
      }
  }

% --------------------------------------------------------------------------
% internal acronym declaring function:
\cs_new: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 }
    \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 }
      { \msg_error:nnxx { acro } { missing } { #1 } { short } }
    \bool_if:cF { l__acro_#1_long_set_bool }
      { \msg_error:nnxx { acro } { missing } { #1 } { long } }
  }

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

% --------------------------------------------------------------------------
% 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: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          .tl_set:N = \l__acro_list_title_tl
  }

\cs_new:Npn \acro_print_acronyms:n #1
  {
    \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} }
  }

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