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()