st-copyurl-multiline-20220221-0.8.5.diff - sites - public wiki contents of suck… | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
st-copyurl-multiline-20220221-0.8.5.diff (4012B) | |
--- | |
1 From 30a04d9ecb3998953bdbe42e5617d00d6002869b Mon Sep 17 00:00:00 2001 | |
2 From: Santtu Lakkala <[email protected]> | |
3 Date: Wed, 16 Feb 2022 20:34:20 +0200 | |
4 Subject: [PATCH] Loop through urls on screen and copy to clipboard | |
5 | |
6 Replace url detection heuristics with a DFA, enabling urls that span | |
7 multiple lines. Also fix the selection not to use snapping so that urls | |
8 are selected exactly. | |
9 --- | |
10 config.def.h | 1 + | |
11 st.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
12 st.h | 1 + | |
13 3 files changed, 95 insertions(+) | |
14 | |
15 diff --git a/config.def.h b/config.def.h | |
16 index 91ab8ca..3f365c7 100644 | |
17 --- a/config.def.h | |
18 +++ b/config.def.h | |
19 @@ -201,6 +201,7 @@ static Shortcut shortcuts[] = { | |
20 { TERMMOD, XK_Y, selpaste, {.i = … | |
21 { ShiftMask, XK_Insert, selpaste, {.i = … | |
22 { TERMMOD, XK_Num_Lock, numlock, {.i = … | |
23 + { MODKEY, XK_l, copyurl, {.i = … | |
24 }; | |
25 | |
26 /* | |
27 diff --git a/st.c b/st.c | |
28 index 51049ba..5b6d919 100644 | |
29 --- a/st.c | |
30 +++ b/st.c | |
31 @@ -152,6 +152,11 @@ typedef struct { | |
32 int narg; /* nb of args */ | |
33 } STREscape; | |
34 | |
35 +typedef struct { | |
36 + int state; | |
37 + size_t length; | |
38 +} URLdfa; | |
39 + | |
40 static void execsh(char *, char **); | |
41 static void stty(char **); | |
42 static void sigchld(int); | |
43 @@ -200,6 +205,7 @@ static void tdefutf8(char); | |
44 static int32_t tdefcolor(const int *, int *, int); | |
45 static void tdeftran(char); | |
46 static void tstrsequence(uchar); | |
47 +static int daddch(URLdfa *, char); | |
48 | |
49 static void drawregion(int, int, int, int); | |
50 | |
51 @@ -2688,3 +2694,90 @@ redraw(void) | |
52 tfulldirt(); | |
53 draw(); | |
54 } | |
55 + | |
56 +int | |
57 +daddch(URLdfa *dfa, char c) | |
58 +{ | |
59 + /* () and [] can appear in urls, but excluding them here will r… | |
60 + * positives when figuring out where a given url ends. | |
61 + */ | |
62 + static const char URLCHARS[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
63 + "abcdefghijklmnopqrstuvwxyz" | |
64 + "0123456789-._~:/?#@!$&'*+,;=%"; | |
65 + static const char RPFX[] = "//:sptth"; | |
66 + | |
67 + if (!strchr(URLCHARS, c)) { | |
68 + dfa->length = 0; | |
69 + dfa->state = 0; | |
70 + | |
71 + return 0; | |
72 + } | |
73 + | |
74 + dfa->length++; | |
75 + | |
76 + if (dfa->state == 2 && c == '/') { | |
77 + dfa->state = 0; | |
78 + } else if (dfa->state == 3 && c == 'p') { | |
79 + dfa->state++; | |
80 + } else if (c != RPFX[dfa->state]) { | |
81 + dfa->state = 0; | |
82 + return 0; | |
83 + } | |
84 + | |
85 + if (dfa->state++ == 7) { | |
86 + dfa->state = 0; | |
87 + return 1; | |
88 + } | |
89 + | |
90 + return 0; | |
91 +} | |
92 + | |
93 +/* | |
94 +** Select and copy the previous url on screen (do nothing if there's no… | |
95 +*/ | |
96 +void | |
97 +copyurl(const Arg *arg) { | |
98 + int row = 0, /* row of current URL */ | |
99 + col = 0, /* column of current URL start */ | |
100 + colend = 0, /* column of last occurrence */ | |
101 + passes = 0; /* how many rows have been scanned */ | |
102 + | |
103 + const char *c = NULL, | |
104 + *match = NULL; | |
105 + URLdfa dfa = { 0 }; | |
106 + | |
107 + row = (sel.ob.x >= 0 && sel.nb.y > 0) ? sel.nb.y : term.bot; | |
108 + LIMIT(row, term.top, term.bot); | |
109 + | |
110 + colend = (sel.ob.x >= 0 && sel.nb.y > 0) ? sel.nb.x : term.col; | |
111 + LIMIT(colend, 0, term.col); | |
112 + | |
113 + /* | |
114 + ** Scan from (term.row - 1,term.col - 1) to (0,0) and find | |
115 + ** next occurrance of a URL | |
116 + */ | |
117 + for (passes = 0; passes < term.row; passes++) { | |
118 + /* Read in each column of every row until | |
119 + ** we hit previous occurrence of URL | |
120 + */ | |
121 + for (col = colend; col--;) | |
122 + if (daddch(&dfa, term.line[row][col].u < 128 ? … | |
123 + break; | |
124 + | |
125 + if (col >= 0) | |
126 + break; | |
127 + | |
128 + if (--row < 0) | |
129 + row = term.row - 1; | |
130 + | |
131 + colend = term.col; | |
132 + } | |
133 + | |
134 + if (passes < term.row) { | |
135 + selstart(col, row, 0); | |
136 + selextend((col + dfa.length - 1) % term.col, row + (col… | |
137 + selextend((col + dfa.length - 1) % term.col, row + (col… | |
138 + xsetsel(getsel()); | |
139 + xclipcopy(); | |
140 + } | |
141 +} | |
142 diff --git a/st.h b/st.h | |
143 index 519b9bd..0458005 100644 | |
144 --- a/st.h | |
145 +++ b/st.h | |
146 @@ -85,6 +85,7 @@ void printscreen(const Arg *); | |
147 void printsel(const Arg *); | |
148 void sendbreak(const Arg *); | |
149 void toggleprinter(const Arg *); | |
150 +void copyurl(const Arg *); | |
151 | |
152 int tattrset(int); | |
153 void tnew(int, int); | |
154 -- | |
155 2.32.0 | |
156 |