Skip to content

Commit

Permalink
[keys] use prettykeys internally for input bindings and other getkeys…
Browse files Browse the repository at this point in the history
…troke uses
  • Loading branch information
saulpw authored and anjakefala committed Nov 6, 2024
1 parent cac5a02 commit 0b63a1b
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 121 deletions.
84 changes: 40 additions & 44 deletions visidata/_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,50 +227,50 @@ def handle_key(self, ch:str, scr) -> bool:
v = self.value

if ch == '': return False
elif ch == 'KEY_IC': self.insert_mode = not self.insert_mode
elif ch == '^A' or ch == 'KEY_HOME': i = 0
elif ch == '^B' or ch == 'KEY_LEFT': i -= 1
elif ch in ('^C', '^Q', '^['): raise EscapeException(ch)
elif ch == '^D' or ch == 'KEY_DC': v = delchar(v, i)
elif ch == '^E' or ch == 'KEY_END': i = len(v)
elif ch == '^F' or ch == 'KEY_RIGHT': i += 1
elif ch == '^G':
elif ch == 'Ins': self.insert_mode = not self.insert_mode
elif ch == 'Ctrl+A' or ch == 'Home': i = 0
elif ch == 'Ctrl+B' or ch == 'Left': i -= 1
elif ch in ('Ctrl+C', 'Ctrl+Q', 'Ctrl+['): raise EscapeException(ch)
elif ch == 'Ctrl+D' or ch == 'Del': v = delchar(v, i)
elif ch == 'Ctrl+E' or ch == 'End': i = len(v)
elif ch == 'Ctrl+F' or ch == 'Right': i += 1
elif ch == 'Ctrl+G':
vd.cycleSidebar()
return False # not considered a first keypress
elif ch in ('^H', 'KEY_BACKSPACE', '^?'): i -= 1; v = delchar(v, i)
elif ch == '^I': v, i = self.completion(v, i, +1)
elif ch == 'KEY_BTAB': v, i = self.completion(v, i, -1)
elif ch in ['^J', '^M']: return True # ENTER to accept value
elif ch == '^K': v = v[:i] # ^Kill to end-of-line
elif ch == '^N':
elif ch in ('Ctrl+H', 'Bksp', 'Ctrl+?'): i -= 1; v = delchar(v, i)
elif ch == 'Tab': v, i = self.completion(v, i, +1)
elif ch == 'Shift+Tab': v, i = self.completion(v, i, -1)
elif ch == 'Enter': return True # ENTER to accept value
elif ch == 'Ctrl+K': v = v[:i] # Ctrl+Kill to end-of-line
elif ch == 'Ctrl+N':
c = ''
while not c:
c = vd.getkeystroke(scr)
c = vd.prettykeys(c)
i += len(c)
v += c
elif ch == '^O':
elif ch == 'Ctrl+O':
edit_v = vd.launchExternalEditor(v)
if self.value == '' and edit_v == '':
# if a cell has a value of None, keep it when the editor exits with no change
raise EscapeException(ch)
else:
self.value = edit_v
return True
elif ch == '^R': v = self.orig_value # ^Reload initial value
elif ch == '^T': v = delchar(splice(v, i-2, v[i-1:i]), i) # swap chars
elif ch == '^U': v = v[i:]; i = 0 # clear to beginning
elif ch == '^V': v = splice(v, i, until_get_wch(scr)); i += 1 # literal character
elif ch == '^W': j = find_nonword(v, 0, i-1, -1); v = v[:j+1] + v[i:]; i = j+1 # erase word
elif ch == '^Y': v = splice(v, i, str(vd.memory.clipval))
elif ch == '^Z': vd.suspend()
elif ch == 'Ctrl+R': v = self.orig_value # Ctrl+Reload initial value
elif ch == 'Ctrl+T': v = delchar(splice(v, i-2, v[i-1:i]), i) # swap chars
elif ch == 'Ctrl+U': v = v[i:]; i = 0 # clear to beginning
elif ch == 'Ctrl+V': v = splice(v, i, until_get_wch(scr)); i += 1 # literal character
elif ch == 'Ctrl+W': j = find_nonword(v, 0, i-1, -1); v = v[:j+1] + v[i:]; i = j+1 # erase word
elif ch == 'Ctrl+Y': v = splice(v, i, str(vd.memory.clipval))
elif ch == 'Ctrl+Z': vd.suspend()
# CTRL+arrow
elif ch == 'kLFT5': i = find_nonword(v, 0, i-1, -1)+1; # word left
elif ch == 'kRIT5': i = find_nonword(v, i+1, len(v)-1, +1)+1; # word right
elif ch == 'kUP5': pass
elif ch == 'kDN5': pass
elif self.history and ch == 'KEY_UP': v, i = self.prev_history(v, i)
elif self.history and ch == 'KEY_DOWN': v, i = self.next_history(v, i)
elif ch == 'Ctrl+Left': i = find_nonword(v, 0, i-1, -1)+1; # word left
elif ch == 'Ctrl+Right': i = find_nonword(v, i+1, len(v)-1, +1)+1; # word right
elif ch == 'Ctrl+Up': pass
elif ch == 'Ctrl+Down': pass
elif self.history and ch == 'Up': v, i = self.prev_history(v, i)
elif self.history and ch == 'Down': v, i = self.next_history(v, i)
elif len(ch) > 1: pass
else:
if self.first_action:
Expand Down Expand Up @@ -481,12 +481,10 @@ def _drawPrompt(val):
updater=_drawPrompt,
record=False,
bindings={
'KEY_BTAB': change_input(-1),
'^I': change_input(+1),
'KEY_SR': change_input(-1),
'KEY_SF': change_input(+1),
'kUP': change_input(-1),
'kDN': change_input(+1),
'Shift+Tab': change_input(-1),
'Tab': change_input(+1),
'Shift+Up': change_input(-1),
'Shift+Down': change_input(+1),
})
break
except ChangeInput as e:
Expand Down Expand Up @@ -623,21 +621,19 @@ def editCell(self, vcolidx=None, rowidx=None, value=None, **kwargs):
value = value or col.getDisplayValue(self.rows[self.cursorRowIndex])

