else/Toolbox/search.py

95 lines
2.7 KiB
Python
Raw Normal View History

2016-12-25 03:18:23 +00:00
import argparse
import fnmatch
import os
import re
import sys
2017-03-30 22:56:12 +00:00
from voussoirkit import clipext
from voussoirkit import expressionmatch
2016-12-25 03:18:23 +00:00
from voussoirkit import safeprint
from voussoirkit import spinal
2017-01-16 06:04:20 +00:00
def search(
terms,
*,
case_sensitive=False,
2017-03-30 22:56:12 +00:00
do_expression=False,
2017-01-16 06:04:20 +00:00
do_glob=False,
2017-03-30 22:56:12 +00:00
do_regex=False,
2017-02-19 01:06:55 +00:00
inverse=False,
2017-01-16 06:04:20 +00:00
local_only=False,
match_any=False,
2017-03-30 22:56:12 +00:00
text=None,
2017-01-16 06:04:20 +00:00
):
2016-12-25 03:18:23 +00:00
def term_matches(text, term):
2017-03-30 22:56:12 +00:00
if not case_sensitive:
text = text.lower()
2016-12-25 03:18:23 +00:00
return (
(term in text) or
(do_regex and re.search(term, text)) or
2017-03-30 22:56:12 +00:00
(do_glob and fnmatch.fnmatch(text, term)) or
(do_expression and term.evaluate(text))
2016-12-25 03:18:23 +00:00
)
2017-02-19 01:06:55 +00:00
if not case_sensitive:
terms = [term.lower() for term in terms]
2017-01-16 06:04:20 +00:00
2017-03-30 22:56:12 +00:00
if do_expression:
terms = ' '.join(terms)
terms = [expressionmatch.ExpressionTree.parse(terms)]
2016-12-25 03:18:23 +00:00
anyall = any if match_any else all
2017-03-30 22:56:12 +00:00
if text is None:
walk = spinal.walk_generator(
depth_first=False,
recurse=not local_only,
yield_directories=True,
)
lines = ((filepath.basename, filepath.absolute_path) for filepath in walk)
else:
lines = text.splitlines()
2017-01-16 06:04:20 +00:00
2017-03-30 22:56:12 +00:00
for line in lines:
if isinstance(line, tuple):
(line, printout) = line
else:
printout = line
matches = anyall(term_matches(line, term) for term in terms)
2017-02-19 01:06:55 +00:00
if matches ^ inverse:
2017-03-30 22:56:12 +00:00
safeprint.safeprint(printout)
2016-12-25 03:18:23 +00:00
def search_argparse(args):
return search(
terms=args.search_terms,
2017-01-16 06:04:20 +00:00
case_sensitive=args.case_sensitive,
2016-12-25 03:18:23 +00:00
do_glob=args.do_glob,
do_regex=args.do_regex,
2017-02-19 01:06:55 +00:00
inverse=args.inverse,
2017-01-16 06:04:20 +00:00
local_only=args.local_only,
2016-12-25 03:18:23 +00:00
match_any=args.match_any,
2017-03-30 22:56:12 +00:00
text=args.text if args.text is None else clipext.resolve(args.text),
2016-12-25 03:18:23 +00:00
)
def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument('search_terms', nargs='+', default=None)
parser.add_argument('--any', dest='match_any', action='store_true')
2017-02-19 01:06:55 +00:00
parser.add_argument('--case', dest='case_sensitive', action='store_true')
2016-12-25 03:18:23 +00:00
parser.add_argument('--regex', dest='do_regex', action='store_true')
parser.add_argument('--glob', dest='do_glob', action='store_true')
2017-03-30 22:56:12 +00:00
parser.add_argument('--expression', dest='do_expression', action='store_true')
2017-01-16 06:04:20 +00:00
parser.add_argument('--local', dest='local_only', action='store_true')
2017-02-19 01:06:55 +00:00
parser.add_argument('--inverse', dest='inverse', action='store_true')
2017-03-30 22:56:12 +00:00
parser.add_argument('--text', dest='text', default=None)
2016-12-25 03:18:23 +00:00
parser.set_defaults(func=search_argparse)
args = parser.parse_args(argv)
args.func(args)
if __name__ == '__main__':
main(sys.argv[1:])