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?
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.
It helps to read the source code. Here is a working validator:
def enter_is_terminate(x):
if x == 10:
x = 7
return x
The validator has to return a character, which the edit function checks with do_command:
def edit(self, validate=None):
"Edit in the widget window and collect the results."
while 1:
ch = self.win.getch()
if validate:
ch = validate(ch)
if not ch:
continue
if not self.do_command(ch):
break
self.win.refresh()
return self.gather()
and do_command only returns 0 for the two cases (a) ASCII BEL and (b) newline on a one-line window:
elif ch == curses.ascii.BEL: # ^g
return 0
elif ch == curses.ascii.NL: # ^j
if self.maxy == 0:
return 0
elif y < self.maxy:
self.win.move(y+1, 0)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With