Show default value for editing on Python input possible?
Asked Answered
P

17

87

Is it possible for python to accept input like this:

Folder name: Download

But instead of the user typing "Download" it is already there as a initial value. If the user wants to edit it as "Downloads" all he has to do is add a 's' and press enter.

Using normal input command:

folder=input('Folder name: ')

all I can get is a blank prompt:

Folder name:

Is there a simple way to do this that I'm missing?

Pameliapamelina answered 28/3, 2010 at 13:51 Comment(0)
H
94

The standard library functions input() and raw_input() don't have this functionality. If you're using Linux you can use the readline module to define an input function that uses a prefill value and advanced line editing:

import readline

def rlinput(prompt, prefill=''):
   readline.set_startup_hook(lambda: readline.insert_text(prefill))
   try:
      return input(prompt)  # or raw_input in Python 2
   finally:
      readline.set_startup_hook()
Headline answered 28/3, 2010 at 14:1 Comment(4)
It might also work as is on Mac OS X. readline or pyreadline could be installed separately.Carnassial
in Windows we should not have been trust :(Chain
"pip install pyreadline" for windows: https://mcmap.net/q/243335/-readline-functionality-on-windows-with-python-2-7Jerz
In my case it doesn't work on Mac but works in Linux. Any ideas how to make it work on Mac?Sitarski
S
23

I'm assuming you mean from the command-line. I've never seen initial values for command line prompts, they're usually of the form:

Folder [default] : 

which in code is simply:

res = raw_input('Folder [default] : ')
res = res or 'default'

Alternatively, you can try to do something using the curses module in Python.

Sanious answered 28/3, 2010 at 13:57 Comment(0)
D
12

This works in windows.

import win32console

_stdin = win32console.GetStdHandle(win32console.STD_INPUT_HANDLE)

def input_def(prompt, default=''):
    keys = []
    for c in unicode(default):
        evt = win32console.PyINPUT_RECORDType(win32console.KEY_EVENT)
        evt.Char = c
        evt.RepeatCount = 1
        evt.KeyDown = True
        keys.append(evt)

    _stdin.WriteConsoleInput(keys)
    return raw_input(prompt)

if __name__ == '__main__':
    name = input_def('Folder name: ')
    print
    print name
Discompose answered 4/5, 2011 at 18:33 Comment(2)
I think the above answer is only for Python 2. The print name is a dead giveaway ;) For Python 3 solution for Windows, see my answer to a similar question, with slightly modified code: https://mcmap.net/q/243336/-how-to-put-text-in-input-line-how-to-ask-for-user-input-on-the-command-line-while-providing-a-39-default-39-answer-that-the-user-can-edit-or-deleteDysphemism
a few modify successfuly run in python3.7 win10. What is the solution for Linux?Platoon
J
8

I finally found a simple alternative that works on Windows and Linux. Essentially, i'm using the pyautogui module to simulate the user's input. in practice, it looks like this:

from pyautogui import typewrite

print("enter folder name: ")
typewrite("Default Value")
folder = input()

Example

A Word of Warning:

  1. Theoretically, the user can insert characters in the middle of the "default" input by pressing a key before typewrite finishes.
  2. pyautogui is notoriously unreliable on headless systems, so make sure to provide a backup solution in case the import fails. If you run into No module named 'Xlib', try to install the python3-xlib or python-xlib package (or the xlib module). Running over ssh can also be a problem.

An example fallback implementation:

Since a missing X-server can logically only happen on linux, here's an implementation that uses sth's answer as fallback:

try:
    from pyautogui import typewrite
    autogui = True
except (ImportError, KeyError):
    import readline
    autogui = False

def rlinput(prompt, prefill=''):
    if autogui:
        print(prompt)
        typewrite(prefill)
        return input()
    else:
        readline.set_startup_hook(lambda: readline.insert_text(prefill))
        try:
            return input(prompt)
        finally:
            readline.set_startup_hook()
Jansson answered 17/9, 2018 at 13:10 Comment(0)
C
4

I think that the best (the easiest and most portable) solution is a combination of @rlotun and @Stephen answers:

default = '/default/path/'
dir = raw_input('Folder [%s]' % default)
dir = dir or default
Chartier answered 28/3, 2010 at 14:56 Comment(1)
I like this method because it allows the default value to be variable.Summand
F
4

I would like to suggest using the clipboard to solve this problem. Paste the clipboard into the input line, edit as required, press enter. Variable clpstack is used to protect existing clipboard contents. This code is for Windows. Linux could use import clipboard.

import pyperclip as clp
clpstack=clp.paste()
clp.copy("192.168.4.1")
HOST = input("Enter telnet host: ")
clp.copy(clpstack)
Fauve answered 18/5, 2018 at 18:25 Comment(1)
This is a nice, simple workaround. The example should perhaps point out that the user needs to do CTRL-V to put the default value on the input line, making it available for possible editing.Gifferd
M
3

Recently faced this problem. None of the above answers seem to be flawless. So I did some research, and found the following solution to be the easiest, and works both for Windows and Linux:

import keyboard

def input_with_default(prompt_, default_):
    keyboard.write(default_)
    return input(prompt_)

if __name__ == "__main__":
    print(input_with_default("Please enter: ", "hello world"))
Mattern answered 29/5, 2021 at 1:4 Comment(1)
Note: keyboard is not part of the standard library. Presumably this answer is refering to pypi.org/project/keyboardBignonia
G
2

