## Get and Put Trivial one line convenience wrappers ```bash #!/usr/bin/env bash cman get "$@" ``` ```bash #!/usr/bin/env bash cman put "$@" ``` ## Cman ```py #!/usr/bin/env python3 # pip install pyperclip prompt = r""" Python wrapper for aclient and cclient, called get and put. Use main() and argparse. get does the same as cat name, unless name starts with . or ,. If name = ., then paste from the clipboard. If name = .clipname, then take the output of cclient get clipname If name = ,clipname, then take the output of aclient get clipname. If any result other than the last doesn't end with a \n, then append a \n. Then concatenate the results and send to output. Output is stdout by default, unless -o is also specified. If -p is also specified, then print anyway (as well as outputting). The argument to -o is similar: . is the clipboard, .clipname pipes output into cclient put clipname, and ,clipname pipes output to aclient put clipname. put is the reverse, but can reference multiple clips. By default put takes input from stdin. Inputs are specified by the -i argument, multiple are possible. Again . .clipname and ,clipname get from cclient get and aclient get and the clipboard. - gets from stdin, and if specified multiple times, stdin is cached and repeated. Other arguments are output names, following the same . .clipname ,clipname convention as before. """ import argparse import subprocess import sys import pyperclip import os def run_cmd(args, input_data=None): """Helper to run external client commands.""" try: process = subprocess.Popen( args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) stdout, stderr = process.communicate(input=input_data) if process.returncode != 0: print(f"Error running {' '.join(args)}: {stderr}", file=sys.stderr) return "" return stdout except FileNotFoundError: print(f"Error: Command '{args[0]}' not found.", file=sys.stderr) return "" def get_content(name, stdin_cache=None): """Fetches content based on the naming convention.""" if name == ".": return pyperclip.paste() elif name.startswith("."): return run_cmd(["cclient", "get", name[1:]]) elif name.startswith(","): return run_cmd(["aclient", "get", name[1:]]) elif name == "-": return stdin_cache if stdin_cache is not None else sys.stdin.read() else: # Standard file 'cat' behavior if os.path.exists(name): with open(name, 'r') as f: return f.read() return "" def put_content(name, content): """Sends content to the specified target.""" if name == ".": pyperclip.copy(content) elif name.startswith("."): run_cmd(["cclient", "put", name[1:]], input_data=content) elif name.startswith(","): run_cmd(["aclient", "put", name[1:]], input_data=content) else: with open(name, 'w') as f: f.write(content) def handle_get(args): results = [] for i, name in enumerate(args.names): content = get_content(name) # Append newline if not the last item and missing a trailing newline if i < len(args.names) - 1 and content and not content.endswith('\n'): content += '\n' results.append(content) final_output = "".join(results) # Handle output logic if args.o: put_content(args.o, final_output) if not args.o or args.p: sys.stdout.write(final_output) def handle_put(args): stdin_cache = None input_contents = [] # If no inputs specified, default to stdin inputs = args.i if args.i else ["-"] for item in inputs: if item == "-" and stdin_cache is None: stdin_cache = sys.stdin.read() input_contents.append(get_content(item, stdin_cache)) combined_input = "".join(input_contents) for target in args.targets: put_content(target, combined_input) def main(): parser = argparse.ArgumentParser(description="Wrapper for aclient and cclient") subparsers = parser.add_subparsers(dest="command", required=True) # GET parser get_parser = subparsers.add_parser("get") get_parser.add_argument("names", nargs="+", help="Names of clips or files") get_parser.add_argument("-o", help="Output target (., .clip, ,clip, or file)") get_parser.add_argument("-p", action="store_true", help="Print to stdout even if -o is used") # PUT parser put_parser = subparsers.add_parser("put") put_parser.add_argument("-i", action="append", help="Input sources (can be multiple)") put_parser.add_argument("targets", nargs="+", help="Output targets (., .clip, ,clip, or file)") args = parser.parse_args() if args.command == "get": handle_get(args) elif args.command == "put": handle_put(args) if __name__ == "__main__": main() ```