#!/usr/bin/env python3 # ollie:parallel read # description: Search file contents using ripgrep. Default output: file:lineno| content (one match per line). # Args: [--path=] [--mode=files_with_matches|content|count] [--glob=] [--type=] [-i] [-A ] [-B ] [-C ] [--multiline] [--head=] [--offset=] import sys import os import subprocess import argparse parser = argparse.ArgumentParser(prog='file_grep', add_help=False) parser.add_argument('pattern') parser.add_argument('--path', default='') parser.add_argument('--mode', default='content', choices=['files_with_matches', 'content', 'count']) parser.add_argument('--glob', default='') parser.add_argument('--type', default='') parser.add_argument('-i', action='store_true') parser.add_argument('-n', action='store_true', default=True) parser.add_argument('-A', type=int, default=None) parser.add_argument('-B', type=int, default=None) parser.add_argument('-C', type=int, default=None) parser.add_argument('--multiline', action='store_true') parser.add_argument('--head', type=int, default=0) parser.add_argument('--offset', type=int, default=0) args = parser.parse_args() search_path = args.path or os.getcwd() cmd = ['rg', '--no-config', '--color=never'] if args.mode == 'files_with_matches': cmd.append('-l') elif args.mode == 'count': cmd.append('--count') elif args.mode == 'content': if args.n: cmd.append('-n') if args.i: cmd.append('-i') if args.multiline: cmd += ['-U', '--multiline-dotall'] if args.glob: cmd += ['-g', args.glob] if args.type: cmd += ['-t', args.type] if args.C is not None: cmd += ['-C', str(args.C)] if args.A is not None: cmd += ['-A', str(args.A)] if args.B is not None: cmd += ['-B', str(args.B)] cmd += ['-e', args.pattern, search_path] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode == 1: print("STATUS=no_matches MATCH_COUNT=0") print("no matches") sys.exit(0) if result.returncode > 1: print(f"STATUS=error") print(f"error: {result.stderr.strip() or f'rg exited with {result.returncode}'}") sys.exit(1) lines = result.stdout.splitlines() total = len(lines) if args.offset: lines = lines[args.offset:] max_matches = args.head if args.head else 50 capped = len(lines) > max_matches if capped: lines = lines[:max_matches] if args.mode == 'content': formatted = [] for line in lines: if line == '--': formatted.append(line) continue for sep in (':', '-'): parts = line.split(sep, 2) if len(parts) == 3 and parts[1].isdigit(): formatted.append(f"{parts[0]}:{parts[1]:>5}| {parts[2]}") break else: formatted.append(line) lines = formatted print(f"STATUS=ok MATCH_COUNT={total}") print('\n'.join(lines)) if capped: print(f"\n(showing {max_matches} of {total} matches; use --head=N or --offset=N for more)")