add the ability to read from file, been wanting this for a very long

time
This commit is contained in:
speedie 2023-05-07 01:41:30 +02:00
parent 442c40b732
commit 63e5be2884
13 changed files with 128 additions and 12 deletions

View file

@ -188,6 +188,7 @@ href="https://git.speedie.site/speedwm">speedwm</a>.</p>
<li>Vim-like modes, including indicator.</li> <li>Vim-like modes, including indicator.</li>
<li>The ability to move around items with keybinds.</li> <li>The ability to move around items with keybinds.</li>
<li>Customizable/dynamic line/column size.</li> <li>Customizable/dynamic line/column size.</li>
<li>Ability to update entries dynamically by reading from file</li>
<li>IME support <li>IME support
<ul> <ul>
<li>Was removed from suckless dmenu years ago due to issues Ive <li>Was removed from suckless dmenu years ago due to issues Ive
@ -330,7 +331,6 @@ easy to have LibreSSL compatibility.</li>
</ul></li> </ul></li>
<li>Matching: Add support for contextual completions similar to <li>Matching: Add support for contextual completions similar to
xprompt</li> xprompt</li>
<li>Matching: FIFO, used to dynamically refresh entries.</li>
<li>Matching: Regex matching <li>Matching: Regex matching
<ul> <ul>
<li>Probably use some minimal public domain library for this, Id like <li>Probably use some minimal public domain library for this, Id like

View file

@ -22,6 +22,7 @@ It is designed to integrate well with my [dwm](https://dwm.suckless.org) fork, [
- Vim-like modes, including indicator. - Vim-like modes, including indicator.
- The ability to move around items with keybinds. - The ability to move around items with keybinds.
- Customizable/dynamic line/column size. - Customizable/dynamic line/column size.
- Ability to update entries dynamically by reading from file
- IME support - IME support
- Was removed from suckless dmenu years ago due to issues I've resolved - Was removed from suckless dmenu years ago due to issues I've resolved
- Powerlines - Powerlines
@ -130,7 +131,6 @@ have LibreSSL compatibility.
- Just need to `XMoveResizeWindow()` as well as `mh += bh` and `y += bh` - Just need to `XMoveResizeWindow()` as well as `mh += bh` and `y += bh`
for each added line. for each added line.
- Matching: Add support for contextual completions similar to xprompt - Matching: Add support for contextual completions similar to xprompt
- Matching: FIFO, used to dynamically refresh entries.
- Matching: Regex matching - Matching: Regex matching
- Probably use some minimal public domain library for this, I'd - Probably use some minimal public domain library for this, I'd
like to avoid adding more external dependencies unless it's a like to avoid adding more external dependencies unless it's a

View file

@ -265,7 +265,11 @@ You may use long, descriptive arguments or the shorter arguments.
: Embed spmenu inside window id : Embed spmenu inside window id
`-H, --hist-file hist file` `-H, --hist-file hist file`
: Specify a path to save the history to : Specify a file to save the history to
`-lf, --list-file list file`
: Specify a file to load entries from
`-ig, --image-gaps gaps` `-ig, --image-gaps gaps`
: Set image gaps to gaps : Set image gaps to gaps

View file

@ -160,6 +160,7 @@ spmenu = {
preselected = 0; // Preselect an item, 0 is the first item (number) preselected = 0; // Preselect an item, 0 is the first item (number)
accuratewidth = 0; // Enable accurate width, could be noticeably slower in some cases (0/1) accuratewidth = 0; // Enable accurate width, could be noticeably slower in some cases (0/1)
delimiters = " "; // Word delimiter, used to delete words (text) delimiters = " "; // Word delimiter, used to delete words (text)
listfile = "NULL"; // File to read entries from. If set to NULL standard input is read. This is read every time a key is pressed. (text)
} ); } );
/* Line options */ /* Line options */

View file

