Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/ShExBy/shex_roo.../lib64/python2..../curses
File: textpad.py
"""Simple textbox editing widget with Emacs-like keybindings."""
[0] Fix | Delete
[1] Fix | Delete
import curses
[2] Fix | Delete
import curses.ascii
[3] Fix | Delete
[4] Fix | Delete
def rectangle(win, uly, ulx, lry, lrx):
[5] Fix | Delete
"""Draw a rectangle with corners at the provided upper-left
[6] Fix | Delete
and lower-right coordinates.
[7] Fix | Delete
"""
[8] Fix | Delete
win.vline(uly+1, ulx, curses.ACS_VLINE, lry - uly - 1)
[9] Fix | Delete
win.hline(uly, ulx+1, curses.ACS_HLINE, lrx - ulx - 1)
[10] Fix | Delete
win.hline(lry, ulx+1, curses.ACS_HLINE, lrx - ulx - 1)
[11] Fix | Delete
win.vline(uly+1, lrx, curses.ACS_VLINE, lry - uly - 1)
[12] Fix | Delete
win.addch(uly, ulx, curses.ACS_ULCORNER)
[13] Fix | Delete
win.addch(uly, lrx, curses.ACS_URCORNER)
[14] Fix | Delete
win.addch(lry, lrx, curses.ACS_LRCORNER)
[15] Fix | Delete
win.addch(lry, ulx, curses.ACS_LLCORNER)
[16] Fix | Delete
[17] Fix | Delete
class Textbox:
[18] Fix | Delete
"""Editing widget using the interior of a window object.
[19] Fix | Delete
Supports the following Emacs-like key bindings:
[20] Fix | Delete
[21] Fix | Delete
Ctrl-A Go to left edge of window.
[22] Fix | Delete
Ctrl-B Cursor left, wrapping to previous line if appropriate.
[23] Fix | Delete
Ctrl-D Delete character under cursor.
[24] Fix | Delete
Ctrl-E Go to right edge (stripspaces off) or end of line (stripspaces on).
[25] Fix | Delete
Ctrl-F Cursor right, wrapping to next line when appropriate.
[26] Fix | Delete
Ctrl-G Terminate, returning the window contents.
[27] Fix | Delete
Ctrl-H Delete character backward.
[28] Fix | Delete
Ctrl-J Terminate if the window is 1 line, otherwise insert newline.
[29] Fix | Delete
Ctrl-K If line is blank, delete it, otherwise clear to end of line.
[30] Fix | Delete
Ctrl-L Refresh screen.
[31] Fix | Delete
Ctrl-N Cursor down; move down one line.
[32] Fix | Delete
Ctrl-O Insert a blank line at cursor location.
[33] Fix | Delete
Ctrl-P Cursor up; move up one line.
[34] Fix | Delete
[35] Fix | Delete
Move operations do nothing if the cursor is at an edge where the movement
[36] Fix | Delete
is not possible. The following synonyms are supported where possible:
[37] Fix | Delete
[38] Fix | Delete
KEY_LEFT = Ctrl-B, KEY_RIGHT = Ctrl-F, KEY_UP = Ctrl-P, KEY_DOWN = Ctrl-N
[39] Fix | Delete
KEY_BACKSPACE = Ctrl-h
[40] Fix | Delete
"""
[41] Fix | Delete
def __init__(self, win, insert_mode=False):
[42] Fix | Delete
self.win = win
[43] Fix | Delete
self.insert_mode = insert_mode
[44] Fix | Delete
self._update_max_yx()
[45] Fix | Delete
self.stripspaces = 1
[46] Fix | Delete
self.lastcmd = None
[47] Fix | Delete
win.keypad(1)
[48] Fix | Delete
[49] Fix | Delete
def _update_max_yx(self):
[50] Fix | Delete
maxy, maxx = self.win.getmaxyx()
[51] Fix | Delete
self.maxy = maxy - 1
[52] Fix | Delete
self.maxx = maxx - 1
[53] Fix | Delete
[54] Fix | Delete
def _end_of_line(self, y):
[55] Fix | Delete
"""Go to the location of the first blank on the given line,
[56] Fix | Delete
returning the index of the last non-blank character."""
[57] Fix | Delete
self._update_max_yx()
[58] Fix | Delete
last = self.maxx
[59] Fix | Delete
while True:
[60] Fix | Delete
if curses.ascii.ascii(self.win.inch(y, last)) != curses.ascii.SP:
[61] Fix | Delete
last = min(self.maxx, last+1)
[62] Fix | Delete
break
[63] Fix | Delete
elif last == 0:
[64] Fix | Delete
break
[65] Fix | Delete
last = last - 1
[66] Fix | Delete
return last
[67] Fix | Delete
[68] Fix | Delete
def _insert_printable_char(self, ch):
[69] Fix | Delete
self._update_max_yx()
[70] Fix | Delete
(y, x) = self.win.getyx()
[71] Fix | Delete
backyx = None
[72] Fix | Delete
while y < self.maxy or x < self.maxx:
[73] Fix | Delete
if self.insert_mode:
[74] Fix | Delete
oldch = self.win.inch()
[75] Fix | Delete
# The try-catch ignores the error we trigger from some curses
[76] Fix | Delete
# versions by trying to write into the lowest-rightmost spot
[77] Fix | Delete
# in the window.
[78] Fix | Delete
try:
[79] Fix | Delete
self.win.addch(ch)
[80] Fix | Delete
except curses.error:
[81] Fix | Delete
pass
[82] Fix | Delete
if not self.insert_mode or not curses.ascii.isprint(oldch):
[83] Fix | Delete
break
[84] Fix | Delete
ch = oldch
[85] Fix | Delete
(y, x) = self.win.getyx()
[86] Fix | Delete
# Remember where to put the cursor back since we are in insert_mode
[87] Fix | Delete
if backyx is None:
[88] Fix | Delete
backyx = y, x
[89] Fix | Delete
[90] Fix | Delete
if backyx is not None:
[91] Fix | Delete
self.win.move(*backyx)
[92] Fix | Delete
[93] Fix | Delete
def do_command(self, ch):
[94] Fix | Delete
"Process a single editing command."
[95] Fix | Delete
self._update_max_yx()
[96] Fix | Delete
(y, x) = self.win.getyx()
[97] Fix | Delete
self.lastcmd = ch
[98] Fix | Delete
if curses.ascii.isprint(ch):
[99] Fix | Delete
if y < self.maxy or x < self.maxx:
[100] Fix | Delete
self._insert_printable_char(ch)
[101] Fix | Delete
elif ch == curses.ascii.SOH: # ^a
[102] Fix | Delete
self.win.move(y, 0)
[103] Fix | Delete
elif ch in (curses.ascii.STX,curses.KEY_LEFT, curses.ascii.BS,curses.KEY_BACKSPACE):
[104] Fix | Delete
if x > 0:
[105] Fix | Delete
self.win.move(y, x-1)
[106] Fix | Delete
elif y == 0:
[107] Fix | Delete
pass
[108] Fix | Delete
elif self.stripspaces:
[109] Fix | Delete
self.win.move(y-1, self._end_of_line(y-1))
[110] Fix | Delete
else:
[111] Fix | Delete
self.win.move(y-1, self.maxx)
[112] Fix | Delete
if ch in (curses.ascii.BS, curses.KEY_BACKSPACE):
[113] Fix | Delete
self.win.delch()
[114] Fix | Delete
elif ch == curses.ascii.EOT: # ^d
[115] Fix | Delete
self.win.delch()
[116] Fix | Delete
elif ch == curses.ascii.ENQ: # ^e
[117] Fix | Delete
if self.stripspaces:
[118] Fix | Delete
self.win.move(y, self._end_of_line(y))
[119] Fix | Delete
else:
[120] Fix | Delete
self.win.move(y, self.maxx)
[121] Fix | Delete
elif ch in (curses.ascii.ACK, curses.KEY_RIGHT): # ^f
[122] Fix | Delete
if x < self.maxx:
[123] Fix | Delete
self.win.move(y, x+1)
[124] Fix | Delete
elif y == self.maxy:
[125] Fix | Delete
pass
[126] Fix | Delete
else:
[127] Fix | Delete
self.win.move(y+1, 0)
[128] Fix | Delete
elif ch == curses.ascii.BEL: # ^g
[129] Fix | Delete
return 0
[130] Fix | Delete
elif ch == curses.ascii.NL: # ^j
[131] Fix | Delete
if self.maxy == 0:
[132] Fix | Delete
return 0
[133] Fix | Delete
elif y < self.maxy:
[134] Fix | Delete
self.win.move(y+1, 0)
[135] Fix | Delete
elif ch == curses.ascii.VT: # ^k
[136] Fix | Delete
if x == 0 and self._end_of_line(y) == 0:
[137] Fix | Delete
self.win.deleteln()
[138] Fix | Delete
else:
[139] Fix | Delete
# first undo the effect of self._end_of_line
[140] Fix | Delete
self.win.move(y, x)
[141] Fix | Delete
self.win.clrtoeol()
[142] Fix | Delete
elif ch == curses.ascii.FF: # ^l
[143] Fix | Delete
self.win.refresh()
[144] Fix | Delete
elif ch in (curses.ascii.SO, curses.KEY_DOWN): # ^n
[145] Fix | Delete
if y < self.maxy:
[146] Fix | Delete
self.win.move(y+1, x)
[147] Fix | Delete
if x > self._end_of_line(y+1):
[148] Fix | Delete
self.win.move(y+1, self._end_of_line(y+1))
[149] Fix | Delete
elif ch == curses.ascii.SI: # ^o
[150] Fix | Delete
self.win.insertln()
[151] Fix | Delete
elif ch in (curses.ascii.DLE, curses.KEY_UP): # ^p
[152] Fix | Delete
if y > 0:
[153] Fix | Delete
self.win.move(y-1, x)
[154] Fix | Delete
if x > self._end_of_line(y-1):
[155] Fix | Delete
self.win.move(y-1, self._end_of_line(y-1))
[156] Fix | Delete
return 1
[157] Fix | Delete
[158] Fix | Delete
def gather(self):
[159] Fix | Delete
"Collect and return the contents of the window."
[160] Fix | Delete
result = ""
[161] Fix | Delete
self._update_max_yx()
[162] Fix | Delete
for y in range(self.maxy+1):
[163] Fix | Delete
self.win.move(y, 0)
[164] Fix | Delete
stop = self._end_of_line(y)
[165] Fix | Delete
if stop == 0 and self.stripspaces:
[166] Fix | Delete
continue
[167] Fix | Delete
for x in range(self.maxx+1):
[168] Fix | Delete
if self.stripspaces and x > stop:
[169] Fix | Delete
break
[170] Fix | Delete
result = result + chr(curses.ascii.ascii(self.win.inch(y, x)))
[171] Fix | Delete
if self.maxy > 0:
[172] Fix | Delete
result = result + "\n"
[173] Fix | Delete
return result
[174] Fix | Delete
[175] Fix | Delete
def edit(self, validate=None):
[176] Fix | Delete
"Edit in the widget window and collect the results."
[177] Fix | Delete
while 1:
[178] Fix | Delete
ch = self.win.getch()
[179] Fix | Delete
if validate:
[180] Fix | Delete
ch = validate(ch)
[181] Fix | Delete
if not ch:
[182] Fix | Delete
continue
[183] Fix | Delete
if not self.do_command(ch):
[184] Fix | Delete
break
[185] Fix | Delete
self.win.refresh()
[186] Fix | Delete
return self.gather()
[187] Fix | Delete
[188] Fix | Delete
if __name__ == '__main__':
[189] Fix | Delete
def test_editbox(stdscr):
[190] Fix | Delete
ncols, nlines = 9, 4
[191] Fix | Delete
uly, ulx = 15, 20
[192] Fix | Delete
stdscr.addstr(uly-2, ulx, "Use Ctrl-G to end editing.")
[193] Fix | Delete
win = curses.newwin(nlines, ncols, uly, ulx)
[194] Fix | Delete
rectangle(stdscr, uly-1, ulx-1, uly + nlines, ulx + ncols)
[195] Fix | Delete
stdscr.refresh()
[196] Fix | Delete
return Textbox(win).edit()
[197] Fix | Delete
[198] Fix | Delete
str = curses.wrapper(test_editbox)
[199] Fix | Delete
print 'Contents of text box:', repr(str)
[200] Fix | Delete
[201] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function