sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

st-copyurl-20220221-0.8.5.diff (3868B)


      1 From 897c3958d01d8df80ebf1666b972b8a658b419ba 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 Based on the previous highlighting patches, slightly simplified and
      7 fixes graphical issues with mixed copyurl and selection.
      8 ---
      9  config.def.h |  1 +
     10  st.c         | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++
     11  st.h         |  1 +
     12  3 files changed, 84 insertions(+)
     13 
     14 diff --git a/config.def.h b/config.def.h
     15 index 91ab8ca..3f365c7 100644
     16 --- a/config.def.h
     17 +++ b/config.def.h
     18 @@ -201,6 +201,7 @@ static Shortcut shortcuts[] = {
     19  	{ TERMMOD,              XK_Y,           selpaste,       {.i =  0} },
     20  	{ ShiftMask,            XK_Insert,      selpaste,       {.i =  0} },
     21  	{ TERMMOD,              XK_Num_Lock,    numlock,        {.i =  0} },
     22 +	{ MODKEY,               XK_l,           copyurl,        {.i =  0} },
     23  };
     24  
     25  /*
     26 diff --git a/st.c b/st.c
     27 index 51049ba..bf3d81a 100644
     28 --- a/st.c
     29 +++ b/st.c
     30 @@ -200,6 +200,7 @@ static void tdefutf8(char);
     31  static int32_t tdefcolor(const int *, int *, int);
     32  static void tdeftran(char);
     33  static void tstrsequence(uchar);
     34 +static const char *findlastany(const char *, const char**, size_t);
     35  
     36  static void drawregion(int, int, int, int);
     37  
     38 @@ -2688,3 +2689,84 @@ redraw(void)
     39  	tfulldirt();
     40  	draw();
     41  }
     42 +
     43 +const char *
     44 +findlastany(const char *str, const char**find, size_t len)
     45 +{
     46 +	const char *found = NULL;
     47 +	int i = 0;
     48 +
     49 +	for (found = str + strlen(str) - 1; found >= str; --found) {
     50 +		for(i = 0; i < len; i++) {
     51 +			if (strncmp(found, find[i], strlen(find[i])) == 0) {
     52 +				return found;
     53 +			}
     54 +		}
     55 +	}
     56 +
     57 +	return NULL;
     58 +}
     59 +
     60 +/*
     61 +** Select and copy the previous url on screen (do nothing if there's no url).
     62 +**
     63 +** FIXME: doesn't handle urls that span multiple lines; will need to add support
     64 +**        for multiline "getsel()" first
     65 +*/
     66 +void
     67 +copyurl(const Arg *arg) {
     68 +	/* () and [] can appear in urls, but excluding them here will reduce false
     69 +	 * positives when figuring out where a given url ends.
     70 +	 */
     71 +	static const char URLCHARS[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     72 +		"abcdefghijklmnopqrstuvwxyz"
     73 +		"0123456789-._~:/?#@!$&'*+,;=%";
     74 +
     75 +	static const char* URLSTRINGS[] = {"http://", "https://"};
     76 +
     77 +	int row = 0, /* row of current URL */
     78 +		col = 0, /* column of current URL start */
     79 +		colend = 0, /* column of last occurrence */
     80 +		passes = 0; /* how many rows have been scanned */
     81 +
     82 +	char linestr[term.col + 1];
     83 +	const char *c = NULL,
     84 +		 *match = NULL;
     85 +
     86 +	row = (sel.ob.x >= 0 && sel.nb.y > 0) ? sel.nb.y : term.bot;
     87 +	LIMIT(row, term.top, term.bot);
     88 +
     89 +	colend = (sel.ob.x >= 0 && sel.nb.y > 0) ? sel.nb.x : term.col;
     90 +	LIMIT(colend, 0, term.col);
     91 +
     92 +	/*
     93 +	** Scan from (term.row - 1,term.col - 1) to (0,0) and find
     94 +	** next occurrance of a URL
     95 +	*/
     96 +	for (passes = 0; passes < term.row; passes++) {
     97 +		/* Read in each column of every row until
     98 +		** we hit previous occurrence of URL
     99 +		*/
    100 +		for (col = 0; col < colend; ++col)
    101 +			linestr[col] = term.line[row][col].u < 128 ? term.line[row][col].u : ' ';
    102 +		linestr[col] = '\0';
    103 +
    104 +		if ((match = findlastany(linestr, URLSTRINGS,
    105 +						sizeof(URLSTRINGS)/sizeof(URLSTRINGS[0]))))
    106 +			break;
    107 +
    108 +		if (--row < 0)
    109 +			row = term.row - 1;
    110 +
    111 +		colend = term.col;
    112 +	};
    113 +
    114 +	if (match) {
    115 +		size_t l = strspn(match, URLCHARS);
    116 +		selstart(match - linestr, row, 0);
    117 +		selextend(match - linestr + l - 1, row, SEL_REGULAR, 0);
    118 +		selextend(match - linestr + l - 1, row, SEL_REGULAR, 1);
    119 +		xsetsel(getsel());
    120 +		xclipcopy();
    121 +	}
    122 +}
    123 diff --git a/st.h b/st.h
    124 index 519b9bd..0458005 100644
    125 --- a/st.h
    126 +++ b/st.h
    127 @@ -85,6 +85,7 @@ void printscreen(const Arg *);
    128  void printsel(const Arg *);
    129  void sendbreak(const Arg *);
    130  void toggleprinter(const Arg *);
    131 +void copyurl(const Arg *);
    132  
    133  int tattrset(int);
    134  void tnew(int, int);
    135 -- 
    136 2.32.0
    137