st-copyurl-multiline-20220221-0.8.5.diff - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) Refs
---
st-copyurl-multiline-20220221-0.8.5.diff (4012B)
---
1 From 30a04d9ecb3998953bdbe42e5617d00d6002869b Mon Sep 17 00:00:00 2001
2 From: Santtu Lakkala <inz@inz.fi>
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 = 0} },
21 { ShiftMask, XK_Insert, selpaste, {.i = 0} },
22 { TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
23 + { MODKEY, XK_l, copyurl, {.i = 0} },
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 reduce false
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 url).
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 ? term.line[row][col].u : ' '))
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 + dfa.length - 1) / term.col, SEL_REGULAR, 0);
137 + selextend((col + dfa.length - 1) % term.col, row + (col + dfa.length - 1) / term.col, SEL_REGULAR, 1);
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