diff kitten: add options to ignore paths when comparing directories

Tested locally & over SSH:

    $ kitty +kitten diff /local/path /local/path2
    $ kitty +kitten diff /local/path ssh:remote:/path
This commit is contained in:
Suvayu Ali 2022-06-05 00:02:13 +02:00
parent a42200a430
commit fbf1ec43c7
6 changed files with 37 additions and 2 deletions

8
kittens/diff/collect.py Normal file → Executable file
View File

@ -4,6 +4,7 @@
import os import os
import re import re
from contextlib import suppress from contextlib import suppress
from fnmatch import fnmatch
from functools import lru_cache from functools import lru_cache
from hashlib import md5 from hashlib import md5
from kitty.guess_mime_type import guess_type from kitty.guess_mime_type import guess_type
@ -37,6 +38,9 @@ class Segment:
class Collection: class Collection:
file_ignores = ['']
ignore_paths = ['']
def __init__(self) -> None: def __init__(self) -> None:
self.changes: Dict[str, str] = {} self.changes: Dict[str, str] = {}
self.renames: Dict[str, str] = {} self.renames: Dict[str, str] = {}
@ -113,7 +117,11 @@ def collect_files(collection: Collection, left: str, right: str) -> None:
def walk(base: str, names: Set[str], pmap: Dict[str, str]) -> None: def walk(base: str, names: Set[str], pmap: Dict[str, str]) -> None:
for dirpath, dirnames, filenames in os.walk(base): for dirpath, dirnames, filenames in os.walk(base):
if any(fnmatch(dirpath, f"*/{pat}") for pat in collection.ignore_paths):
continue
for filename in filenames: for filename in filenames:
if any(fnmatch(filename, f"{pat}") for pat in collection.file_ignores):
continue
path = os.path.abspath(os.path.join(dirpath, filename)) path = os.path.abspath(os.path.join(dirpath, filename))
path_name_map[path] = name = os.path.relpath(path, base) path_name_map[path] = name = os.path.relpath(path, base)
names.add(name) names.add(name)

2
kittens/diff/main.py Normal file → Executable file
View File

@ -655,6 +655,8 @@ def main(args: List[str]) -> None:
opts = init_config(cli_opts) opts = init_config(cli_opts)
set_diff_command(opts.diff_cmd) set_diff_command(opts.diff_cmd)
lines_for_path.replace_tab_by = opts.replace_tab_by lines_for_path.replace_tab_by = opts.replace_tab_by
Collection.file_ignores = opts.file_ignores
Collection.ignore_paths = opts.ignore_paths
left, right = map(get_remote_file, (left, right)) left, right = map(get_remote_file, (left, right))
if os.path.isdir(left) != os.path.isdir(right): if os.path.isdir(left) != os.path.isdir(right):
raise SystemExit('The items to be diffed should both be either directories or files. Comparing a directory to a file is not valid.') raise SystemExit('The items to be diffed should both be either directories or files. Comparing a directory to a file is not valid.')

11
kittens/diff/options/definition.py Normal file → Executable file
View File

@ -47,6 +47,17 @@ opt('replace_tab_by', '\\x20\\x20\\x20\\x20',
option_type='python_string', option_type='python_string',
long_text='The string to replace tabs with. Default is to use four spaces.' long_text='The string to replace tabs with. Default is to use four spaces.'
) )
opt('file_ignores', '',
option_type='pattern_list',
long_text='List of file patterns that are ignored when directories are compared'
)
opt('ignore_paths', '',
option_type='pattern_list',
long_text='List of directory patterns that are ignored when directories are compared'
)
egr() # }}} egr() # }}}
# colors {{{ # colors {{{

View File

