From 8ad50ca71479ca182407d4612f7cb40c982c5f2b Mon Sep 17 00:00:00 2001 From: Ethan Dalool Date: Tue, 11 Jun 2019 22:45:04 -0700 Subject: [PATCH] Add pipeable to voussoirkit. --- voussoirkit/bytestring.py | 15 ++----- voussoirkit/pathclass.py | 12 ++++++ voussoirkit/pipeable.py | 89 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 11 deletions(-) create mode 100644 voussoirkit/pipeable.py diff --git a/voussoirkit/bytestring.py b/voussoirkit/bytestring.py index 04ed511..60c2432 100644 --- a/voussoirkit/bytestring.py +++ b/voussoirkit/bytestring.py @@ -2,6 +2,7 @@ import re import sys from voussoirkit import clipext +from voussoirkit import pipeable __VERSION__ = '0.0.1' @@ -113,7 +114,6 @@ def parsebytes(string): if not string.startswith(byte_value): raise ValueError('Number is not at start of string') - # if the string has no text besides the number, just return that int. string = string.replace(byte_value, '') byte_value = float(byte_value) @@ -126,16 +126,9 @@ def parsebytes(string): return int(byte_value * multiplier) def main(args=None): - if args is None: - args = sys.argv[1:] - - if len(args) != 1: - print('Usage: bytestring.py ') - return 1 - number = clipext.resolve(sys.argv[1]) - n = int(number) - print(bytestring(n)) - return 0 + for line in pipeable.go(args, strip=True, skip_blank=True): + n = int(line) + pipeable.output(bytestring(n)) if __name__ == '__main__': sys.exit(main(sys.argv[1:])) diff --git a/voussoirkit/pathclass.py b/voussoirkit/pathclass.py index 082ffb6..c230ab5 100644 --- a/voussoirkit/pathclass.py +++ b/voussoirkit/pathclass.py @@ -157,6 +157,18 @@ class Path: def stat(self): return os.stat(self.absolute_path) + def walk(self): + directories = [] + for child in self.listdir(): + if child.is_dir: + directories.append(child) + else: + yield child + + for directory in directories: + yield directory + yield from directory.walk() + def with_child(self, basename): return self.join(os.path.basename(basename)) diff --git a/voussoirkit/pipeable.py b/voussoirkit/pipeable.py new file mode 100644 index 0000000..babffb6 --- /dev/null +++ b/voussoirkit/pipeable.py @@ -0,0 +1,89 @@ +#import pyperclip moved to stay lazy. +import sys + +builtin_input = input + +CLIPBOARD_STRINGS = ['!c', '!clip', '!clipboard'] +INPUT_STRINGS = ['!i', '!in', '!input', '!stdin'] +EOF = '\x1a' + +IN_PIPE = not sys.stdin.isatty() +OUT_PIPE = not sys.stdout.isatty() + +class NoArguments(Exception): + pass + +def argv(index): + try: + return sys.argv[index] + except IndexError: + return None + +def multi_line_input(prompt=None): + if prompt is not None and not IN_PIPE: + sys.stderr.write(prompt) + sys.stderr.flush() + + has_eof = False + while not has_eof: + line = sys.stdin.readline() + parts = line.split(EOF) + line = parts[0] + has_eof = len(parts) > 1 + if line == '': + break + line = line.rstrip('\n') + yield line + +def input(arg=None, *, input_prompt=None, skip_blank=False, strip=False): + if arg is not None: + arg_lower = arg.lower() + + if arg is None: + if IN_PIPE: + lines = multi_line_input() + else: + raise ValueError(arg) + + elif arg_lower in INPUT_STRINGS: + lines = multi_line_input(prompt=input_prompt) + if not IN_PIPE: + # Wait until the user finishes all their lines before continuing. + lines = list(lines) + + elif arg_lower in CLIPBOARD_STRINGS: + import pyperclip + lines = pyperclip.paste().splitlines() + + else: + lines = arg.splitlines() + + for line in lines: + if strip: + line = line.strip() + if skip_blank and not line: + continue + yield line + +def output(line, end='\n'): + sys.stdout.write(line) + if not line.endswith(end): + sys.stdout.write(end) + if not OUT_PIPE: + sys.stdout.flush() + +def go(args=None, *input_args, **input_kwargs): + if args is None: + args = sys.argv[1:] + + if not args: + # There are no arguments, and... + if IN_PIPE: + # we are being piped to, so read the pipe. + args = [INPUT_STRINGS[0]] + else: + # we are on the terminal, so cry for help. + raise NoArguments() + + for arg in args: + yield from input(arg, *input_args, **input_kwargs)