diff --git a/README.rst b/README.rst index ba4f52b..6285f0c 100644 --- a/README.rst +++ b/README.rst @@ -261,6 +261,19 @@ will be printed. Current shell profile: demo +.cd +~~~ + +You can change the current working directory of the aws-shell by using +the ``.cd`` command:: + + aws> !pwd + /usr + aws> .cd /tmp + aws> !pwd + /tmp + + Executing Shell Commands ------------------------ diff --git a/awsshell/app.py b/awsshell/app.py index 680a43c..f1fee21 100644 --- a/awsshell/app.py +++ b/awsshell/app.py @@ -45,6 +45,24 @@ class InputInterrupt(Exception): pass +class ChangeDirHandler(object): + def __init__(self, output=sys.stdout, err=sys.stderr, chdir=os.chdir): + self._output = output + self._err = err + self._chdir = chdir + + def run(self, command, application): + # command is a list of parsed commands + if len(command) != 2: + self._err.write("invalid syntax, must be: .cd dirname\n") + return + dirname = os.path.expandvars(os.path.expanduser(command[1])) + try: + self._chdir(dirname) + except OSError as e: + self._err.write("cd: %s\n" % e) + + class EditHandler(object): def __init__(self, popen_cls=None, env=None): if popen_cls is None: @@ -121,6 +139,7 @@ class DotCommandHandler(object): HANDLER_CLASSES = { 'edit': EditHandler, 'profile': ProfileHandler, + 'cd': ChangeDirHandler, } def __init__(self, output=sys.stdout, err=sys.stderr): diff --git a/tests/unit/test_app.py b/tests/unit/test_app.py index 55fa697..dcb55cb 100644 --- a/tests/unit/test_app.py +++ b/tests/unit/test_app.py @@ -93,3 +93,26 @@ def test_delegates_to_complete_changing_profile(): shell.profile = 'mynewprofile' assert completer.change_profile.call_args == mock.call('mynewprofile') assert shell.profile == 'mynewprofile' + + +def test_cd_handler_can_chdir(): + chdir = mock.Mock() + handler = app.ChangeDirHandler(chdir=chdir) + handler.run(['.cd', 'foo/bar'], None) + assert chdir.call_args == mock.call('foo/bar') + + +def test_chdir_syntax_error_prints_err_msg(errstream): + chdir = mock.Mock() + handler = app.ChangeDirHandler(err=errstream, chdir=chdir) + handler.run(['.cd'], None) + assert 'invalid syntax' in errstream.getvalue() + assert not chdir.called + + +def test_error_displayed_when_chdir_fails(errstream): + chdir = mock.Mock() + chdir.side_effect = OSError("FAILED") + handler = app.ChangeDirHandler(err=errstream, chdir=chdir) + handler.run(['.cd', 'foo'], None) + assert 'FAILED' in errstream.getvalue()