#compdef atonal-util
#
# ZSH completion for atonal-util. Install to a $fpath directory. Consult
# the perl distribution of the App::MusicTools module for the related
# CLI program. This completion is from the zsh-compdef/ subdirectory of
# that perl distribution.

if [[ ${#forte_numbers} -eq 0 ]]; then
  forte_numbers=(3-1 3-10 3-11 3-12 3-2 3-3 3-4 3-5 3-6 3-7 3-8 3-9 4-1 4-10 4-11 4-12 4-13 4-14 4-16 4-17 4-18 4-19 4-2 4-20 4-21 4-22 4-23 4-24 4-25 4-26 4-27 4-28 4-3 4-4 4-5 4-6 4-7 4-8 4-9 4-z15 4-z29 5-1 5-10 5-11 5-13 5-14 5-15 5-16 5-19 5-2 5-20 5-21 5-22 5-23 5-24 5-25 5-26 5-27 5-28 5-29 5-3 5-30 5-31 5-32 5-33 5-34 5-35 5-4 5-5 5-6 5-7 5-8 5-9 5-z12 5-z17 5-z18 5-z36 5-z37 5-z38 6-1 6-14 6-15 6-16 6-18 6-2 6-20 6-21 6-22 6-27 6-30 6-31 6-32 6-33 6-34 6-35 6-5 6-7 6-8 6-9 6-z10 6-z11 6-z12 6-z13 6-z17 6-z19 6-z23 6-z24 6-z25 6-z26 6-z28 6-z29 6-z3 6-z36 6-z37 6-z38 6-z39 6-z4 6-z40 6-z41 6-z42 6-z43 6-z44 6-z45 6-z46 6-z47 6-z48 6-z49 6-z50 6-z6 7-1 7-10 7-11 7-13 7-14 7-15 7-16 7-19 7-2 7-20 7-21 7-22 7-23 7-24 7-25 7-26 7-27 7-28 7-29 7-3 7-30 7-31 7-32 7-33 7-34 7-35 7-4 7-5 7-6 7-7 7-8 7-9 7-z12 7-z17 7-z18 7-z36 7-z37 7-z38 8-1 8-10 8-11 8-12 8-13 8-14 8-16 8-17 8-18 8-19 8-2 8-20 8-21 8-22 8-23 8-24 8-25 8-26 8-27 8-28 8-3 8-4 8-5 8-6 8-7 8-8 8-9 8-z15 8-z29 9-1 9-10 9-11 9-12 9-2 9-3 9-4 9-5 9-6 9-7 9-8 9-9)
fi

if [[ ${#pitches} -eq 0 ]]; then
  pitches=(c d e f g a b des ees ges aes bes cis dis fis gis ais 0 1 2 3 4 5 6 7 8 9 10 11)
fi

# XXX --scaledegrees=anything is messing up subsequent completion
_atonal-util() {
  _arguments \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '(- *)--help[display help]' \
    '--ly[emit notes not pitch numbers]' \
    '(- *)--listmodes[show available modes]' \
    '--rs=[record separator]:sep:' \
    {--sd,--scaledegrees}'=[degrees in the scale]:scaledegrees:' \
    '*::atonal-util command:_atonalutil_mode'
}

_atonalutil_mode() {
  _atonalutil_modes=(
    'basic:prime_form and interval_class_content info' \
    'beats2set:rhythmic beats to set class' \
    'circular_permute:all permutations of pitch set' \
    'combos:combination tones' \
    'complement:complement of set' \
    'equivs:Tn and TnI equivalents' \
    'findall:find pitch sets satisfying some pitches' \
    'findin:find pitches satisfying a base set' \
    'fnums:return all Forte Numbers and pitch sets' \
    'freq2pitch:converts frequencies to MIDI note numbers' \
    'forte2pcs:return pitch set for Forte Number' \
    'gen_melody:generates random atonal melody' \
    'half_prime_form:half prime or more normal form' \
    'interval_class_content:ICC' \
    'intervals2pcs:intervals to pitch set' \
    'invariance_matrix:invarience under TnI' \
    'invariants:list of invariants of a given pitch set' \
    'invert:inversion' \
    'ly2pitch:lilypond note name to pitch number' \
    'ly2struct:lilypond note name to freq. and dur.' \
    'multiply:multiplication' \
    'normal_form:normal_form' \
    'notes2time:convert note values to time durations' \
    'pcs2forte:return Forte Number for a given pitch set' \
    'pcs2intervals:pitch set to intervals' \
    'pitch2freq:MIDI pitch to frequency conversion' \
    'pitch2intervalclass:pitch to interval class' \
    'pitch2ly:pitch lilypond note name conversion' \
    'prime_form:prime_form' \
    'recipe:list of methods to operate on a set with' \
    'retrograde:reverse' \
    'rotate:specific permutation' \
    'set2beats:set class to rhythmic beats' \
    'set_complex:2D pitch set to inversion chart' \
    'subsets:subsets of a given pitch set' \
    'tcis:transposition inversion common-tone structure' \
    'tcs:transposition common-tone structure' \
    'tension:tension values for given pitch set' \
    'time2notes:milliseconds to lilypond note duration conversion' \
    'transpose:Tn' \
    'transpose_invert:TnI' \
    'variances:intersection, difference, and union of two sets' \
    'whatscalesfit:what scales match the given notes'
    'zrelation:whether two sets share same ICC'
  )

  if (( CURRENT == 1 )); then
    _describe -t commands 'atonalutil command' _atonalutil_modes
  else
    local curcontext="$curcontext"

    cmd="${_atonalutil_modes[(r)$words[1]:*]%%:*}"
    if (( $#cmd )); then
      curcontext="${curcontext%:*:*}:atonalutil-${cmd}:"
      _call_function ret _atonalutil_$cmd || _message 'no more arguments'
    else
      _message "unknown atonalutil command: $words[1]"
    fi
    return ret
  fi
}

# XXX too much copy-n-paste hereafter
_atonalutil_basic() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--rs=[record separator]:sep:' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_beats2set() {
  _arguments -s \
    {--sd,--scaledegrees}'=[beats per measure]:scaledegrees:' \
    '--rs=[record separator]:sep:' \
    '*:beatornot:(x .)'
}
_atonalutil_circular_permute() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_combos() {
  _arguments -s \
    {--concertfreq=,--cf=}'[concert frequency]:frequency:(409 415 422.5 440)' \
    {--concertpitch=,--cp=}'[concert pitch]:pitch:(69)' \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--pitches[input pitches instead of frequencies]' \
    '--relative=[relative starting pitch]:pitch:_values "pitches" $pitches' \
    '--scala=[scala .scl file]:filename:_files'
}
_atonalutil_complement() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_equivs() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_findall() {
  _arguments -s \
    '--exclude=[omit result if contains]:pitches:_values -s , "pitches" $pitches' \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--fn=[forte number prefixes]:fn:' \
    '--ly[emit notes not pitch numbers]' \
    '--root=[root pitch]:pitch:_values "pitch" $pitches' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_findin() {
  _arguments -s \
    '--exclude=[omit result if contains]:pitches:_values -s , "pitches" $pitches' \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--root=[root pitch]:pitch:_values "pitches" $pitches' \
    '--pitchset=[base pitch set]:ps:_values "forte number" $forte_numbers'\
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_fnums() {
  _arguments -s \
    '--tension=[tension flag]:tension:(cope)'
}
_atonalutil_forte2pcs() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--rs=[record separator]:sep:' \
    '1:fortenumber:_values "forte number" $forte_numbers'
}
_atonalutil_freq2pitch() {
  _arguments -s \
    {--concertfreq=,--cf=}'[concert frequency]:frequency:(409 415 422.5 440)' \
    {--concertpitch=,--cp=}'[concert pitch]:pitch:(69)' \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--scala=[scala .scl file]:filename:_files'
}
_atonalutil_gen_melody() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--rs=[record separator]:sep:'
}
_atonalutil_half_prime_form() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--rs=[record separator]:sep:' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_interval_class_content() {
  _arguments -s \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_intervals2pcs() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--pitch=[starting pitch]:pitch:_values "pitches" $pitches' \
    '--rs=[record separator]:sep:' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_invariance_matrix() {
  _arguments -s \
    '--rs=[record separator]:sep:' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_invariants() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_invert() { 
  _arguments -s \
    '--axis=[inversion axis]:pitch:_values "pitch" $pitches' \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--rs=[record separator]:sep:' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_ly2pitch() { 
  _arguments -s \
    '--relative=[pitch]:pitch:_values "pitches" $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_ly2struct() { 
  _arguments -s \
    '--beats=[beat value]:beat:(16 8 4 2 1)' \
    {--concertfreq=,--cf=}'[concert frequency]:frequency:(409 415 422.5 440)' \
    {--concertpitch=,--cp=}'[concert pitch]:pitch:(69)' \
    '--relative=[pitch]:pitch:_values "pitches" $pitches' \
    '--scala=[scala .scl file]:filename:_files' \
    '--tempo=[beats per minute]:bpm:(40 60 66 72 88 96 108 120 144 168 196)' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_multiply() {
  _arguments -s \
    '--factor=[multiplication factor]:number:' \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_normal_form() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--rs=[record separator]:sep:' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_notes2time() {
  _arguments -s \
    '--beats=[beat value]:beat:(16 8 4 2 1)' \
    '(--noms)--ms[emit time in ms]' \
    '--tempo=[beats per minute]:bpm:(40 60 66 72 88 96 108 120 144 168 196)'
}
_atonalutil_pcs2forte() {
  _arguments -s \
    '*:note:_values "pitches" $pitches'
 }
_atonalutil_pcs2intervals() {
  _arguments -s \
    '--rs=[record separator]:sep:' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_pitch2freq() {
  _arguments -s \
    {--concertfreq=,--cf=}'[concert frequency]:frequency:(409 415 422.5 440)' \
    {--concertpitch=,--cp=}'[concert pitch]:pitch:(69)' \
    '--relative=[relative starting pitch]:pitch:_values "pitches" $pitches' \
    '--scala=[scala .scl file]:filename:_files' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_pitch2intervalclass() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]'
    '1:note:_values "pitches" $pitches'
}
_atonalutil_pitch2ly() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--mode=[note relativity]:mode:(absolute relative)' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_prime_form() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--rs=[record separator]:sep:' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_recipe() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--file=[recipe file]:filename:_files' \
    '--rs=[record separator]:sep:'
}
_atonalutil_retrograde() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--rs=[record separator]:sep:' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_rotate() { 
  _arguments -s \
    '--rotate=[rotate by]:value:( )' \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--rs=[record separator]:sep:' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_set2beats() {
  _arguments -s \
    {--sd,--scaledegrees}'=[beats per measure]:scaledegrees:' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_set_complex() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--rs=[record separator]:sep:' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_subsets() {
  _arguments -s \
    '--length=[length]:value:( )' \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--rs=[record separator]:sep:' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_tcis() {
  _arguments -s \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_tcs() {
  _arguments -s \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_tension() {
  _arguments -s \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_time2notes() {
  _arguments -s \
    '--beats=[beat value]:beat:(16 8 4 2 1)' \
    '--tempo=[beats per minute]:bpm:(40 60 66 72 88 96 108 120 144 168 196)'
}
_atonalutil_transpose() {
  _arguments -s \
    '--transpose=[transposition value]:pitch:_values "pitch" $pitches' \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--rs=[record separator]:sep:' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_transpose_invert() {
  _arguments -s \
    '--axis=[inversion axis]:value:( )' \
    '--transpose=[transposition value]:pitch:_values "pitch" $pitches' \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--rs=[record separator]:sep:' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_variances() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '--ly[emit notes not pitch numbers]' \
    '--rs=[record separator]:sep:'
}
_atonalutil_whatscalesfit() {
  _arguments -s \
    '(--noflats)--flats[print notes as flats]' \
    '(--flats)--noflats[print notes not as flats]' \
    '1:noteorfnum:_values "forte number or pitches" $forte_numbers $pitches' \
    '*:note:_values "pitches" $pitches'
}
_atonalutil_zrelation() { }
