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