static-httpd

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit d0eff3842a231f52840bcd8f5e14c8d4e89dd5f5
parent 47704a7f2321fe1fd35f856183196f0dc7a70e17
Author: fjbalon <fjbalon@templier.es>
Date:   Thu, 25 Jun 2026 16:18:15 +0200

Añadido artículo sobre dmenu

Diffstat:
Admenu/index.html | 330+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mindex.html | 5+++++
2 files changed, 335 insertions(+), 0 deletions(-)

diff --git a/dmenu/index.html b/dmenu/index.html @@ -0,0 +1,330 @@ +<!DOCTYPE html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<meta name="viewport" content="width=device-width, initial-scale=1" /> +<title>Configuración propia del lanzador de aplicación dmenu</title> +<link rel="icon" type="image/png" href="/favicon.png" /> +<link rel="stylesheet" type="text/css" href="../article.css" /> +</head> +<body> +<header> +<p class="title">Configuración propia del lanzador de aplicación dmenu</p> +<p class="date">25 de junio de 2026 • fjbalon</p> +</header> +<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> +<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> +<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> +<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> + +<style> + .diff .add {color:#00ff9d;} + .diff .del {color:#ff5f5f;} + .diff .header {color:#569cd6;} + .diff .hunk {color:#d7ba7d;} + .diff .info {color:#848484;} +</style> + +<ol> +<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: +<pre><code class="diff"><span class="info">diff --git a/dmenu.c b/dmenu.c</span> +<span class="hunk">@@ -54,8 +54,9 @@ static Clr *scheme[SchemeLast];</span> + + #include "config.h" + +<span class="del">-static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;</span> +<span class="del">-static char *(*fstrstr)(const char *, const char *) = strstr;</span> +<span class="add">+static char * cistrstr(const char *s, const char *sub);</span> +<span class="add">+static int (*fstrncmp)(const char *, const char *, size_t) = strncasecmp;</span> +<span class="add">+static char *(*fstrstr)(const char *, const char *) = cistrstr;</span> + + static unsigned int + textw_clamp(const char *str, unsigned int n) +<span class="hunk">@@ -733,9 +734,9 @@ main(int argc, char *argv[])</span> + topbar = 0; + else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ + fast = 1; +<span class="del">- else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */</span> +<span class="del">- fstrncmp = strncasecmp;</span> +<span class="del">- fstrstr = cistrstr;</span> +<span class="add">+ else if (!strcmp(argv[i], "-s")) { /* case-sensitive item matching */</span> +<span class="add">+ fstrncmp = strncmp;</span> +<span class="add">+ fstrstr = strstr;</span> + } else if (i + 1 == argc) + usage(); + /* these options take one argument */</code></pre> +</li> +<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. +<pre><code class="diff"><span class="info">diff --git a/config.h b/config.h</span> +<span class="info">index 1edb647..64eab2a 100644</span> +<span class="info">--- a/config.h</span> +<span class="info">+++ b/config.h</span> +<span class="hunk">@@ -11,6 +11,8 @@ static const char *colors[SchemeLast][2] = {</span> + /* fg bg */ + [SchemeNorm] = { "#bbbbbb", "#222222" }, + [SchemeSel] = { "#eeeeee", "#005577" }, +<span class="add">+ [SchemeSelHighlight] = { "#ffc978", "#005577" },</span> +<span class="add">+ [SchemeNormHighlight] = { "#ffc978", "#222222" },</span> + [SchemeOut] = { "#000000", "#00ffff" }, + }; + /* -l option; if nonzero, dmenu uses vertical list with given number of lines */ +<span class="info">diff --git a/dmenu.c b/dmenu.c</span> +<span class="info">index 40f93e0..662131a 100644</span> +<span class="info">--- a/dmenu.c</span> +<span class="info">+++ b/dmenu.c</span> +<span class="hunk">@@ -25,7 +25,9 @@</span> + #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + + /* enums */ +<span class="del">-enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */</span> +<span class="add">+enum { SchemeNorm, SchemeSel, SchemeNormHighlight, SchemeSelHighlight,</span> +<span class="add">+ SchemeOut, SchemeLast }; /* color schemes */</span> +<span class="add">+</span> + + struct item { + char *text; +<span class="hunk">@@ -129,9 +131,47 @@ cistrstr(const char *h, const char *n)</span> + return NULL; + } + +<span class="add">+static void</span> +<span class="add">+drawhighlights(struct item *item, int x, int y, int maxw)</span> +<span class="add">+{</span> +<span class="add">+ int i, indent;</span> +<span class="add">+ char c, *highlight;</span> +<span class="add">+</span> +<span class="add">+ if (!(strlen(item-&gt;text) &amp;&amp; strlen(text)))</span> +<span class="add">+ return;</span> +<span class="add">+</span> +<span class="add">+ drw_setscheme(drw, scheme[item == sel</span> +<span class="add">+ ? SchemeSelHighlight</span> +<span class="add">+ : SchemeNormHighlight]);</span> +<span class="add">+ for (i = 0, highlight = item-&gt;text; *highlight &amp;&amp; text[i];) {</span> +<span class="add">+ if (!fstrncmp(highlight, &amp;text[i], 1)) {</span> +<span class="add">+ /* get indentation */</span> +<span class="add">+ c = *highlight;</span> +<span class="add">+ *highlight = '\0';</span> +<span class="add">+ indent = TEXTW(item-&gt;text);</span> +<span class="add">+ *highlight = c;</span> +<span class="add">+</span> +<span class="add">+ /* highlight character */</span> +<span class="add">+ c = highlight[1];</span> +<span class="add">+ highlight[1] = '\0';</span> +<span class="add">+ drw_text(</span> +<span class="add">+ drw,</span> +<span class="add">+ x + indent - (lrpad / 2.),</span> +<span class="add">+ y,</span> +<span class="add">+ MIN(maxw - indent, TEXTW(highlight) - lrpad),</span> +<span class="add">+ bh, 0, highlight, 0</span> +<span class="add">+ );</span> +<span class="add">+ highlight[1] = c;</span> +<span class="add">+ ++i;</span> +<span class="add">+ }</span> +<span class="add">+ ++highlight;</span> +<span class="add">+ }</span> +<span class="add">+}</span> +<span class="add">+</span> + static int + drawitem(struct item *item, int x, int y, int w) + { +<span class="add">+ int r;</span> + if (item == sel) + drw_setscheme(drw, scheme[SchemeSel]); + else if (item-&gt;out) +<span class="hunk">@@ -139,7 +179,9 @@ drawitem(struct item *item, int x, int y, int w)</span> + else + drw_setscheme(drw, scheme[SchemeNorm]); + +<span class="del">- return drw_text(drw, x, y, w, bh, lrpad / 2, item-&gt;text, 0);</span> +<span class="add">+ r = drw_text(drw, x, y, w, bh, lrpad / 2, item-&gt;text, 0);</span> +<span class="add">+ drawhighlights(item, x, y, w);</span> +<span class="add">+ return r;</span> + } + + static void +<span class="hunk">@@ -716,7 +758,8 @@ static void</span> + usage(void) + { + die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" +<span class="del">- " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]");</span> +<span class="add">+ " [-nb color] [-nf color] [-sb color] [-sf color]\n"</span> +<span class="add">+ " [-nhb color] [-nhf color] [-shb color] [-shf color] [-w windowid]");</span> + } + + int +<span class="hunk">@@ -756,6 +799,14 @@ main(int argc, char *argv[])</span> + colors[SchemeSel][ColBg] = argv[++i]; + else if (!strcmp(argv[i], "-sf")) /* selected foreground color */ + colors[SchemeSel][ColFg] = argv[++i]; +<span class="add">+ else if (!strcmp(argv[i], "-nhb")) /* normal hi background color */</span> +<span class="add">+ colors[SchemeNormHighlight][ColBg] = argv[++i];</span> +<span class="add">+ else if (!strcmp(argv[i], "-nhf")) /* normal hi foreground color */</span> +<span class="add">+ colors[SchemeNormHighlight][ColFg] = argv[++i];</span> +<span class="add">+ else if (!strcmp(argv[i], "-shb")) /* selected hi background color */</span> +<span class="add">+ colors[SchemeSelHighlight][ColBg] = argv[++i];</span> +<span class="add">+ else if (!strcmp(argv[i], "-shf")) /* selected hi foreground color */</span> +<span class="add">+ colors[SchemeSelHighlight][ColFg] = argv[++i];</span> + else if (!strcmp(argv[i], "-w")) /* embedding window id */ + embed = argv[++i]; + else</code></pre> +<pre><code class="diff"><span class="info">diff --git a/config.h b/config.h</span> +<span class="info">index 1edb647..a4e6174 100644</span> +<span class="info">--- a/config.h</span> +<span class="info">+++ b/config.h</span> +<span class="hunk">@@ -2,6 +2,7 @@</span> + /* Default settings; can be overriden by command line. */ + + static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ +<span class="add">+static int fuzzy = 1; /* -F option; if 0, dmenu doesn't use fuzzy matching */</span> + /* -fn option overrides fonts[0]; default X11 font or font set */ + static const char *fonts[] = { + "monospace:size=10" +<span class="info">diff --git a/config.mk b/config.mk</span> +<span class="info">index 137f7c8..6a19175 100644</span> +<span class="info">--- a/config.mk</span> +<span class="info">+++ b/config.mk</span> +<span class="hunk">@@ -21,7 +21,7 @@ FREETYPEINC = /usr/include/freetype2</span> + + # includes and libs + INCS = -I$(X11INC) -I$(FREETYPEINC) +<span class="del">-LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS)</span> +<span class="add">+LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm</span> + + # flags + CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) +<span class="info">diff --git a/dmenu.c b/dmenu.c</span> +<span class="info">index 40f93e0..03e1f45 100644</span> +<span class="info">--- a/dmenu.c</span> +<span class="info">+++ b/dmenu.c</span> +<span class="hunk">@@ -1,6 +1,7 @@</span> + /* See LICENSE file for copyright and license details. */ + #include &lt;ctype.h&gt; + #include &lt;locale.h&gt; +<span class="add">+#include &lt;math.h&gt;</span> + #include &lt;stdio.h&gt; + #include &lt;stdlib.h&gt; + #include &lt;string.h&gt; +<span class="hunk">@@ -31,6 +32,7 @@ struct item {</span> + char *text; + struct item *left, *right; + int out; +<span class="add">+ double distance;</span> + }; + + static char text[BUFSIZ] = ""; +<span class="hunk">@@ -226,9 +228,93 @@ grabkeyboard(void)</span> + die("cannot grab keyboard"); + } + +<span class="add">+int</span> +<span class="add">+compare_distance(const void *a, const void *b)</span> +<span class="add">+{</span> +<span class="add">+ struct item *da = *(struct item **) a;</span> +<span class="add">+ struct item *db = *(struct item **) b;</span> +<span class="add">+</span> +<span class="add">+ if (!db)</span> +<span class="add">+ return 1;</span> +<span class="add">+ if (!da)</span> +<span class="add">+ return -1;</span> +<span class="add">+</span> +<span class="add">+ return da-&gt;distance == db-&gt;distance ? 0 : da-&gt;distance &lt; db-&gt;distance ? -1 : 1;</span> +<span class="add">+}</span> +<span class="add">+</span> +<span class="add">+void</span> +<span class="add">+fuzzymatch(void)</span> +<span class="add">+{</span> +<span class="add">+ /* bang - we have so much memory */</span> +<span class="add">+ struct item *it;</span> +<span class="add">+ struct item **fuzzymatches = NULL;</span> +<span class="add">+ char c;</span> +<span class="add">+ int number_of_matches = 0, i, pidx, sidx, eidx;</span> +<span class="add">+ int text_len = strlen(text), itext_len;</span> +<span class="add">+</span> +<span class="add">+ matches = matchend = NULL;</span> +<span class="add">+</span> +<span class="add">+ /* walk through all items */</span> +<span class="add">+ for (it = items; it &amp;&amp; it-&gt;text; ++it) {</span> +<span class="add">+ if (text_len) {</span> +<span class="add">+ itext_len = strlen(it-&gt;text);</span> +<span class="add">+ pidx = 0; /* pointer */</span> +<span class="add">+ sidx = eidx = -1; /* start of match, end of match */</span> +<span class="add">+ /* walk through item text */</span> +<span class="add">+ for (i = 0; i &lt; itext_len &amp;&amp; (c = it-&gt;text[i]); ++i) {</span> +<span class="add">+ /* fuzzy match pattern */</span> +<span class="add">+ if (!fstrncmp(&amp;text[pidx], &amp;c, 1)) {</span> +<span class="add">+ if(sidx == -1)</span> +<span class="add">+ sidx = i;</span> +<span class="add">+ ++pidx;</span> +<span class="add">+ if (pidx == text_len) {</span> +<span class="add">+ eidx = i;</span> +<span class="add">+ break;</span> +<span class="add">+ }</span> +<span class="add">+ }</span> +<span class="add">+ }</span> +<span class="add">+ /* build list of matches */</span> +<span class="add">+ if (eidx != -1) {</span> +<span class="add">+ /* compute distance */</span> +<span class="add">+ /* add penalty if match starts late (log(sidx+2))</span> +<span class="add">+ * add penalty for long a match without many matching characters */</span> +<span class="add">+ it-&gt;distance = log(sidx + 2) + (double)(eidx - sidx - text_len);</span> +<span class="add">+ /* fprintf(stderr, "distance %s %f\n", it-&gt;text, it-&gt;distance); */</span> +<span class="add">+ appenditem(it, &amp;matches, &amp;matchend);</span> +<span class="add">+ ++number_of_matches;</span> +<span class="add">+ }</span> +<span class="add">+ } else {</span> +<span class="add">+ appenditem(it, &amp;matches, &amp;matchend);</span> +<span class="add">+ }</span> +<span class="add">+ }</span> +<span class="add">+</span> +<span class="add">+ if (number_of_matches) {</span> +<span class="add">+ /* initialize array with matches */</span> +<span class="add">+ if (!(fuzzymatches = realloc(fuzzymatches,</span> +<span class="add">+ number_of_matches * sizeof(struct item *))))</span> +<span class="add">+ die("cannot realloc %u bytes:", number_of_matches * sizeof(struct item *));</span> +<span class="add">+ for (i = 0, it = matches; it &amp;&amp; i &lt; number_of_matches; ++i, it = it-&gt;right)</span> +<span class="add">+ fuzzymatches[i] = it;</span> +<span class="add">+ /* sort matches according to distance */</span> +<span class="add">+ qsort(fuzzymatches, number_of_matches, sizeof(struct item*), compare_distance);</span> +<span class="add">+ /* rebuild list of matches */</span> +<span class="add">+ matches = matchend = NULL;</span> +<span class="add">+ for (i = 0, it = fuzzymatches[i]; i &lt; number_of_matches &amp;&amp; it &amp;&amp;</span> +<span class="add">+ it-&gt;text; ++i, it = fuzzymatches[i])</span> +<span class="add">+ appenditem(it, &amp;matches, &amp;matchend);</span> +<span class="add">+ free(fuzzymatches);</span> +<span class="add">+ }</span> +<span class="add">+ curr = sel = matches;</span> +<span class="add">+ calcoffsets();</span> +<span class="add">+}</span> +<span class="add">+</span> + static void + match(void) + { +<span class="add">+ if (fuzzy) {</span> +<span class="add">+ fuzzymatch();</span> +<span class="add">+ return;</span> +<span class="add">+ }</span> + static char **tokv = NULL; + static int tokn = 0; + +<span class="hunk">@@ -715,7 +801,7 @@ setup(void)</span> + static void + usage(void) + { +<span class="del">- die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"</span> +<span class="add">+ die("usage: dmenu [-bFfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"</span> + " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]"); + } + +<span class="hunk">@@ -732,6 +818,8 @@ main(int argc, char *argv[])</span> + exit(0); + } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */ + topbar = 0; +<span class="add">+ else if (!strcmp(argv[i], "-F")) /* disables fuzzy matching */</span> +<span class="add">+ fuzzy = 0;</span> + else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ + fast = 1; + else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */</code></pre> +</li> +</ol> +</body> +</html> diff --git a/index.html b/index.html @@ -19,6 +19,11 @@ <hr/> <section class="blog"> +<a href="./dmenu/" class="article"> + <p class="title">Configuración propia del lanzador de aplicación dmenu</p> + <p class="info">25 de junio de 2026 · fjbalon</p><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 ...</p> +</a> + <a href="./slock/" class="article"> <p class="title">Configuración propia del bloqueador de pantalla slock</p> <p class="info">22 de junio de 2026 · fjbalon</p><p>Un software que me gusta bastante de la caja de herramientas de suckless es slock, un bloqueador de pantalla minimalista; tan minimalista que yo creo que es el bloqueador de pantalla x más sencillo q...</p>