triple-click to select non-whitespace segment

The previous patch to plumb non-whitespace segments was
confusing due to lack of visual feedback. This removes
the empty selecton plumb behavior, and instead makes
triple clicking work to get a plumbable selection.
This commit is contained in:
Ori Bernstein 2020-04-11 14:19:46 -07:00
parent ebb3e31118
commit 2d1dac07f7

View file

@ -170,7 +170,7 @@ int alnum(int);
void escapedump(int,uchar *,int);
void paste(void);
void snarfsel(void);
void plumbsel(Point);
void plumbsel(void);
static Channel *pidchan;
@ -982,47 +982,14 @@ snarfsel(void)
free(s);
}
/*
* Grabs the non-whitespace text around a character
* cell, matching the behavior in rio for plumbing.
* Does not modify the selection.
*/
char*
surrounding(Point p)
{
int c, x0, x1;
char *s, *e;
for(x0 = p.x; x0 > 0; x0--){
c = *onscreenr(x0 - 1, p.y);
if(c == 0 || c == ' ' || c == '\t' || c == '\n')
break;
}
for(x1 = p.x; x1 <= xmax; x1++){
c = *onscreenr(x1, p.y);
if(c == 0 || c == ' ' || c == '\t' || c == '\n')
break;
}
if(x0 == x1)
return nil;
s = malloc((x1 - x0 + 1)*UTFmax);
if(s == nil)
return nil;
e = selrange(s, x0, p.y, x1, p.y);
*e = 0;
return s;
}
void
plumbsel(Point p)
plumbsel(void)
{
char *s, wdir[1024];
int plumb;
s = selection();
if(s == nil || *s == 0)
s = surrounding(p);
if(s == nil)
return;
if(getwd(wdir, sizeof wdir) == nil){
free(s);
@ -1061,6 +1028,13 @@ isalnum(Rune c)
return 1;
}
int
isspace(Rune c)
{
return c == 0 || c == ' ' || c == '\t' ||
c == '\n' || c == '\r' || c == '\v';
}
void
unselect(void)
{
@ -1071,11 +1045,23 @@ unselect(void)
selrect = ZR;
}
int
inmode(Rune r, int mode)
{
return (mode == 1) ? isalnum(r) : r && !isspace(r);
}
/*
* Selects different things based on mode.
* 0: selects swept-over text.
* 1: selects alphanumeric segment
* 2: selects non-whitespace segment.
*/
void
select(Point p, Point q, int line)
select(Point p, Point q, int mode)
{
if(onscreenr(p.x, p.y) > onscreenr(q.x, q.y)){
select(q, p, line);
select(q, p, mode);
return;
}
unselect();
@ -1089,17 +1075,17 @@ select(Point p, Point q, int line)
q.y = ymax;
if(!blocksel) q.x = xmax+1;
}
if(line && eqpt(p, q)){
while(p.x > 0 && isalnum(*onscreenr(p.x-1, p.y)))
if(mode != 0 && eqpt(p, q)){
while(p.x > 0 && inmode(*onscreenr(p.x-1, p.y), mode))
p.x--;
while(q.x <= xmax && isalnum(*onscreenr(q.x, q.y)))
while(q.x <= xmax && inmode(*onscreenr(q.x, q.y), mode))
q.x++;
if(p.x != q.x)
line = 0;
mode = 0;
}
if(p.x < 0 || line)
if(p.x < 0 || mode)
p.x = 0;
if(q.x > xmax+1 || line)
if(q.x > xmax+1 || mode)
q.x = xmax+1;
selrect = Rpt(p, q);
for(; p.y <= q.y; p.y++)
@ -1110,13 +1096,18 @@ void
selecting(void)
{
Point p, q;
static ulong t;
static ulong t, mode;
p = pos(mc->xy);
t += mc->msec;
mode++;
do{
q = pos(mc->xy);
select(p, q, t < 200);
if(t > 200)
mode = 0;
if(mode > 2)
mode = 2;
select(p, q, mode);
drawscreen();
readmouse(mc);
} while(button1());
@ -1210,7 +1201,7 @@ readmenu(void)
return;
case Mplumb:
plumbsel(p);
plumbsel();
return;
case Mpage: /* pause and clear at end of screen */