docs: def query(question, values, default=None, list_values = False, ignorecase = True ):
      """Preset a few options
      
      The question argument is a string, nothing magical.
      
      The values argument accepts input in two different forms. The simpler form
      (a tuple with strings) looks like:
      
          .. code-block:: python
          
              ('Male','Female')
      
      And it will pop up a question asking the user for a gender and requiring
      the user to enter either 'male' or 'female' (case doesn't matter unless
      you set the third arguement to false).
      The other form is something like:
      
          .. code-block:: python
          
              ({'values':('Male','M'),'fg':'cyan'},
              {'values':('Female','F'),'fg':'magenta'})
      
      This will pop up a question with Male/Female (each with appropriate
      colouring). Additionally, if the user types in just 'M', it will be
      treated as if 'Male' was typed in. The first item in the 'values' tuple
      is treated as default and is the one that is returned by the function
      if the user chooses one in that group.
      In addition the function can handle non-string objects quite fine. It
      simple displays the output object.__str__() and compares the user's input
      against that. So the the code
      
          .. code-block:: python
          
              query("Python rocks? ",(True, False))
      
      will return a bool (True) when the user types in the string 'True' (Of
      course there isn't any other reasonable answer than True anyways :P)
      
      ``default`` is the value function returns if the user types nothing in. This is
      can be used to cancel the input so-to-speek
      
      Using list_values = False will display a list, with descriptions printed out
      from the 'desc' keyword
      """
      values = list(values)
      for i in range(len(values)):
          if not isinstance(values[i], dict):
              values[i] = {'values': [values[i]]}
      try:
          import readline, rlcomplete
          wordlist = [ str(v) for value in values
                      for v in value['values']]
          completer = rlcomplete.ListCompleter(wordlist, ignorecase)
          readline.parse_and_bind("tab: complete")
          readline.set_completer(completer.complete)
      except ImportError:
          pass
      valuelist = []
      for item in values:
          entry = ( display('bright', item.get('fg'), item.get('bg')) +
              str(item['values'][0]) + display(['default']) )
          if str(item['values'][0]) == str(default): entry = '['+entry+']'
          if list_values: entry += ' : ' + item['desc']
          valuelist.append(entry)
      if list_values: question += os.linesep + os.linesep.join(valuelist) + os.linesep
      else: question += ' (' + '/'.join(valuelist) + ')'
      return input_object(question, cast = query_cast, default=default,
                   castarg=[values,ignorecase])