Skip to content
23 changes: 21 additions & 2 deletions awsshell/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,13 @@ def __init__(self, completer, model_completer, docs,
self.show_completion_columns = None
self.show_help = None
self.theme = None
self.key_bindings = None

self.load_config()

if self.key_bindings is None:
self.set_default_key_bindings()

def load_config(self):
"""Load the config from the config file or template."""
config = Config()
Expand All @@ -268,6 +272,8 @@ def load_config(self):
'show_completion_columns')
self.show_help = self.config_section.as_bool('show_help')
self.theme = self.config_section['theme']
if 'keys' in self.config_section:
self.key_bindings = self.config_section['keys']

def save_config(self):
"""Save the config to the config file."""
Expand All @@ -277,8 +283,19 @@ def save_config(self):
self.show_completion_columns
self.config_section['show_help'] = self.show_help
self.config_section['theme'] = self.theme
self.config_section['keys'] = self.key_bindings
self.config_obj.write()

def set_default_key_bindings(self):
self.key_bindings = {
'toggle_fuzzy': 'F2',
'toggle_editor': 'F3',
'toggle_column': 'F4',
'toggle_help': 'F5',
'toggle_focus': 'F9',
'exit': 'F10'
}

@property
def cli(self):
if self._cli is None or self.refresh_cli:
Expand Down Expand Up @@ -410,7 +427,8 @@ def set_show_help(show_help):
lambda: self.enable_vi_bindings, set_enable_vi_bindings,
lambda: self.show_completion_columns, set_show_completion_columns,
lambda: self.show_help, set_show_help,
self.stop_input_and_refresh_cli)
self.stop_input_and_refresh_cli,
self.key_bindings)

def create_application(self, completer, history,
display_completions_in_columns):
Expand All @@ -419,7 +437,8 @@ def create_application(self, completer, history,
lambda: self.model_completer.match_fuzzy,
lambda: self.enable_vi_bindings,
lambda: self.show_completion_columns,
lambda: self.show_help)
lambda: self.show_help,
self.key_manager.key_bindings)
style_factory = StyleFactory(self.theme)
buffers = {
'clidocs': Buffer(read_only=True)
Expand Down
46 changes: 46 additions & 0 deletions awsshell/awsshellrc
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,49 @@ show_help = True
# pastie, paraiso-light, trac, default, fruity.
# to disable themes, set theme = none
theme = vim

# Keyboard Shortcuts
[[keys]]
toggle_fuzzy = F2
toggle_editor = F3
toggle_column = F4
toggle_help = F5
toggle_focus = F9
exit = F10

# Keyboard Shortcuts Possible Values
# ControlA, ControlB, .., ContolZ

# ControlSpace
# ControlBackslash
# ControlSquareClose
# ControlCircumflex
# ControlUnderscore
# ControlLeft
# ControlRight
# ControlUp
# ControlDown

# Up
# Down
# Right
# Left

# ShiftLeft
# ShiftUp
# ShiftDown
# ShiftRight

# Home
# End
# Delete
# ShiftDelete
# ControlDelete
# PageUp
# PageDown
# BackTab
# Insert
# Backspace

# F1, F2, .. , F24

34 changes: 21 additions & 13 deletions awsshell/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ class KeyManager(object):
def __init__(self, get_match_fuzzy, set_match_fuzzy,
get_enable_vi_bindings, set_enable_vi_bindings,
get_show_completion_columns, set_show_completion_columns,
get_show_help, set_show_help, stop_input_and_refresh_cli):
get_show_help, set_show_help, stop_input_and_refresh_cli,
key_bindings):
self.manager = None
self.key_bindings = key_bindings
self._create_key_manager(
get_match_fuzzy, set_match_fuzzy,
get_enable_vi_bindings, set_enable_vi_bindings,
Expand Down Expand Up @@ -99,8 +101,9 @@ def _create_key_manager(self, get_match_fuzzy, set_match_fuzzy,
enable_auto_suggest_bindings=True,
enable_open_in_editor=False)

@self.manager.registry.add_binding(Keys.F2)
def handle_f2(_):
@self.manager.registry.add_binding(
getattr(Keys, self.key_bindings['toggle_fuzzy']))
def handle_toggle_fuzzy(_):
"""Toggle fuzzy matching.

:type _: :class:`prompt_toolkit.Event`
Expand All @@ -109,8 +112,9 @@ def handle_f2(_):
"""
set_match_fuzzy(not get_match_fuzzy())

@self.manager.registry.add_binding(Keys.F3)
def handle_f3(_):
@self.manager.registry.add_binding(
getattr(Keys, self.key_bindings['toggle_editor']))
def handle_toggle_editor(_):
"""Toggle Vi mode keybindings matching.

Disabling Vi keybindings will enable Emacs keybindings.
Expand All @@ -122,8 +126,9 @@ def handle_f3(_):
set_enable_vi_bindings(not get_enable_vi_bindings())
stop_input_and_refresh_cli()

@self.manager.registry.add_binding(Keys.F4)
def handle_f4(_):
@self.manager.registry.add_binding(
getattr(Keys, self.key_bindings['toggle_column']))
def handle_toggle_column(_):
"""Toggle multiple column completions.

:type _: :class:`prompt_toolkit.Event`
Expand All @@ -133,8 +138,9 @@ def handle_f4(_):
set_show_completion_columns(not get_show_completion_columns())
stop_input_and_refresh_cli()

@self.manager.registry.add_binding(Keys.F5)
def handle_f5(_):
@self.manager.registry.add_binding(
getattr(Keys, self.key_bindings['toggle_help']))
def handle_toggle_help(_):
"""Toggle the help container.

:type _: :class:`prompt_toolkit.Event`
Expand All @@ -144,8 +150,9 @@ def handle_f5(_):
set_show_help(not get_show_help())
stop_input_and_refresh_cli()

@self.manager.registry.add_binding(Keys.F9)
def handle_f9(event):
@self.manager.registry.add_binding(
getattr(Keys, self.key_bindings['toggle_focus']))
def handle_toggle_focus(event):
"""Switch between the default and docs buffers.

:type event: :class:`prompt_toolkit.Event`
Expand All @@ -158,8 +165,9 @@ def handle_f9(event):
else:
event.cli.focus(u'clidocs')

@self.manager.registry.add_binding(Keys.F10)
def handle_f10(event):
@self.manager.registry.add_binding(
getattr(Keys, self.key_bindings['exit']))
def handle_exit(event):
"""Quit when the `F10` key is pressed.

:type event: :class:`prompt_toolkit.Event`
Expand Down
27 changes: 19 additions & 8 deletions awsshell/toolbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ class Toolbar(object):
"""

def __init__(self, get_match_fuzzy, get_enable_vi_bindings,
get_show_completion_columns, get_show_help):
get_show_completion_columns, get_show_help, key_bindings):
self.key_bindings = key_bindings
self.handler = self._create_toolbar_handler(
get_match_fuzzy, get_enable_vi_bindings,
get_show_completion_columns, get_show_help)
get_show_completion_columns, get_show_help,)

