Search code examples
pythonncursescursespython-curses

Python curses: Make enter key terminate Textbox?


I have an application where people are asked to enter their user name and password. I want them to be able to just press enter to send the name and password. To do this, I've made this:

import curses, curses.textpad
def setup_input():
    inp = curses.newwin(8,55, 0,0)
    inp.addstr(1,1, "Please enter your username:")
    sub = inp.subwin(2,1)
    sub.border()
    sub2 = sub.subwin(3,2)
    global tb
    tb = curses.textpad.Textbox(sub2)
    inp.refresh()
    tb.edit(enter_is_terminate)

def enter_is_terminate(x):
    if x == 10:
        tb.do_command(7)
    tb.do_command(x)

setup_input()

Unfortunately this doesn't work as expected. The standard character for termination (Triggered by CTRL+G) is 7 and the enter character is 10, but with the above code, all other keys are still handled correctly but when I press enter, it just gives me a newline, instead of terminating the edit mode of the Textbox. What am I doing wrong?


Solution

  • Found this on the documentation:

    If validator is supplied, it must be a function. It will be called for each keystroke entered with the keystroke as a parameter; command dispatch is done on the result.

    So instead of running tb.do_command yourself, just return the key you want to 'input'.

    def enter_is_terminate(x):
        if x == 10:
            return 7
    

    Also, now you don't need to define tb as a global variable, which is usually a good thing. :)


    If you'd be happy with just a one line input, you wouldn't have to handle the enter key yourself.

    On the documentation it sais this:

    Control-J -- Terminate if the window is 1 line, otherwise insert newline.

    So if you define the textbox's sub window with line count of 1 you don't need to handle the enter key yourself.

    def setup_input():
        inp = curses.newwin(8,55, 0,0)
        inp.addstr(1,1, "Please enter your username:")
        sub = inp.subwin(3, 41, 2, 1)
        sub.border()
        sub2 = sub.subwin(1, 40, 3, 2)
        tb = curses.textpad.Textbox(sub2)
        inp.refresh()
        tb.edit()
    

    I also gave the sub a specific line and col count so the border is nicely around the textbox.