Support babi - for reading from stdin

Resolves #42
This commit is contained in:
Anthony Sottile
2020-03-19 18:52:03 -07:00
parent b59d03858c
commit b683657f23
3 changed files with 51 additions and 7 deletions

View File

@@ -226,11 +226,17 @@ class File:
self.selection = Selection()
self._file_hls: Tuple[FileHL, ...] = ()
def ensure_loaded(self, status: Status) -> None:
def ensure_loaded(self, status: Status, stdin: str) -> None:
if self.lines:
return
if self.filename is not None and os.path.isfile(self.filename):
if self.filename == '-':
status.update('(from stdin)')
self.filename = None
self.modified = True
sio = io.StringIO(stdin)
self.lines, self.nl, mixed, self.sha256 = get_lines(sio)
elif self.filename is not None and os.path.isfile(self.filename):
with open(self.filename, newline='') as f:
self.lines, self.nl, mixed, self.sha256 = get_lines(f)
else:

View File

@@ -1,5 +1,7 @@
import argparse
import curses
import os
import sys
from typing import Optional
from typing import Sequence
@@ -9,9 +11,11 @@ from babi.screen import EditResult
from babi.screen import make_stdscr
from babi.screen import Screen
CONSOLE = 'CONIN$' if sys.platform == 'win32' else '/dev/tty'
def _edit(screen: Screen) -> EditResult:
screen.file.ensure_loaded(screen.status)
def _edit(screen: Screen, stdin: str) -> EditResult:
screen.file.ensure_loaded(screen.status, stdin)
while True:
screen.status.tick(screen.margin)
@@ -32,13 +36,17 @@ def _edit(screen: Screen) -> EditResult:
screen.status.update(f'unknown key: {key}')
def c_main(stdscr: 'curses._CursesWindow', args: argparse.Namespace) -> int:
def c_main(
stdscr: 'curses._CursesWindow',
args: argparse.Namespace,
stdin: str,
) -> int:
with perf_log(args.perf_log) as perf:
screen = Screen(stdscr, args.filenames or [None], perf)
with screen.history.save():
while screen.files:
screen.i = screen.i % len(screen.files)
res = _edit(screen)
res = _edit(screen, stdin)
if res == EditResult.EXIT:
del screen.files[screen.i]
screen.status.clear()
@@ -59,8 +67,16 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
parser.add_argument('--perf-log')
args = parser.parse_args(argv)
if '-' in args.filenames:
print('reading stdin...', file=sys.stderr)
stdin = sys.stdin.read()
tty = os.open(CONSOLE, os.O_RDONLY)
os.dup2(tty, sys.stdin.fileno())
else:
stdin = ''
with make_stdscr() as stdscr:
return c_main(stdscr, args)
return c_main(stdscr, args, stdin)
if __name__ == '__main__':

View File

@@ -0,0 +1,22 @@
import shlex
import sys
from babi.screen import VERSION_STR
from testing.runner import PrintsErrorRunner
def test_open_from_stdin():
with PrintsErrorRunner('env', 'TERM=screen', 'bash', '--norc') as h:
cmd = (sys.executable, '-mcoverage', 'run', '-m', 'babi', '-')
babi_cmd = ' '.join(shlex.quote(part) for part in cmd)
h.press_and_enter(fr"echo $'hello\nworld' | {babi_cmd}")
h.await_text(VERSION_STR, timeout=2)
h.await_text('<<new file>> *')
h.await_text('hello\nworld')
h.press('^X')
h.press('n')
h.await_text_missing('<<new file>>')
h.press_and_enter('exit')
h.await_exit()