Show potential completions

When entering multi-key commands, display potential completions
in the status bar as a reminder to the user.

Change-Id: I498781576a60789b0f810f08cbc9c8c74d52784f
This commit is contained in:
James E. Blair 2016-04-29 19:16:29 -05:00
parent 2efa0606f7
commit 7a149db6cf
6 changed files with 120 additions and 69 deletions

View File

@ -465,18 +465,24 @@ class App(object):
self.screens.append(self.frame.body)
self.frame.body = overlay
def getGlobalCommands(self):
return list(mywid.GLOBAL_HELP)
def getGlobalHelp(self):
keys = [(k, self.config.keymap.formatKeys(k), t) for (k, t) in self.getGlobalCommands()]
for d in self.config.dashboards.values():
keys.append(('', d['key'], d['name']))
return keys
def help(self):
if not hasattr(self.frame.body, 'help'):
return
global_help = [(self.config.keymap.formatKeys(k), t)
for (k, t) in mywid.GLOBAL_HELP]
for d in self.config.dashboards.values():
global_help.append((keymap.formatKey(d['key']), d['name']))
global_help = self.getGlobalHelp()
parts = [('Global Keys', global_help),
('This Screen', self.frame.body.help())]
keylen = 0
for title, items in parts:
for keys, text in items:
for cmd, keys, text in items:
keylen = max(len(keys), keylen)
text = ''
for title, items in parts:
@ -484,7 +490,7 @@ class App(object):
text += '\n'
text += title+'\n'
text += '%s\n' % ('='*len(title),)
for keys, cmdtext in items:
for cmd, keys, cmdtext in items:
text += '{keys:{width}} {text}\n'.format(
keys=keys, width=keylen, text=cmdtext)
dialog = mywid.MessageDialog('Help for %s' % version(), text)
@ -675,7 +681,19 @@ class App(object):
self.changeScreen(view)
elif keymap.FURTHER_INPUT in commands:
self.input_buffer.append(key)
self.status.update(message=''.join(self.input_buffer))
msg = ''.join(self.input_buffer)
commands = dict(self.getGlobalCommands())
if hasattr(self.frame.body, 'getCommands'):
commands.update(dict(self.frame.body.getCommands()))
further_commands = self.config.keymap.getFurtherCommands(keys)
completions = []
for (key, cmds) in further_commands:
for cmd in cmds:
if cmd in commands:
completions.append(key)
completions = ' '.join(completions)
msg = '%s: %s' % (msg, completions)
self.status.update(message=msg)
return
self.clearInputBuffer()

View File

@ -250,6 +250,25 @@ class KeyMap(object):
ret.append(FURTHER_INPUT)
return ret
def getFurtherCommands(self, keys):
if not keys:
return []
tree = self.keytree
for key in keys:
tree = tree.keys.get(key)
if not tree:
return []
return self._getFurtherCommands('', tree)
def _getFurtherCommands(self, keys, tree):
if keys:
ret = [(formatKey(keys), tree.commands[:])]
else:
ret = []
for subtree in tree.keys.values():
ret.extend(self._getFurtherCommands(keys + subtree.key, subtree))
return ret
def getKeys(self, command):
return self.commandmap.get(command, [])

View File

