@@ -15,7 +15,7 @@ def rectangle(win, uly, ulx, lry, lrx):
1515 win .addch (lry , lrx , curses .ACS_LRCORNER )
1616 win .addch (lry , ulx , curses .ACS_LLCORNER )
1717
18- class textbox :
18+ class Textbox :
1919 """Editing widget using the interior of a window object.
2020 Supports the following Emacs-like key bindings:
2121
@@ -25,6 +25,7 @@ class textbox:
2525 Ctrl-E Go to right edge (nospaces off) or end of line (nospaces on).
2626 Ctrl-F Cursor right, wrapping to next line when appropriate.
2727 Ctrl-G Terminate, returning the window contents.
28+ Ctrl-H Delete character backward.
2829 Ctrl-J Terminate if the window is 1 line, otherwise insert newline.
2930 Ctrl-K If line is blank, delete it, otherwise clear to end of line.
3031 Ctrl-L Refresh screen
@@ -36,33 +37,33 @@ class textbox:
3637 is not possible. The following synonyms are supported where possible:
3738
3839 KEY_LEFT = Ctrl-B, KEY_RIGHT = Ctrl-F, KEY_UP = Ctrl-P, KEY_DOWN = Ctrl-N
40+ KEY_BACKSPACE = Ctrl-h
3941 """
4042 def __init__ (self , win ):
4143 self .win = win
4244 (self .maxy , self .maxx ) = win .getmaxyx ()
4345 self .maxy = self .maxy - 1
4446 self .maxx = self .maxx - 1
4547 self .stripspaces = 1
48+ self .lastcmd = None
4649 win .keypad (1 )
4750
4851 def firstblank (self , y ):
4952 "Go to the location of the first blank on the given line."
50- (oldy , oldx ) = self .win .getyx ()
51- self .win .move (y , self .maxx - 1 )
52- last = self .maxx - 1
53+ last = self .maxx
5354 while 1 :
54- if last == 0 :
55- break
5655 if ascii .ascii (self .win .inch (y , last )) != ascii .SP :
5756 last = last + 1
5857 break
58+ elif last == 0 :
59+ break
5960 last = last - 1
60- self .win .move (oldy , oldx )
6161 return last
6262
6363 def do_command (self , ch ):
6464 "Process a single editing command."
6565 (y , x ) = self .win .getyx ()
66+ self .lastcmd = ch
6667 if ascii .isprint (ch ):
6768 if y < self .maxy or x < self .maxx :
6869 # The try-catch ignores the error we trigger from some curses
@@ -72,9 +73,9 @@ def do_command(self, ch):
7273 self .win .addch (ch )
7374 except ERR :
7475 pass
75- elif ch == ascii .SOH : # Ctrl- a
76+ elif ch == ascii .SOH : # ^ a
7677 self .win .move (y , 0 )
77- elif ch in (ascii .STX , curses .KEY_LEFT ): # Ctrl-b
78+ elif ch in (ascii .STX ,curses .KEY_LEFT , ascii . BS , curses . KEY_BACKSPACE ):
7879 if x > 0 :
7980 self .win .move (y , x - 1 )
8081 elif y == 0 :
@@ -83,43 +84,44 @@ def do_command(self, ch):
8384 self .win .move (y - 1 , self .firstblank (y - 1 ))
8485 else :
8586 self .win .move (y - 1 , self .maxx )
86- elif ch == ascii .EOT : # Ctrl-d
87+ if ch in (ascii .BS , curses .KEY_BACKSPACE ):
88+ self .win .delch ()
89+ elif ch == ascii .EOT : # ^d
8790 self .win .delch ()
88- elif ch == ascii .ENQ : # Ctrl- e
91+ elif ch == ascii .ENQ : # ^ e
8992 if self .stripspaces :
9093 self .win .move (y , self .firstblank (y , maxx ))
9194 else :
9295 self .win .move (y , self .maxx )
93- elif ch in (ascii .ACK , curses .KEY_RIGHT ): # Ctrl- f
96+ elif ch in (ascii .ACK , curses .KEY_RIGHT ): # ^ f
9497 if x < self .maxx :
9598 self .win .move (y , x + 1 )
96- elif y == self .maxx :
99+ elif y == self .maxy :
97100 pass
98101 else :
99102 self .win .move (y + 1 , 0 )
100- elif ch == ascii .BEL : # Ctrl- g
103+ elif ch == ascii .BEL : # ^ g
101104 return 0
102- elif ch == ascii .NL : # Ctrl- j
105+ elif ch == ascii .NL : # ^ j
103106 if self .maxy == 0 :
104107 return 0
105108 elif y < self .maxy :
106109 self .win .move (y + 1 , 0 )
107- elif ch == ascii .VT : # Ctrl- k
110+ elif ch == ascii .VT : # ^ k
108111 if x == 0 and self .firstblank (y ) == 0 :
109112 self .win .deleteln ()
110113 else :
111114 self .win .clrtoeol ()
112- elif ch == ascii .FF : # Ctrl- l
115+ elif ch == ascii .FF : # ^ l
113116 self .win .refresh ()
114- elif ch in (ascii .SO , curses .KEY_DOWN ): # Ctrl- n
117+ elif ch in (ascii .SO , curses .KEY_DOWN ): # ^ n
115118 if y < self .maxy :
116119 self .win .move (y + 1 , x )
117- elif ch == ascii .SI : # Ctrl- o
120+ elif ch == ascii .SI : # ^ o
118121 self .win .insertln ()
119- elif ch in (ascii .DLE , curses .KEY_UP ): # Ctrl- p
122+ elif ch in (ascii .DLE , curses .KEY_UP ): # ^ p
120123 if y > 0 :
121124 self .win .move (y - 1 , x )
122- self .win .refresh ()
123125 return 1
124126
125127 def gather (self ):
@@ -128,6 +130,7 @@ def gather(self):
128130 for y in range (self .maxy + 1 ):
129131 self .win .move (y , 0 )
130132 stop = self .firstblank (y )
133+ #sys.stderr.write("y=%d, firstblank(y)=%d\n" % (y, stop))
131134 if stop == 0 and self .stripspaces :
132135 continue
133136 for x in range (self .maxx + 1 ):
@@ -144,16 +147,19 @@ def edit(self, validate=None):
144147 ch = self .win .getch ()
145148 if validate :
146149 ch = validate (ch )
150+ if not ch :
151+ continue
147152 if not self .do_command (ch ):
148153 break
154+ self .win .refresh ()
149155 return self .gather ()
150156
151157if __name__ == '__main__' :
152158 def test_editbox (stdscr ):
153159 win = curses .newwin (4 , 9 , 15 , 20 )
154160 rectangle (stdscr , 14 , 19 , 19 , 29 )
155161 stdscr .refresh ()
156- return textbox (win ).edit ()
162+ return Textbox (win ).edit ()
157163
158164 str = curses .wrapper (test_editbox )
159165 print str
0 commit comments