Introduction
Introduction Statistics Contact Development Disclaimer Help
st-clickurl-0.8.5.diff - sites - public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log
Files
Refs
---
st-clickurl-0.8.5.diff (5778B)
---
1 From d5b492049f48dc411b0dd7dc01a403304c20438d Mon Sep 17 00:00:00 2001
2 From: Jishnu Sen <[email protected]>
3 Date: Sun, 7 Apr 2024 22:54:46 -0700
4 Subject: [PATCH] Highlight URLs with control and follow with click
5
6 ---
7 config.def.h | 11 +++++++
8 st.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++
9 st.h | 9 ++++++
10 x.c | 24 +++++++++++++-
11 4 files changed, 132 insertions(+), 1 deletion(-)
12
13 diff --git a/config.def.h b/config.def.h
14 index 91ab8ca..4961830 100644
15 --- a/config.def.h
16 +++ b/config.def.h
17 @@ -472,3 +472,14 @@ static char ascii_printable[] =
18 " !\"#$%&'()*+,-./0123456789:;<=>?"
19 "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
20 "`abcdefghijklmnopqrstuvwxyz{|}~";
21 +
22 +/*
23 + * Open urls starting with urlprefixes, contatining urlchars
24 + * by passing as ARG1 to urlhandler.
25 + */
26 +char* urlhandler = "xdg-open";
27 +char urlchars[] =
28 + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
29 + "abcdefghijklmnopqrstuvwxyz"
30 + "0123456789-._~:/?#@!$&'*+,;=%";
31 +char* urlprefixes[] = {"http://", "https://", NULL};
32 diff --git a/st.c b/st.c
33 index 51049ba..8f2156c 100644
34 --- a/st.c
35 +++ b/st.c
36 @@ -643,6 +643,95 @@ getsel(void)
37 return str;
38 }
39
40 +char *
41 +strstrany(char* s, char** strs) {
42 + char *match;
43 + for (int i = 0; strs[i]; i++) {
44 + if ((match = strstr(s, strs[i]))) {
45 + return match;
46 + }
47 + }
48 + return NULL;
49 +}
50 +
51 +void
52 +highlighturls(void)
53 +{
54 + char *match;
55 + char *linestr = calloc(sizeof(char), term.col+1); /* assume asc…
56 + for (int i = term.top; i < term.bot; i++) {
57 + int url_start = -1;
58 + for (int j = 0; j < term.col; j++) {
59 + if (term.line[i][j].u < 127) {
60 + linestr[j] = term.line[i][j].u;
61 + }
62 + linestr[term.col] = '\0';
63 + }
64 + while ((match = strstrany(linestr + url_start + 1, urlp…
65 + url_start = match - linestr;
66 + for (int c = url_start; c < term.col && strchr(…
67 + term.line[i][c].mode |= ATTR_URL;
68 + tsetdirt(i, c);
69 + }
70 + }
71 + }
72 + free(linestr);
73 +}
74 +
75 +void
76 +unhighlighturls(void)
77 +{
78 + for (int i = term.top; i < term.bot; i++) {
79 + for (int j = 0; j < term.col; j++) {
80 + Glyph* g = &term.line[i][j];
81 + if (g->mode & ATTR_URL) {
82 + g->mode &= ~ATTR_URL;
83 + tsetdirt(i, j);
84 + }
85 + }
86 + }
87 + return;
88 +}
89 +
90 +void
91 +followurl(int x, int y) {
92 + char *linestr = calloc(sizeof(char), term.col+1); /* assume asc…
93 + char *match;
94 + for (int i = 0; i < term.col; i++) {
95 + if (term.line[x][i].u < 127) {
96 + linestr[i] = term.line[x][i].u;
97 + }
98 + linestr[term.col] = '\0';
99 + }
100 + int url_start = -1;
101 + while ((match = strstrany(linestr + url_start + 1, urlprefixes)…
102 + url_start = match - linestr;
103 + int url_end = url_start;
104 + for (int c = url_start; c < term.col && strchr(urlchars…
105 + url_end++;
106 + }
107 + if (url_start <= y && y < url_end) {
108 + linestr[url_end] = '\0';
109 + break;
110 + }
111 + }
112 + if (url_start == -1) {
113 + free(linestr);
114 + return;
115 + }
116 +
117 + pid_t chpid;
118 + if ((chpid = fork()) == 0) {
119 + if (fork() == 0)
120 + execlp(urlhandler, urlhandler, linestr + url_st…
121 + exit(1);
122 + }
123 + if (chpid > 0)
124 + waitpid(chpid, NULL, 0);
125 + free(linestr);
126 + unhighlighturls();
127 +}
128 +
129 void
130 selclear(void)
131 {
132 diff --git a/st.h b/st.h
133 index 519b9bd..354e7f9 100644
134 --- a/st.h
135 +++ b/st.h
136 @@ -34,6 +34,7 @@ enum glyph_attribute {
137 ATTR_WIDE = 1 << 9,
138 ATTR_WDUMMY = 1 << 10,
139 ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
140 + ATTR_URL = 1 << 14,
141 };
142
143 enum selection_mode {
144 @@ -105,6 +106,10 @@ void selextend(int, int, int, int);
145 int selected(int, int);
146 char *getsel(void);
147
148 +void highlighturls(void);
149 +void unhighlighturls(void);
150 +void followurl(int, int);
151 +
152 size_t utf8encode(Rune, char *);
153
154 void *xmalloc(size_t);
155 @@ -126,3 +131,7 @@ extern unsigned int tabspaces;
156 extern unsigned int defaultfg;
157 extern unsigned int defaultbg;
158 extern unsigned int defaultcs;
159 +extern char *urlhandler;
160 +extern char urlchars[];
161 +extern char *urlprefixes[];
162 +extern int nurlprefixes;
163 diff --git a/x.c b/x.c
164 index 8a16faa..13f68e4 100644
165 --- a/x.c
166 +++ b/x.c
167 @@ -191,6 +191,7 @@ static void usage(void);
168
169 static void (*handler[LASTEvent])(XEvent *) = {
170 [KeyPress] = kpress,
171 + [KeyRelease] = kpress,
172 [ClientMessage] = cmessage,
173 [ConfigureNotify] = resize,
174 [VisibilityNotify] = visibility,
175 @@ -445,6 +446,15 @@ mouseaction(XEvent *e, uint release)
176 /* ignore Button<N>mask for Button<N> - it's set on release */
177 uint state = e->xbutton.state & ~buttonmask(e->xbutton.button);
178
179 + if (release == 0 &&
180 + e->xbutton.button == Button1 &&
181 + (match(ControlMask, state) ||
182 + match(ControlMask, state & ~forcemousemod))) {
183 + followurl(evrow(e), evcol(e));
184 + return 1;
185 + }
186 +
187 +
188 for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) {
189 if (ms->release == release &&
190 ms->button == e->xbutton.button &&
191 @@ -1476,7 +1486,7 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs,…
192 XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
193
194 /* Render underline and strikethrough. */
195 - if (base.mode & ATTR_UNDERLINE) {
196 + if (base.mode & ATTR_UNDERLINE || base.mode & ATTR_URL) {
197 XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + …
198 width, 1);
199 }
200 @@ -1831,6 +1841,18 @@ kpress(XEvent *ev)
201 len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &…
202 else
203 len = XLookupString(e, buf, sizeof buf, &ksym, NULL);
204 +
205 + /* 0. highlight URLs when control held */
206 + if (ksym == XK_Control_L) {
207 + highlighturls();
208 + } else if (ev->type == KeyRelease && e->keycode == XKeysymToKey…
209 + unhighlighturls();
210 + }
211 +
212 + /* KeyRelease not relevant to shortcuts */
213 + if (ev->type == KeyRelease)
214 + return;
215 +
216 /* 1. shortcuts */
217 for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) {
218 if (ksym == bp->keysym && match(bp->mod, e->state)) {
219 --
220 2.44.0
221
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.