ref: 10522cecea250586efa3bda353f555211bef3a67
parent: bfcd6944a21217315bd79810dd5482b73ebeef6a
author: Jacob Moody <moody@posixcafe.org>
date: Sat Apr 19 17:39:08 EDT 2025
vdiff: fix scrolling and clean up * accept list of patches from argv * fix issue where menu would take precedence over scrolling * fix issues when collapsing and expanding would scroll awkwardly
--- a/sys/man/1/vdiff
+++ b/sys/man/1/vdiff
@@ -11,12 +11,12 @@
.I nstrip
]
[
-.I file
+.I patches...
]
.SH DESCRIPTION
-.I vdiff
-reads unified diff output from
-.I file
+.I Vdiff
+reads unified diff output from the list of
+.I patches
or standard input and displays a colored version.
Each file within the diff is displayed in a separate block that can be collapsed by clicking on the file name.
Right clicking on a line will send a
@@ -34,6 +34,9 @@
A menu may be summoned with button 2 of the mouse.
It provides menu items for collapsing and expanding all files,
as well as items for each patch present in the input.
+.I Vdiff
+understands terminators supplied by
+.IR git/export (2).
.PP
The
.B -b
--- a/sys/src/cmd/vdiff.c
+++ b/sys/src/cmd/vdiff.c
@@ -245,12 +245,16 @@
}
void
-clampoffset(void)
+clampoffset(int off)
{
if(offset<0)
offset = 0;
- if(offset+viewh>totalh)
- offset = totalh - viewh;
+ if(offset+viewh>totalh){
+ if(off > 0)
+ offset = totalh - viewh;
+ else
+ offset = 0;
+ }
}
void
@@ -261,7 +265,7 @@
if(off>0 && offset+viewh>totalh)
return;
offset += off;
- clampoffset();
+ clampoffset(off);
redraw();
}
@@ -312,8 +316,10 @@
}
totalh = totalh - Margin + Vpadding;
scrollsize = viewh / 2.0;
- if(offset > 0 && offset+viewh>totalh)
- offset = totalh - viewh;
+ if(viewh <= totalh)
+ clampoffset(1);
+ else
+ clampoffset(0);
redraw();
}
@@ -362,7 +368,7 @@
return "expand";
default:
i -= Nmenu;
- if(i >= npatches)
+ if(i >= npatches || npatches == 1)
return nil;
if(patches[i].name == nil)
patches[i].name = smprint("%d", i);
@@ -387,7 +393,23 @@
}
}
+Menu menu = {
+ nil,
+ genmenu,
+};
+
void
+collapse(int v)
+{
+ int i;
+
+ for(i = 0; i < cur->nblocks; i++)
+ if(cur->blocks[i]->f != nil)
+ cur->blocks[i]->v = v;
+ eresize(0);
+}
+
+void
emouse(Mouse m)
{
Block *b;
@@ -406,12 +428,30 @@
}else if(m.buttons&2){
offset = (m.xy.y - scrollr.min.y) * totalh/Dy(scrollr);
offset = offset/lineh * lineh;
- clampoffset();
+ if(viewh <= totalh)
+ clampoffset(1);
+ else
+ clampoffset(0);
redraw();
}else if(m.buttons&4){
scroll(n);
return;
}
+ }else if(!scrolling && m.buttons&2){
+ n = menuhit(2, mctl, &menu, nil);
+ switch(n){
+ case -1:
+ break;
+ case Mexpand: case Mcollapse:
+ collapse(n);
+ break;
+ default:
+ n -= Nmenu;
+ if(cur == patches+n)
+ break;
+ cur = patches+n;
+ eresize(0);
+ }
}else if(m.buttons&8){
scroll(-n);
}else if(m.buttons&16){
@@ -564,19 +604,8 @@
}
void
-collapse(int v)
+parse(int fd, char *name)
{
- int i;
-
- for(i = 0; i < cur->nblocks; i++)
- if(cur->blocks[i]->f != nil)
- cur->blocks[i]->v = v;
- eresize(0);
-}
-
-void
-parse(int fd)
-{
Biobuf *bp;
Block *b;
char *s, *f, *tab;
@@ -605,7 +634,7 @@
cur = patches+npatches-1;
cur->blocks = nil;
cur->nblocks = 0;
- cur->name = nil;
+ cur->name = name;
b = addblock();
n = 0;
ab = 0;
@@ -640,8 +669,10 @@
if(f != nil && (f = strchr(f+1, ' '))){
f++;
if(strcmp(f, "uncommitted") != 0){
- cur->name = strdup(f);
- cur->name[9] = '\0';
+ if(name != nil)
+ cur->name = smprint("%s %.*s", name, 9, f);
+ else
+ cur->name = smprint("%.*s", 9, f);
}
}
t = Lnone;
@@ -659,13 +690,13 @@
}
if(gotterm)
npatches--;
- cur = patches;
+ Bterm(bp);
}
void
usage(void)
{
- fprint(2, "usage: %s [-b] [-p nstrip] [file]\n", argv0);
+ fprint(2, "usage: %s [-b] [-p nstrip] [patches...]\n", argv0);
exits("usage");
}
@@ -681,11 +712,7 @@
{ nil, &k, CHANRCV },
{ nil, nil, CHANEND },
};
- Menu menu = {
- nil,
- genmenu,
- };
- int b, n;
+ int i, b, fd;
b = 0;
ARGBEGIN{
@@ -699,17 +726,16 @@
usage();
break;
}ARGEND;
- switch(argc){
- default:
- usage();
- case 1:
- close(0);
- if(open(argv[0], OREAD) < 0)
+ if(argc == 0)
+ parse(0, nil);
+ else for(i = 0; i < argc; i++){
+ fd = open(argv[i], OREAD);
+ if(fd < 0)
sysfatal("open: %r");
- case 0:
- break;
+ parse(fd, argv[i]);
+ close(fd);
}
- parse(0);
+ cur = patches;
if(cur->nblocks==1 && cur->blocks[0]->nlines==0){
fprint(2, "no diff\n");
exits(nil);
@@ -731,23 +757,7 @@
for(;;){
switch(alt(a)){
case Emouse:
- if((m.buttons&2) != 0){
- n = menuhit(2, mctl, &menu, nil);
- switch(n){
- case -1:
- break;
- case Mexpand: case Mcollapse:
- collapse(n);
- break;
- default:
- n -= Nmenu;
- if(cur == patches+n)
- break;
- cur = patches+n;
- eresize(0);
- }
- } else
- emouse(m);
+ emouse(m);
break;
case Eresize:
eresize(1);
--
⑨