Loop through urls on screen and copy to clipboard
Replace url detection heuristics with a DFA, enabling urls that span multiple lines. Also fix the selection not to use snapping so that urls are selected exactly.
This commit is contained in:
parent
5bfe4b3592
commit
77ce1529ac
@ -216,6 +216,7 @@ static Shortcut shortcuts[] = {
|
|||||||
{ TERMMOD, XK_Y, selpaste, {.i = 0} },
|
{ TERMMOD, XK_Y, selpaste, {.i = 0} },
|
||||||
{ ShiftMask, XK_Insert, selpaste, {.i = 0} },
|
{ ShiftMask, XK_Insert, selpaste, {.i = 0} },
|
||||||
{ TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
|
{ TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
|
||||||
|
{ MODKEY, XK_l, copyurl, {.i = 0} },
|
||||||
{ ShiftMask, XK_Page_Up, kscrollup, {.i = -1} },
|
{ ShiftMask, XK_Page_Up, kscrollup, {.i = -1} },
|
||||||
{ ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} },
|
{ ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} },
|
||||||
};
|
};
|
||||||
|
93
st.c
93
st.c
@ -159,6 +159,11 @@ typedef struct {
|
|||||||
int narg; /* nb of args */
|
int narg; /* nb of args */
|
||||||
} STREscape;
|
} STREscape;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int state;
|
||||||
|
size_t length;
|
||||||
|
} URLdfa;
|
||||||
|
|
||||||
static void execsh(char *, char **);
|
static void execsh(char *, char **);
|
||||||
static void stty(char **);
|
static void stty(char **);
|
||||||
static void sigchld(int);
|
static void sigchld(int);
|
||||||
@ -208,6 +213,7 @@ static void tdefutf8(char);
|
|||||||
static int32_t tdefcolor(const int *, int *, int);
|
static int32_t tdefcolor(const int *, int *, int);
|
||||||
static void tdeftran(char);
|
static void tdeftran(char);
|
||||||
static void tstrsequence(uchar);
|
static void tstrsequence(uchar);
|
||||||
|
static int daddch(URLdfa *, char);
|
||||||
|
|
||||||
static void drawregion(int, int, int, int);
|
static void drawregion(int, int, int, int);
|
||||||
|
|
||||||
@ -2737,3 +2743,90 @@ redraw(void)
|
|||||||
tfulldirt();
|
tfulldirt();
|
||||||
draw();
|
draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
daddch(URLdfa *dfa, char c)
|
||||||
|
{
|
||||||
|
/* () and [] can appear in urls, but excluding them here will reduce false
|
||||||
|
* positives when figuring out where a given url ends.
|
||||||
|
*/
|
||||||
|
static const char URLCHARS[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
"abcdefghijklmnopqrstuvwxyz"
|
||||||
|
"0123456789-._~:/?#@!$&'*+,;=%";
|
||||||
|
static const char RPFX[] = "//:sptth";
|
||||||
|
|
||||||
|
if (!strchr(URLCHARS, c)) {
|
||||||
|
dfa->length = 0;
|
||||||
|
dfa->state = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dfa->length++;
|
||||||
|
|
||||||
|
if (dfa->state == 2 && c == '/') {
|
||||||
|
dfa->state = 0;
|
||||||
|
} else if (dfa->state == 3 && c == 'p') {
|
||||||
|
dfa->state++;
|
||||||
|
} else if (c != RPFX[dfa->state]) {
|
||||||
|
dfa->state = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dfa->state++ == 7) {
|
||||||
|
dfa->state = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Select and copy the previous url on screen (do nothing if there's no url).
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
copyurl(const Arg *arg) {
|
||||||
|
int row = 0, /* row of current URL */
|
||||||
|
col = 0, /* column of current URL start */
|
||||||
|
colend = 0, /* column of last occurrence */
|
||||||
|
passes = 0; /* how many rows have been scanned */
|
||||||
|
|
||||||
|
const char *c = NULL,
|
||||||
|
*match = NULL;
|
||||||
|
URLdfa dfa = { 0 };
|
||||||
|
|
||||||
|
row = (sel.ob.x >= 0 && sel.nb.y > 0) ? sel.nb.y : term.bot;
|
||||||
|
LIMIT(row, term.top, term.bot);
|
||||||
|
|
||||||
|
colend = (sel.ob.x >= 0 && sel.nb.y > 0) ? sel.nb.x : term.col;
|
||||||
|
LIMIT(colend, 0, term.col);
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Scan from (term.row - 1,term.col - 1) to (0,0) and find
|
||||||
|
** next occurrance of a URL
|
||||||
|
*/
|
||||||
|
for (passes = 0; passes < term.row; passes++) {
|
||||||
|
/* Read in each column of every row until
|
||||||
|
** we hit previous occurrence of URL
|
||||||
|
*/
|
||||||
|
for (col = colend; col--;)
|
||||||
|
if (daddch(&dfa, term.line[row][col].u < 128 ? term.line[row][col].u : ' '))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (col >= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (--row < 0)
|
||||||
|
row = term.row - 1;
|
||||||
|
|
||||||
|
colend = term.col;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (passes < term.row) {
|
||||||
|
selstart(col, row, 0);
|
||||||
|
selextend((col + dfa.length - 1) % term.col, row + (col + dfa.length - 1) / term.col, SEL_REGULAR, 0);
|
||||||
|
selextend((col + dfa.length - 1) % term.col, row + (col + dfa.length - 1) / term.col, SEL_REGULAR, 1);
|
||||||
|
xsetsel(getsel());
|
||||||
|
xclipcopy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1
st.h
1
st.h
@ -87,6 +87,7 @@ void printscreen(const Arg *);
|
|||||||
void printsel(const Arg *);
|
void printsel(const Arg *);
|
||||||
void sendbreak(const Arg *);
|
void sendbreak(const Arg *);
|
||||||
void toggleprinter(const Arg *);
|
void toggleprinter(const Arg *);
|
||||||
|
void copyurl(const Arg *);
|
||||||
|
|
||||||
int tattrset(int);
|
int tattrset(int);
|
||||||
void tnew(int, int);
|
void tnew(int, int);
|
||||||
|
Loading…
Reference in New Issue
Block a user