st-copyurl-multiline-20230406-211964d.diff (4361B)
1 From 7405bdc89e4c43cfbeabd0d4d822bc62d1e76730 Mon Sep 17 00:00:00 2001 2 From: Gildasio Junior <gildasiojunior@riseup.net> 3 Date: Thu, 6 Apr 2023 14:51:06 -0300 4 Subject: [PATCH] Loop through urls on screen in both directions 5 6 Using previous patches one can loop through urls in the screen in one 7 direction: botton-up. This patch add a way that can go in the opposite 8 direction: top-down. 9 10 This is usefull in a screen with lots of urls. 11 --- 12 config.def.h | 2 + 13 st.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++ 14 st.h | 1 + 15 3 files changed, 104 insertions(+) 16 17 diff --git a/config.def.h b/config.def.h 18 index 91ab8ca..4df78eb 100644 19 --- a/config.def.h 20 +++ b/config.def.h 21 @@ -201,6 +201,8 @@ static Shortcut shortcuts[] = { 22 { TERMMOD, XK_Y, selpaste, {.i = 0} }, 23 { ShiftMask, XK_Insert, selpaste, {.i = 0} }, 24 { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, 25 + { MODKEY, XK_l, copyurl, {.i = 0} }, 26 + { MODKEY|ShiftMask, XK_L, copyurl, {.i = 1} }, 27 }; 28 29 /* 30 diff --git a/st.c b/st.c 31 index 134e724..c451015 100644 32 --- a/st.c 33 +++ b/st.c 34 @@ -152,6 +152,11 @@ typedef struct { 35 int narg; /* nb of args */ 36 } STREscape; 37 38 +typedef struct { 39 + int state; 40 + size_t length; 41 +} URLdfa; 42 + 43 static void execsh(char *, char **); 44 static void stty(char **); 45 static void sigchld(int); 46 @@ -201,6 +206,7 @@ static void tdefutf8(char); 47 static int32_t tdefcolor(const int *, int *, int); 48 static void tdeftran(char); 49 static void tstrsequence(uchar); 50 +static int daddch(URLdfa *, char); 51 52 static void drawregion(int, int, int, int); 53 54 @@ -2666,3 +2672,98 @@ redraw(void) 55 tfulldirt(); 56 draw(); 57 } 58 + 59 +int 60 +daddch(URLdfa *dfa, char c) 61 +{ 62 + /* () and [] can appear in urls, but excluding them here will reduce false 63 + * positives when figuring out where a given url ends. 64 + */ 65 + static const char URLCHARS[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 66 + "abcdefghijklmnopqrstuvwxyz" 67 + "0123456789-._~:/?#@!$&'*+,;=%"; 68 + static const char RPFX[] = "//:sptth"; 69 + 70 + if (!strchr(URLCHARS, c)) { 71 + dfa->length = 0; 72 + dfa->state = 0; 73 + 74 + return 0; 75 + } 76 + 77 + dfa->length++; 78 + 79 + if (dfa->state == 2 && c == '/') { 80 + dfa->state = 0; 81 + } else if (dfa->state == 3 && c == 'p') { 82 + dfa->state++; 83 + } else if (c != RPFX[dfa->state]) { 84 + dfa->state = 0; 85 + return 0; 86 + } 87 + 88 + if (dfa->state++ == 7) { 89 + dfa->state = 0; 90 + return 1; 91 + } 92 + 93 + return 0; 94 +} 95 + 96 +/* 97 +** Select and copy the previous url on screen (do nothing if there's no url). 98 +*/ 99 +void 100 +copyurl(const Arg *arg) { 101 + int row = 0, /* row of current URL */ 102 + col = 0, /* column of current URL start */ 103 + colend = 0, /* column of last occurrence */ 104 + passes = 0; /* how many rows have been scanned */ 105 + 106 + const char *c = NULL, 107 + *match = NULL; 108 + URLdfa dfa = { 0 }; 109 + 110 + row = (sel.ob.x >= 0 && sel.nb.y > 0) ? sel.nb.y : term.bot; 111 + LIMIT(row, term.top, term.bot); 112 + 113 + colend = (sel.ob.x >= 0 && sel.nb.y > 0) ? sel.nb.x : term.col; 114 + LIMIT(colend, 0, term.col); 115 + 116 + /* 117 + ** Scan from (term.row - 1,term.col - 1) to (0,0) and find 118 + ** next occurrance of a URL 119 + */ 120 + for (passes = 0; passes < term.row; passes++) { 121 + /* Read in each column of every row until 122 + ** we hit previous occurrence of URL 123 + */ 124 + for (col = colend; col--;) 125 + if (daddch(&dfa, term.line[row][col].u < 128 ? term.line[row][col].u : ' ')) 126 + break; 127 + 128 + if (col >= 0) 129 + break; 130 + 131 + /* .i = 0 --> botton-up 132 + * .i = 1 --> top-down 133 + */ 134 + if (!arg->i) { 135 + if (--row < 0) 136 + row = term.row - 1; 137 + } else { 138 + if (++row >= term.row) 139 + row = 0; 140 + } 141 + 142 + colend = term.col; 143 + } 144 + 145 + if (passes < term.row) { 146 + selstart(col, row, 0); 147 + selextend((col + dfa.length - 1) % term.col, row + (col + dfa.length - 1) / term.col, SEL_REGULAR, 0); 148 + selextend((col + dfa.length - 1) % term.col, row + (col + dfa.length - 1) / term.col, SEL_REGULAR, 1); 149 + xsetsel(getsel()); 150 + xclipcopy(); 151 + } 152 +} 153 diff --git a/st.h b/st.h 154 index fd3b0d8..baa8f29 100644 155 --- a/st.h 156 +++ b/st.h 157 @@ -85,6 +85,7 @@ void printscreen(const Arg *); 158 void printsel(const Arg *); 159 void sendbreak(const Arg *); 160 void toggleprinter(const Arg *); 161 +void copyurl(const Arg *); 162 163 int tattrset(int); 164 void tnew(int, int); 165 -- 166 2.40.0 167