@ -276,6 +276,8 @@ void readargs(int argc, char *argv[]) {
input = argv[++i]; input = argv[++i];
else if (!strcmp(argv[i], "-fn") || (!strcmp(argv[i], "--font"))) // font or font set else if (!strcmp(argv[i], "-fn") || (!strcmp(argv[i], "--font"))) // font or font set
fonts[0] = argv[++i]; fonts[0] = argv[++i];
else if (!strcmp(argv[i], "-lf") || (!strcmp(argv[i], "--lf"))) // list file
listfile = argv[++i];
else if (!strcmp(argv[i], "-nmt") || (!strcmp(argv[i], "--normal-mode-text"))) // normal mode text else if (!strcmp(argv[i], "-nmt") || (!strcmp(argv[i], "--normal-mode-text"))) // normal mode text
strcpy(normtext, argv[++i]); strcpy(normtext, argv[++i]);
else if (!strcmp(argv[i], "-imt") || (!strcmp(argv[i], "--insert-mode-text"))) // insert mode text else if (!strcmp(argv[i], "-imt") || (!strcmp(argv[i], "--insert-mode-text"))) // insert mode text
@ -531,7 +533,8 @@ void usage(void) {
"spmenu -ngbc, --no-global-colors Don't recognize global colors (such as *.color1) on runtime\n" "spmenu -ngbc, --no-global-colors Don't recognize global colors (such as *.color1) on runtime\n"
"spmenu -m, --monitor <monitor> Specify a monitor to run spmenu on\n" "spmenu -m, --monitor <monitor> Specify a monitor to run spmenu on\n"
"spmenu -w, --embed <window id> Embed spmenu inside <window id>\n" "spmenu -w, --embed <window id> Embed spmenu inside <window id>\n"
"spmenu -H, --hist-file <hist file> Specify a path to save the history to\n" "spmenu -H, --hist-file <hist file> Specify a file to save the history to\n"
"spmenu -lf, --list-file <list file> Specify a file to load entries from\n"
"spmenu -ig, --image-gaps <gaps> Set image gaps to <gaps>\n" "spmenu -ig, --image-gaps <gaps> Set image gaps to <gaps>\n"
"spmenu -txp, --text-padding <padding> Set text padding to <padding>\n" "spmenu -txp, --text-padding <padding> Set text padding to <padding>\n"
"spmenu -lp, --vertical-padding <padding> Set the vertical padding\n" "spmenu -lp, --vertical-padding <padding> Set the vertical padding\n"

View file

@ -443,6 +443,9 @@ void conf_init(void) {
config_setting_lookup_int(conf, "accuratewidth", &accuratewidth); // spmenu.match.accuratewidth config_setting_lookup_int(conf, "accuratewidth", &accuratewidth); // spmenu.match.accuratewidth
config_setting_lookup_string(conf, "delimiters", &dest); // spmenu.match.delimiters config_setting_lookup_string(conf, "delimiters", &dest); // spmenu.match.delimiters
worddelimiters = strdup(dest); worddelimiters = strdup(dest);
if (config_setting_lookup_string(conf, "listfile", &dest)) // spmenu.match.listfile
if (dest && strcmp(strdup(dest), "NULL"))
listfile = strdup(dest);
} }
} }

View file

