feat: installed patches

This commit is contained in:
Ryan Kes 2020-11-28 11:14:26 +01:00
parent 0e531bb769
commit 5f8d30520c
14 changed files with 815 additions and 57 deletions

View file

@ -1,22 +0,0 @@
The MIT License (MIT)
=====================
Copyright © `2019` `Ryan Kes <alrayyes at gmail dot com>`
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

22
LICENSE.org Normal file
View file

@ -0,0 +1,22 @@
* The MIT License (MIT)
Copyright © =<2020>= =<Ryan Kes>=
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,4 +1,4 @@
# Maintainer: Ryan Kes <alrayyes@gmail.com> # Maintainer: Ryan Kes <ryan@ryankes.eu>
pkgname=dmenu pkgname=dmenu
pkgver=5.0 pkgver=5.0
@ -10,10 +10,23 @@ license=('MIT')
depends=('sh' 'libxinerama' 'libxft' 'freetype2' 'menu-calc' 'pass' 'yubikey-oath-dmenu' 'otf-nerd-fonts-fira-code') depends=('sh' 'libxinerama' 'libxft' 'freetype2' 'menu-calc' 'pass' 'yubikey-oath-dmenu' 'otf-nerd-fonts-fira-code')
sha512sums=('2b6a7cdf5aefc5e7ca7a4944883c3c16ee6f5005d2a96b61482d4899ad395f9cb8926907681d88b9df3e1188cf421dad4cc17e343b752f6cb8b161d33384b3f3' sha512sums=('2b6a7cdf5aefc5e7ca7a4944883c3c16ee6f5005d2a96b61482d4899ad395f9cb8926907681d88b9df3e1188cf421dad4cc17e343b752f6cb8b161d33384b3f3'
'e2aefad0eb1d7abd31ed359d62687096b1657bb47bae963ff7626c7b0f5da40ce3dccc154234f9f785e02d518fde9dc4843f8a02030a393c5e0188066ff459e5' '2597b08c19aa0c0dede048b2ce27b2d0c1f11ffcaefa431aca256d7a8821b453d383e88ef34ca10cebb7b5d8118953b38e2dfb2ced417d1a394fe8df67779d0c'
'ad8183cca1ad1dd5b786896f94d127eeea53cece291c485f928388a7589402f49ed7e0ee8bdae71cc2ed41f3276b96591349cd820621f345376a54d557307fdf') 'ad8183cca1ad1dd5b786896f94d127eeea53cece291c485f928388a7589402f49ed7e0ee8bdae71cc2ed41f3276b96591349cd820621f345376a54d557307fdf'
'beed0f7725d84b4d73cb35fb7d78d7db90c7fa15ed0ac4d6cf19e6469caf83167bc3edae246c30a2f0a79e765b46d9a37997a9a72f5dec147cc0a904fa2ef790'
'ce806c6481b20d5b2352fc387816878c75285162f6404b3a969a95f9dbd6c7476fd4c6571f260886fa30ccc40e4a388ea8f6902e40ff90447e04bec3faf0669d'
'6ce4ce0ddb9c1058f253ce46cdae8949c468d97ce7d787831d8a4f4ebd4db672761e2552703f58d36d01b2933dea624a30627629027b9a5960b404542a40a732'
'dd46c1ac2ea8d5ffc29c01ec83ef7dc771d50475252a5723495a4969e5315e29ce059c2ee4f82f6c8b75d12868e27b3d9dfe74f9825ab86ac7a407902b29a2ab'
'e6ff377a4a4ed9e98d05a8870d6c57a5f89f853b0ec1160c3702642f899d8079eca595775b3d9f436bd67626fd4df659e511faa6d026130b07eef09a7c0c8b85'
'15d88ea4f10c2fa6fb3eb7478f23b24210a0da3542ae7a5be609013500c15564eedd8153d850f079c2c1f4bab1f5e61ff51153e4c85445ee04a0de5c851e305a')
_patches=() _patches=(
"dmenu-border-4.9.diff"
"dmenu-fuzzyhighlight-4.9.diff"
"dmenu-fuzzymatch-4.9.diff"
"local-dmenu-morecolor-20190922-4bf895b.diff"
"local-dmenu-mousesupport-5.0.diff"
"dmenu-numbers-4.9.diff"
)
source=(https://dl.suckless.org/tools/dmenu-${pkgver}.tar.gz source=(https://dl.suckless.org/tools/dmenu-${pkgver}.tar.gz
config.h config.h

View file

@ -1,13 +0,0 @@
# My Dmenu Build
[Dmenu](https://tools.suckless.org/dmenu) [Arch](https://www.archlinux.org/) package with a few patches installed to keep things nice.
```
makepkg -si
```
## License
This theme is released under the MIT License. For more information read the [license][license].
[license]: https://github.com/alrayyes/dmenu/blob/master/LICENSE.md

24
README.org Normal file
View file

@ -0,0 +1,24 @@
* Description
[[https://tools.suckless.org/dmenu/][Dmenu]] Arch package with a few patches installed to keep things nice:
- [[https://tools.suckless.org/dmenu/patches/border/][border]]
- [[https://tools.suckless.org/dmenu/patches/center/][center]]
- [[https://tools.suckless.org/dmenu/patches/fuzzyhighlight/][fuzzyhighlight]]
- [[https://tools.suckless.org/dmenu/patches/fuzzymatch/][fuzzymatch]]
- [[https://tools.suckless.org/dmenu/patches/morecolor/][morecolor]]
- [[https://tools.suckless.org/dmenu/patches/mouse-support/][mousesupport]]
- [[https://tools.suckless.org/dmenu/patches/numbers/][numbers]]
* Install
#+begin_src shell
makepkg -si
#+end_src
- Default font is
[[https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/FiraCode][Fira Code Nerd Font Mono]]
- When modifying [[https://github.com/alrayyes/dwm/blob/master/config.h][config.h]] be sure to run =updpkgsums= to update checksums before
running =makepkg -si=
* License
This theme is released under the MIT License. For more information read
the [[file:LICENSE.org][license]].

View file

@ -2,16 +2,23 @@
/* Default settings; can be overriden by command line. */ /* Default settings; can be overriden by command line. */
static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
static int min_width = 500; /* minimum width when centered */
static int fuzzy = 1; /* -F option; if 0, dmenu doesn't use fuzzy matching */
/* -fn option overrides fonts[0]; default X11 font or font set */ /* -fn option overrides fonts[0]; default X11 font or font set */
static const char *fonts[] = { static const char *fonts[] = {
"FuraCode Nerd Font Mono:style=Regular:pixelsize=18:antialias=true:autohint=true" "FuraCode Nerd Font "
}; "Mono:style=Regular:pixelsize=18:antialias=true:autohint=true"};
static const char *prompt = NULL; /* -p option; prompt to the left of input field */ static const char *prompt =
NULL; /* -p option; prompt to the left of input field */
static const char *colors[SchemeLast][2] = { static const char *colors[SchemeLast][2] = {
/* fg bg */ /* fg bg */
[SchemeNorm] = {"#bbbbbb", "#222222"}, [SchemeNorm] = {"#bbbbbb", "#222222"},
[SchemeSel] = {"#eeeeee", "#005577"}, [SchemeSel] = {"#eeeeee", "#005577"},
[SchemeSelHighlight] = {"#ffc978", "#005577"},
[SchemeNormHighlight] = {"#ffc978", "#222222"},
[SchemeOut] = {"#000000", "#00ffff"}, [SchemeOut] = {"#000000", "#00ffff"},
[SchemeMid] = {"#eeeeee", "#770000"},
}; };
/* -l option; if nonzero, dmenu uses vertical list with given number of lines */ /* -l option; if nonzero, dmenu uses vertical list with given number of lines */
static unsigned int lines = 0; static unsigned int lines = 0;
@ -21,3 +28,6 @@ static unsigned int lines = 0;
* for example: " /?\"&[]" * for example: " /?\"&[]"
*/ */
static const char worddelimiters[] = " "; static const char worddelimiters[] = " ";
/* Size of the window border */
static unsigned int border_width = 0;

View file

@ -2,16 +2,23 @@
/* Default settings; can be overriden by command line. */ /* Default settings; can be overriden by command line. */
static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
static int min_width = 500; /* minimum width when centered */
static int fuzzy = 1; /* -F option; if 0, dmenu doesn't use fuzzy matching */
/* -fn option overrides fonts[0]; default X11 font or font set */ /* -fn option overrides fonts[0]; default X11 font or font set */
static const char *fonts[] = { static const char *fonts[] = {
"FuraCode Nerd Font Mono:style=Regular:pixelsize=18:antialias=true:autohint=true" "FuraCode Nerd Font "
}; "Mono:style=Regular:pixelsize=18:antialias=true:autohint=true"};
static const char *prompt = NULL; /* -p option; prompt to the left of input field */ static const char *prompt =
NULL; /* -p option; prompt to the left of input field */
static const char *colors[SchemeLast][2] = { static const char *colors[SchemeLast][2] = {
/* fg bg */ /* fg bg */
[SchemeNorm] = {"#bbbbbb", "#222222"}, [SchemeNorm] = {"#bbbbbb", "#222222"},
[SchemeSel] = {"#eeeeee", "#005577"}, [SchemeSel] = {"#eeeeee", "#005577"},
[SchemeSelHighlight] = {"#ffc978", "#005577"},
[SchemeNormHighlight] = {"#ffc978", "#222222"},
[SchemeOut] = {"#000000", "#00ffff"}, [SchemeOut] = {"#000000", "#00ffff"},
[SchemeMid] = {"#eeeeee", "#770000"},
}; };
/* -l option; if nonzero, dmenu uses vertical list with given number of lines */ /* -l option; if nonzero, dmenu uses vertical list with given number of lines */
static unsigned int lines = 0; static unsigned int lines = 0;
@ -21,3 +28,6 @@ static unsigned int lines = 0;
* for example: " /?\"&[]" * for example: " /?\"&[]"
*/ */
static const char worddelimiters[] = " "; static const char worddelimiters[] = " ";
/* Size of the window border */
static unsigned int border_width = 0;

25
dmenu-border-4.9.diff Normal file
View file

@ -0,0 +1,25 @@
diff -up dmenu-4.9-b/config.def.h dmenu-4.9-a/config.def.h
--- dmenu-4.9-b/config.def.h 2019-02-02 13:55:02.000000000 +0100
+++ dmenu-4.9-a/config.def.h 2019-05-19 02:10:12.740040403 +0200
@@ -21,3 +21,6 @@ static unsigned int lines = 0;
* for example: " /?\"&[]"
*/
static const char worddelimiters[] = " ";
+
+/* Size of the window border */
+static const unsigned int border_width = 5;
diff -up dmenu-4.9-b/dmenu.c dmenu-4.9-a/dmenu.c
--- dmenu-4.9-b/dmenu.c 2019-02-02 13:55:02.000000000 +0100
+++ dmenu-4.9-a/dmenu.c 2019-05-19 02:11:20.966710117 +0200
@@ -654,9 +654,10 @@ setup(void)
swa.override_redirect = True;
swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
- win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0,
+ win = XCreateWindow(dpy, parentwin, x, y, mw, mh, border_width,
CopyFromParent, CopyFromParent, CopyFromParent,
CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
+ XSetWindowBorder(dpy, win, scheme[SchemeSel][ColBg].pixel);
XSetClassHint(dpy, win, &ch);
/* open input methods */

View file

@ -0,0 +1,120 @@
From 8cd37e1ab9e7cb025224aeb3543f1a5be8bceb93 Mon Sep 17 00:00:00 2001
From: Nihal Jere <nihal@nihaljere.xyz>
Date: Sat, 11 Jan 2020 21:16:08 -0600
Subject: [PATCH] center patch now has adjustable minimum width
---
config.def.h | 2 ++
dmenu.1 | 3 +++
dmenu.c | 39 ++++++++++++++++++++++++++++++++-------
3 files changed, 37 insertions(+), 7 deletions(-)
diff --git a/config.def.h b/config.def.h
index 1edb647..88ef264 100644
--- a/config.def.h
+++ b/config.def.h
@@ -2,6 +2,8 @@
/* Default settings; can be overriden by command line. */
static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
+static int centered = 0; /* -c option; centers dmenu on screen */
+static int min_width = 500; /* minimum width when centered */
/* -fn option overrides fonts[0]; default X11 font or font set */
static const char *fonts[] = {
"monospace:size=10"
diff --git a/dmenu.1 b/dmenu.1
index 323f93c..c036baa 100644
--- a/dmenu.1
+++ b/dmenu.1
@@ -40,6 +40,9 @@ which lists programs in the user's $PATH and runs the result in their $SHELL.
.B \-b
dmenu appears at the bottom of the screen.
.TP
+.B \-c
+dmenu appears centered on the screen.
+.TP
.B \-f
dmenu grabs the keyboard before reading stdin if not reading from a tty. This
is faster, but will lock up X until stdin reaches end\-of\-file.
diff --git a/dmenu.c b/dmenu.c
index 65f25ce..041c7f8 100644
--- a/dmenu.c
+++ b/dmenu.c
@@ -89,6 +89,15 @@ calcoffsets(void)
break;
}
+static int
+max_textw(void)
+{
+ int len = 0;
+ for (struct item *item = items; item && item->text; item++)
+ len = MAX(TEXTW(item->text), len);
+ return len;
+}
+
static void
cleanup(void)
{
@@ -611,6 +620,7 @@ setup(void)
bh = drw->fonts->h + 2;
lines = MAX(lines, 0);
mh = (lines + 1) * bh;
+ promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
#ifdef XINERAMA
i = 0;
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
@@ -637,9 +647,16 @@ setup(void)
if (INTERSECT(x, y, 1, 1, info[i]))
break;
- x = info[i].x_org;
- y = info[i].y_org + (topbar ? 0 : info[i].height - mh);
- mw = info[i].width;
+ if (centered) {
+ mw = MIN(MAX(max_textw() + promptw, min_width), info[i].width);
+ x = info[i].x_org + ((info[i].width - mw) / 2);
+ y = info[i].y_org + ((info[i].height - mh) / 2);
+ } else {
+ x = info[i].x_org;
+ y = info[i].y_org + (topbar ? 0 : info[i].height - mh);
+ mw = info[i].width;
+ }
+
XFree(info);
} else
#endif
@@ -647,11 +664,17 @@ setup(void)
if (!XGetWindowAttributes(dpy, parentwin, &wa))
die("could not get embedding window attributes: 0x%lx",
parentwin);
- x = 0;
- y = topbar ? 0 : wa.height - mh;
- mw = wa.width;
+
+ if (centered) {
+ mw = MIN(MAX(max_textw() + promptw, min_width), wa.width);
+ x = (wa.width - mw) / 2;
+ y = (wa.height - mh) / 2;
+ } else {
+ x = 0;
+ y = topbar ? 0 : wa.height - mh;
+ mw = wa.width;
+ }
}
- promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
inputw = MIN(inputw, mw/3);
match();
@@ -709,6 +732,8 @@ main(int argc, char *argv[])
topbar = 0;
else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */
fast = 1;
+ else if (!strcmp(argv[i], "-c")) /* centers dmenu on screen */
+ centered = 1;
else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
fstrncmp = strncasecmp;
fstrstr = cistrstr;
--
2.24.1

View file

@ -0,0 +1,152 @@
Author: Chris Noxz <chris@noxz.tech>
note: This patch is meant to be used together with fuzzymatch
diff -upN dmenu-4.9/config.def.h dmenu-4.9-fuzzyhighlight/config.def.h
--- dmenu-4.9/config.def.h 2019-02-02 13:55:02.000000000 +0100
+++ dmenu-4.9-fuzzyhighlight/config.def.h 2020-04-04 10:26:36.990890854 +0200
@@ -11,6 +11,8 @@ static const char *colors[SchemeLast][2]
/* fg bg */
[SchemeNorm] = { "#bbbbbb", "#222222" },
[SchemeSel] = { "#eeeeee", "#005577" },
+ [SchemeSelHighlight] = { "#ffc978", "#005577" },
+ [SchemeNormHighlight] = { "#ffc978", "#222222" },
[SchemeOut] = { "#000000", "#00ffff" },
};
/* -l option; if nonzero, dmenu uses vertical list with given number of lines */
diff -upN dmenu-4.9/dmenu.1 dmenu-4.9-fuzzyhighlight/dmenu.1
--- dmenu-4.9/dmenu.1 2019-02-02 13:55:02.000000000 +0100
+++ dmenu-4.9-fuzzyhighlight/dmenu.1 2020-04-04 10:30:16.430054933 +0200
@@ -20,6 +20,14 @@ dmenu \- dynamic menu
.IR color ]
.RB [ \-sf
.IR color ]
+.RB [ \-nhb
+.IR color ]
+.RB [ \-nhf
+.IR color ]
+.RB [ \-shb
+.IR color ]
+.RB [ \-shf
+.IR color ]
.RB [ \-w
.IR windowid ]
.P
@@ -75,6 +83,18 @@ defines the selected background color.
.BI \-sf " color"
defines the selected foreground color.
.TP
+.BI \-nhb " color"
+defines the normal highlight background color.
+.TP
+.BI \-nhf " color"
+defines the normal highlight foreground color.
+.TP
+.BI \-shb " color"
+defines the selected highlight background color.
+.TP
+.BI \-shf " color"
+defines the selected highlight foreground color.
+.TP
.B \-v
prints version information to stdout, then exits.
.TP
diff -upN dmenu-4.9/dmenu.c dmenu-4.9-fuzzyhighlight/dmenu.c
--- dmenu-4.9/dmenu.c 2019-02-02 13:55:02.000000000 +0100
+++ dmenu-4.9-fuzzyhighlight/dmenu.c 2020-04-04 10:27:43.888026309 +0200
@@ -26,7 +26,9 @@
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
/* enums */
-enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */
+enum { SchemeNorm, SchemeSel, SchemeNormHighlight, SchemeSelHighlight,
+ SchemeOut, SchemeLast }; /* color schemes */
+
struct item {
char *text;
@@ -113,9 +115,49 @@ cistrstr(const char *s, const char *sub)
return NULL;
}
+static void
+drawhighlights(struct item *item, int x, int y, int maxw)
+{
+ int i, indent;
+ char *highlight;
+ char c;
+
+ if (!(strlen(item->text) && strlen(text)))
+ return;
+
+ drw_setscheme(drw, scheme[item == sel
+ ? SchemeSelHighlight
+ : SchemeNormHighlight]);
+ for (i = 0, highlight = item->text; *highlight && text[i];) {
+ if (*highlight == text[i]) {
+ /* get indentation */
+ c = *highlight;
+ *highlight = '\0';
+ indent = TEXTW(item->text);
+ *highlight = c;
+
+ /* highlight character */
+ c = highlight[1];
+ highlight[1] = '\0';
+ drw_text(
+ drw,
+ x + indent - (lrpad / 2),
+ y,
+ MIN(maxw - indent, TEXTW(highlight) - lrpad),
+ bh, 0, highlight, 0
+ );
+ highlight[1] = c;
+ i++;
+ }
+ highlight++;
+ }
+}
+
+
static int
drawitem(struct item *item, int x, int y, int w)
{
+ int r;
if (item == sel)
drw_setscheme(drw, scheme[SchemeSel]);
else if (item->out)
@@ -123,7 +165,9 @@ drawitem(struct item *item, int x, int y
else
drw_setscheme(drw, scheme[SchemeNorm]);
- return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0);
+ r = drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0);
+ drawhighlights(item, x, y, w);
+ return r;
}
static void
@@ -683,7 +727,8 @@ static void
usage(void)
{
fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
- " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
+ " [-nb color] [-nf color] [-sb color] [-sf color]\n"
+ " [-nhb color] [-nhf color] [-shb color] [-shf color] [-w windowid]\n", stderr);
exit(1);
}
@@ -724,6 +769,14 @@ main(int argc, char *argv[])
colors[SchemeSel][ColBg] = argv[++i];
else if (!strcmp(argv[i], "-sf")) /* selected foreground color */
colors[SchemeSel][ColFg] = argv[++i];
+ else if (!strcmp(argv[i], "-nhb")) /* normal hi background color */
+ colors[SchemeNormHighlight][ColBg] = argv[++i];
+ else if (!strcmp(argv[i], "-nhf")) /* normal hi foreground color */
+ colors[SchemeNormHighlight][ColFg] = argv[++i];
+ else if (!strcmp(argv[i], "-shb")) /* selected hi background color */
+ colors[SchemeSelHighlight][ColBg] = argv[++i];
+ else if (!strcmp(argv[i], "-shf")) /* selected hi foreground color */
+ colors[SchemeSelHighlight][ColFg] = argv[++i];
else if (!strcmp(argv[i], "-w")) /* embedding window id */
embed = argv[++i];
else

163
dmenu-fuzzymatch-4.9.diff Normal file
View file

@ -0,0 +1,163 @@
From 94353eb52055927d9079f3d9e33da1c954abf386 Mon Sep 17 00:00:00 2001
From: aleks <aleks.stier@icloud.com>
Date: Wed, 26 Jun 2019 13:25:10 +0200
Subject: [PATCH] Add support for fuzzy-matching
---
config.def.h | 1 +
config.mk | 2 +-
dmenu.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 91 insertions(+), 1 deletion(-)
diff --git a/config.def.h b/config.def.h
index 1edb647..51612b9 100644
--- a/config.def.h
+++ b/config.def.h
@@ -2,6 +2,7 @@
/* Default settings; can be overriden by command line. */
static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
+static int fuzzy = 1; /* -F option; if 0, dmenu doesn't use fuzzy matching */
/* -fn option overrides fonts[0]; default X11 font or font set */
static const char *fonts[] = {
"monospace:size=10"
diff --git a/config.mk b/config.mk
index 0929b4a..d14309a 100644
--- a/config.mk
+++ b/config.mk
@@ -20,7 +20,7 @@ FREETYPEINC = /usr/include/freetype2
# includes and libs
INCS = -I$(X11INC) -I$(FREETYPEINC)
-LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS)
+LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm
# flags
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
diff --git a/dmenu.c b/dmenu.c
index 6b8f51b..96ddc98 100644
--- a/dmenu.c
+++ b/dmenu.c
@@ -1,6 +1,7 @@
/* See LICENSE file for copyright and license details. */
#include <ctype.h>
#include <locale.h>
+#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -32,6 +33,7 @@ struct item {
char *text;
struct item *left, *right;
int out;
+ double distance;
};
static char text[BUFSIZ] = "";
@@ -210,9 +212,94 @@ grabkeyboard(void)
die("cannot grab keyboard");
}
+int
+compare_distance(const void *a, const void *b)
+{
+ struct item *da = *(struct item **) a;
+ struct item *db = *(struct item **) b;
+
+ if (!db)
+ return 1;
+ if (!da)
+ return -1;
+
+ return da->distance == db->distance ? 0 : da->distance < db->distance ? -1 : 1;
+}
+
+void
+fuzzymatch(void)
+{
+ /* bang - we have so much memory */
+ struct item *it;
+ struct item **fuzzymatches = NULL;
+ char c;
+ int number_of_matches = 0, i, pidx, sidx, eidx;
+ int text_len = strlen(text), itext_len;
+
+ matches = matchend = NULL;
+
+ /* walk through all items */
+ for (it = items; it && it->text; it++) {
+ if (text_len) {
+ itext_len = strlen(it->text);
+ pidx = 0; /* pointer */
+ sidx = eidx = -1; /* start of match, end of match */
+ /* walk through item text */
+ for (i = 0; i < itext_len && (c = it->text[i]); i++) {
+ /* fuzzy match pattern */
+ if (!fstrncmp(&text[pidx], &c, 1)) {
+ if(sidx == -1)
+ sidx = i;
+ pidx++;
+ if (pidx == text_len) {
+ eidx = i;
+ break;
+ }
+ }
+ }
+ /* build list of matches */
+ if (eidx != -1) {
+ /* compute distance */
+ /* add penalty if match starts late (log(sidx+2))
+ * add penalty for long a match without many matching characters */
+ it->distance = log(sidx + 2) + (double)(eidx - sidx - text_len);
+ /* fprintf(stderr, "distance %s %f\n", it->text, it->distance); */
+ appenditem(it, &matches, &matchend);
+ number_of_matches++;
+ }
+ } else {
+ appenditem(it, &matches, &matchend);
+ }
+ }
+
+ if (number_of_matches) {
+ /* initialize array with matches */
+ if (!(fuzzymatches = realloc(fuzzymatches, number_of_matches * sizeof(struct item*))))
+ die("cannot realloc %u bytes:", number_of_matches * sizeof(struct item*));
+ for (i = 0, it = matches; it && i < number_of_matches; i++, it = it->right) {
+ fuzzymatches[i] = it;
+ }
+ /* sort matches according to distance */
+ qsort(fuzzymatches, number_of_matches, sizeof(struct item*), compare_distance);
+ /* rebuild list of matches */
+ matches = matchend = NULL;
+ for (i = 0, it = fuzzymatches[i]; i < number_of_matches && it && \
+ it->text; i++, it = fuzzymatches[i]) {
+ appenditem(it, &matches, &matchend);
+ }
+ free(fuzzymatches);
+ }
+ curr = sel = matches;
+ calcoffsets();
+}
+
static void
match(void)
{
+ if (fuzzy) {
+ fuzzymatch();
+ return;
+ }
static char **tokv = NULL;
static int tokn = 0;
@@ -702,6 +789,8 @@ main(int argc, char *argv[])
topbar = 0;
else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */
fast = 1;
+ else if (!strcmp(argv[i], "-F")) /* grabs keyboard before reading stdin */
+ fuzzy = 0;
else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
fstrncmp = strncasecmp;
fstrstr = cistrstr;
--
2.22.0

81
dmenu-numbers-4.9.diff Normal file
View file

@ -0,0 +1,81 @@
From 61abc60dbfaa8ec63fcd176307308aee88a19e32 Mon Sep 17 00:00:00 2001
From: Miles Alan <m@milesalan.com>
Date: Sat, 10 Aug 2019 17:20:08 -0500
Subject: [PATCH] Display number of matched and total items in top right corner
---
dmenu.c | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/dmenu.c b/dmenu.c
index 6b8f51b..98c5810 100644
--- a/dmenu.c
+++ b/dmenu.c
@@ -24,6 +24,8 @@
* MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org)))
#define LENGTH(X) (sizeof X / sizeof X[0])
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
+#define NUMBERSMAXDIGITS 100
+#define NUMBERSBUFSIZE (NUMBERSMAXDIGITS * 2) + 1
/* enums */
enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */
@@ -34,6 +36,7 @@ struct item {
int out;
};
+static char numbers[NUMBERSBUFSIZE] = "";
static char text[BUFSIZ] = "";
static char *embed;
static int bh, mw, mh;
@@ -126,6 +129,21 @@ drawitem(struct item *item, int x, int y, int w)
return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0);
}
+static void
+recalculatenumbers()
+{
+ unsigned int numer = 0, denom = 0;
+ struct item *item;
+ if (matchend) {
+ numer++;
+ for (item = matchend; item && item->left; item = item->left)
+ numer++;
+ }
+ for (item = items; item && item->text; item++)
+ denom++;
+ snprintf(numbers, NUMBERSBUFSIZE, "%d/%d", numer, denom);
+}
+
static void
drawmenu(void)
{
@@ -151,6 +169,7 @@ drawmenu(void)
drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0);
}
+ recalculatenumbers();
if (lines > 0) {
/* draw vertical list */
for (item = curr; item != next; item = item->right)
@@ -165,13 +184,15 @@ drawmenu(void)
}
x += w;
for (item = curr; item != next; item = item->right)
- x = drawitem(item, x, 0, MIN(TEXTW(item->text), mw - x - TEXTW(">")));
+ x = drawitem(item, x, 0, MIN(TEXTW(item->text), mw - x - TEXTW(">") - TEXTW(numbers)));
if (next) {
w = TEXTW(">");
drw_setscheme(drw, scheme[SchemeNorm]);
- drw_text(drw, mw - w, 0, w, bh, lrpad / 2, ">", 0);
+ drw_text(drw, mw - w - TEXTW(numbers), 0, w, bh, lrpad / 2, ">", 0);
}
}
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ drw_text(drw, mw - TEXTW(numbers), 0, TEXTW(numbers), bh, lrpad / 2, numbers, 0);
drw_map(drw, win, 0, 0, mw, mh);
}
--
2.19.2

View file

@ -0,0 +1,32 @@
diff -up a/config.def.h b/config.def.h
--- a/config.def.h 2020-11-28 10:43:05.242935618 +0100
+++ b/config.def.h 2020-11-28 10:44:59.249845805 +0100
@@ -15,6 +15,7 @@ static const char *colors[SchemeLast][2]
[SchemeSelHighlight] = { "#ffc978", "#005577" },
[SchemeNormHighlight] = { "#ffc978", "#222222" },
[SchemeOut] = { "#000000", "#00ffff" },
+ [SchemeMid] = { "#eeeeee", "#770000" },
};
/* -l option; if nonzero, dmenu uses vertical list with given number of lines */
static unsigned int lines = 0;
diff -up a/dmenu.c b/dmenu.c
--- a/dmenu.c 2020-11-28 10:43:05.242935618 +0100
+++ b/dmenu.c 2020-11-28 10:45:57.066625600 +0100
@@ -28,7 +28,7 @@
/* enums */
enum { SchemeNorm, SchemeSel, SchemeNormHighlight, SchemeSelHighlight,
- SchemeOut, SchemeLast }; /* color schemes */
+ SchemeOut, SchemeMid, SchemeLast }; /* color schemes */
struct item {
@@ -162,6 +162,8 @@ drawitem(struct item *item, int x, int y
int r;
if (item == sel)
drw_setscheme(drw, scheme[SchemeSel]);
+ else if (item->left == sel || item->right == sel)
+ drw_setscheme(drw, scheme[SchemeMid]);
else if (item->out)
drw_setscheme(drw, scheme[SchemeOut]);
else

View file

@ -0,0 +1,141 @@
diff -up a/dmenu.c b/dmenu.c
--- a/dmenu.c 2020-11-28 10:50:19.430405801 +0100
+++ b/dmenu.c 2020-11-28 11:01:30.877939721 +0100
@@ -634,6 +634,117 @@ draw:
}
static void
+buttonpress(XEvent *e)
+{
+ struct item *item;
+ XButtonPressedEvent *ev = &e->xbutton;
+ int x = 0, y = 0, h = bh, w;
+
+ if (ev->window != win)
+ return;
+
+ /* right-click: exit */
+ if (ev->button == Button3)
+ exit(1);
+
+ if (prompt && *prompt)
+ x += promptw;
+
+ /* input field */
+ w = (lines > 0 || !matches) ? mw - x : inputw;
+
+ /* left-click on input: clear input,
+ * NOTE: if there is no left-arrow the space for < is reserved so
+ * add that to the input width */
+ if (ev->button == Button1 &&
+ ((lines <= 0 && ev->x >= 0 && ev->x <= x + w +
+ ((!prev || !curr->left) ? TEXTW("<") : 0)) ||
+ (lines > 0 && ev->y >= y && ev->y <= y + h))) {
+ insert(NULL, -cursor);
+ drawmenu();
+ return;
+ }
+ /* middle-mouse click: paste selection */
+ if (ev->button == Button2) {
+ XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY,
+ utf8, utf8, win, CurrentTime);
+ drawmenu();
+ return;
+ }
+ /* scroll up */
+ if (ev->button == Button4 && prev) {
+ sel = curr = prev;
+ calcoffsets();
+ drawmenu();
+ return;
+ }
+ /* scroll down */
+ if (ev->button == Button5 && next) {
+ sel = curr = next;
+ calcoffsets();
+ drawmenu();
+ return;
+ }
+ if (ev->button != Button1)
+ return;
+ if (ev->state & ~ControlMask)
+ return;
+ if (lines > 0) {
+ /* vertical list: (ctrl)left-click on item */
+ w = mw - x;
+ for (item = curr; item != next; item = item->right) {
+ y += h;
+ if (ev->y >= y && ev->y <= (y + h)) {
+ puts(item->text);
+ if (!(ev->state & ControlMask))
+ if (sel) {
+ sel->out = 1;
+ drawmenu();
+ }
+ return;
+ }
+ }
+ } else if (matches) {
+ /* left-click on left arrow */
+ x += inputw;
+ w = TEXTW("<");
+ if (prev && curr->left) {
+ if (ev->x >= x && ev->x <= x + w) {
+ sel = curr = prev;
+ calcoffsets();
+ drawmenu();
+ return;
+ }
+ }
+ /* horizontal list: (ctrl)left-click on item */
+ for (item = curr; item != next; item = item->right) {
+ x += w;
+ w = MIN(TEXTW(item->text), mw - x - TEXTW(">"));
+ if (ev->x >= x && ev->x <= x + w) {
+ puts(item->text);
+ if (!(ev->state & ControlMask))
+ exit(0);
+ sel = item;
+ if (sel) {
+ sel->out = 1;
+ drawmenu();
+ }
+ return;
+ }
+ }
+ /* left-click on right arrow */
+ w = TEXTW(">");
+ x = mw - w;
+ if (next && ev->x >= x && ev->x <= x + w) {
+ sel = curr = next;
+ calcoffsets();
+ drawmenu();
+ return;
+ }
+ }
+}
+
+static void
paste(void)
{
char *p, *q;
@@ -694,6 +805,9 @@ run(void)
break;
cleanup();
exit(1);
+ case ButtonPress:
+ buttonpress(&ev);
+ break;
case Expose:
if (ev.xexpose.count == 0)
drw_map(drw, win, 0, 0, mw, mh);
@@ -791,7 +905,8 @@ setup(void)
/* create menu window */
swa.override_redirect = True;
swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
- swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
+ swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask |
+ ButtonPressMask;
win = XCreateWindow(dpy, parentwin, x, y, mw, mh, border_width,
CopyFromParent, CopyFromParent, CopyFromParent,
CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);