7

HighLine is a Ruby library for easing console input and output. It provides methods that lets you request input and validate it. Is there something that provides functionality similar to it in Python?

To show what HighLine does see the following example:

require 'highline/import'

input = ask("Yes or no? ") do |q|
  q.responses[:not_valid] = "Answer y or n for yes or no"
  q.default = 'y'
  q.validate = /\A[yn]\Z/i
end

It asks "Yes or no? " and lets the user input something. As long as the user does not input y or n (case-insensitive) it prints "Answer y or n for yes or no" and lets the user type an answer again. Also if the user press Enter it defaults to y. Finally, when it is done the input is stored in input. Here is an example result where the user first input "EH???" and then "y":

Yes or no? |y| EH???
Answer y or n for yes or no
?  y

Is there similarly simple way to do the same in Python?

N.N.
  • 8,336
  • 12
  • 54
  • 94
  • It doesn't look so difficult to implement. It's just a regex. See the [`re`](http://docs.python.org/2/library/re.html) module. – Bakuriu Feb 19 '13 at 17:29
  • Your exact example in Python is available on [Sergii Boiko's github](https://github.com/cris/ruby-quiz-in-python/blob/master/src/highline.py) – Burhan Khalid Feb 19 '13 at 18:20
  • @BurhanKhalid If it answers the question you might want to elaborate it into answer. – N.N. Feb 19 '13 at 20:01
  • A similar approach is described in http://stackoverflow.com/a/2827094/789593 – N.N. Feb 20 '13 at 12:44

2 Answers2

3

The following should work similarly for you, although it will not be exactly the same style of asking as it is in Ruby.

class ValidInput(object):
    def __init__(self,prompt,default="",regex_validate="",
             invalid_response="",correct_response=""):
        self.prompt=prompt
        self.default=default
        self.regex_validate=regex_validate
        self.invalid_response=invalid_response
        self.correct_response=correct_response
    def ask(self):
        fin=""
        while True:
            v_in=raw_input(self.prompt)
            if re.match(v_in,self.regex_validate):
                fin=v_in
                print self.correct_response
                break
            else:
                print self.invalid_response
                if self.default=="break":
                      break
                continue
        return fin

And you would use it like:

my_input=ValidInput("My prompt (Y/N): ",regex_validate="your regex matching string here",
                    invalid_response="The response to be printed when it does not match the regex",
                    correct_response="The response to be printed when it is matched to the regex.")

my_input.ask()
N.N.
  • 8,336
  • 12
  • 54
  • 94
IT Ninja
  • 6,174
  • 10
  • 42
  • 65
  • You seem to have forgot `import re`. Is the `continue` necessary? Why have you got `print self.invalid_response` before `if self.default=="break": \ break`? Any particular reason you did not use Python 3? – N.N. Feb 20 '13 at 06:35
  • Why do you use `re.match` and not `re.search` (the former [only match the first character of a string](http://docs.python.org/3/library/re.html#search-vs-match))? Also you seem to have placed the parameters in `re.match` in the wrong order. Also, I do not think it is warranted to make a class when a module will do. Especially when a module will make the semantics of it simpler. Also, the default mechanism does not work for your implementation. Also, correct_response is not needed. To fix all this I have posted [an answer](http://stackoverflow.com/a/14977144/789593). – N.N. Feb 20 '13 at 10:09
3

You can use the Python 3 module cliask. The module is inspired by the answer of IT Ninja, fixes some deficiencies in it and allows validation via a regex, a predicate, a tuple or a list.

The easiest way to get the module is to install it via pip (see the readme for other ways of installing):

sudo pip install cliask

You can then use the module by importing like in the following example:

import cliask

yn = cliask.agree('Yes or no? ',
                  default='y')
animal = cliask.ask('Cow or cat? ',
                    validator=('cow', 'cat'),
                    invalid_response='You must say cow or cat')

print(yn)
print(animal)

And here is how a session might look when running the example:

Yes or no? |y| EH???
Please enter "yes" or "no"
Yes or no? |y| y
Cow or cat? rabbit
You must say cow or cat
Cow or cat? cat
True
cat
Community
  • 1
  • 1
N.N.
  • 8,336
  • 12
  • 54
  • 94
  • Nice! I highly suggest this one over mine, I was more or less just providing a basic example of how you might impliment this. – IT Ninja Feb 20 '13 at 14:11