diff --git a/vimtabdiff.py b/vimtabdiff.py index 9c32d0b..525d6c6 100755 --- a/vimtabdiff.py +++ b/vimtabdiff.py @@ -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" @@ -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: @@ -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