From 2b54ac1e1e86a9a53d95f539305e95bee4722f54 Mon Sep 17 00:00:00 2001 From: rina Date: Fri, 22 Mar 2024 14:19:08 +1000 Subject: [PATCH 1/4] add lint.py for whitespace checking. --- scripts/lint.py | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100755 scripts/lint.py diff --git a/scripts/lint.py b/scripts/lint.py new file mode 100755 index 00000000..f77c1e3d --- /dev/null +++ b/scripts/lint.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# vim: set ts=2 sts=2 sw=2 et : + +# a simple linter to detect and remove trailing whitespace in OCaml files. + +import sys +import shlex +import argparse +import subprocess + +def trace(args): + print('$', *map(shlex.quote, args), file=sys.stderr) + return args + +def lint(args) -> int: + cmd = ( + ['grep', '-Rn', r'\s$'] + + [f'--include={f}' for f in args.include] + + [f'--exclude-dir={f}' for f in args.exclude_dir] + ) + + if not args.fix: + ret = subprocess.run(trace(cmd + args.files)) + if ret.returncode == 0: + print("\nfound trailing whitespace in above files!") + return 1 + else: + return 0 + else: + cmd += ['-l', '--null'] + ret = subprocess.run(trace(cmd + args.files), stdout=subprocess.PIPE) + files = [x.decode('utf-8') for x in ret.stdout.split(b'\0') if x] + print('files to fix:', files) + print() + + if files: + return subprocess.call(trace(['sed', '-i', r's/\s\+$//g'] + files)) + return 0 + +def main(): + argp = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) + argp.add_argument('--fix', action='store_true', help='remove trailing whitespace in-place') + argp.add_argument('--include', nargs='*', default=['*.ml', '*.mli', '*.cpp', '*.hpp'], help='grep file globs to include') + argp.add_argument('--exclude-dir', nargs='*', default=['_build', 'build'], help='grep directory globs to include') + argp.add_argument('files', nargs='*', default=['.'], help='directories to include') + + args = argp.parse_intermixed_args() + + sys.exit(lint(args)) + +if __name__ == '__main__': + main() + From 2fbf9d0ace528b239c80322b9a9e362f87369622 Mon Sep 17 00:00:00 2001 From: rina Date: Wed, 27 Mar 2024 12:10:15 +1000 Subject: [PATCH 2/4] use git grep --- scripts/lint.py | 54 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/scripts/lint.py b/scripts/lint.py index f77c1e3d..e7159c09 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -3,32 +3,39 @@ # a simple linter to detect and remove trailing whitespace in OCaml files. +import os import sys import shlex import argparse import subprocess +from pathlib import Path + def trace(args): print('$', *map(shlex.quote, args), file=sys.stderr) return args +def concat(xss): + return [x for xs in xss for x in xs] + def lint(args) -> int: cmd = ( - ['grep', '-Rn', r'\s$'] - + [f'--include={f}' for f in args.include] - + [f'--exclude-dir={f}' for f in args.exclude_dir] + ['git', 'grep', '-n', '--break', '--no-recursive'] + ) + cmd_files = ( + # ['-l', '-e', r'', '--'] + ['-e', r'\s$', '--'] + # non-directories should be added literally + + [f for f in args.files if not f.is_dir()] + # directories are searched for files matching the includes. + # NOTE: include pattern might not begin with * so we must add an extra * to recurse + + [f'{d}/{i}' for d in args.files for i in args.include if d.is_dir()] + + [f'{d}/*/{i}' for d in args.files for i in args.include if d.is_dir() if not i.startswith('*')] ) - if not args.fix: - ret = subprocess.run(trace(cmd + args.files)) - if ret.returncode == 0: - print("\nfound trailing whitespace in above files!") - return 1 - else: - return 0 - else: + if args.fix: cmd += ['-l', '--null'] - ret = subprocess.run(trace(cmd + args.files), stdout=subprocess.PIPE) + ret = subprocess.run(trace(cmd + cmd_files), stdout=subprocess.PIPE) files = [x.decode('utf-8') for x in ret.stdout.split(b'\0') if x] print('files to fix:', files) print() @@ -36,15 +43,30 @@ def lint(args) -> int: if files: return subprocess.call(trace(['sed', '-i', r's/\s\+$//g'] + files)) return 0 + else: + if args.list: + cmd += ['-l'] + ret = subprocess.run(trace(cmd + cmd_files)) + if ret.returncode == 0: + print("\nfound trailing whitespace in above files!") + return 1 + else: + return 0 + def main(): argp = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) - argp.add_argument('--fix', action='store_true', help='remove trailing whitespace in-place') - argp.add_argument('--include', nargs='*', default=['*.ml', '*.mli', '*.cpp', '*.hpp'], help='grep file globs to include') - argp.add_argument('--exclude-dir', nargs='*', default=['_build', 'build'], help='grep directory globs to include') - argp.add_argument('files', nargs='*', default=['.'], help='directories to include') + g = argp.add_mutually_exclusive_group() + g.add_argument('--check', action='store_true', default=True, help='check for trailing whitespace and print lines') + g.add_argument('--fix', action='store_true', help='remove trailing whitespace in-place') + g.add_argument('--list', action='store_true', help='list files with trailing whitespace') + argp.add_argument('--include', nargs='*', default=['dune', '*.ml', '*.mli', '*.cpp', '*.hpp', '*.scala'], help='grep file globs to include') + argp.add_argument('--untracked', action='store_true', help='include untracked files') + # argp.add_argument('--exclude-dir', nargs='*', default=['_build', 'build', 'target', 'out', '.git'], help='grep directory globs to include') + argp.add_argument('files', nargs='*', default=[Path('.')], type=Path, help='files or directories to include') args = argp.parse_intermixed_args() + args.check = not (args.fix or args.list) sys.exit(lint(args)) From 815e980d32e0e079dde4121c45b6cfd60c487799 Mon Sep 17 00:00:00 2001 From: rina Date: Wed, 27 Mar 2024 12:17:47 +1000 Subject: [PATCH 3/4] add colors --- scripts/lint.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/lint.py b/scripts/lint.py index e7159c09..67e5bf96 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -20,11 +20,13 @@ def concat(xss): def lint(args) -> int: cmd = ( - ['git', 'grep', '-n', '--break', '--no-recursive'] + ['git'] + + ['-c', 'color.grep.matchSelected=white red', '-c', 'color.grep.function=yellow'] + + ['grep', '-n', '--show-function', '--break', '--no-recursive'] ) cmd_files = ( # ['-l', '-e', r'', '--'] - ['-e', r'\s$', '--'] + ['-e', r'\s\+$', '--'] # non-directories should be added literally + [f for f in args.files if not f.is_dir()] # directories are searched for files matching the includes. From 67716bccb367eafa6da141a31bc6573aefaf8968 Mon Sep 17 00:00:00 2001 From: rina Date: Wed, 27 Mar 2024 12:19:59 +1000 Subject: [PATCH 4/4] fix trace --- scripts/lint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/lint.py b/scripts/lint.py index 67e5bf96..acd89942 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -12,7 +12,7 @@ from pathlib import Path def trace(args): - print('$', *map(shlex.quote, args), file=sys.stderr) + print('$', *map(shlex.quote, map(str, args)), file=sys.stderr) return args def concat(xss):