bindings={
'kUP': acceptThenFunc('go-up', 'rename-col' if rowidx < 0 else 'edit-cell'),
'KEY_SR': acceptThenFunc('go-up', 'rename-col' if rowidx < 0 else 'edit-cell'),
'kDN': acceptThenFunc('go-down', 'rename-col' if rowidx < 0 else 'edit-cell'),
'KEY_SF': acceptThenFunc('go-down', 'rename-col' if rowidx < 0 else 'edit-cell'),
'KEY_SRIGHT': acceptThenFunc('go-right', 'rename-col' if rowidx < 0 else 'edit-cell'),
'KEY_SLEFT': acceptThenFunc('go-left', 'rename-col' if rowidx < 0 else 'edit-cell'),
'^I': acceptThenFunc('go-right', 'rename-col' if rowidx < 0 else 'edit-cell'),
'KEY_BTAB': acceptThenFunc('go-left', 'rename-col' if rowidx < 0 else 'edit-cell'),
'Shift+Up': acceptThenFunc('go-up', 'rename-col' if rowidx < 0 else 'edit-cell'),
'Shift+Down': acceptThenFunc('go-down', 'rename-col' if rowidx < 0 else 'edit-cell'),
'Shift+Right': acceptThenFunc('go-right', 'rename-col' if rowidx < 0 else 'edit-cell'),
'Shift+Left': acceptThenFunc('go-left', 'rename-col' if rowidx < 0 else 'edit-cell'),
'Tab': acceptThenFunc('go-right', 'rename-col' if rowidx < 0 else 'edit-cell'),
'Shift+Tab': acceptThenFunc('go-left', 'rename-col' if rowidx < 0 else 'edit-cell'),
}

if vcolidx >= self.nVisibleCols-1:
bindings['^I'] = acceptThenFunc('go-down', 'go-leftmost', 'edit-cell')
bindings['Tab'] = acceptThenFunc('go-down', 'go-leftmost', 'edit-cell')

