From 821face23454b877f0738be8ed7ec91df6b2ce61 Mon Sep 17 00:00:00 2001 From: Max Regan Date: Mon, 17 Oct 2022 13:54:32 +0000 Subject: [PATCH] Add "py", a CLI for python one-liners --- .mgr_config/bin/py | 54 ++++++++++++++++++++++++++++++++ .py-env.py | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 .mgr_config/bin/py create mode 100644 .py-env.py diff --git a/.mgr_config/bin/py b/.mgr_config/bin/py new file mode 100644 index 0000000..c5882e2 --- /dev/null +++ b/.mgr_config/bin/py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 + +import argparse +import sys + +from pathlib import Path + +source = " ".join(sys.argv[1:]) +INPUT_SRC_NAME = "" + +global_vars = {} +local_vars = {} + +py_env_conf = Path.home() / ".py-env.py" +if py_env_conf.exists(): + with open(Path.home() / ".py-env.py") as f: + code = compile(f.read(), "py-env.py", "exec") + exec(code) + +try: + code = compile(source, INPUT_SRC_NAME, "eval") + val = eval(code) + + # If it's a string, just print it + if type(val) == str: + print(val) + exit(0) + + # If it's not iterable, just print it + try: + it = iter(val) + except TypeError as e: + if val is not None: + print(val) + exit(0) + + # It's iterable, print each element as a line + try: + for item in val: + print(item) + exit(0) + except Exception as e: + e.args = ("Failed to print all elements",) + e.args + raise + +except (SyntaxError, NameError) as e: + pass + +try: + code = compile(source, INPUT_SRC_NAME, "exec") + exec(code) +except (SyntaxError, NameError) as e: + e.args = ("Invalid Python code",) + e.args + raise e diff --git a/.py-env.py b/.py-env.py new file mode 100644 index 0000000..1e5d611 --- /dev/null +++ b/.py-env.py @@ -0,0 +1,76 @@ + +import itertools +import json +import operator +import os +import sys +import yaml + +from functools import partial, reduce +from math import * +from pathlib import Path +from itertools import chain + +try: + from tabulate import tabulate +except ImportError: + pass + +try: + import rich + from rich import inspect, print as pp +except ImportError: + pass + + +# Always write heavyweight/blocking code in this file lazily to keep startup +# time short. In the same vein, be careful not to consume stdin unless an object +# in this file is called or iterated upon, e.g. stdin_str() + +# Returns a lazily-evaluable map which executes multiple map functions +def maps(items, *map_funs): + it = items + for func in map_funs: + it = map(func, it) + return it + + +# Returns a lazily-evaluable filter which executes multiple predicate functions +def filters(items, *pred_funs): + it = items + for pred in pred_funs: + it = filter(pred, it) + return it + + +# Concatenate two items, there's likely a safer way to do this to avoid summing ints +concat = lambda a, b: "".join([a, b]) +# Joins an interable of strings +join = "".join + + +# Return an iterable for file. This doesn't close the handle, but for this +# little scripting interface this is fine. +def read(filename): + return open(filename, "r") + + +def read_str(filename): + return concats(read(filename)) + + +stdin_str = sys.stdin.read +# An iterable which yields the characters of stdin +stdin = (c for l in sys.stdin for c in l) +# An iterable which yields the lines of stdin +lines = map(str.strip, sys.stdin) +# An iterable which yields integers supplied via stdin lines +ints = map(int, lines) +# An iterable which yields the bytes of stdin +byts = map(lambda x: bytes(x, "utf-8"), stdin) # better name? 'bytes' is taken + +jr = json.loads +jw = json.dumps +yr = lambda x: yaml.load(x, Loader=yaml.SafeLoader) +yw = yaml.dump +pwd = Path.cwd()