@ -7,6 +7,7 @@ void eventloop(void) {
while (!XNextEvent(dpy, &ev)) { while (!XNextEvent(dpy, &ev)) {
if (XFilterEvent(&ev, None)) if (XFilterEvent(&ev, None))
continue; continue;
switch(ev.type) { switch(ev.type) {
case DestroyNotify: case DestroyNotify:
if (ev.xdestroywindow.window != win) if (ev.xdestroywindow.window != win)
@ -31,6 +32,15 @@ void eventloop(void) {
grabfocus(); grabfocus();
break; break;
case KeyPress: // read key array and call functions case KeyPress: // read key array and call functions
if (listfile) {
readfile();
if (listchanged) {
match();
drawmenu();
}
}
if (incremental) { if (incremental) {
puts(text); puts(text);
fflush(stdout); fflush(stdout);

View file

@ -112,3 +112,75 @@ void readstdin(void) {
inputw = items ? TEXTWM(items[imax].text) : 0; inputw = items ? TEXTWM(items[imax].text) : 0;
lines = MIN(lines, i); lines = MIN(lines, i);
} }
void readfile(void) {
if (passwd){
inputw = lines = 0;
return;
}
size_t len;
static size_t cap = 0;
char *l;
FILE *ef = fopen(listfile, "r");
if (!ef) return;
items = NULL;
//list = NULL;
listsize = 0;
for (;;) {
l = NULL;
len = 0;
if (-1 == getline(&l, &len, ef)) {
if (ferror(ef)) die("spmenu: failed to read file\n");
free(l);
break;
}
if (cap == listsize) {
cap += 64 * sizeof(char*);
list = realloc(list, cap);
if (!list) die("spmenu: failed to realloc memory");
}
strtok(l, "\n");
list[listsize] = l;
listsize++;
}
if (fclose(ef)) {
die("spmenu: failed to close file %s\n", listfile);
}
if (!list_items) {
list_items = items;
items = calloc(listsize + 1, sizeof(struct item));
if (!items) die("spmenu: cannot alloc memory\n");
int i = 0;
for (i = 0; i < listsize; i++) {
items[i].text = list[i];
}
if (i == olistcount) {
listcount = i;
listchanged = 0;
} else {
olistcount = listcount;
listcount = i;
listchanged = 1;
}
} else {
free(items);
items = list_items;
list_items = NULL;
}
//match();
//drawmenu();
}

View file

@ -1 +1,2 @@
static void readstdin(void); static void readstdin(void);
static void readfile(void);

View file

@ -79,6 +79,7 @@ static int casesensitive = 0; /* Case-sensitive by default? (0/1)
static int preselected = 0; /* Which line should spmenu preselect? */ static int preselected = 0; /* Which line should spmenu preselect? */
static int accuratewidth = 0; /* Enable accurate width. May have a performance hit if you are matching a lot of items at once */ static int accuratewidth = 0; /* Enable accurate width. May have a performance hit if you are matching a lot of items at once */
static int fuzzy = 1; /* Whether or not to enable fuzzy matching by default */ static int fuzzy = 1; /* Whether or not to enable fuzzy matching by default */
static char *listfile = NULL; /* File to read entries from instead of stdin. NULL means read from stdin instead. */
/* Line options */ /* Line options */
static int lineheight = 1; /* Line height (0: Calculate automatically) */ static int lineheight = 1; /* Line height (0: Calculate automatically) */

View file

@ -286,7 +286,10 @@ Specify a monitor to run spmenu on
Embed spmenu inside window id Embed spmenu inside window id
.TP .TP
\f[V]-H, --hist-file hist file\f[R] \f[V]-H, --hist-file hist file\f[R]
Specify a path to save the history to Specify a file to save the history to
.TP
\f[V]-lf, --list-file list file\f[R]
Specify a file to load entries from
.TP .TP
\f[V]-ig, --image-gaps gaps\f[R] \f[V]-ig, --image-gaps gaps\f[R]
Set image gaps to gaps Set image gaps to gaps

View file

@ -149,7 +149,7 @@ static int vp; // vertical padding for bar
static int sp; // side padding for bar static int sp; // side padding for bar
static int cursorstate = 1; // cursor state static int cursorstate = 1; // cursor state
static size_t cursor; static size_t cursor;
static struct item *items = NULL, *backup_items; static struct item *items = NULL, *backup_items, *list_items;
static struct item *matches, *matchend; static struct item *matches, *matchend;
static struct item *prev, *curr, *next, *sel; static struct item *prev, *curr, *next, *sel;
static int screen; static int screen;
@ -229,6 +229,12 @@ static void setupdisplay(void);
static int max_textw(void); static int max_textw(void);
static size_t nextrune(int inc); static size_t nextrune(int inc);
static char **list;
static size_t listsize;
static int listcount;
static int olistcount;
static int listchanged = 0;
// user configuration // user configuration
#include "options.h" #include "options.h"
#include "keybinds.h" #include "keybinds.h"
@ -256,8 +262,6 @@ static char *(*fstrstr)(const char *, const char *) = cistrstr;
#include "libs/img.c" #include "libs/img.c"
#include "libs/rtl.h" #include "libs/rtl.h"
#include "libs/rtl.c" #include "libs/rtl.c"
#include "libs/event.h"
#include "libs/event.c"
#include "libs/key.c" #include "libs/key.c"
#include "libs/mouse.c" #include "libs/mouse.c"
#include "libs/sort.c" #include "libs/sort.c"
@ -273,6 +277,8 @@ static char *(*fstrstr)(const char *, const char *) = cistrstr;
#include "libs/history.c" #include "libs/history.c"
#include "libs/arg.c" #include "libs/arg.c"
#include "libs/stream.c" #include "libs/stream.c"
#include "libs/event.h"
#include "libs/event.c"
void appenditem(struct item *item, struct item **list, struct item **last) { void appenditem(struct item *item, struct item **list, struct item **last) {
if (*last) if (*last)
@ -736,9 +742,17 @@ int main(int argc, char *argv[]) {
// fast (-f) means we grab keyboard before reading standard input // fast (-f) means we grab keyboard before reading standard input
if (fast && !isatty(0)) { if (fast && !isatty(0)) {
grabkeyboard(); grabkeyboard();
if (!listfile)
readstdin(); readstdin();
else
readfile();
} else { } else {
if (listfile)
readfile();
else
readstdin(); readstdin();
grabkeyboard(); grabkeyboard();
} }

View file

@ -505,7 +505,11 @@ Embed spmenu inside window id
</dd> </dd>
<dt><code>-H, --hist-file hist file</code></dt> <dt><code>-H, --hist-file hist file</code></dt>
<dd> <dd>
Specify a path to save the history to Specify a file to save the history to
</dd>
<dt><code>-lf, --list-file list file</code></dt>
<dd>
Specify a file to load entries from
</dd> </dd>
<dt><code>-ig, --image-gaps gaps</code></dt> <dt><code>-ig, --image-gaps gaps</code></dt>
<dd> <dd>