if vcolidx <= 0:
bindings['KEY_BTAB'] = acceptThenFunc('go-up', 'go-rightmost', 'edit-cell')
bindings['Shift+Tab'] = acceptThenFunc('go-up', 'go-rightmost', 'edit-cell')

# update local bindings with kwargs.bindings instead of the inverse, to preserve kwargs.bindings for caller
bindings.update(kwargs.get('bindings', {}))
Expand Down
24 changes: 12 additions & 12 deletions visidata/canvas_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,18 +129,18 @@ def slide(self, rows, dx, dy):
TextCanvas.addCommand('', 'go-up', 'cursorBox.y1 -= 1')
TextCanvas.addCommand('', 'go-left', 'cursorBox.x1 -= 1')
TextCanvas.addCommand('', 'go-right', 'cursorBox.x1 += 1')
TextCanvas.addCommand('kRIT5', 'resize-cursor-wider', 'cursorBox.w += 1', 'increase cursor width by one character')
TextCanvas.addCommand('kLFT5', 'resize-cursor-thinner', 'cursorBox.w -= 1', 'decrease cursor width by one character')
TextCanvas.addCommand('kUP5', 'resize-cursor-shorter', 'cursorBox.h -= 1', 'decrease cursor height by one character')
TextCanvas.addCommand('kDN5', 'resize-cursor-taller', 'cursorBox.h += 1', 'increase cursor height by one character')
TextCanvas.addCommand('gzKEY_LEFT', 'resize-cursor-min-width', 'cursorBox.w = 1')
TextCanvas.addCommand('gzKEY_UP', 'resize-cursor-min-height', 'cursorBox.h = 1')
TextCanvas.addCommand('Ctrl+Right', 'resize-cursor-wider', 'cursorBox.w += 1', 'increase cursor width by one character')
TextCanvas.addCommand('Ctrl+Left', 'resize-cursor-thinner', 'cursorBox.w -= 1', 'decrease cursor width by one character')
TextCanvas.addCommand('Ctrl+Up', 'resize-cursor-shorter', 'cursorBox.h -= 1', 'decrease cursor height by one character')
TextCanvas.addCommand('Ctrl+Down', 'resize-cursor-taller', 'cursorBox.h += 1', 'increase cursor height by one character')
TextCanvas.addCommand('gzLeft', 'resize-cursor-min-width', 'cursorBox.w = 1')
TextCanvas.addCommand('gzUp', 'resize-cursor-min-height', 'cursorBox.h = 1')
TextCanvas.addCommand('z_', 'resize-cursor-min', 'cursorBox.h = cursorBox.w = 1')
TextCanvas.addCommand('g_', 'resize-cursor-max', 'cursorBox.x1=cursorBox.y1=0; cursorBox.h=maxY+1; cursorBox.w=maxX+1')
TextCanvas.bindkey('zKEY_RIGHT', 'resize-cursor-wider')
TextCanvas.bindkey('zKEY_LEFT', 'resize-cursor-thinner')
TextCanvas.bindkey('zKEY_UP', 'resize-cursor-shorter')
TextCanvas.bindkey('zKEY_DOWN', 'resize-cursor-taller')
TextCanvas.bindkey('zRight', 'resize-cursor-wider')
TextCanvas.bindkey('zLeft', 'resize-cursor-thinner')
TextCanvas.bindkey('zUp', 'resize-cursor-shorter')
TextCanvas.bindkey('zDown', 'resize-cursor-taller')
TextCanvas.addCommand('BUTTON1_PRESSED', 'move-cursor', 'sheet.cursorBox = CharBox(None, mouseX, mouseY, 1, 1)', 'start cursor box with left mouse button press')
TextCanvas.addCommand('BUTTON1_RELEASED', 'end-cursor', 'cursorBox.x2=mouseX+2; cursorBox.y2=mouseY+2; cursorBox.normalize()', 'end cursor box with left mouse button release')