I like this, It works on window

def inputWdefault(prompt, default):
    bck = chr(8) * len(default)
    ret = input(prompt + default + bck)
    return ret or default
Globin answered 22/8, 2018 at 12:30 Comment(0)
D
2

I found PyInquirer to be very helpful, especially when building interactive console applications frequently. Prompting a user with a default modifiable value would look as follows:

from PyInquirer import prompt

question = [
    {
        'type': 'input',
        'name': 'first_name',
        'message': 'Name please',
        'default': 'Max'
    }
]

answer = prompt(question)
print('Hello {}'.format(answer['first_name']))
Daegal answered 11/7, 2020 at 12:42 Comment(0)
F
1

I liked the approach taken by @MCO so I refactored the code. I tested it on X Windows and Microsoft Windows 10 WSL 2 using Microsoft Terminal:

def input_with_default(prompt, prefill=''):
    try:
        from pyautogui import typewrite
        print(prompt)
        typewrite(prefill)
        return input()
    except (ImportError, KeyError):
        import readline
        readline.set_startup_hook(lambda: readline.insert_text(prefill))
    try:
        return input(prompt)
    finally:
        readline.set_startup_hook()
Frantic answered 15/10, 2020 at 10:17 Comment(0)
E
0

Not the best aproach but for the sake of sharing... You could use Javascript to get all sort of inputs in IPython Notebook.

from IPython.display import HTML
newvar = ""
htm = """
<input id="inptval" style="width:60%;" type="text" value="This is an editable default value.">
<button onclick="set_value()" style="width:20%;">OK</button>

<script type="text/Javascript">
    function set_value(){
        var input_value = document.getElementById('inptval').value;
        var command = "newvar = '" + input_value + "'";
        var kernel = IPython.notebook.kernel;
        kernel.execute(command);
    }
</script>
"""
HTML(htm)

On the next cell you can use the new variable:

print newvar
Ectosarc answered 16/3, 2014 at 5:22 Comment(0)
C
0

We can use Tkinter and use a StringVar to do this. The limitation is that the input is through a Tkinter window.

from tkinter import Tk, LEFT, BOTH, StringVar
from tkinter.ttk import Entry, Frame


class Example(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
        self.initUI()

    def initUI(self):
        self.parent.title("Entry")
        self.pack(fill=BOTH, expand=1)
        self.contents = StringVar()
        # give the StringVar a default value
        self.contents.set('test')
        self.entry = Entry(self)
        self.entry.pack(side=LEFT, padx=15)
        self.entry["textvariable"] = self.contents
        self.entry.bind('<Key-Return>', self.on_changed)

    def on_changed(self, event):
        print('contents: {}'.format(self.contents.get()))
        return True


def main():
    root = Tk()
    ex = Example(root)
    root.geometry("250x100+300+300")
    root.mainloop()


if __name__ == '__main__':
    main()
Corrigendum answered 4/4, 2018 at 0:11 Comment(0)
P
0

If you are writing a CLI, you might want to consider using the python-click library for this.

You would achieve your goal with the following code:

import click

user_input = click.prompt(text="Folder name", default="Download")
print(f"{user_input=}")

If you run this code, and type in nothing, then you get:

$ python3 cli_code.py
Folder name [Download]: 
user_input='Download'

If you run this code, and type in 'my-dir', then you get:

$ python3 cli_code.py
Folder name [Download]: my-dir
user_input='my-dir'
Precede answered 10/10, 2021 at 11:30 Comment(0)
A
0

Try using an "f-string" and "or" combination, say:

default_name = "that_folder"

this_folder = input(f"Folder name: ({default_name}) ") or default_name
print(this_folder)

If you hit Return without typing in the folder name, the default_name will be assumed.

Aliquant answered 3/12, 2021 at 3:54 Comment(0)
S
0

Simple approach:

max_blob_size = input("What is the threshold size? [Default = 1M]") or "1M"
Silden answered 23/11, 2023 at 9:51 Comment(0)
P
-1

This is not a very Good Answer but it is a work around for windows. As hard as I tried, I could not get Readline or pyReadline to work on my Windows10 computer with Python Ver 3.5. So I wrote this instead. Not the best code in the world since I've only been using Python for 3 months. But it works.

    import os

    def note_input(defaultvalue):
        #Create a textfile
        txtfile = open("txtfile.txt", "w")
        #
        # populate it with the default value
        txtfile.write(defaultvalue)
        txtfile.close()
        #
        # call Notepad
        os.system("notepad.exe txtfile.txt") 
        # input("Just holding until notepad is close : ") (did not need this line) 
        #
        # get the Value Entered/Changed in Notepad
        txtfile = open("txtfile.txt", "r")
        func_value = txtfile.read()
        txtfile.close()
        return func_value
    # END DEF

Notepad stopped the program from running until it was closed, so the input() line below it was not needed. Once notepad was opened the first time and placed where I wanted it on the screen, It was like a popup input window. I assume you can use any text editor like Notepad++ or Scripe or Code Writer, etc.

Ponder answered 22/3, 2017 at 3:4 Comment(0)
D
-3

If you do that, the user would have to delete the existing word. What about providing a default value if the user hits "return"?

>>> default_folder = "My Documents"
>>> try: folder = input("folder name [%s]:" %default_folder)
... except SyntaxError: folder = default_folder
Dorettadorette answered 28/3, 2010 at 14:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.