From 965fe76ca51b95df909320fb9a92156dda105c9e Mon Sep 17 00:00:00 2001 From: Ollie Agent Date: Sun, 19 Jul 2026 20:40:56 +0200 Subject: [PATCH] file_grep: fall back to GNU grep when rg is unavailable --- tools/file_grep | 78 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/tools/file_grep b/tools/file_grep index 1401bdb..6e2b750 100644 --- a/tools/file_grep +++ b/tools/file_grep @@ -1,11 +1,12 @@ #!/usr/bin/env python3 # ollie:parallel read -# description: Search file contents using ripgrep. Default output: file:lineno| content (one match per line). +# description: Search file contents using ripgrep (or grep fallback). 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 shutil import argparse parser = argparse.ArgumentParser(prog='file_grep', add_help=False) @@ -28,32 +29,59 @@ args = parser.parse_args() search_path = args.path or os.getcwd() -cmd = ['rg', '--no-config', '--color=never'] +use_rg = shutil.which('rg') is not None -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 use_rg: + cmd = ['rg', '--no-config', '--color=never'] -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)] + 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') -cmd += ['-e', args.pattern, search_path] + 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] +else: + # Fallback to GNU grep -r + cmd = ['grep', '-r', '--color=never'] + + if args.mode == 'files_with_matches': + cmd.append('-l') + elif args.mode == 'count': + cmd.append('-c') + elif args.mode == 'content': + if args.n: + cmd.append('-n') + + if args.i: + cmd.append('-i') + if args.glob: + cmd += ['--include=' + args.glob] + 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: @@ -62,7 +90,7 @@ if result.returncode == 1: sys.exit(0) if result.returncode > 1: print(f"STATUS=error") - print(f"error: {result.stderr.strip() or f'rg exited with {result.returncode}'}") + print(f"error: {result.stderr.strip() or f'search exited with {result.returncode}'}") sys.exit(1) lines = result.stdout.splitlines()