From 0ee831dacd4ae230f2a27b19d9122f9958b76974 Mon Sep 17 00:00:00 2001 From: Andy Chu Date: Sat, 10 Oct 2020 23:27:30 -0700 Subject: [PATCH] [oil-language] Implement read --all Addresses issue #711. --- osh/builtin_misc.py | 44 ++++++++++++++++++++++++++++++++++----- spec/oil-builtins.test.sh | 15 +++++++++++++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/osh/builtin_misc.py b/osh/builtin_misc.py index 6835aa3dfc..86582fb62d 100755 --- a/osh/builtin_misc.py +++ b/osh/builtin_misc.py @@ -162,10 +162,7 @@ def ReadLineFromStdin(delim_char): def _ReadLine(): # type: () -> str - """Read a line from stdin. - - TODO: use a more efficient function in C - """ + """Read a line from stdin.""" # TODO: This should be an array of integers in C++ chars = [] # type: List[str] while True: @@ -181,6 +178,20 @@ def _ReadLine(): return ''.join(chars) +def _ReadAll(): + # type: () -> str + """Read all of stdin.""" + chunks = [] # type: List[str] + while True: + c = posix.read(0, 4096) + if len(c) == 0: + break + + chunks.append(c) + + return ''.join(chunks) + + class Read(vm._Builtin): def __init__(self, splitter, mem): # type: (SplitContext, Mem) -> None @@ -204,6 +215,16 @@ def _Line(self, arg, var_name): self.mem.SetVar(lhs, value.Str(line), scope_e.LocalOnly) return 0 + def _All(self, var_name): + # type: (str) -> int + contents = _ReadAll() + + # No error conditions? + + lhs = lvalue.Named(var_name) + self.mem.SetVar(lhs, value.Str(contents), scope_e.LocalOnly) + return 0 + def Run(self, cmd_val): # type: (cmd_value__Argv) -> int attrs, arg_r = flag_spec.ParseCmdVal('read', cmd_val) @@ -227,7 +248,20 @@ def Run(self, cmd_val): return self._Line(arg, var_name) if arg.all: - e_usage('--all not implemented yet') + var_name, var_spid = arg_r.Peek2() + if var_name is None: + var_name = '_all' + else: + if var_name.startswith(':'): # optional : sigil + var_name = var_name[1:] + arg_r.Next() + + next_arg, next_spid = arg_r.Peek2() + if next_arg is not None: + raise error.Usage('got extra argument', span_id=next_spid) + + return self._All(var_name) + if arg.q: e_usage('--qsn not implemented yet') diff --git a/spec/oil-builtins.test.sh b/spec/oil-builtins.test.sh index 83a9d230ec..bb9dcec768 100644 --- a/spec/oil-builtins.test.sh +++ b/spec/oil-builtins.test.sh @@ -151,6 +151,21 @@ line=a line=b ## END +#### read --all +echo foo | read --all +echo "[$_all]" + +echo bad > tmp.txt +read --all :x < tmp.txt +echo "[$x]" + +## STDOUT: +[foo +] +[bad +] +## END + #### shopt supports long flags shopt -p nullglob