Compare commits

..

3 Commits

Author SHA1 Message Date
e26e40413f Change download url to branch
Backport from 065ef47b2
2023-03-06 11:04:49 -05:00
5e2943624a Use shlex to split custom vim command
This allows to include spaces in vim command
Add example to change default diff algorithm
Move to first line on each file

Backport from da5e24260
2023-03-06 11:01:40 -05:00
32e186695a Keep new changes on right
Saves and restores splitright option
Backported from 512df2948
2023-03-06 10:53:14 -05:00
2 changed files with 37 additions and 68 deletions

View File

@ -24,34 +24,20 @@ You may need to add `~/bin` to your PATH variable if not already done. See [here
# Usage
```help
usage: vimtabdiff.py [-h] [--vim VIM] [--onlydiffs] pathA pathB
usage: vimtabdiff.py [-h] [--vim VIM] pathA pathB
Show diff of files from two directories in vim tabs
Show diff of files from two directories in vim tabs
positional arguments:
positional arguments:
pathA
pathB
options:
options:
-h, --help show this help message and exit
--vim VIM vim command to run
--onlydiffs only open files where there is a diff
```
## Relevant vim tips
* `gt` → Go to next tab
* `gT` → Go to previous tab
* `:tabr` → Go to first tab
* `:drop filenam<Tab>` → Go to the tab with filename
* `g<Tab>` → Go to last used tab (Works in vim version > 8.2.1401)
* `:set mouse=a` → Now clicking on a tab works
* `]c` → Go to next diff hunk
* `[c` → Go to previous diff hunk
* `do`, `dp` → Diff obtain, Diff put
* `zo`, `zc`, `zi` → Fold open, Fold close, toggle all folds
# See Git diffs
# Git difftool
## Setup
@ -79,7 +65,7 @@ Using clean vim without reading `vimrc`
Git config file (`~/.gitconfig`) should look like this
```TOML
```toml
[alias]
...
dt = difftool --tool vimtabdiff --dir-diff
@ -97,7 +83,4 @@ Using better diff algorithm
# Similar
* https://gist.github.com/Osse/4709787 is very similar, written as a `zsh` script.
* https://github.com/will133/vim-dirdiff is a Vim plugin that uses an interactive list of files instead of tabs.
* https://github.com/Soares/tabdiff.vim is a Vim plugin takes a list of files as aguments.
* [`:Git difftool -y`](https://github.com/tpope/vim-fugitive/blob/d507d00bd04794119beeb41da118774a96815b65/doc/fugitive.txt#L92) is a command from vim-fugitive which is a vim git plugin.
https://gist.github.com/Osse/4709787

View File

@ -1,45 +1,34 @@
#!/usr/bin/python3
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import os
import argparse
import pathlib
import itertools
import tempfile
import subprocess
import shlex
from pathlib import Path
from typing import TypeVar
from collections.abc import Iterator, Callable
R = TypeVar('R')
def star(f: Callable[..., R]) -> Callable[[tuple], R]:
def star(f):
""" see https://stackoverflow.com/q/21892989 """
return lambda args: f(*args)
def parse_args() -> argparse.Namespace:
def parse_args():
parser = argparse.ArgumentParser(
description="Show diff of files from two directories in vim tabs",
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("pathA")
parser.add_argument("pathB")
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"
)
return parser.parse_args()
def get_dir_info(dirpath: Path | None) -> tuple[list[Path], list[Path]]:
if not dirpath:
def get_dir_info(dirname):
if not dirname:
return [], []
dirs, files = [], []
for p in dirpath.iterdir():
dirp = pathlib.Path(dirname)
for p in dirp.iterdir():
if p.is_dir():
dirs.append(p)
else:
@ -47,26 +36,27 @@ 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]]:
aItems = [(item, 'A') for item in aPaths]
bItems = [(item, 'B') for item in bPaths]
def get_pairs(aItems, bItems):
aItems = [(item, 'A') for item in aItems]
bItems = [(item, 'B') for item in bItems]
abItems = aItems + bItems
abItems.sort(key=star(lambda item, tag: (item.name, tag)))
for _, items in itertools.groupby(abItems,
key=star(lambda item, _: item.name)):
match list(items):
case [(aItem, _), (bItem, _)]:
items = list(items)
# NOTE: python 3.10's match expression can make this better
if len(items) == 2:
(aItem, _), (bItem, _) = items
yield aItem, bItem
case [(item, 'A'),]:
else:
(item, tag), = items
if tag == 'A':
yield item, None
case [(item, 'B'),]:
else:
yield None, item
def get_file_pairs(
a: Path | None,
b: Path | None) -> Iterator[tuple[Path | None, Path | None]]:
def get_file_pairs(a, b):
aDirs, aFiles = get_dir_info(a)
bDirs, bFiles = get_dir_info(b)
yield from get_pairs(aFiles, bFiles)
@ -74,7 +64,7 @@ def get_file_pairs(
yield from get_file_pairs(aDir, bDir)
def main() -> None:
def main():
args = parse_args()
vimCmdFile = tempfile.NamedTemporaryFile(mode='w', delete=False)
with vimCmdFile:
@ -86,13 +76,9 @@ def main() -> None:
for a, b in get_file_pairs(args.pathA, args.pathB):
aPath = a.resolve() if a else os.devnull
bPath = b.resolve() if b else os.devnull
if (
args.onlydiffs
and a and b
and open(aPath, mode="rb").read() == open(bPath, mode="rb").read()
):
continue
print(f"tabedit {aPath} | vsp {bPath}", file=vimCmdFile)
print(
f"tabedit {aPath} | vsp {bPath}",
file=vimCmdFile)
cmds = f"""
let &splitright = s:spr
tabdo windo :1