Expand All @@ -155,8 +155,8 @@ def slide(self, rows, dx, dy):
TextCanvas.addCommand('zu', 'unselect-top-cursor', 'source.unselect(list(itercursor(n=1)))')
TextCanvas.addCommand('d', 'delete-cursor', 'source.deleteBy(lambda r,rows=cursorRows: r in rows)', 'delete first item under cursor')
TextCanvas.addCommand('gd', 'delete-selected', 'source.deleteSelected()', 'delete selected rows on source sheet')
TextCanvas.addCommand(ENTER, 'dive-cursor', 'vs=copy(source); vs.rows=cursorRows; vs.source=sheet; vd.push(vs)', 'dive into source rows under cursor')
TextCanvas.addCommand('g'+ENTER, 'dive-selected', 'vd.push(type(source)(source=sheet, rows=source.selectedRows))', 'dive into selected source rows')
TextCanvas.addCommand('Enter', 'dive-cursor', 'vs=copy(source); vs.rows=cursorRows; vs.source=sheet; vd.push(vs)', 'dive into source rows under cursor')
TextCanvas.addCommand('gEnter', 'dive-selected', 'vd.push(type(source)(source=sheet, rows=source.selectedRows))', 'dive into selected source rows')

TextCanvas.addCommand('H', 'slide-left-obj', 'slide(source.selectedRows, -1, 0)', 'slide selected objects left one character')
TextCanvas.addCommand('J', 'slide-down-obj', 'slide(source.selectedRows, 0, +1)', 'slide selected objects down one character')
Expand Down
4 changes: 2 additions & 2 deletions visidata/clipboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,8 @@ def paste_after(sheet, rowidx):
Sheet.addCommand('gzx', 'cut-cells', 'copyCells(cursorCol, onlySelectedRows); cursorCol.setValues(onlySelectedRows, None)', 'delete (cut) contents of current column for selected rows and move them to clipboard')


Sheet.bindkey('KEY_DC', 'delete-cell'),
Sheet.bindkey('gKEY_DC', 'delete-cells'),
Sheet.bindkey('Del', 'delete-cell'),
Sheet.bindkey('gDel', 'delete-cells'),

