Add a configurable keymap
Multiple keymaps may be added in either Gertty itself or in config files, individual keys may be overriden in the standard map, and the map can be selected via config file or command line option just as palettes are. Change the help text to be dynamically generated based on the current keymap. Change-Id: I5f8e63897fab3aa14493465256b5d4516cf47dcd
This commit is contained in:
parent
9e38b52b63
commit
6815021f3f
@ -25,6 +25,7 @@ import urwid
|
||||
from gertty import db
|
||||
from gertty import config
|
||||
from gertty import gitrepo
|
||||
from gertty import keymap
|
||||
from gertty import mywid
|
||||
from gertty import sync
|
||||
from gertty import search
|
||||
@ -36,9 +37,9 @@ import gertty.view
|
||||
WELCOME_TEXT = """\
|
||||
Welcome to Gertty!
|
||||
|
||||
To get started, you should subscribe to some projects. Press the "l"
|
||||
key to list all the projects, navigate to the ones you are interested
|
||||
in, and then press "s" to subscribe to them. Gertty will
|
||||
To get started, you should subscribe to some projects. Press the "L"
|
||||
key (shift-L) to list all the projects, navigate to the ones you are
|
||||
interested in, and then press "s" to subscribe to them. Gertty will
|
||||
automatically sync changes in your subscribed projects.
|
||||
|
||||
Press the F1 key anywhere to get help. Your terminal emulator may
|
||||
@ -74,7 +75,8 @@ class StatusHeader(urwid.WidgetWrap):
|
||||
|
||||
class SearchDialog(mywid.ButtonDialog):
|
||||
signals = ['search', 'cancel']
|
||||
def __init__(self):
|
||||
def __init__(self, app):
|
||||
self.app = app
|
||||
search_button = mywid.FixedButton('Search')
|
||||
cancel_button = mywid.FixedButton('Cancel')
|
||||
urwid.connect_signal(search_button, 'click',
|
||||
@ -89,15 +91,18 @@ class SearchDialog(mywid.ButtonDialog):
|
||||
|
||||
def keypress(self, size, key):
|
||||
r = super(SearchDialog, self).keypress(size, key)
|
||||
if r == 'enter':
|
||||
commands = self.app.config.keymap.getCommands(r)
|
||||
self.app.log.debug('search %s %s' % (r, commands))
|
||||
if keymap.ACTIVATE in commands:
|
||||
self._emit('search')
|
||||
return None
|
||||
return r
|
||||
|
||||
class App(object):
|
||||
def __init__(self, server=None, palette='default', debug=False, disable_sync=False):
|
||||
def __init__(self, server=None, palette='default', keymap='default',
|
||||
debug=False, disable_sync=False):
|
||||
self.server = server
|
||||
self.config = config.Config(server, palette)
|
||||
self.config = config.Config(server, palette, keymap)
|
||||
if debug:
|
||||
level = logging.DEBUG
|
||||
else:
|
||||
@ -107,6 +112,7 @@ class App(object):
|
||||
level=level)
|
||||
self.log = logging.getLogger('gertty.App')
|
||||
self.log.debug("Starting")
|
||||
self.config.keymap.updateCommandMap()
|
||||
self.search = search.SearchCompiler(self)
|
||||
self.db = db.Database(self)
|
||||
self.sync = sync.Sync(self)
|
||||
@ -198,13 +204,25 @@ class App(object):
|
||||
def help(self):
|
||||
if not hasattr(self.loop.widget, 'help'):
|
||||
return
|
||||
text = mywid.GLOBAL_HELP
|
||||
global_help = [(self.config.keymap.formatKeys(k), t)
|
||||
for (k, t) in mywid.GLOBAL_HELP]
|
||||
for d in self.config.dashboards.values():
|
||||
space = max(9 - len(d['key']), 0) * ' '
|
||||
text += '<%s>%s %s\n' % (d['key'], space, d['name'])
|
||||
text += "\nThis Screen\n"
|
||||
text += "===========\n"
|
||||
text += self.loop.widget.help()
|
||||
global_help.append((keymap.formatKey(d['key']), d['name']))
|
||||
parts = [('Global Keys', global_help),
|
||||
('This Screen', self.loop.widget.help())]
|
||||
keylen = 0
|
||||
for title, items in parts:
|
||||
for keys, text in items:
|
||||
keylen = max(len(keys), keylen)
|
||||
text = ''
|
||||
for title, items in parts:
|
||||
if text:
|
||||
text += '\n'
|
||||
text += title+'\n'
|
||||
text += '%s\n' % ('='*len(title),)
|
||||
for keys, cmdtext in items:
|
||||
text += '{keys:{width}} {text}\n'.format(
|
||||
keys=keys, width=keylen, text=cmdtext)
|
||||
dialog = mywid.MessageDialog('Help', text)
|
||||
lines = text.split('\n')
|
||||
urwid.connect_signal(dialog, 'close',
|
||||
@ -281,7 +299,7 @@ class App(object):
|
||||
return self.error(e.message)
|
||||
|
||||
def searchDialog(self):
|
||||
dialog = SearchDialog()
|
||||
dialog = SearchDialog(self)
|
||||
urwid.connect_signal(dialog, 'cancel',
|
||||
lambda button: self.backScreen())
|
||||
urwid.connect_signal(dialog, 'search',
|
||||
@ -305,13 +323,14 @@ class App(object):
|
||||
return None
|
||||
|
||||
def unhandledInput(self, key):
|
||||
if key == 'esc':
|
||||
commands = self.config.keymap.getCommands(key)
|
||||
if keymap.PREV_SCREEN in commands:
|
||||
self.backScreen()
|
||||
elif key == 'f1' or key == '?':
|
||||
elif keymap.HELP in commands:
|
||||
self.help()
|
||||
elif key == 'ctrl q':
|
||||
elif keymap.QUIT in commands:
|
||||
self.quit()
|
||||
elif key == 'ctrl o':
|
||||
elif keymap.CHANGE_SEARCH in commands:
|
||||
self.searchDialog()
|
||||
elif key in self.config.dashboards:
|
||||
d = self.config.dashboards[key]
|
||||
@ -339,10 +358,12 @@ def main():
|
||||
help='disable remote syncing')
|
||||
parser.add_argument('-p', dest='palette', default='default',
|
||||
help='Color palette to use')
|
||||
parser.add_argument('-k', dest='keymap', default='default',
|
||||
help='Keymap to use')
|
||||
parser.add_argument('server', nargs='?',
|
||||
help='the server to use (as specified in config file)')
|
||||
args = parser.parse_args()
|
||||
g = App(args.server, args.palette, args.debug, args.no_sync)
|
||||
g = App(args.server, args.palette, args.keymap, args.debug, args.no_sync)
|
||||
g.run()
|
||||
|
||||
|
||||
|
@ -27,6 +27,7 @@ import voluptuous as v
|
||||
|
||||
import gertty.commentlink
|
||||
import gertty.palette
|
||||
import gertty.keymap
|
||||
|
||||
try:
|
||||
OrderedDict = collections.OrderedDict
|
||||
@ -89,10 +90,17 @@ class ConfigSchema(object):
|
||||
|
||||
hide_comments = [hide_comment]
|
||||
|
||||
keymap = {v.Required('name'): str,
|
||||
v.Match('(?!name)'): v.Any([str], str)}
|
||||
|
||||
keymaps = [keymap]
|
||||
|
||||
def getSchema(self, data):
|
||||
schema = v.Schema({v.Required('servers'): self.servers,
|
||||
'palettes': self.palettes,
|
||||
'palette': str,
|
||||
'keymaps': self.keymaps,
|
||||
'keymap': str,
|
||||
'commentlinks': self.commentlinks,
|
||||
'dashboards': self.dashboards,
|
||||
'reviewkeys': self.reviewkeys,
|
||||
@ -103,7 +111,7 @@ class ConfigSchema(object):
|
||||
return schema
|
||||
|
||||
class Config(object):
|
||||
def __init__(self, server=None, palette='default',
|
||||
def __init__(self, server=None, palette='default', keymap='default',
|
||||
path=DEFAULT_CONFIG_PATH):
|
||||
self.path = os.path.expanduser(path)
|
||||
|
||||
@ -144,6 +152,14 @@ class Config(object):
|
||||
self.palettes[p['name']].update(p)
|
||||
self.palette = self.palettes[self.config.get('palette', palette)]
|
||||
|
||||
self.keymaps = {'default': gertty.keymap.KeyMap({})}
|
||||
for p in self.config.get('keymaps', []):
|
||||
if p['name'] not in self.keymaps:
|
||||
self.keymaps[p['name']] = gertty.keymap.KeyMap(p)
|
||||
else:
|
||||
self.keymaps[p['name']].update(p)
|
||||
self.keymap = self.keymaps[self.config.get('keymap', keymap)]
|
||||
|
||||
self.commentlinks = [gertty.commentlink.CommentLink(c)
|
||||
for c in self.config.get('commentlinks', [])]
|
||||
self.commentlinks.append(
|
||||
|
162
gertty/keymap.py
Normal file
162
gertty/keymap.py
Normal file
@ -0,0 +1,162 @@
|
||||
# Copyright 2014 OpenStack Foundation
|
||||
# Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import re
|
||||
import string
|
||||
|
||||
import urwid
|
||||
|
||||
# urwid command map:
|
||||
REDRAW_SCREEN = urwid.REDRAW_SCREEN
|
||||
CURSOR_UP = urwid.CURSOR_UP
|
||||
CURSOR_DOWN = urwid.CURSOR_DOWN
|
||||
CURSOR_LEFT = urwid.CURSOR_LEFT
|
||||
CURSOR_RIGHT = urwid.CURSOR_RIGHT
|
||||
CURSOR_PAGE_UP = urwid.CURSOR_PAGE_UP
|
||||
CURSOR_PAGE_DOWN = urwid.CURSOR_PAGE_DOWN
|
||||
CURSOR_MAX_LEFT = urwid.CURSOR_MAX_LEFT
|
||||
CURSOR_MAX_RIGHT = urwid.CURSOR_MAX_RIGHT
|
||||
ACTIVATE = urwid.ACTIVATE
|
||||
# Global gertty commands:
|
||||
PREV_SCREEN = 'previous screen'
|
||||
HELP = 'help'
|
||||
QUIT = 'quit'
|
||||
CHANGE_SEARCH = 'change search'
|
||||
# Change screen:
|
||||
TOGGLE_REVIEWED = 'toggle reviewed'
|
||||
TOGGLE_HIDDEN = 'toggle hidden'
|
||||
REVIEW = 'review'
|
||||
DIFF = 'diff'
|
||||
CHECKOUT = 'checkout'
|
||||
CHERRY_PICK = 'cherry pick'
|
||||
SEARCH_RESULTS = 'search results'
|
||||
NEXT_CHANGE = 'next change'
|
||||
PREV_CHANGE = 'previous change'
|
||||
TOGGLE_HIDDEN_COMMENTS = 'toggle hidden comments'
|
||||
REFRESH = 'refresh'
|
||||
# Project list screen:
|
||||
TOGGLE_LIST_REVIEWED = 'toggle list reviewed'
|
||||
TOGGLE_LIST_SUBSCRIBED = 'toggle list subscribed'
|
||||
TOGGLE_SUBSCRIBED = 'toggle subscribed'
|
||||
# Diff screens:
|
||||
SELECT_PATCHSETS = 'select patchsets'
|
||||
NEXT_SELECTABLE = 'next selectable'
|
||||
PREV_SELECTABLE = 'prev selectable'
|
||||
|
||||
DEFAULT_KEYMAP = {
|
||||
REDRAW_SCREEN: 'ctrl l',
|
||||
CURSOR_UP: 'up',
|
||||
CURSOR_DOWN: 'down',
|
||||
CURSOR_LEFT: 'left',
|
||||
CURSOR_RIGHT: 'right',
|
||||
CURSOR_PAGE_UP: 'page up',
|
||||
CURSOR_PAGE_DOWN: 'page down',
|
||||
CURSOR_MAX_LEFT: 'home',
|
||||
CURSOR_MAX_RIGHT: 'end',
|
||||
ACTIVATE: 'enter',
|
||||
|
||||
PREV_SCREEN: 'esc',
|
||||
HELP: ['f1', 'h'],
|
||||
QUIT: 'ctrl q',
|
||||
CHANGE_SEARCH: 'ctrl o',
|
||||
|
||||
TOGGLE_REVIEWED: 'v',
|
||||
TOGGLE_HIDDEN: 'k',
|
||||
REVIEW: 'r',
|
||||
DIFF: 'd',
|
||||
CHECKOUT: 'c',
|
||||
CHERRY_PICK: 'x',
|
||||
SEARCH_RESULTS: 'u',
|
||||
NEXT_CHANGE: 'n',
|
||||
PREV_CHANGE: 'p',
|
||||
TOGGLE_HIDDEN_COMMENTS: 't',
|
||||
REFRESH: 'ctrl r',
|
||||
|
||||
TOGGLE_LIST_REVIEWED: 'l',
|
||||
TOGGLE_LIST_SUBSCRIBED: 'L',
|
||||
TOGGLE_SUBSCRIBED: 's',
|
||||
|
||||
SELECT_PATCHSETS: 'p',
|
||||
NEXT_SELECTABLE: 'tab',
|
||||
PREV_SELECTABLE: 'shift tab',
|
||||
}
|
||||
|
||||
URWID_COMMANDS = frozenset((
|
||||
urwid.REDRAW_SCREEN,
|
||||
urwid.CURSOR_UP,
|
||||
urwid.CURSOR_DOWN,
|
||||
urwid.CURSOR_LEFT,
|
||||
urwid.CURSOR_RIGHT,
|
||||
urwid.CURSOR_PAGE_UP,
|
||||
urwid.CURSOR_PAGE_DOWN,
|
||||
urwid.CURSOR_MAX_LEFT,
|
||||
urwid.CURSOR_MAX_RIGHT,
|
||||
urwid.ACTIVATE,
|
||||
))
|
||||
|
||||
FORMAT_SUBS = (
|
||||
(re.compile('ctrl '), 'CTRL-'),
|
||||
(re.compile('meta '), 'META-'),
|
||||
(re.compile('f(\d+)'), 'F\\1'),
|
||||
(re.compile('([a-z][a-z]+)'), lambda x: string.upper(x.group(1))),
|
||||
)
|
||||
|
||||
def formatKey(key):
|
||||
for subre, repl in FORMAT_SUBS:
|
||||
key = subre.sub(repl, key)
|
||||
return key
|
||||
|
||||
class KeyMap(object):
|
||||
def __init__(self, config):
|
||||
# key -> [commands]
|
||||
self.keymap = {}
|
||||
self.commandmap = {}
|
||||
self.update(DEFAULT_KEYMAP)
|
||||
self.update(config)
|
||||
|
||||
def update(self, config):
|
||||
# command -> [keys]
|
||||
for command, keys in config.items():
|
||||
if command == 'name':
|
||||
continue
|
||||
if type(keys) != type([]):
|
||||
keys = [keys]
|
||||
self.commandmap[command] = keys
|
||||
self.keymap = {}
|
||||
for command, keys in self.commandmap.items():
|
||||
for key in keys:
|
||||
if key in self.keymap:
|
||||
self.keymap[key].append(command)
|
||||
else:
|
||||
self.keymap[key] = [command]
|
||||
|
||||
def getCommands(self, key):
|
||||
return self.keymap.get(key, [])
|
||||
|
||||
def getKeys(self, command):
|
||||
return self.commandmap.get(command, [])
|
||||
|
||||
def updateCommandMap(self):
|
||||
"Update the urwid command map with this keymap"
|
||||
for key, commands in self.keymap.items():
|
||||
for command in commands:
|
||||
command = command.replace('-', ' ')
|
||||
if command in URWID_COMMANDS:
|
||||
urwid.command_map[key]=command
|
||||
|
||||
def formatKeys(self, command):
|
||||
keys = self.getKeys(command)
|
||||
keys = [formatKey(k) for k in keys]
|
||||
return ' or '.join(keys)
|
@ -14,14 +14,18 @@
|
||||
|
||||
import urwid
|
||||
|
||||
GLOBAL_HELP = """\
|
||||
Global Keys
|
||||
===========
|
||||
<F1> or <?> Display help.
|
||||
<ESC> Back to previous screen.
|
||||
<CTRL-Q> Quit Gertty.
|
||||
<CTRL-O> Search for changes.
|
||||
"""
|
||||
from gertty import keymap
|
||||
|
||||
GLOBAL_HELP = (
|
||||
(keymap.HELP,
|
||||
"Display help"),
|
||||
(keymap.PREV_SCREEN,
|
||||
"Back to previous screen"),
|
||||
(keymap.QUIT,
|
||||
"Quit Gertty"),
|
||||
(keymap.CHANGE_SEARCH,
|
||||
"Search for changes"),
|
||||
)
|
||||
|
||||
class TextButton(urwid.Button):
|
||||
def selectable(self):
|
||||
@ -176,7 +180,7 @@ class HyperText(urwid.Text):
|
||||
if self.focusNextItem():
|
||||
return False
|
||||
return key
|
||||
elif key == 'enter':
|
||||
elif self._command_map[key] == urwid.ACTIVATE:
|
||||
self.select()
|
||||
return False
|
||||
return key
|
||||
|
@ -18,6 +18,7 @@ import datetime
|
||||
import urwid
|
||||
|
||||
from gertty import gitrepo
|
||||
from gertty import keymap
|
||||
from gertty import mywid
|
||||
from gertty import sync
|
||||
from gertty.view import side_diff as view_side_diff
|
||||
@ -97,7 +98,8 @@ class ReviewDialog(urwid.WidgetWrap):
|
||||
|
||||
def keypress(self, size, key):
|
||||
r = super(ReviewDialog, self).keypress(size, key)
|
||||
if r=='esc':
|
||||
commands = self.app.config.keymap.getCommands(r)
|
||||
if keymap.PREV_SCREEN in commands:
|
||||
self._emit('cancel')
|
||||
return None
|
||||
return r
|
||||
@ -282,27 +284,38 @@ class CommitMessageBox(mywid.HyperText):
|
||||
super(CommitMessageBox, self).set_text(text)
|
||||
|
||||
class ChangeView(urwid.WidgetWrap):
|
||||
_help = """
|
||||
<c> Checkout the most recent revision into the local repo.
|
||||
<d> Show the diff of the mont recent revision.
|
||||
<k> Toggle the hidden flag for the current change.
|
||||
<n> Go to the next change in the list.
|
||||
<p> Go to the previous change in the list.
|
||||
<r> Leave a review for the most recent revision.
|
||||
<t> Toggle display of hidden comments.
|
||||
<u> Back to the list of changes.
|
||||
<v> Toggle the reviewed flag for the current change.
|
||||
<x> Cherry-pick the most recent revision onto the local repo.
|
||||
<ctrl-r> Refresh this change.
|
||||
"""
|
||||
|
||||
def help(self):
|
||||
text = self._help
|
||||
key = self.app.config.keymap.formatKeys
|
||||
ret = [
|
||||
(key(keymap.CHECKOUT),
|
||||
"Checkout the most recent revision into the local repo"),
|
||||
(key(keymap.DIFF),
|
||||
"Show the diff of the mont recent revision"),
|
||||
(key(keymap.TOGGLE_HIDDEN),
|
||||
"Toggle the hidden flag for the current change"),
|
||||
(key(keymap.NEXT_CHANGE),
|
||||
"Go to the next change in the list"),
|
||||
(key(keymap.PREV_CHANGE),
|
||||
"Go to the previous change in the list"),
|
||||
(key(keymap.REVIEW),
|
||||
"Leave a review for the most recent revision"),
|
||||
(key(keymap.TOGGLE_HIDDEN_COMMENTS),
|
||||
"Toggle display of hidden comments"),
|
||||
(key(keymap.SEARCH_RESULTS),
|
||||
"Back to the list of changes"),
|
||||
(key(keymap.TOGGLE_REVIEWED),
|
||||
"Toggle the reviewed flag for the current change"),
|
||||
(key(keymap.CHERRY_PICK),
|
||||
"Cherry-pick the most recent revision onto the local repo"),
|
||||
(key(keymap.REFRESH),
|
||||
"Refresh this change"),
|
||||
]
|
||||
|
||||
for k in self.app.config.reviewkeys.values():
|
||||
space = max(6 - len(k['key']), 0) * ' '
|
||||
action = ', '.join(['{category}:{value}'.format(**a) for a in k['approvals']])
|
||||
text += '<%s>%s %s\n' % (k['key'], space, action)
|
||||
return text
|
||||
ret.append((keymap.formatKey(k['key']), action))
|
||||
|
||||
return ret
|
||||
|
||||
def __init__(self, app, change_key):
|
||||
super(ChangeView, self).__init__(urwid.Pile([]))
|
||||
@ -608,37 +621,39 @@ class ChangeView(urwid.WidgetWrap):
|
||||
|
||||
def keypress(self, size, key):
|
||||
r = super(ChangeView, self).keypress(size, key)
|
||||
if r == 'v':
|
||||
commands = self.app.config.keymap.getCommands(r)
|
||||
if keymap.TOGGLE_REVIEWED in commands:
|
||||
self.toggleReviewed()
|
||||
self.refresh()
|
||||
return None
|
||||
if r == 'k':
|
||||
if keymap.TOGGLE_HIDDEN in commands:
|
||||
self.toggleHidden()
|
||||
self.refresh()
|
||||
return None
|
||||
if r == 'r':
|
||||
if keymap.REVIEW in commands:
|
||||
row = self.revision_rows[self.last_revision_key]
|
||||
row.review_button.openReview()
|
||||
return None
|
||||
if r == 'd':
|
||||
if keymap.DIFF in commands:
|
||||
row = self.revision_rows[self.last_revision_key]
|
||||
row.diff(None)
|
||||
return None
|
||||
if r == 'c':
|
||||
if keymap.CHECKOUT in commands:
|
||||
row = self.revision_rows[self.last_revision_key]
|
||||
row.checkout(None)
|
||||
return None
|
||||
if r == 'x':
|
||||
if keymap.CHERRY_PICK in commands:
|
||||
row = self.revision_rows[self.last_revision_key]
|
||||
row.cherryPick(None)
|
||||
return None
|
||||
if r == 'u':
|
||||
if keymap.SEARCH_RESULTS in commands:
|
||||
widget = self.app.findChangeList()
|
||||
self.app.backScreen(widget)
|
||||
return None
|
||||
if r in ['n', 'p']:
|
||||
if ((keymap.NEXT_CHANGE in commands) or
|
||||
(keymap.PREV_CHANGE in commands)):
|
||||
widget = self.app.findChangeList()
|
||||
if r == 'n':
|
||||
if keymap.NEXT_CHANGE in commands:
|
||||
new_change_key = widget.getNextChangeKey(self.change_key)
|
||||
else:
|
||||
new_change_key = widget.getPrevChangeKey(self.change_key)
|
||||
@ -649,11 +664,11 @@ class ChangeView(urwid.WidgetWrap):
|
||||
except gertty.view.DisplayError as e:
|
||||
self.app.error(e.message)
|
||||
return None
|
||||
if r == 't':
|
||||
if keymap.TOGGLE_HIDDEN_COMMENTS in commands:
|
||||
self.hide_comments = not self.hide_comments
|
||||
self.refresh()
|
||||
return None
|
||||
if r == 'ctrl r':
|
||||
if keymap.REFRESH in commands:
|
||||
self.app.sync.submitTask(
|
||||
sync.SyncChangeTask(self.change_rest_id, priority=sync.HIGH_PRIORITY))
|
||||
self.app.status.update()
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
import urwid
|
||||
|
||||
from gertty import keymap
|
||||
from gertty import mywid
|
||||
from gertty import sync
|
||||
from gertty.view import change as view_change
|
||||
@ -68,15 +69,18 @@ class ChangeListHeader(urwid.WidgetWrap):
|
||||
self._w.contents.append((urwid.Text(' %s' % category[0]), self._w.options('given', 3)))
|
||||
|
||||
class ChangeListView(urwid.WidgetWrap):
|
||||
_help = """
|
||||
<k> Toggle the hidden flag for the currently selected change.
|
||||
<l> Toggle whether only unreviewed or all changes are displayed.
|
||||
<v> Toggle the reviewed flag for the currently selected change.
|
||||
<ctrl-r> Sync all projects.
|
||||
"""
|
||||
|
||||
def help(self):
|
||||
return self._help
|
||||
key = self.app.config.keymap.formatKeys
|
||||
return [
|
||||
(key(keymap.TOGGLE_HIDDEN),
|
||||
"Toggle the hidden flag for the currently selected change"),
|
||||
(key(keymap.TOGGLE_LIST_REVIEWED),
|
||||
"Toggle whether only unreviewed or all changes are displayed"),
|
||||
(key(keymap.TOGGLE_REVIEWED),
|
||||
"Toggle the reviewed flag for the currently selected change"),
|
||||
(key(keymap.REFRESH),
|
||||
"Sync all projects")
|
||||
]
|
||||
|
||||
def __init__(self, app, query, query_desc=None, unreviewed=False):
|
||||
super(ChangeListView, self).__init__(urwid.Pile([]))
|
||||
@ -152,30 +156,32 @@ class ChangeListView(urwid.WidgetWrap):
|
||||
return ret
|
||||
|
||||
def keypress(self, size, key):
|
||||
if key=='l':
|
||||
r = super(ChangeListView, self).keypress(size, key)
|
||||
commands = self.app.config.keymap.getCommands(r)
|
||||
if keymap.TOGGLE_LIST_REVIEWED in commands:
|
||||
self.unreviewed = not self.unreviewed
|
||||
self.refresh()
|
||||
return None
|
||||
if key=='v':
|
||||
if keymap.TOGGLE_REVIEWED in commands:
|
||||
if not len(self.listbox.body):
|
||||
return None
|
||||
pos = self.listbox.focus_position
|
||||
reviewed = self.toggleReviewed(self.listbox.body[pos].change_key)
|
||||
self.refresh()
|
||||
return None
|
||||
if key=='k':
|
||||
if keymap.TOGGLE_HIDDEN in commands:
|
||||
if not len(self.listbox.body):
|
||||
return None
|
||||
pos = self.listbox.focus_position
|
||||
hidden = self.toggleHidden(self.listbox.body[pos].change_key)
|
||||
self.refresh()
|
||||
return None
|
||||
if key == 'ctrl r':
|
||||
if keymap.REFRESH in commands:
|
||||
self.app.sync.submitTask(
|
||||
sync.SyncSubscribedProjectsTask(sync.HIGH_PRIORITY))
|
||||
self.app.status.update()
|
||||
return None
|
||||
return super(ChangeListView, self).keypress(size, key)
|
||||
return key
|
||||
|
||||
def onSelect(self, button, change_key):
|
||||
try:
|
||||
|
@ -17,6 +17,7 @@ import logging
|
||||
|
||||
import urwid
|
||||
|
||||
from gertty import keymap
|
||||
from gertty import mywid
|
||||
from gertty import gitrepo
|
||||
|
||||
@ -144,13 +145,14 @@ class DiffContextButton(urwid.WidgetWrap):
|
||||
self.view.expandChunk(self.diff, self.chunk, from_end=-10)
|
||||
|
||||
class BaseDiffView(urwid.WidgetWrap):
|
||||
_help = """
|
||||
<Enter> Add an inline comment
|
||||
<p> Select old/new patchsets to diff
|
||||
"""
|
||||
|
||||
def help(self):
|
||||
return self._help
|
||||
key = self.app.config.keymap.formatKeys
|
||||
return [
|
||||
(key(keymap.ACTIVATE),
|
||||
"Add an inline comment"),
|
||||
(key(keymap.SELECT_PATCHSETS),
|
||||
"Select old/new patchsets to diff"),
|
||||
]
|
||||
|
||||
def __init__(self, app, new_revision_key):
|
||||
super(BaseDiffView, self).__init__(urwid.Pile([]))
|
||||
@ -346,10 +348,11 @@ class BaseDiffView(urwid.WidgetWrap):
|
||||
old_focus = self.listbox.focus
|
||||
r = super(BaseDiffView, self).keypress(size, key)
|
||||
new_focus = self.listbox.focus
|
||||
commands = self.app.config.keymap.getCommands(r)
|
||||
if (isinstance(old_focus, BaseDiffCommentEdit) and
|
||||
(old_focus != new_focus or key == 'esc')):
|
||||
(old_focus != new_focus or (keymap.PREV_SCREEN in commands))):
|
||||
self.cleanupEdit(old_focus)
|
||||
if r == 'p':
|
||||
if keymap.SELECT_PATCHSETS in commands:
|
||||
self.openPatchsetDialog()
|
||||
return None
|
||||
return r
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
import urwid
|
||||
|
||||
from gertty import keymap
|
||||
from gertty import mywid
|
||||
from gertty import sync
|
||||
from gertty.view import change_list as view_change_list
|
||||
@ -66,15 +67,18 @@ class ProjectListHeader(urwid.WidgetWrap):
|
||||
super(ProjectListHeader, self).__init__(urwid.Columns(cols))
|
||||
|
||||
class ProjectListView(urwid.WidgetWrap):
|
||||
_help = """
|
||||
<l> Toggle whether only subscribed projects or all projects are listed.
|
||||
<L> Toggle listing of projects with unreviewed changes.
|
||||
<s> Toggle the subscription flag for the currently selected project.
|
||||
<ctrl-r> Sync all projects.
|
||||
"""
|
||||
|
||||
def help(self):
|
||||
return self._help
|
||||
key = self.app.config.keymap.formatKeys
|
||||
return [
|
||||
(key(keymap.TOGGLE_LIST_SUBSCRIBED),
|
||||
"Toggle whether only subscribed projects or all projects are listed"),
|
||||
(key(keymap.TOGGLE_LIST_REVIEWED),
|
||||
"Toggle listing of projects with unreviewed changes"),
|
||||
(key(keymap.TOGGLE_SUBSCRIBED),
|
||||
"Toggle the subscription flag for the currently selected project"),
|
||||
(key(keymap.REFRESH),
|
||||
"Sync all projects")
|
||||
]
|
||||
|
||||
def __init__(self, app):
|
||||
super(ProjectListView, self).__init__(urwid.Pile([]))
|
||||
@ -138,15 +142,17 @@ class ProjectListView(urwid.WidgetWrap):
|
||||
project_name, unreviewed=True))
|
||||
|
||||
def keypress(self, size, key):
|
||||
if key=='L':
|
||||
r = super(ProjectListView, self).keypress(size, key)
|
||||
commands = self.app.config.keymap.getCommands(r)
|
||||
if keymap.TOGGLE_LIST_REVIEWED in commands:
|
||||
self.unreviewed = not self.unreviewed
|
||||
self.refresh()
|
||||
return None
|
||||
if key=='l':
|
||||
if keymap.TOGGLE_LIST_SUBSCRIBED in commands:
|
||||
self.subscribed = not self.subscribed
|
||||
self.refresh()
|
||||
return None
|
||||
if key=='s':
|
||||
if keymap.TOGGLE_SUBSCRIBED in commands:
|
||||
if not len(self.listbox.body):
|
||||
return None
|
||||
pos = self.listbox.focus_position
|
||||
@ -156,11 +162,9 @@ class ProjectListView(urwid.WidgetWrap):
|
||||
if subscribed:
|
||||
self.app.sync.submitTask(sync.SyncProjectTask(project_key))
|
||||
return None
|
||||
if key == 'ctrl r':
|
||||
if keymap.REFRESH in commands:
|
||||
self.app.sync.submitTask(
|
||||
sync.SyncSubscribedProjectsTask(sync.HIGH_PRIORITY))
|
||||
self.app.status.update()
|
||||
return None
|
||||
return super(ProjectListView, self).keypress(size, key)
|
||||
|
||||
|
||||
return r
|
||||
|
@ -17,13 +17,15 @@ import logging
|
||||
|
||||
import urwid
|
||||
|
||||
from gertty import keymap
|
||||
from gertty import mywid
|
||||
from gertty import gitrepo
|
||||
from gertty.view.diff import *
|
||||
|
||||
class SideDiffCommentEdit(BaseDiffCommentEdit):
|
||||
def __init__(self, context, old_key=None, new_key=None, old=u'', new=u''):
|
||||
def __init__(self, app, context, old_key=None, new_key=None, old=u'', new=u''):
|
||||
super(SideDiffCommentEdit, self).__init__([])
|
||||
self.app = app
|
||||
self.context = context
|
||||
# If we save a comment, the resulting key will be stored here
|
||||
self.old_key = old_key
|
||||
@ -38,7 +40,9 @@ class SideDiffCommentEdit(BaseDiffCommentEdit):
|
||||
|
||||
def keypress(self, size, key):
|
||||
r = super(SideDiffCommentEdit, self).keypress(size, key)
|
||||
if r in ['tab', 'shift tab']:
|
||||
commands = self.app.config.keymap.getCommands(r)
|
||||
if ((keymap.NEXT_SELECTABLE in commands) or
|
||||
(keymap.PREV_SELECTABLE in commands)):
|
||||
if self.focus_position == 3:
|
||||
self.focus_position = 1
|
||||
else:
|
||||
@ -137,7 +141,7 @@ class SideDiffView(BaseDiffView):
|
||||
(old_comment_key, old_comment) = old_list.pop(0)
|
||||
if new_list:
|
||||
(new_comment_key, new_comment) = new_list.pop(0)
|
||||
lines.append(SideDiffCommentEdit(context,
|
||||
lines.append(SideDiffCommentEdit(self.app, context,
|
||||
old_comment_key,
|
||||
new_comment_key,
|
||||
old_comment, new_comment))
|
||||
@ -178,14 +182,14 @@ class SideDiffView(BaseDiffView):
|
||||
(old_comment_key, old_comment) = old_list.pop(0)
|
||||
if new_list:
|
||||
(new_comment_key, new_comment) = new_list.pop(0)
|
||||
lines.append(SideDiffCommentEdit(context,
|
||||
lines.append(SideDiffCommentEdit(self.app, context,
|
||||
old_comment_key,
|
||||
new_comment_key,
|
||||
old_comment, new_comment))
|
||||
return lines
|
||||
|
||||
def makeCommentEdit(self, edit):
|
||||
return SideDiffCommentEdit(edit.context)
|
||||
return SideDiffCommentEdit(self.app, edit.context)
|
||||
|
||||
def cleanupEdit(self, edit):
|
||||
if edit.old_key:
|
||||
|
Loading…
x
Reference in New Issue
Block a user