\LeadsheetsExplLibrary{chordnames}
  {2014/08/10 typesetting chord names with easy syntax}

\leadsheets_load_library:n {musicsymbols}

\bool_new:N \l__leadsheets_output_notation_german_bool
\bool_new:N \l__leadsheets_input_notation_german_bool
\bool_new:N \l__leadsheets_notation_literal_bool
\bool_set_true:N \l__leadsheets_notation_literal_bool

\tl_new:N \l__leadsheets_chord_tl
\tl_new:N \l__leadsheets_tension_tl
\tl_new:N \l__leadsheets_format_tl

\cs_new_protected:Npn \leadsheets_tension_sym:Nn #1#2
  { \tl_replace_all:Nnn #1 {#2} { \textsuperscript{#2} } }

\cs_new_protected:Npn \leadsheets_chord_sym:Nnn #1#2#3
  { \tl_replace_all:Nnn #1 {#2} {#3} }

\tl_new:N \l__leadsheets_sharp_tl
\tl_new:N \l__leadsheets_flat_tl
\tl_new:N \l__leadsheets_doublesharp_tl
\tl_new:N \l__leadsheets_doubleflat_tl
\tl_new:N \l__leadsheets_full_dim_tl
\tl_new:N \l__leadsheets_half_dim_tl
\tl_new:N \l__leadsheets_aug_tl
\tl_new:N \l__leadsheets_major_tl
\tl_new:N \l__leadsheets_minor_tl
\tl_new:N \l__leadsheets_sus_tl
\tl_new:N \l__leadsheets_dim_tl
\tl_new:N \l__leadsheets_add_tl
\tl_new:N \l__leadsheets_major_seven_tl

\tl_set:Nn \l__leadsheets_sharp_tl       {\sharp}
\tl_set:Nn \l__leadsheets_flat_tl        {\flat}
\tl_set:Nn \l__leadsheets_doublesharp_tl {\doublesharp}
\tl_set:Nn \l__leadsheets_doubleflat_tl  {\doubleflat}
\tl_set:Nn \l__leadsheets_half_dim_tl    {\o{}}
\tl_set:Nn \l__leadsheets_full_dim_tl    {o}
\tl_set:Nn \l__leadsheets_aug_tl         {+}
\tl_set:Nn \l__leadsheets_major_tl       {}
\tl_set:Nn \l__leadsheets_minor_tl       {m}
\tl_set:Nn \l__leadsheets_sus_tl         {\textsuperscript{sus}}
\tl_set:Nn \l__leadsheets_dim_tl         {\textsuperscript{dim}}
\tl_set:Nn \l__leadsheets_add_tl         {\textsuperscript{add}}
\tl_set:Nn \l__leadsheets_major_seven_tl {\textsuperscript{maj7}}
\tl_set:Nn \l__leadsheets_major_nine_tl  {\textsuperscript{maj9}}

\group_begin:
% for convenient input of sharps:
\char_set_catcode_other:N \#
% because ^ is active in the song environment:
\char_set_catcode_active:N \^
% # is other so we need another parameter character:
\char_set_catcode_parameter:N \!

\cs_gset_protected:Npn \leadsheets_chord:
  {
    \group_begin:
      \tl_use:N \l__leadsheets_format_tl
      \char_set_catcode_other:N \#
      \char_set_catcode_active:N \^
      \leadsheets_chord_aux:n
  }

\cs_gset_protected:Npn \leadsheets_chord_aux:n !1
 {
    \tl_set:Nn \l__leadsheets_chord_tl {!1}
    \leadsheets_chord_sym:Nnn  \l__leadsheets_chord_tl {maj7}
      {\l__leadsheets_major_seven_tl}
    \leadsheets_chord_sym:Nnn  \l__leadsheets_chord_tl {maj9}
      {\l__leadsheets_major_nine_tl}
    \leadsheets_chord_sym:Nnn  \l__leadsheets_chord_tl {sus}
      {\l__leadsheets_sus_tl}
    \leadsheets_chord_sym:Nnn  \l__leadsheets_chord_tl {^} {\textsuperscript}
    \bool_if:NF \l__leadsheets_notation_literal_bool
      {
        % convert to English to German input:
        \bool_if:NT \l__leadsheets_input_notation_german_bool
          {
            \leadsheets_chord_sym:Nnn \l__leadsheets_chord_tl {B}   {@@@}
            \leadsheets_chord_sym:Nnn \l__leadsheets_chord_tl {H}   {B}
            \leadsheets_chord_sym:Nnn \l__leadsheets_chord_tl {@@@} {Bb}
          }
        % convert to English to German output:
        \bool_if:NT \l__leadsheets_output_notation_german_bool
          {
            \leadsheets_chord_sym:Nnn \l__leadsheets_chord_tl {Bb}  {@@@}
            \leadsheets_chord_sym:Nnn \l__leadsheets_chord_tl {B}   {H}
            \leadsheets_chord_sym:Nnn \l__leadsheets_chord_tl {@@@} {B}
            \leadsheets_chord_sym:Nnn \l__leadsheets_chord_tl {B#}  {H}
          }
      }
    \leadsheets_chord_sym:Nnn  \l__leadsheets_chord_tl {#b} {}
    \leadsheets_chord_sym:Nnn  \l__leadsheets_chord_tl {b#} {}
    \leadsheets_chord_sym:Nnn  \l__leadsheets_chord_tl {##}
      {\l__leadsheets_doublesharp_tl}
    \leadsheets_chord_sym:Nnn  \l__leadsheets_chord_tl {bb}
      {\l__leadsheets_doubleflat_tl}
    \leadsheets_chord_sym:Nnn  \l__leadsheets_chord_tl {#} {\l__leadsheets_sharp_tl}
    \leadsheets_chord_sym:Nnn  \l__leadsheets_chord_tl {b} {\l__leadsheets_flat_tl}
    \leadsheets_chord_sym:Nnn  \l__leadsheets_chord_tl {dim} {\l__leadsheets_dim_tl}
    \leadsheets_chord_sym:Nnn  \l__leadsheets_chord_tl {add} {\l__leadsheets_add_tl}
    \leadsheets_tension_sym:Nn \l__leadsheets_chord_tl {0}
    \leadsheets_tension_sym:Nn \l__leadsheets_chord_tl {1}
    \leadsheets_tension_sym:Nn \l__leadsheets_chord_tl {2}
    \leadsheets_tension_sym:Nn \l__leadsheets_chord_tl {3}
    \leadsheets_tension_sym:Nn \l__leadsheets_chord_tl {4}
    \leadsheets_tension_sym:Nn \l__leadsheets_chord_tl {5}
    \leadsheets_tension_sym:Nn \l__leadsheets_chord_tl {6}
    \leadsheets_tension_sym:Nn \l__leadsheets_chord_tl {7}
    \leadsheets_tension_sym:Nn \l__leadsheets_chord_tl {8}
    \leadsheets_tension_sym:Nn \l__leadsheets_chord_tl {9}
    \leadsheets_chord_sym:Nnn  \l__leadsheets_chord_tl {/o}
      {\textsuperscript{\l__leadsheets_half_dim_tl}}
    \leadsheets_chord_sym:Nnn  \l__leadsheets_chord_tl {o}
      {\textsuperscript{\l__leadsheets_full_dim_tl}}
    \leadsheets_chord_sym:Nnn  \l__leadsheets_chord_tl {+}
      {\textsuperscript{\l__leadsheets_aug_tl}}
    \leadsheets_chord_sym:Nnn \l__leadsheets_chord_tl  {(}
      { \leadsheets_tension:w( }
    \leadsheets_chord_sym:Nnn \l__leadsheets_chord_tl  {mi}
      {\l__leadsheets_minor_tl}
    \leadsheets_chord_sym:Nnn \l__leadsheets_chord_tl  {ma}
      {\l__leadsheets_major_tl}
    \tl_replace_all:Nnn \l__leadsheets_chord_tl
      {\textsuperscript\textsuperscript}
      {\textsuperscript}
    \tl_use:N \l__leadsheets_chord_tl
    \group_end:
  }

\group_end:

\cs_new_protected:Npn \leadsheets_tension:w (#1)
  {
    \group_begin:
      \tl_set:Nn \l__leadsheets_tension_tl {#1}
      \leadsheets_chord_sym:Nnn \l__leadsheets_tension_tl
        {\textsuperscript}
        {\use:n}
      \textsuperscript { ( \tl_use:N \l__leadsheets_tension_tl ) }
    \group_end:
  }

\keys_define:nn {leadsheets/chordnames}
  {
    format       .tl_set:N = \l__leadsheets_format_tl ,
    sharp        .tl_set:N = \l__leadsheets_sharp_tl ,
    flat         .tl_set:N = \l__leadsheets_flat_tl ,
    double-sharp .tl_set:N = \l__leadsheets_doublesharp_tl ,
    double-flat  .tl_set:N = \l__leadsheets_doubleflat_tl ,
    half-dim     .tl_set:N = \l__leadsheets_half_dim_tl ,
    full-dim     .tl_set:N = \l__leadsheets_full_dim_tl ,
    aug          .tl_set:N = \l__leadsheets_aug_tl ,
    major        .tl_set:N = \l__leadsheets_major_tl ,
    minor        .tl_set:N = \l__leadsheets_minor_tl ,
    sus          .tl_set:N = \l__leadsheets_sus_tl ,
    add          .tl_set:N = \l__leadsheets_add_tl ,
    dim          .tl_set:N = \l__leadsheets_dim_tl ,
    major-seven  .tl_set:N = \l__leadsheets_major_seven_tl ,
    major-nine   .tl_set:N = \l__leadsheets_major_nine_tl ,
    output-notation .choice: ,
    output-notation/literal .code:n =
      \bool_set_false:N \l__leadsheets_input_notation_german_bool
      \bool_set_false:N \l__leadsheets_output_notation_german_bool
      \bool_set_true:N \l__leadsheets_notation_literal_bool ,
    output-notation/german  .code:n =
      \bool_set_true:N \l__leadsheets_output_notation_german_bool
      \bool_set_false:N \l__leadsheets_notation_literal_bool ,
    output-notation/english .code:n =
      \bool_set_false:N \l__leadsheets_output_notation_german_bool
      \bool_set_false:N \l__leadsheets_notation_literal_bool ,
    input-notation .choice: ,
    input-notation/literal  .code:n =
      \bool_set_false:N \l__leadsheets_input_notation_german_bool
      \bool_set_false:N \l__leadsheets_output_notation_german_bool
      \bool_set_true:N \l__leadsheets_notation_literal_bool ,
    input-notation/german   .code:n =
      \bool_set_true:N \l__leadsheets_input_notation_german_bool
      \bool_set_false:N \l__leadsheets_notation_literal_bool ,
    input-notation/english  .code:n =
      \bool_set_false:N \l__leadsheets_input_notation_german_bool
      \bool_set_false:N \l__leadsheets_notation_literal_bool
  }

\NewDocumentCommand \setchordnames {m}
  { \keys_set:nn {leadsheets/chordnames} {#1} }

\NewDocumentCommand \chordname {} { \leadsheets_chord: }

\endinput
