Get and Put
Trivial one line convenience wrappers
#!/usr/bin/env bash
cman get "$@"
#!/usr/bin/env bash
cman put "$@"
Cman
#!/usr/bin/env python3
# pip install pyperclip
prompt = r"""
Python wrapper for aclient and cclient, called get and put.
Use main() and argparse.
get <name> <name> <name>
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()