@ -385,55 +385,57 @@ class CommitMessageBox(mywid.HyperText):
@mouse_scroll_decorator.ScrollByWheel
class ChangeView(urwid.WidgetWrap):
def help(self):
key = self.app.config.keymap.formatKeys
ret = [
(key(keymap.LOCAL_CHECKOUT),
def getCommands(self):
return [
(keymap.LOCAL_CHECKOUT,
"Checkout the most recent revision into the local repo"),
(key(keymap.DIFF),
(keymap.DIFF,
"Show the diff of the most recent revision"),
(key(keymap.TOGGLE_HIDDEN),
(keymap.TOGGLE_HIDDEN,
"Toggle the hidden flag for the current change"),
(key(keymap.NEXT_CHANGE),
(keymap.NEXT_CHANGE,
"Go to the next change in the list"),
(key(keymap.PREV_CHANGE),
(keymap.PREV_CHANGE,
"Go to the previous change in the list"),
(key(keymap.REVIEW),
(keymap.REVIEW,
"Leave a review for the most recent revision"),
(key(keymap.TOGGLE_HELD),
(keymap.TOGGLE_HELD,
"Toggle the held flag for the current change"),
(key(keymap.TOGGLE_HIDDEN_COMMENTS),
(keymap.TOGGLE_HIDDEN_COMMENTS,
"Toggle display of hidden comments"),
(key(keymap.SEARCH_RESULTS),
(keymap.SEARCH_RESULTS,
"Back to the list of changes"),
(key(keymap.TOGGLE_REVIEWED),
(keymap.TOGGLE_REVIEWED,
"Toggle the reviewed flag for the current change"),
(key(keymap.TOGGLE_STARRED),
(keymap.TOGGLE_STARRED,
"Toggle the starred flag for the current change"),
(key(keymap.LOCAL_CHERRY_PICK),
(keymap.LOCAL_CHERRY_PICK,
"Cherry-pick the most recent revision onto the local repo"),
(key(keymap.ABANDON_CHANGE),
(keymap.ABANDON_CHANGE,
"Abandon this change"),
(key(keymap.EDIT_COMMIT_MESSAGE),
(keymap.EDIT_COMMIT_MESSAGE,
"Edit the commit message of this change"),
(key(keymap.REBASE_CHANGE),
(keymap.REBASE_CHANGE,
"Rebase this change (remotely)"),
(key(keymap.RESTORE_CHANGE),
(keymap.RESTORE_CHANGE,
"Restore this change"),
(key(keymap.REFRESH),
(keymap.REFRESH,
"Refresh this change"),
(key(keymap.EDIT_TOPIC),
(keymap.EDIT_TOPIC,
"Edit the topic of this change"),
(key(keymap.SUBMIT_CHANGE),
(keymap.SUBMIT_CHANGE,
"Submit this change"),
(key(keymap.CHERRY_PICK_CHANGE),
(keymap.CHERRY_PICK_CHANGE,
"Propose this change to another branch"),
]
def help(self):
key = self.app.config.keymap.formatKeys
commands = self.getCommands()
ret = [(c[0], key(c[0]), c[1]) for c in commands]
for k in self.app.config.reviewkeys.values():
action = ', '.join(['{category}:{value}'.format(**a) for a in k['approvals']])
ret.append((keymap.formatKey(k['key']), action))
ret.append(('', keymap.formatKey(k['key']), action))
return ret
def __init__(self, app, change_key):

View File

@ -209,49 +209,53 @@ class ChangeListView(urwid.WidgetWrap):
required_columns = set(['Number', 'Subject', 'Updated'])
optional_columns = set(['Topic', 'Branch'])
def help(self):
key = self.app.config.keymap.formatKeys
def getCommands(self):
if self.project_key:
refresh_help = "Sync current project"
else:
refresh_help = "Sync subscribed projects"
return [
(key(keymap.TOGGLE_HELD),
(keymap.TOGGLE_HELD,
"Toggle the held flag for the currently selected change"),
(key(keymap.LOCAL_CHECKOUT),
(keymap.LOCAL_CHECKOUT,
"Checkout the most recent revision of the selected change into the local repo"),
(key(keymap.TOGGLE_HIDDEN),
(keymap.TOGGLE_HIDDEN,
"Toggle the hidden flag for the currently selected change"),
(key(keymap.TOGGLE_LIST_REVIEWED),
(keymap.TOGGLE_LIST_REVIEWED,
"Toggle whether only unreviewed or all changes are displayed"),
(key(keymap.TOGGLE_REVIEWED),
(keymap.TOGGLE_REVIEWED,
"Toggle the reviewed flag for the currently selected change"),
(key(keymap.TOGGLE_STARRED),
(keymap.TOGGLE_STARRED,
"Toggle the starred flag for the currently selected change"),
(key(keymap.TOGGLE_MARK),
(keymap.TOGGLE_MARK,
"Toggle the process mark for the currently selected change"),
(key(keymap.REFINE_CHANGE_SEARCH),
(keymap.REFINE_CHANGE_SEARCH,
"Refine the current search query"),
(key(keymap.ABANDON_CHANGE),
(keymap.ABANDON_CHANGE,
"Abandon the marked changes"),
(key(keymap.EDIT_TOPIC),
(keymap.EDIT_TOPIC,
"Set the topic of the marked changes"),
(key(keymap.RESTORE_CHANGE),
(keymap.RESTORE_CHANGE,
"Restore the marked changes"),
(key(keymap.REFRESH),
(keymap.REFRESH,
refresh_help),
(key(keymap.REVIEW),
(keymap.REVIEW,
"Leave reviews for the marked changes"),
(key(keymap.SORT_BY_NUMBER),
(keymap.SORT_BY_NUMBER,
"Sort changes by number"),
(key(keymap.SORT_BY_UPDATED),
(keymap.SORT_BY_UPDATED,
"Sort changes by how recently the change was updated"),
(key(keymap.SORT_BY_REVERSE),
(keymap.SORT_BY_REVERSE,
"Reverse the sort"),
(key(keymap.LOCAL_CHERRY_PICK),
(keymap.LOCAL_CHERRY_PICK,
"Cherry-pick the most recent revision of the selected change onto the local repo"),
]
def help(self):
key = self.app.config.keymap.formatKeys
commands = self.getCommands()
return [(c[0], key(c[0]), c[1]) for c in commands]
def __init__(self, app, query, query_desc=None, project_key=None,
unreviewed=False, sort_by=None, reverse=None):
super(ChangeListView, self).__init__(urwid.Pile([]))

View File

@ -157,17 +157,21 @@ class DiffContextButton(urwid.WidgetWrap):
@mouse_scroll_decorator.ScrollByWheel
class BaseDiffView(urwid.WidgetWrap):
def help(self):
key = self.app.config.keymap.formatKeys
def getCommands(self):
return [
(key(keymap.ACTIVATE),
(keymap.ACTIVATE,
"Add an inline comment"),
(key(keymap.SELECT_PATCHSETS),
(keymap.SELECT_PATCHSETS,
"Select old/new patchsets to diff"),
(key(keymap.INTERACTIVE_SEARCH),
(keymap.INTERACTIVE_SEARCH,
"Interactive search"),
]
def help(self):
key = self.app.config.keymap.formatKeys
commands = self.getCommands()
return [(c[0], key(c[0]), c[1]) for c in commands]
def __init__(self, app, new_revision_key):
super(BaseDiffView, self).__init__(urwid.Pile([]))
self.log = logging.getLogger('gertty.view.diff')

View File

@ -199,33 +199,37 @@ class ProjectListHeader(urwid.WidgetWrap):
@mouse_scroll_decorator.ScrollByWheel
class ProjectListView(urwid.WidgetWrap):
def help(self):
key = self.app.config.keymap.formatKeys
def getCommands(self):
return [
(key(keymap.TOGGLE_LIST_SUBSCRIBED),
(keymap.TOGGLE_LIST_SUBSCRIBED,
"Toggle whether only subscribed projects or all projects are listed"),
(key(keymap.TOGGLE_LIST_REVIEWED),
(keymap.TOGGLE_LIST_REVIEWED,
"Toggle listing of projects with unreviewed changes"),
(key(keymap.TOGGLE_SUBSCRIBED),
(keymap.TOGGLE_SUBSCRIBED,
"Toggle the subscription flag for the selected project"),
(key(keymap.REFRESH),
(keymap.REFRESH,
"Sync subscribed projects"),
(key(keymap.TOGGLE_MARK),
(keymap.TOGGLE_MARK,
"Toggle the process mark for the selected project"),
(key(keymap.NEW_PROJECT_TOPIC),
(keymap.NEW_PROJECT_TOPIC,
"Create project topic"),
(key(keymap.DELETE_PROJECT_TOPIC),
(keymap.DELETE_PROJECT_TOPIC,
"Delete selected project topic"),
(key(keymap.MOVE_PROJECT_TOPIC),
(keymap.MOVE_PROJECT_TOPIC,
"Move selected project to topic"),
(key(keymap.COPY_PROJECT_TOPIC),
(keymap.COPY_PROJECT_TOPIC,
"Copy selected project to topic"),
(key(keymap.REMOVE_PROJECT_TOPIC),
(keymap.REMOVE_PROJECT_TOPIC,
"Remove selected project from topic"),
(key(keymap.RENAME_PROJECT_TOPIC),
(keymap.RENAME_PROJECT_TOPIC,
"Rename selected project topic"),
]
def help(self):
key = self.app.config.keymap.formatKeys
commands = self.getCommands()
return [(c[0], key(c[0]), c[1]) for c in commands]
def __init__(self, app):
super(ProjectListView, self).__init__(urwid.Pile([]))
self.log = logging.getLogger('gertty.view.project_list')