st-copyurl-20190202-3be4cf1.diff - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) Refs
---
st-copyurl-20190202-3be4cf1.diff (4677B)
---
1 From f0d27279e47dac9bc413830cc116662dde91837c Mon Sep 17 00:00:00 2001
2 From: Michael Buch <michaelbuch12@gmail.com>
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 = 0} },
18 { ShiftMask, XK_Insert, selpaste, {.i = 0} },
19 { TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
20 + { MODKEY, XK_l, copyurl, {.i = 0} },
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])) == 0) {
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 url).
71 +**
72 +** FIXME: doesn't handle urls that span multiple lines; will need to add support
73 +** for multiline "getsel()" first
74 +*/
75 +void
76 +copyurl(const Arg *arg) {
77 + /* () and [] can appear in urls, but excluding them here will reduce false
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, defaultbg);
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 ascii */
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)/sizeof(URLSTRINGS[0]))))
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 ), defaultbg, defaultfg);
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