From 5537be6a7625b344d9e5ca71b65d037e6dca2b86 Mon Sep 17 00:00:00 2001 From: "Dustin C. Hatch" Date: Thu, 6 Apr 2017 10:03:46 -0500 Subject: [PATCH] snips: Reimplement snips/dmenu_snips The snip manager is now split into two parts, a `snips` script, and a `dmenu_snips` front-end. Rather than storing snips in a single YAML document, each snips is stored in a separate file. --- dmenu_snips.py | 60 ------------------------------- dmenu_snips.sh | 3 ++ snips.py | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 60 deletions(-) delete mode 100755 dmenu_snips.py create mode 100755 dmenu_snips.sh create mode 100755 snips.py diff --git a/dmenu_snips.py b/dmenu_snips.py deleted file mode 100755 index 5607466..0000000 --- a/dmenu_snips.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python -import argparse -import locale -import os -import subprocess -import yaml - - -SNIPS_PATH = os.path.expanduser(os.environ.get('SNIPS_PATH', '~/.snips')) - - -codec = locale.getpreferredencoding() - - -def dmenu(options, args=None): - cmd = ['dmenu'] - if args: - cmd += args - p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE) - with p.stdout: - with p.stdin: - for option in options: - p.stdin.write(option.encode(codec) + b'\n') - return p.stdout.read().strip().decode(codec) - - -def load_snips(path): - with open(path) as f: - return yaml.safe_load(f) - - -def xclip(data, selection='clipboard'): - cmd = ['xclip', '-selection', selection] - p = subprocess.Popen(cmd, stdin=subprocess.PIPE) - with p.stdin: - p.stdin.write(data.encode(codec)) - - -def parse_args(): - parser = argparse.ArgumentParser() - parser.add_argument( - 'snips', nargs='?', default=SNIPS_PATH, - help='Path to snips YAML document', - ) - parser.add_argument( - '--selection', '-s', default='clipboard', - help='X11 selection (clipboard) to use', - ) - return parser.parse_args() - - -def main(): - args = parse_args() - snips = load_snips(args.snips) - selected = dmenu(sorted(snips.keys()), ['-i']) - xclip(snips[selected], args.selection) - - -if __name__ == '__main__': - main() diff --git a/dmenu_snips.sh b/dmenu_snips.sh new file mode 100755 index 0000000..8309db1 --- /dev/null +++ b/dmenu_snips.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +snips list | dmenu -i | snips copy -I diff --git a/snips.py b/snips.py new file mode 100755 index 0000000..398a44c --- /dev/null +++ b/snips.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +from __future__ import print_function, unicode_literals +import argparse +import os +import subprocess +import sys + + +SNIPS_PATH = os.environ.get('SNIPS_PATH', os.path.expanduser('~/.snips')) + + +def list_snips(path): + for dirpath, dirnames, filenames in os.walk(path): + for dirname in dirnames: + if dirname.startswith('.'): + dirnames.remove(dirname) + subdir = dirpath[len(path) + len(os.sep):] + for filename in filenames: + if filename.startswith('.'): + continue + try: + os.stat(os.path.join(dirpath, filename)) + except OSError as e: + sys.stderr.write('Error reading snip: {}\n'.format(e)) + continue + yield os.path.join(subdir, filename) + + +def get_snip(path, key): + try: + f = open(os.path.join(path, key), 'rb') + except IOError as e: + sys.stderr.write('Error reading snip: {}\n'.format(e)) + raise SystemExit(1) + with f: + return f.read() + + +def xclip(data, selection='clipboard'): + cmd = ['xclip', '-selection', selection] + p = subprocess.Popen(cmd, stdin=subprocess.PIPE) + with p.stdin: + p.stdin.write(data) + + +def cmd_list(args): + print('\n'.join(list_snips(args.path))) + + +def cmd_copy(args): + if args.stdin: + key = sys.stdin.readline().strip() + else: + key = args.snip + xclip(get_snip(args.path, key), args.selection) + + +def parse_args(): + parser = argparse.ArgumentParser() + sp = parser.add_subparsers(metavar='action') + sp.required = True + + s_list = sp.add_parser('list') + s_list.set_defaults(func=cmd_list) + + s_copy = sp.add_parser('copy') + g_snip = s_copy.add_mutually_exclusive_group() + g_snip.required = True + g_snip.add_argument( + '--stdin', '-I', action='store_true', default=False, + help='Read the snip to copy from standard input' + ) + g_snip.add_argument( + 'snip', nargs='?', + help='Snip to copy', + ) + s_copy.add_argument( + '--selection', '-s', default='clipboard', + help='X11 selection (clipboard) to use', + ) + s_copy.set_defaults(func=cmd_copy) + + parser.add_argument( + '--path', '-p', default=SNIPS_PATH, + help='Path to snips directory', + ) + return parser.parse_args() + + +def main(): + args = parse_args() + args.func(args) + + +if __name__ == '__main__': + main()