55

I'm using Python 2.7's raw_input to read from stdin.

I want to let the user change a given default string.

Code:

i = raw_input("Please enter name:")

Console:

Please enter name: Jack

The user should be presented with Jack but can change (backspace) it to something else.

The Please enter name: argument would be the prompt for raw_input and that part shouldn't be changeable by the user.

Georgy
  • 6,348
  • 7
  • 46
  • 58
ifschleife
  • 985
  • 1
  • 8
  • 20
  • Possible duplicate of [Show default value for editing on Python input possible?](https://stackoverflow.com/questions/2533120/show-default-value-for-editing-on-python-input-possible) – Georgy Jul 05 '19 at 12:05

7 Answers7

84

You could do:

i = raw_input("Please enter name[Jack]:") or "Jack"

This way, if user just presses return without entering anything, "i" will be assigned "Jack".

codefreak
  • 6,322
  • 3
  • 35
  • 49
28

Python2.7 get raw_input and set a default value:

Put this in a file called a.py:

import readline
def rlinput(prompt, prefill=''):
   readline.set_startup_hook(lambda: readline.insert_text(prefill))
   try:
      return raw_input(prompt)
   finally:
      readline.set_startup_hook()

default_value = "an insecticide"
stuff = rlinput("Caffeine is: ", default_value)
print("final answer: " + stuff)

Run the program, it stops and presents the user with this:

el@defiant ~ $ python2.7 a.py
Caffeine is: an insecticide

The cursor is at the end, user presses backspace until 'an insecticide' is gone, types something else, then presses enter:

el@defiant ~ $ python2.7 a.py
Caffeine is: water soluable

Program finishes like this, final answer gets what the user typed:

el@defiant ~ $ python2.7 a.py 
Caffeine is: water soluable
final answer: water soluable

Equivalent to above, but works in Python3:

import readline    
def rlinput(prompt, prefill=''):
   readline.set_startup_hook(lambda: readline.insert_text(prefill))
   try:
      return input(prompt)
   finally:
      readline.set_startup_hook()

default_value = "an insecticide"
stuff = rlinput("Caffeine is: ", default_value)
print("final answer: " + stuff)

More info on what's going on here:

https://stackoverflow.com/a/2533142/445131

Community
  • 1
  • 1
Eric Leschinski
  • 123,728
  • 82
  • 382
  • 321
7

In dheerosaur's answer If user press Enter to select default value in reality it wont be saved as python considers it as '' string so Extending a bit on what dheerosaur.

default = "Jack"
user_input = raw_input("Please enter name: %s"%default + chr(8)*4)
if not user_input:
    user_input = default

Fyi .. The ASCII value of backspace is 08

Anuj
  • 8,652
  • 8
  • 29
  • 30
5

I only add this because you should write a simple function for reuse. Here is the one I wrote:

def default_input( message, defaultVal ):
    if defaultVal:
        return raw_input( "%s [%s]:" % (message,defaultVal) ) or defaultVal
    else:
        return raw_input( "%s " % (message) )
chubbsondubs
  • 34,812
  • 24
  • 97
  • 134
  • This doesn't fit the question. – buhtz says get vaccinated Sep 02 '16 at 19:41
  • I re-read the question and I still think it does. You might want to explain your position better. – chubbsondubs Sep 05 '16 at 13:45
  • 1
    @chubbsndubs Cited from the question: "but can change (backspace) it to something else". This means that the user should be able to edit the default value. – buhtz says get vaccinated Sep 05 '16 at 20:23
  • 1
    You're being overly pedantic. My suggestion gives the OP the feature they requested in a slightly different way. It's implied that if the OP can alter their requirements, which I see as very minor change, then this solution will work for them. If not fine the answer is you can't do it with raw_input(), and you're looking at a non-portable solution using readline maybe. – chubbsondubs Sep 06 '16 at 14:45
4

On platforms with readline, you can use the method described here: https://stackoverflow.com/a/2533142/1090657

On Windows, you can use the msvcrt module:

from msvcrt import getch, putch

def putstr(str):
    for c in str:
        putch(c)

def input(prompt, default=None):
    putstr(prompt)
    if default is None:
        data = []
    else:
        data = list(default)
        putstr(data)
    while True:
        c = getch()
        if c in '\r\n':
            break
        elif c == '\003': # Ctrl-C
            putstr('\r\n')
            raise KeyboardInterrupt
        elif c == '\b': # Backspace
            if data:
                putstr('\b \b') # Backspace and wipe the character cell
                data.pop()
        elif c in '\0\xe0': # Special keys
            getch()
        else:
            putch(c)
            data.append(c)
    putstr('\r\n')
    return ''.join(data)

Note that arrows keys don't work for the windows version, when it's used, nothing will happen.

Community
  • 1
  • 1
quantum
  • 3,292
  • 25
  • 48
0

For windows users with gitbash/msys2 or cygwin you can use it's built in readline through python subprocess. It is a sort of hack but works quite well and doesn't require any third party code. For personal tools this works really well.

Msys2 specific: If you want ctrl+c to immediately exit, you will need to run your program with
winpty python program.py

import subprocess
import shlex

def inputMsysOrCygwin(prompt = "", prefilled = ""):
    """Run your program with winpty python program.py if you want ctrl+c to behave properly while in subprocess"""
    try:
        bashCmd = "read -e -p {} -i {} bash_input; printf '%s' \"$bash_input\"".format(shlex.quote(prompt), shlex.quote(prefilled))
        userInput = subprocess.check_output(["sh", "-c", bashCmd], encoding='utf-8')
        return userInput
    except FileNotFoundError:
        raise FileNotFoundError("Invalid environment: inputMsysOrCygwin can only be run from bash where 'read' is available.")

userInput = ""
try:
    #cygwin or msys2 shell
    userInput = inputMsysOrCygwin("Prompt: ", "This is default text")
except FileNotFoundError:
    #cmd or powershell context where bash and read are not available 
    userInput = input("Prompt [This is default text]: ") or "This is default text"

print("userInput={}".format(userInput))
Will Bender
  • 135
  • 5
-3

Try this: raw_input("Please enter name: Jack" + chr(8)*4)

The ASCII value of backspace is 08.

dheerosaur
  • 12,775
  • 6
  • 28
  • 30