st-copyurl-20190202-3be4cf1.diff - sites - public wiki contents of suckless.org | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
st-copyurl-20190202-3be4cf1.diff (4677B) | |
--- | |
1 From f0d27279e47dac9bc413830cc116662dde91837c Mon Sep 17 00:00:00 2001 | |
2 From: Michael Buch <[email protected]> | |
3 Date: Sat, 2 Feb 2019 14:10:31 +0000 | |
4 Subject: [PATCH] Highlight selected urls | |
5 | |
6 --- | |
7 config.def.h | 1 + | |
8 st.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++ | |
9 st.h | 1 + | |
10 3 files changed, 126 insertions(+) | |
11 | |
12 diff --git a/config.def.h b/config.def.h | |
13 index 0e01717..3fb13ec 100644 | |
14 --- a/config.def.h | |
15 +++ b/config.def.h | |
16 @@ -178,6 +178,7 @@ static Shortcut shortcuts[] = { | |
17 { TERMMOD, XK_Y, selpaste, {.i = … | |
18 { ShiftMask, XK_Insert, selpaste, {.i = … | |
19 { TERMMOD, XK_Num_Lock, numlock, {.i = … | |
20 + { MODKEY, XK_l, copyurl, {.i = … | |
21 }; | |
22 | |
23 /* | |
24 diff --git a/st.c b/st.c | |
25 index b8e6077..6970e51 100644 | |
26 --- a/st.c | |
27 +++ b/st.c | |
28 @@ -200,6 +200,8 @@ static void tdefutf8(char); | |
29 static int32_t tdefcolor(int *, int *, int); | |
30 static void tdeftran(char); | |
31 static void tstrsequence(uchar); | |
32 +static void tsetcolor(int, int, int, uint32_t, uint32_t); | |
33 +static char * findlastany(char *, const char**, size_t); | |
34 | |
35 static void drawregion(int, int, int, int); | |
36 | |
37 @@ -2602,3 +2604,125 @@ redraw(void) | |
38 tfulldirt(); | |
39 draw(); | |
40 } | |
41 + | |
42 +void | |
43 +tsetcolor( int row, int start, int end, uint32_t fg, uint32_t bg ) | |
44 +{ | |
45 + int i = start; | |
46 + for( ; i < end; ++i ) | |
47 + { | |
48 + term.line[row][i].fg = fg; | |
49 + term.line[row][i].bg = bg; | |
50 + } | |
51 +} | |
52 + | |
53 +char * | |
54 +findlastany(char *str, const char** find, size_t len) | |
55 +{ | |
56 + char* found = NULL; | |
57 + int i = 0; | |
58 + for(found = str + strlen(str) - 1; found >= str; --found) { | |
59 + for(i = 0; i < len; i++) { | |
60 + if(strncmp(found, find[i], strlen(find[i])) == … | |
61 + return found; | |
62 + } | |
63 + } | |
64 + } | |
65 + | |
66 + return NULL; | |
67 +} | |
68 + | |
69 +/* | |
70 +** Select and copy the previous url on screen (do nothing if there's no… | |
71 +** | |
72 +** FIXME: doesn't handle urls that span multiple lines; will need to ad… | |
73 +** for multiline "getsel()" first | |
74 +*/ | |
75 +void | |
76 +copyurl(const Arg *arg) { | |
77 + /* () and [] can appear in urls, but excluding them here will r… | |
78 + * positives when figuring out where a given url ends. | |
79 + */ | |
80 + static char URLCHARS[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
81 + "abcdefghijklmnopqrstuvwxyz" | |
82 + "0123456789-._~:/?#@!$&'*+,;=%"; | |
83 + | |
84 + static const char* URLSTRINGS[] = {"http://", "https://"}; | |
85 + | |
86 + /* remove highlighting from previous selection if any */ | |
87 + if(sel.ob.x >= 0 && sel.oe.x >= 0) | |
88 + tsetcolor(sel.nb.y, sel.ob.x, sel.oe.x + 1, defaultfg, … | |
89 + | |
90 + int i = 0, | |
91 + row = 0, /* row of current URL */ | |
92 + col = 0, /* column of current URL start */ | |
93 + startrow = 0, /* row of last occurrence */ | |
94 + colend = 0, /* column of last occurrence */ | |
95 + passes = 0; /* how many rows have been scanned */ | |
96 + | |
97 + char *linestr = calloc(sizeof(char), term.col+1); /* assume asc… | |
98 + char *c = NULL, | |
99 + *match = NULL; | |
100 + | |
101 + row = (sel.ob.x >= 0 && sel.nb.y > 0) ? sel.nb.y : term.bot; | |
102 + LIMIT(row, term.top, term.bot); | |
103 + startrow = row; | |
104 + | |
105 + colend = (sel.ob.x >= 0 && sel.nb.y > 0) ? sel.nb.x : term.col; | |
106 + LIMIT(colend, 0, term.col); | |
107 + | |
108 + /* | |
109 + ** Scan from (term.bot,term.col) to (0,0) and find | |
110 + ** next occurrance of a URL | |
111 + */ | |
112 + while(passes !=term.bot + 2) { | |
113 + /* Read in each column of every row until | |
114 + ** we hit previous occurrence of URL | |
115 + */ | |
116 + for (col = 0, i = 0; col < colend; ++col,++i) { | |
117 + /* assume ascii */ | |
118 + if (term.line[row][col].u > 127) | |
119 + continue; | |
120 + linestr[i] = term.line[row][col].u; | |
121 + } | |
122 + linestr[term.col] = '\0'; | |
123 + | |
124 + if ((match = findlastany(linestr, URLSTRINGS, | |
125 + sizeof(URLSTRINGS)/size… | |
126 + break; | |
127 + | |
128 + if (--row < term.top) | |
129 + row = term.bot; | |
130 + | |
131 + colend = term.col; | |
132 + passes++; | |
133 + }; | |
134 + | |
135 + if (match) { | |
136 + /* must happen before trim */ | |
137 + selclear(); | |
138 + sel.ob.x = strlen(linestr) - strlen(match); | |
139 + | |
140 + /* trim the rest of the line from the url match */ | |
141 + for (c = match; *c != '\0'; ++c) | |
142 + if (!strchr(URLCHARS, *c)) { | |
143 + *c = '\0'; | |
144 + break; | |
145 + } | |
146 + | |
147 + /* highlight selection by inverting terminal colors */ | |
148 + tsetcolor(row, sel.ob.x, sel.ob.x + strlen( match ), de… | |
149 + | |
150 + /* select and copy */ | |
151 + sel.mode = 1; | |
152 + sel.type = SEL_REGULAR; | |
153 + sel.oe.x = sel.ob.x + strlen(match)-1; | |
154 + sel.ob.y = sel.oe.y = row; | |
155 + selnormalize(); | |
156 + tsetdirt(sel.nb.y, sel.ne.y); | |
157 + xsetsel(getsel()); | |
158 + xclipcopy(); | |
159 + } | |
160 + | |
161 + free(linestr); | |
162 +} | |
163 diff --git a/st.h b/st.h | |
164 index 38c61c4..67e7419 100644 | |
165 --- a/st.h | |
166 +++ b/st.h | |
167 @@ -84,6 +84,7 @@ void printscreen(const Arg *); | |
168 void printsel(const Arg *); | |
169 void sendbreak(const Arg *); | |
170 void toggleprinter(const Arg *); | |
171 +void copyurl(const Arg *); | |
172 | |
173 int tattrset(int); | |
174 void tnew(int, int); | |
175 -- | |
176 2.20.1 | |
177 |