Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 50 additions & 26 deletions vimtabdiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def parse_args() -> argparse.Namespace:
epilog="See https://github.com/balki/vimtabdiff for more info")
parser.add_argument("pathA", type=Path)
parser.add_argument("pathB", type=Path)
parser.add_argument("pathC", type=Path, nargs='?')
parser.add_argument("--vim", help="vim command to run", default="vim")
parser.add_argument(
"--onlydiffs", help="only open files where there is a diff", action="store_true"
Expand All @@ -50,31 +51,48 @@ def get_dir_info(dirpath: Path | None) -> tuple[list[Path], list[Path]]:
return dirs, files


def get_pairs(aPaths: list[Path],
bPaths: list[Path]) -> Iterator[tuple[Path | None, Path | None]]:
def get_triplets(
aPaths: list[Path],
bPaths: list[Path],
cPaths: list[Path]) -> Iterator[tuple[
Path | None,
Path | None,
Path | None]]:
aItems = [(item, 'A') for item in aPaths]
bItems = [(item, 'B') for item in bPaths]
abItems = aItems + bItems
abItems.sort(key=star(lambda item, tag: (item.name, tag)))
for _, items in itertools.groupby(abItems,
cItems = [(item, 'C') for item in cPaths]
abcItems = aItems + bItems + cItems
abcItems.sort(key=star(lambda item, tag: (item.name, tag)))
for _, items in itertools.groupby(abcItems,
key=star(lambda item, _: item.name)):
match list(items):
case [(aItem, _), (bItem, _)]:
yield aItem, bItem
case [(item, 'A'),]:
yield item, None
case [(item, 'B'),]:
yield None, item


def get_file_pairs(
case [(aItem, _), (bItem, _), (cItem, _)]:
yield aItem, bItem, cItem
case [(aItem, 'A'), (bItem, 'B')]:
yield aItem, bItem, None
case [(aItem, 'A'), (cItem, 'C')]:
yield aItem, None, cItem
case [(bItem, 'B'), (cItem, 'C')]:
yield None, bItem, cItem
case [(item, 'A')]:
yield item, None, None
case [(item, 'B')]:
yield None, item, None
case [(item, 'C')]:
yield None, None, item


def get_file_triplets(
a: Path | None,
b: Path | None) -> Iterator[tuple[Path | None, Path | None]]:
b: Path | None,
c: Path | None) -> Iterator[tuple[
Path | None, Path | None, Path | None]]:
aDirs, aFiles = get_dir_info(a)
bDirs, bFiles = get_dir_info(b)
yield from get_pairs(aFiles, bFiles)
for aDir, bDir in get_pairs(aDirs, bDirs):
yield from get_file_pairs(aDir, bDir)
cDirs, cFiles = get_dir_info(c)
yield from get_triplets(aFiles, bFiles, cFiles)
for aDir, bDir, cDir in get_triplets(aDirs, bDirs, cDirs):
yield from get_file_triplets(aDir, bDir, cDir)


def main() -> None:
Expand All @@ -86,17 +104,23 @@ def main() -> None:
set splitright
"""
print(cmds, file=vimCmdFile)
for a, b in get_file_pairs(args.pathA, args.pathB):
for a, b, c in get_file_triplets(args.pathA, args.pathB, args.pathC):
aPath = a.resolve() if a else os.devnull
bPath = b.resolve() if b else os.devnull
if (
(args.skipmissing and (not a or not b)) or
(args.onlydiffs
and a and b
and open(aPath, mode="rb").read() == open(bPath, mode="rb").read())
):
cPath = c.resolve() if c else os.devnull
if args.skipmissing and (not a or not b or (args.pathC and not c)):
continue
print(f"tabedit {aPath} | vsp {bPath}", file=vimCmdFile)
if args.onlydiffs and a and b:
aContents = open(aPath, mode="rb").read()
if aContents == open(bPath, mode="rb").read():
if args.pathC is None:
continue
if aContents == open(cPath, mode="rb").read():
continue
if args.pathC is None:
print(f"tabedit {aPath} | vsp {bPath}", file=vimCmdFile)
else:
print(f"tabedit {aPath} | vsp {bPath} | vsp {cPath}", file=vimCmdFile)
cmds = f"""
let &splitright = s:spr
tabdo windo :1
Expand Down