@ -1,7 +1,7 @@
# generated by gen-config.py DO NOT edit # generated by gen-config.py DO NOT edit
import typing import typing
from kittens.diff.options.utils import parse_map, syntax_aliases from kittens.diff.options.utils import parse_map, pattern_list, syntax_aliases
from kitty.conf.utils import merge_dicts, positive_int, python_string, to_color, to_color_or_none from kitty.conf.utils import merge_dicts, positive_int, python_string, to_color, to_color_or_none
@ -86,6 +86,12 @@ class Parser:
for k in parse_map(val): for k in parse_map(val):
ans['map'].append(k) ans['map'].append(k)
def file_ignores(self, val: str, ans: typing.Dict[str, typing.List[str]]):
ans['file_ignores'] = pattern_list(val)
def ignore_paths(self, val: str, ans: typing.Dict[str, typing.List[str]]):
ans['ignore_paths'] = pattern_list(val)
def create_result_dict() -> typing.Dict[str, typing.Any]: def create_result_dict() -> typing.Dict[str, typing.Any]:
return { return {

View File

@ -14,12 +14,14 @@ option_names = ( # {{{
'added_margin_bg', 'added_margin_bg',
'background', 'background',
'diff_cmd', 'diff_cmd',
'file_ignores',
'filler_bg', 'filler_bg',
'foreground', 'foreground',
'highlight_added_bg', 'highlight_added_bg',
'highlight_removed_bg', 'highlight_removed_bg',
'hunk_bg', 'hunk_bg',
'hunk_margin_bg', 'hunk_margin_bg',
'ignore_paths',
'map', 'map',
'margin_bg', 'margin_bg',
'margin_fg', 'margin_fg',
@ -43,12 +45,14 @@ class Options:
added_margin_bg: Color = Color(205, 255, 216) added_margin_bg: Color = Color(205, 255, 216)
background: Color = Color(255, 255, 255) background: Color = Color(255, 255, 255)
diff_cmd: str = 'auto' diff_cmd: str = 'auto'
file_ignores: typing.List[str] = ['']
filler_bg: Color = Color(250, 251, 252) filler_bg: Color = Color(250, 251, 252)
foreground: Color = Color(0, 0, 0) foreground: Color = Color(0, 0, 0)
highlight_added_bg: Color = Color(172, 242, 189) highlight_added_bg: Color = Color(172, 242, 189)
highlight_removed_bg: Color = Color(253, 184, 192) highlight_removed_bg: Color = Color(253, 184, 192)
hunk_bg: Color = Color(241, 248, 255) hunk_bg: Color = Color(241, 248, 255)
hunk_margin_bg: Color = Color(219, 237, 255) hunk_margin_bg: Color = Color(219, 237, 255)
ignore_paths: typing.List[str] = ['']
margin_bg: Color = Color(250, 251, 252) margin_bg: Color = Color(250, 251, 252)
margin_fg: Color = Color(170, 170, 170) margin_fg: Color = Color(170, 170, 170)
margin_filler_bg: typing.Optional[kitty.fast_data_types.Color] = None margin_filler_bg: typing.Optional[kitty.fast_data_types.Color] = None

6
kittens/diff/options/utils.py Normal file → Executable file
View File

@ -3,7 +3,7 @@
# License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net> # License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
from typing import Any, Dict, Iterable, Tuple, Union from typing import Any, Dict, Iterable, List, Tuple, Union
from kitty.conf.utils import ( from kitty.conf.utils import (
KeyFuncWrapper, KittensKeyDefinition, parse_kittens_key KeyFuncWrapper, KittensKeyDefinition, parse_kittens_key
@ -58,6 +58,10 @@ def syntax_aliases(raw: str) -> Dict[str, str]:
return ans return ans
def pattern_list(raw: str) -> List[str]:
return [pat for pat in raw.split(' ') if pat]
def parse_map(val: str) -> Iterable[KittensKeyDefinition]: def parse_map(val: str) -> Iterable[KittensKeyDefinition]:
x = parse_kittens_key(val, func_with_args.args_funcs) x = parse_kittens_key(val, func_with_args.args_funcs)
if x is not None: if x is not None: