static-httpd

Sitio web estático (HTML + CSS) que sostiene el blog del autor
Log | Files | Refs

index.html (18281B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
      5 <meta name="viewport" content="width=device-width, initial-scale=1" />
      6 <title>Configuración propia del lanzador de aplicación dmenu</title>
      7 <link rel="icon" type="image/png" href="/favicon.png" />
      8 <link rel="stylesheet" type="text/css" href="../article.css" />
      9 </head>
     10 <body>
     11 <header>
     12 <p class="title">Configuración propia del lanzador de aplicación dmenu</p>
     13 <p class="date">25 de junio de 2026 • fjbalon</p>
     14 </header>
     15 <p>dmenu es un lanzador de aplicaciones, extremadamente ligero y rápido para el sistemas de ventanas X, diseñado originalmente para el gestor de ventanas dwm, de suckless. Es una herramienta que, para mí, casa matrimonialmente con dwm; no pudiendo ser verdaderamente usable uno sin el otro. Al menos, dwm no sería tan útil sin él.</p>
     16 <p>Puede encontrar mi propia versión del código en mi servidor de git: <a href="https://templier.es/git/dmenu/">/git/dmenu/</a>.</p>
     17 <p>La versión inicial es muy sencilla, al ser llamado mediante el comando <emb>dmenu</emb>, que por defecto dwm trae con acceso directo mediante teclas (<kbd>Mod1</kbd>+<kbd>p</kbd>, aunque yo personalmente lo he modificado a <kbd>Mod4</kbd>+<kbd>r</kbd>, me gusta más), ejecuta en la barra superior el lanzador, que conforme escribes irá indicando una lista de coincidencias, con una siempre seleccionada.</p>
     18 <p>Pero el código tiene algunas limitaciones para con mi forma de trabajar, por lo que he aplicado algunos cambios para que sea más ameno y útil su uso. Estos son los cambios que he realizado:</p>
     19 
     20 <ol>
     21 <li>Originalmente, como suele ser en el entorno de Linux, es <i>case sensitive</i>. Generalmente lo prefiero así, es más preciso. Sin embargo, siendo que se trata de un lanzador que quiero que sea rápido, o que me ayude a buscar con facilidad; prefiero que sea <i>case insensitive</i>. En suckless hay un parche oficial para ello (<a href="https://tools.suckless.org/dmenu/patches/case-insensitive/">case-insensitive</a>), que he aplicado:
     22 <pre><code class="diff"><span class="info">diff --git a/dmenu.c b/dmenu.c</span>
     23 <span class="hunk">@@ -54,8 +54,9 @@ static Clr *scheme[SchemeLast];</span>
     24  
     25  #include "config.h"
     26  
     27 <span class="del">-static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;</span>
     28 <span class="del">-static char *(*fstrstr)(const char *, const char *) = strstr;</span>
     29 <span class="add">+static char * cistrstr(const char *s, const char *sub);</span>
     30 <span class="add">+static int (*fstrncmp)(const char *, const char *, size_t) = strncasecmp;</span>
     31 <span class="add">+static char *(*fstrstr)(const char *, const char *) = cistrstr;</span>
     32  
     33  static unsigned int
     34  textw_clamp(const char *str, unsigned int n)
     35 <span class="hunk">@@ -733,9 +734,9 @@ main(int argc, char *argv[])</span>
     36              topbar = 0;
     37          else if (!strcmp(argv[i], "-f"))   /* grabs keyboard before reading stdin */
     38              fast = 1;
     39 <span class="del">-        else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */</span>
     40 <span class="del">-            fstrncmp = strncasecmp;</span>
     41 <span class="del">-            fstrstr = cistrstr;</span>
     42 <span class="add">+        else if (!strcmp(argv[i], "-s")) { /* case-sensitive item matching */</span>
     43 <span class="add">+            fstrncmp = strncmp;</span>
     44 <span class="add">+            fstrstr = strstr;</span>
     45          } else if (i + 1 == argc)
     46              usage();
     47          /* these options take one argument */</code></pre>
     48 </li>
     49 <li>Del mismo modo, y con una pretensión de pérdida de cierta precisión con el objetivo de ganar eficiencia y velocidad de lanzamiento, implemento <b>búsqueda difusa</b> mediante la aplicación del parche <a href="https://tools.suckless.org/dmenu/patches/fuzzymatch/">fuzzymatch</a>, que garantiza que el contenido resultado no tiene por qué coincidir matemáticamente con el patrón de búsqueda (por ejemplo, la búsqueda de <emb>rvt</emb> podrá dar como resultado <emb>urxvt</emb>), en combinación con el parche <a href="https://tools.suckless.org/dmenu/patches/fuzzyhighlight/">fuzzyhighlight</a>, que resalta las coincidencias en la búsqueda.
     50 <pre><code class="diff"><span class="info">diff --git a/config.h b/config.h</span>
     51 <span class="info">index 1edb647..64eab2a 100644</span>
     52 <span class="info">--- a/config.h</span>
     53 <span class="info">+++ b/config.h</span>
     54 <span class="hunk">@@ -11,6 +11,8 @@ static const char *colors[SchemeLast][2] = {</span>
     55      /*     fg         bg       */
     56      [SchemeNorm] = { "#bbbbbb", "#222222" },
     57      [SchemeSel] = { "#eeeeee", "#005577" },
     58 <span class="add">+    [SchemeSelHighlight] = { "#ffc978", "#005577" },</span>
     59 <span class="add">+    [SchemeNormHighlight] = { "#ffc978", "#222222" },</span>
     60      [SchemeOut] = { "#000000", "#00ffff" },
     61  };
     62  /* -l option; if nonzero, dmenu uses vertical list with given number of lines */
     63 <span class="info">diff --git a/dmenu.c b/dmenu.c</span>
     64 <span class="info">index 40f93e0..662131a 100644</span>
     65 <span class="info">--- a/dmenu.c</span>
     66 <span class="info">+++ b/dmenu.c</span>
     67 <span class="hunk">@@ -25,7 +25,9 @@</span>
     68  #define TEXTW(X)              (drw_fontset_getwidth(drw, (X)) + lrpad)
     69  
     70  /* enums */
     71 <span class="del">-enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */</span>
     72 <span class="add">+enum { SchemeNorm, SchemeSel, SchemeNormHighlight, SchemeSelHighlight,</span>
     73 <span class="add">+       SchemeOut, SchemeLast }; /* color schemes */</span>
     74 <span class="add">+</span>
     75  
     76  struct item {
     77      char *text;
     78 <span class="hunk">@@ -129,9 +131,47 @@ cistrstr(const char *h, const char *n)</span>
     79      return NULL;
     80  }
     81  
     82 <span class="add">+static void</span>
     83 <span class="add">+drawhighlights(struct item *item, int x, int y, int maxw)</span>
     84 <span class="add">+{</span>
     85 <span class="add">+    int i, indent;</span>
     86 <span class="add">+    char c, *highlight;</span>
     87 <span class="add">+</span>
     88 <span class="add">+    if (!(strlen(item-&gt;text) &amp;&amp; strlen(text)))</span>
     89 <span class="add">+        return;</span>
     90 <span class="add">+</span>
     91 <span class="add">+    drw_setscheme(drw, scheme[item == sel</span>
     92 <span class="add">+                       ? SchemeSelHighlight</span>
     93 <span class="add">+                       : SchemeNormHighlight]);</span>
     94 <span class="add">+    for (i = 0, highlight = item-&gt;text; *highlight &amp;&amp; text[i];) {</span>
     95 <span class="add">+        if (!fstrncmp(highlight, &amp;text[i], 1)) {</span>
     96 <span class="add">+            /* get indentation */</span>
     97 <span class="add">+            c = *highlight;</span>
     98 <span class="add">+            *highlight = '\0';</span>
     99 <span class="add">+            indent = TEXTW(item-&gt;text);</span>
    100 <span class="add">+            *highlight = c;</span>
    101 <span class="add">+</span>
    102 <span class="add">+            /* highlight character */</span>
    103 <span class="add">+            c = highlight[1];</span>
    104 <span class="add">+            highlight[1] = '\0';</span>
    105 <span class="add">+            drw_text(</span>
    106 <span class="add">+                drw,</span>
    107 <span class="add">+                x + indent - (lrpad / 2.),</span>
    108 <span class="add">+                y,</span>
    109 <span class="add">+                MIN(maxw - indent, TEXTW(highlight) - lrpad),</span>
    110 <span class="add">+                bh, 0, highlight, 0</span>
    111 <span class="add">+            );</span>
    112 <span class="add">+            highlight[1] = c;</span>
    113 <span class="add">+            ++i;</span>
    114 <span class="add">+        }</span>
    115 <span class="add">+        ++highlight;</span>
    116 <span class="add">+    }</span>
    117 <span class="add">+}</span>
    118 <span class="add">+</span>
    119  static int
    120  drawitem(struct item *item, int x, int y, int w)
    121  {
    122 <span class="add">+    int r;</span>
    123      if (item == sel)
    124          drw_setscheme(drw, scheme[SchemeSel]);
    125      else if (item-&gt;out)
    126 <span class="hunk">@@ -139,7 +179,9 @@ drawitem(struct item *item, int x, int y, int w)</span>
    127      else
    128          drw_setscheme(drw, scheme[SchemeNorm]);
    129  
    130 <span class="del">-    return drw_text(drw, x, y, w, bh, lrpad / 2, item-&gt;text, 0);</span>
    131 <span class="add">+    r = drw_text(drw, x, y, w, bh, lrpad / 2, item-&gt;text, 0);</span>
    132 <span class="add">+    drawhighlights(item, x, y, w);</span>
    133 <span class="add">+    return r;</span>
    134  }
    135  
    136  static void
    137 <span class="hunk">@@ -716,7 +758,8 @@ static void</span>
    138  usage(void)
    139  {
    140      die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
    141 <span class="del">-        "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]");</span>
    142 <span class="add">+        "             [-nb color] [-nf color] [-sb color] [-sf color]\n"</span>
    143 <span class="add">+        "             [-nhb color] [-nhf color] [-shb color] [-shf color] [-w windowid]");</span>
    144  }
    145  
    146  int
    147 <span class="hunk">@@ -756,6 +799,14 @@ main(int argc, char *argv[])</span>
    148              colors[SchemeSel][ColBg] = argv[++i];
    149          else if (!strcmp(argv[i], "-sf"))  /* selected foreground color */
    150              colors[SchemeSel][ColFg] = argv[++i];
    151 <span class="add">+        else if (!strcmp(argv[i], "-nhb")) /* normal hi background color */</span>
    152 <span class="add">+            colors[SchemeNormHighlight][ColBg] = argv[++i];</span>
    153 <span class="add">+        else if (!strcmp(argv[i], "-nhf")) /* normal hi foreground color */</span>
    154 <span class="add">+            colors[SchemeNormHighlight][ColFg] = argv[++i];</span>
    155 <span class="add">+        else if (!strcmp(argv[i], "-shb")) /* selected hi background color */</span>
    156 <span class="add">+            colors[SchemeSelHighlight][ColBg] = argv[++i];</span>
    157 <span class="add">+        else if (!strcmp(argv[i], "-shf")) /* selected hi foreground color */</span>
    158 <span class="add">+            colors[SchemeSelHighlight][ColFg] = argv[++i];</span>
    159          else if (!strcmp(argv[i], "-w"))   /* embedding window id */
    160              embed = argv[++i];
    161          else</code></pre>
    162 <pre><code class="diff"><span class="info">diff --git a/config.h b/config.h</span>
    163 <span class="info">index 1edb647..a4e6174 100644</span>
    164 <span class="info">--- a/config.h</span>
    165 <span class="info">+++ b/config.h</span>
    166 <span class="hunk">@@ -2,6 +2,7 @@</span>
    167  /* Default settings; can be overriden by command line. */
    168  
    169  static int topbar = 1;                      /* -b  option; if 0, dmenu appears at bottom     */
    170 <span class="add">+static int fuzzy  = 1;                      /* -F  option; if 0, dmenu doesn't use fuzzy matching */</span>
    171  /* -fn option overrides fonts[0]; default X11 font or font set */
    172  static const char *fonts[] = {
    173      "monospace:size=10"
    174 <span class="info">diff --git a/config.mk b/config.mk</span>
    175 <span class="info">index 137f7c8..6a19175 100644</span>
    176 <span class="info">--- a/config.mk</span>
    177 <span class="info">+++ b/config.mk</span>
    178 <span class="hunk">@@ -21,7 +21,7 @@ FREETYPEINC = /usr/include/freetype2</span>
    179  
    180  # includes and libs
    181  INCS = -I$(X11INC) -I$(FREETYPEINC)
    182 <span class="del">-LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS)</span>
    183 <span class="add">+LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm</span>
    184  
    185  # flags
    186  CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
    187 <span class="info">diff --git a/dmenu.c b/dmenu.c</span>
    188 <span class="info">index 40f93e0..03e1f45 100644</span>
    189 <span class="info">--- a/dmenu.c</span>
    190 <span class="info">+++ b/dmenu.c</span>
    191 <span class="hunk">@@ -1,6 +1,7 @@</span>
    192  /* See LICENSE file for copyright and license details. */
    193  #include &lt;ctype.h&gt;
    194  #include &lt;locale.h&gt;
    195 <span class="add">+#include &lt;math.h&gt;</span>
    196  #include &lt;stdio.h&gt;
    197  #include &lt;stdlib.h&gt;
    198  #include &lt;string.h&gt;
    199 <span class="hunk">@@ -31,6 +32,7 @@ struct item {</span>
    200      char *text;
    201      struct item *left, *right;
    202      int out;
    203 <span class="add">+    double distance;</span>
    204  };
    205  
    206  static char text[BUFSIZ] = "";
    207 <span class="hunk">@@ -226,9 +228,93 @@ grabkeyboard(void)</span>
    208      die("cannot grab keyboard");
    209  }
    210  
    211 <span class="add">+int</span>
    212 <span class="add">+compare_distance(const void *a, const void *b)</span>
    213 <span class="add">+{</span>
    214 <span class="add">+    struct item *da = *(struct item **) a;</span>
    215 <span class="add">+    struct item *db = *(struct item **) b;</span>
    216 <span class="add">+</span>
    217 <span class="add">+    if (!db)</span>
    218 <span class="add">+        return 1;</span>
    219 <span class="add">+    if (!da)</span>
    220 <span class="add">+        return -1;</span>
    221 <span class="add">+</span>
    222 <span class="add">+    return da-&gt;distance == db-&gt;distance ? 0 : da-&gt;distance &lt; db-&gt;distance ? -1 : 1;</span>
    223 <span class="add">+}</span>
    224 <span class="add">+</span>
    225 <span class="add">+void</span>
    226 <span class="add">+fuzzymatch(void)</span>
    227 <span class="add">+{</span>
    228 <span class="add">+    /* bang - we have so much memory */</span>
    229 <span class="add">+    struct item *it;</span>
    230 <span class="add">+    struct item **fuzzymatches = NULL;</span>
    231 <span class="add">+    char c;</span>
    232 <span class="add">+    int number_of_matches = 0, i, pidx, sidx, eidx;</span>
    233 <span class="add">+    int text_len = strlen(text), itext_len;</span>
    234 <span class="add">+</span>
    235 <span class="add">+    matches = matchend = NULL;</span>
    236 <span class="add">+</span>
    237 <span class="add">+    /* walk through all items */</span>
    238 <span class="add">+    for (it = items; it &amp;&amp; it-&gt;text; ++it) {</span>
    239 <span class="add">+        if (text_len) {</span>
    240 <span class="add">+            itext_len = strlen(it-&gt;text);</span>
    241 <span class="add">+            pidx = 0; /* pointer */</span>
    242 <span class="add">+            sidx = eidx = -1; /* start of match, end of match */</span>
    243 <span class="add">+            /* walk through item text */</span>
    244 <span class="add">+            for (i = 0; i &lt; itext_len &amp;&amp; (c = it-&gt;text[i]); ++i) {</span>
    245 <span class="add">+                /* fuzzy match pattern */</span>
    246 <span class="add">+                if (!fstrncmp(&amp;text[pidx], &amp;c, 1)) {</span>
    247 <span class="add">+                    if(sidx == -1)</span>
    248 <span class="add">+                        sidx = i;</span>
    249 <span class="add">+                    ++pidx;</span>
    250 <span class="add">+                    if (pidx == text_len) {</span>
    251 <span class="add">+                        eidx = i;</span>
    252 <span class="add">+                        break;</span>
    253 <span class="add">+                    }</span>
    254 <span class="add">+                }</span>
    255 <span class="add">+            }</span>
    256 <span class="add">+            /* build list of matches */</span>
    257 <span class="add">+            if (eidx != -1) {</span>
    258 <span class="add">+                /* compute distance */</span>
    259 <span class="add">+                /* add penalty if match starts late (log(sidx+2))</span>
    260 <span class="add">+                 * add penalty for long a match without many matching characters */</span>
    261 <span class="add">+                it-&gt;distance = log(sidx + 2) + (double)(eidx - sidx - text_len);</span>
    262 <span class="add">+                /* fprintf(stderr, "distance %s %f\n", it-&gt;text, it-&gt;distance); */</span>
    263 <span class="add">+                appenditem(it, &amp;matches, &amp;matchend);</span>
    264 <span class="add">+                ++number_of_matches;</span>
    265 <span class="add">+            }</span>
    266 <span class="add">+        } else {</span>
    267 <span class="add">+            appenditem(it, &amp;matches, &amp;matchend);</span>
    268 <span class="add">+        }</span>
    269 <span class="add">+    }</span>
    270 <span class="add">+</span>
    271 <span class="add">+    if (number_of_matches) {</span>
    272 <span class="add">+        /* initialize array with matches */</span>
    273 <span class="add">+        if (!(fuzzymatches = realloc(fuzzymatches,</span>
    274 <span class="add">+                                     number_of_matches * sizeof(struct item *))))</span>
    275 <span class="add">+            die("cannot realloc %u bytes:", number_of_matches * sizeof(struct item *));</span>
    276 <span class="add">+        for (i = 0, it = matches; it &amp;&amp; i &lt; number_of_matches; ++i, it = it-&gt;right)</span>
    277 <span class="add">+            fuzzymatches[i] = it;</span>
    278 <span class="add">+        /* sort matches according to distance */</span>
    279 <span class="add">+        qsort(fuzzymatches, number_of_matches, sizeof(struct item*), compare_distance);</span>
    280 <span class="add">+        /* rebuild list of matches */</span>
    281 <span class="add">+        matches = matchend = NULL;</span>
    282 <span class="add">+        for (i = 0, it = fuzzymatches[i]; i &lt; number_of_matches &amp;&amp; it &amp;&amp;</span>
    283 <span class="add">+                it-&gt;text; ++i, it = fuzzymatches[i])</span>
    284 <span class="add">+            appenditem(it, &amp;matches, &amp;matchend);</span>
    285 <span class="add">+        free(fuzzymatches);</span>
    286 <span class="add">+    }</span>
    287 <span class="add">+    curr = sel = matches;</span>
    288 <span class="add">+    calcoffsets();</span>
    289 <span class="add">+}</span>
    290 <span class="add">+</span>
    291  static void
    292  match(void)
    293  {
    294 <span class="add">+    if (fuzzy) {</span>
    295 <span class="add">+        fuzzymatch();</span>
    296 <span class="add">+        return;</span>
    297 <span class="add">+    }</span>
    298      static char **tokv = NULL;
    299      static int tokn = 0;
    300  
    301 <span class="hunk">@@ -715,7 +801,7 @@ setup(void)</span>
    302  static void
    303  usage(void)
    304  {
    305 <span class="del">-    die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"</span>
    306 <span class="add">+    die("usage: dmenu [-bFfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"</span>
    307          "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]");
    308  }
    309  
    310 <span class="hunk">@@ -732,6 +818,8 @@ main(int argc, char *argv[])</span>
    311              exit(0);
    312          } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */
    313              topbar = 0;
    314 <span class="add">+        else if (!strcmp(argv[i], "-F"))   /* disables fuzzy matching */</span>
    315 <span class="add">+            fuzzy = 0;</span>
    316          else if (!strcmp(argv[i], "-f"))   /* grabs keyboard before reading stdin */
    317              fast = 1;
    318          else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */</code></pre>
    319 </li>
    320 </ol>
    321 </body>
    322 </html>