def _create_toolbar_handler(self, get_match_fuzzy, get_enable_vi_bindings,
get_show_completion_columns, get_show_help):
Expand Down Expand Up @@ -93,17 +94,27 @@ def get_toolbar_items(cli):
show_buffer_name = 'doc'
return [
(match_fuzzy_token,
' [F2] Fuzzy: {0} '.format(match_fuzzy_cfg)),
' [{0}] Fuzzy: {1} '.format(
self.key_bindings['toggle_fuzzy'],
match_fuzzy_cfg)),
(enable_vi_bindings_token,
' [F3] Keys: {0} '.format(enable_vi_bindings_cfg)),
' [{0}] Keys: {1} '.format(
self.key_bindings['toggle_editor'],
enable_vi_bindings_cfg)),
(show_columns_token,
' [F4] {0} Column '.format(show_columns_cfg)),
' [{0}] {1} Column '.format(
self.key_bindings['toggle_column'],
show_columns_cfg)),
(show_help_token,
' [F5] Help: {0} '.format(show_help_cfg)),
' [{0}] Help: {1} '.format(
self.key_bindings['toggle_help'],
show_help_cfg)),
(Token.Toolbar,
' [F9] Focus: {0} '.format(show_buffer_name)),
' [{0}] Focus: {1} '.format(
self.key_bindings['toggle_focus'],
show_buffer_name)),
(Token.Toolbar,
' [F10] Exit ')
' [{0}] Exit '.format(self.key_bindings['exit']))
]

return get_toolbar_items
12 changes: 6 additions & 6 deletions tests/integration/test_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,35 +37,35 @@ def feed_key(self, key):
self.processor.feed(KeyPress(key, u''))
self.processor.process_keys()

def test_F2(self):
def test_toggle_fuzzy(self):
match_fuzzy = self.aws_shell.model_completer.match_fuzzy
self.feed_key(Keys.F2)
assert match_fuzzy != self.aws_shell.model_completer.match_fuzzy

def test_F3(self):
def test_toggle_editor(self):
enable_vi_bindings = self.aws_shell.enable_vi_bindings
with self.assertRaises(InputInterrupt):
self.feed_key(Keys.F3)
assert enable_vi_bindings != self.aws_shell.enable_vi_bindings

def test_F4(self):
def test_toggle_column(self):
show_completion_columns = self.aws_shell.show_completion_columns
with self.assertRaises(InputInterrupt):
self.feed_key(Keys.F4)
assert show_completion_columns != \
self.aws_shell.show_completion_columns

def test_F5(self):
def test_toggle_help(self):
show_help = self.aws_shell.show_help
with self.assertRaises(InputInterrupt):
self.feed_key(Keys.F5)
assert show_help != self.aws_shell.show_help

def test_F9(self):
def test_toggle_focus(self):
assert self.aws_shell.cli.current_buffer_name == u'DEFAULT_BUFFER'
self.feed_key(Keys.F9)
assert self.aws_shell.cli.current_buffer_name == u'clidocs'

def test_F10(self):
def test_press_exit(self):
self.feed_key(Keys.F10)
assert self.aws_shell.cli.is_exiting
3 changes: 2 additions & 1 deletion tests/unit/test_toolbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ def setUp(self):
lambda: self.aws_shell.model_completer.match_fuzzy,
lambda: self.aws_shell.enable_vi_bindings,
lambda: self.aws_shell.show_completion_columns,
lambda: self.aws_shell.show_help)
lambda: self.aws_shell.show_help,
self.aws_shell.key_bindings)

def test_toolbar_on(self):
self.aws_shell.model_completer.match_fuzzy = True
Expand Down
4 changes: 3 additions & 1 deletion tests/unit/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ def test_can_use_as_context_manager(self):
filename = f.name
f.write("foobar")
f.flush()
self.assertEqual(open(filename).read(), "foobar")
f = open(filename)
self.assertEqual(f.read(), "foobar")
f.close()

def test_is_removed_after_exiting_context(self):
with temporary_file('w') as f:
Expand Down