docs: def from_shorthand(shorthand_string, slash=None):
      """Take a chord written in shorthand and return the notes in the chord.
  
      The function can recognize triads, sevenths, sixths, ninths, elevenths,
      thirteenths, slashed chords and a number of altered chords.
  
      The second argument should not be given and is only used for a recursive
      call when a slashed chord or polychord is found.
  
      See http://tinyurl.com/3hn6v8u for a nice overview of chord patterns.
  
      Examples:
      >>> from_shorthand('Amin')
      ['A', 'C', 'E']
      >>> from_shorthand('Am/M7')
      ['A', 'C', 'E', 'G#']
      >>> from_shorthand('A')
      ['A', 'C#', 'E']
      >>> from_shorthand('A/G')
      ['G', 'A', 'C#', 'E']
      >>> from_shorthand('Dm|G')
      ['G', 'B', 'D', 'F', 'A']
  
      Recognised abbreviations: the letters "m" and "M" in the following
      abbreviations can always be substituted by respectively "min", "mi" or
      "-" and "maj" or "ma".
      
      Example:
      >>> from_shorthand('Amin7') == from_shorthand('Am7')
      True
  
      Triads: 'm', 'M' or '', 'dim'
  
      Sevenths: 'm7', 'M7', '7', 'm7b5', 'dim7', 'm/M7' or 'mM7'
  
      Augmented chords: 'aug' or '+', '7#5' or 'M7+5', 'M7+', 'm7+', '7+'
  
      Suspended chords: 'sus4', 'sus2', 'sus47' or '7sus4', 'sus', '11',
      'sus4b9' or 'susb9'
  
      Sixths: '6', 'm6', 'M6', '6/7' or '67', '6/9' or '69'
  
      Ninths: '9' or 'add9', 'M9', 'm9', '7b9', '7#9'
  
      Elevenths: '11' or 'add11', '7#11', 'm11'
  
      Thirteenths: '13' or 'add13', 'M13', 'm13'
  
      Altered chords: '7b5', '7b9', '7#9', '67' or '6/7'
  
      Special: '5', 'NC', 'hendrix'
      """
      # warning reduce??
      if type(shorthand_string) == list:
          res = []
          for x in shorthand_string:
              res.append(from_shorthand(x))
          return res
      if shorthand_string in ['NC', 'N.C.']:
          return []
  
      # Shrink shorthand_string to a format recognised by chord_shorthand
      shorthand_string = shorthand_string.replace('min', 'm')
      shorthand_string = shorthand_string.replace('mi', 'm')
      shorthand_string = shorthand_string.replace('-', 'm')
      shorthand_string = shorthand_string.replace('maj', 'M')
      shorthand_string = shorthand_string.replace('ma', 'M')
  
      # Get the note name
      if not notes.is_valid_note(shorthand_string[0]):
          raise NoteFormatError, "Unrecognised note '%s' in chord '%s'"\
               % (shorthand_string[0], shorthand_string)
      name = shorthand_string[0]
  
      # Look for accidentals
      for n in shorthand_string[1:]:
          if n == '#':
              name += n
          elif n == 'b':
              name += n
          else:
              break
  
      # Look for slashes and polychords '|'
      slash_index = -1
      s = 0
      rest_of_string = shorthand_string[len(name):]
      for n in rest_of_string:
          if n == '/':
              slash_index = s
          elif n == '|':
              # Generate polychord
              return from_shorthand(shorthand_string[:len(name) + s],
                      from_shorthand(shorthand_string[len(name) + s + 1:]))
          s += 1
  
      # Generate slash chord
      if slash_index != -1 and rest_of_string not in ['m/M7', '6/9', '6/7']:
          res = shorthand_string[:len(name) + slash_index]
          return from_shorthand(shorthand_string[:len(name) + slash_index],
                                shorthand_string[len(name) + slash_index + 1:])
      shorthand_start = len(name)
  
      short_chord = shorthand_string[shorthand_start:]
      if chord_shorthand.has_key(short_chord):
          res = chord_shorthand[short_chord](name)
          if slash != None:
              # Add slashed chords
              if type(slash) == str:
                  if notes.is_valid_note(slash):
                      res = [slash] + res
                  else:
                      raise NoteFormatError, \
                          "Unrecognised note '%s' in slash chord'%s'" % (slash,
                              slash + shorthand_string)
              elif type(slash) == list:
                  # Add polychords
                  r = slash
                  for n in res:
                      if n != r[-1]:
                          r.append(n)
                  return r
          return res
      else:
          raise FormatError, 'Unknown shorthand: %s' % shorthand_string