diff --git a/README.md b/README.md index d899fec..0a251e2 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ these are all of the current key bindings in babi - ^S: save - ^O: save as - ^X: quit +- ^P: open file - arrow keys: movement - ^A / home: move to beginning of line - ^E / end: move to end of line diff --git a/babi/main.py b/babi/main.py index 1222a11..1c4e728 100644 --- a/babi/main.py +++ b/babi/main.py @@ -58,6 +58,8 @@ def c_main( elif res == EditResult.PREV: screen.i -= 1 screen.status.clear() + elif res == EditResult.OPEN: + screen.i = len(screen.files) - 1 else: raise AssertionError(f'unreachable {res}') return 0 diff --git a/babi/screen.py b/babi/screen.py index 3bc264d..a4f178f 100644 --- a/babi/screen.py +++ b/babi/screen.py @@ -28,7 +28,7 @@ from babi.prompt import PromptResult from babi.status import Status VERSION_STR = 'babi v0' -EditResult = enum.Enum('EditResult', 'EXIT NEXT PREV') +EditResult = enum.Enum('EditResult', 'EXIT NEXT PREV OPEN') # TODO: find a place to populate these, surely there's a database somewhere SEQUENCE_KEYNAME = { @@ -73,11 +73,11 @@ class Screen: ) -> None: self.stdscr = stdscr color_manager = ColorManager.make() - hl_factories = ( + self.hl_factories = ( Syntax.from_screen(stdscr, color_manager), TrailingWhitespace(color_manager), ) - self.files = [File(f, hl_factories) for f in filenames] + self.files = [File(f, self.hl_factories) for f in filenames] self.i = 0 self.history = History() self.perf = perf @@ -451,6 +451,14 @@ class Screen: self.file.filename = response return self.save() + def open_file(self) -> Optional[EditResult]: + response = self.prompt('enter filename', history='open') + if response is not PromptResult.CANCELLED: + self.files.append(File(response, self.hl_factories)) + return EditResult.OPEN + else: + return None + def quit_save_modified(self) -> Optional[EditResult]: if self.file.modified: response = self.quick_prompt( @@ -488,6 +496,7 @@ class Screen: b'^S': save, b'^O': save_filename, b'^X': quit_save_modified, + b'^P': open_file, b'kLFT3': lambda screen: EditResult.PREV, b'kRIT3': lambda screen: EditResult.NEXT, b'^Z': background, diff --git a/tests/features/conftest.py b/tests/features/conftest.py index b843d6f..71ff9ed 100644 --- a/tests/features/conftest.py +++ b/tests/features/conftest.py @@ -254,6 +254,7 @@ KEYS = [ Key('^E', b'^E', '\x05'), Key('^J', b'^J', '\n'), Key('^O', b'^O', '\x0f'), + Key('^P', b'^P', '\x10'), Key('^R', b'^R', '\x12'), Key('^S', b'^S', '\x13'), Key('^U', b'^U', '\x15'), diff --git a/tests/features/open_test.py b/tests/features/open_test.py new file mode 100644 index 0000000..c6e2a40 --- /dev/null +++ b/tests/features/open_test.py @@ -0,0 +1,38 @@ +from testing.runner import and_exit + + +def test_open_cancelled(run, tmpdir): + f = tmpdir.join('f') + f.write('hello world') + + with run(str(f)) as h, and_exit(h): + h.await_text('hello world') + + h.press('^P') + h.await_text('enter filename:') + h.press('^C') + + h.await_text('cancelled') + h.await_text('hello world') + + +def test_open(run, tmpdir): + f = tmpdir.join('f') + f.write('hello world') + g = tmpdir.join('g') + g.write('goodbye world') + + with run(str(f)) as h: + h.await_text('hello world') + + h.press('^P') + h.press_and_enter(str(g)) + + h.await_text('[2/2]') + h.await_text('goodbye world') + + h.press('^X') + h.await_text('hello world') + + h.press('^X') + h.await_exit()