vd.addMenuItems('''
Edit > Delete > current row > delete-row
Expand Down
12 changes: 6 additions & 6 deletions visidata/features/cmdpalette.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ def _draw_palette(value):

navailitems = min(len(palrows), nitems)

bindings['^I'] = lambda *args: tab(1, navailitems) or args
bindings['KEY_BTAB'] = lambda *args: tab(-1, navailitems) or args
bindings['Ctrl+I'] = lambda *args: tab(1, navailitems) or args
bindings['Shift+Tab'] = lambda *args: tab(-1, navailitems) or args

for i in range(nitems-len(palrows)):
palrows.append((None, None))
Expand All @@ -132,16 +132,16 @@ def _draw_palette(value):
if not topitem: return
if multiple:
bindings[' '] = partial(add_to_input, value=topitem[value_key])
bindings['^J'] = partial(accept_input_if_subset, value=topitem[value_key])
bindings['Enter'] = partial(accept_input_if_subset, value=topitem[value_key])
else:
bindings['^J'] = partial(accept_input, value=topitem[value_key])
bindings['Enter'] = partial(accept_input, value=topitem[value_key])
elif item and i == tabitem:
if not item: return
if multiple:
bindings['^J'] = partial(accept_input_if_subset, value=item[value_key])
bindings['Enter'] = partial(accept_input_if_subset, value=item[value_key])
bindings[' '] = partial(add_to_input, value=item[value_key])
else:
bindings['^J'] = partial(accept_input, value=item[value_key])
bindings['Enter'] = partial(accept_input, value=item[value_key])
attr = colors.color_menu_spec

match_summary = formatter(m, item, trigger_key) if item else ' '
Expand Down
2 changes: 1 addition & 1 deletion visidata/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def run(self, scr):

while True:
k = vd.getkeystroke(self.scrForm, self)
if k in ['^C', '^Q', '^[', 'q']:
if k in ['Ctrl+C', 'Ctrl+Q', 'Ctrl+[', 'q']:
return {}
if curinput and k in curinput.keystrokes:
return {curinput.input: k}
Expand Down
8 changes: 4 additions & 4 deletions visidata/help.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,10 @@ def openManPage(vd):
BaseSheet.addCommand('z^H', 'help-commands', 'vd.push(HelpSheet(name + "_commands", source=sheet, revbinds={}))', 'list commands and keybindings available on current sheet')
BaseSheet.addCommand('gz^H', 'help-commands-all', 'vd.push(HelpSheet("all_commands", source=None, revbinds={}))', 'list commands and keybindings for all sheet types')

BaseSheet.bindkey('KEY_F(1)', 'sysopen-help')
BaseSheet.bindkey('zKEY_F(1)', 'help-commands')
BaseSheet.bindkey('zKEY_BACKSPACE', 'help-commands')
BaseSheet.bindkey('gKEY_BACKSPACE', 'sysopen-help')
BaseSheet.bindkey('F1', 'sysopen-help')
BaseSheet.bindkey('zF1', 'help-commands')
BaseSheet.bindkey('zBksp', 'help-commands')
BaseSheet.bindkey('gBksp', 'sysopen-help')

HelpSheet.addCommand(None, 'exec-command', 'quit(sheet); draw_all(); activeStack[0].execCommand(cursorRow.longname)', 'execute command on undersheet')
BaseSheet.addCommand(None, 'open-tutorial-visidata', 'launchBrowser("https://jsvine.github.io/intro-to-visidata/")', 'open https://jsvine.github.io/intro-to-visidata/')
Expand Down
1 change: 0 additions & 1 deletion visidata/mainloop.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,6 @@ def mainloop(vd, scr):
vd.warning('duplicate prefix: ' + keystroke)
vd.keystrokes = ''
else:
keystroke = vd.prettykeys(keystroke)
vd.keystrokes += keystroke

vd.drawRightStatus(sheet._scr, sheet) # visible for commands that wait for input
Expand Down
16 changes: 8 additions & 8 deletions visidata/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,15 +442,15 @@ def _clickedDuringMenu():

currentItem = sheet.getMenuItem()

if k == '^[': # ESC
if k == 'Ctrl+[': # ESC
nEscapes += 1 #1470
if nEscapes > 1:
return
continue
else:
nEscapes = 0

if k in ['^C', '^Q', 'q', '^H', 'KEY_BACKSPACE']:
if k in ['Ctrl+C', 'Ctrl+Q', 'q', 'Ctrl+H', 'Bksp']:
return

elif k in ['KEY_MOUSE']:
Expand All @@ -460,25 +460,25 @@ def _clickedDuringMenu():
elif r == 'doit':
break

elif k in ['KEY_RIGHT', 'l']:
elif k in ['Right', 'l']:
if currentItem.menus and sheet.activeMenuItems[1] != 0: # not first item
sheet.activeMenuItems.append(0)
else:
sheet.activeMenuItems = [sheet.activeMenuItems[0]+1, 0]

elif k in ['KEY_LEFT', 'h']:
elif k in ['Left', 'h']:
if len(sheet.activeMenuItems) > 2:
sheet.activeMenuItems.pop(-1)
else:
sheet.activeMenuItems = [sheet.activeMenuItems[0]-1, 0]

elif k in ['KEY_DOWN', 'j']:
elif k in ['Down', 'j']:
sheet.activeMenuItems[-1] += 1

elif k in ['KEY_UP', 'k']:
elif k in ['Up', 'k']:
sheet.activeMenuItems[-1] -= 1

elif k in [ENTER, ' ', '^J', '^M']:
elif k in ['Enter', ' ']:
if currentItem.menus:
sheet.activeMenuItems.append(0)
else:
Expand Down Expand Up @@ -512,6 +512,6 @@ def _clickedDuringMenu():
BaseSheet.addCommand('Alt+s', 'menu-system', 'pressMenu("System")', '')
BaseSheet.addCommand('Alt+h', 'menu-help', 'pressMenu("Help")', 'open the Help menu')
BaseSheet.bindkey('Ctrl+H', 'menu-help')
BaseSheet.bindkey('KEY_BACKSPACE', 'menu-help')
BaseSheet.bindkey('Bksp', 'menu-help')

vd.addGlobals({'Menu': Menu})
Loading

0 comments on commit 0b63a1b

Please sign in to comment.