add a bind file which scripts can use to gain full control over keybinds

This commit is contained in:
speedie 2023-05-22 22:47:37 +02:00
parent f482aea8db
commit 95b420944c
12 changed files with 819 additions and 587 deletions

View file

@ -288,7 +288,6 @@ You may use long, descriptive arguments or the shorter arguments.
`-lf, --list-file list file`
: Specify a file to load entries from
`-ig, --image-gaps gaps`
: Set image gaps to gaps
@ -338,19 +337,28 @@ You may use long, descriptive arguments or the shorter arguments.
: Set config file to load to file
`-lcfg, --load-config`
: Load spmenu configuration (~/.spmenu.conf or ~/.config/spmenu/spmenu.conf)
: Load spmenu configuration (~/.config/spmenu/spmenu.conf) on runtime
`-ncfg, --no-load-config`
: Don't load spmenu configuration (~/.spmenu.conf or ~/.config/spmenu/spmenu.conf)
: Don't load spmenu configuration (~/.config/spmenu/spmenu.conf) on runtime
`-bf, --bind-file file`
: Set bind file to load to file
`-lbi, --load-binds`
: Exclusively load binds from file (~/.config/spmenu/binds.conf) on runtime
`-nlbi, --no-load-binds`
: Don't exclusively load binds from file (~/.config/spmenu/binds.conf) on runtime
`-tm, --theme theme`
: Load theme 'theme' on runtime.
: Load theme 'theme' on runtime
`-ltm, --load-theme`
: Load theme
: Load theme (~/.config/spmenu/theme.conf) on runtime
`-nltm, --no-load-theme`
: Don't load theme
: Don't load theme (~/.config/spmenu/theme.conf) on runtime
`-v, --version`
: Print spmenu version to stdout
@ -831,3 +839,6 @@ email me.
## See also
- spmenu_run(1)
- [spmenu wiki](https://spmenu.speedie.site)
- [spmenu git repository](https://git.speedie.site/spmenu)
- [spmenu GitHub mirror](https://github.com/speediegq/spmenu)

View file

@ -155,3 +155,6 @@ email me.
## See also
- spmenu(1)
- [spmenu wiki](https://spmenu.speedie.site)
- [spmenu git repository](https://git.speedie.site/spmenu)
- [spmenu GitHub mirror](https://github.com/speediegq/spmenu)

View file

@ -201,7 +201,8 @@ spmenu = {
/* File options */
file = ( { xresources = 1; // Load .Xresources on startup (0/1)
global = 1; // Read global .Xresources colors, programs like Pywal use this. (*.color0, *.color1, etc.) (0/1)
theme = 1; // Load theme (~/.theme.conf or ~/.config/spmenu/theme.conf) on runtime
theme = 1; // Load theme (~/.config/spmenu/theme.conf) on runtime
binds = 1; // Load binds (~/.config/spmenu/binds.conf) on runtime
} );
/* Input options */

View file

@ -15,20 +15,28 @@ void readargs(int argc, char *argv[]) {
loadtheme = 1;
} else if (!strcmp(argv[j], "-nltm") || (!strcmp(argv[j], "--no-load-theme"))) {
loadtheme = 0;
} else if (!strcmp(argv[j], "-lbi") || (!strcmp(argv[j], "--load-binds"))) {
loadbinds = 1;
} else if (!strcmp(argv[j], "-nlbi") || (!strcmp(argv[j], "--no-load-binds"))) {
loadbinds = 0;
#if USECONFIG
} else if (!strcmp(argv[j], "-cf") || (!strcmp(argv[j], "--config-file"))) { // specify a config file
if (argv[j+1]) {
cconf = 1;
argconf = argv[++j];
} else {
die("This argument requires a second argument.\n");
die("This argument requires a second argument.");
}
} else if (!strcmp(argv[j], "-bf") || (!strcmp(argv[j], "--bind-file"))) { // specify a bind file
if (argv[j+1]) {
argbinds = argv[++j];
} else {
die("This argument requires a second argument.");
}
} else if (!strcmp(argv[j], "-tm") || (!strcmp(argv[j], "--theme"))) { // specify a theme
if (argv[j+1]) {
ctheme = 1;
argtheme = argv[++j];
} else {
die("This argument requires a second argument.\n");
die("This argument requires a second argument.");
}
#endif
}
@ -216,6 +224,10 @@ void readargs(int argc, char *argv[]) {
|| !strcmp(argv[i], "-nltm")
|| !strcmp(argv[i], "--load-theme")
|| !strcmp(argv[i], "--no-load-theme")
|| !strcmp(argv[i], "-lbi")
|| !strcmp(argv[i], "-nlbi")
|| !strcmp(argv[i], "--load-binds")
|| !strcmp(argv[i], "--no-load-binds")
|| !strcmp(argv[i], "-gbc")
|| !strcmp(argv[i], "-ngbc")
|| !strcmp(argv[i], "--global-colors")
@ -227,6 +239,9 @@ void readargs(int argc, char *argv[]) {
|| !strcmp(argv[i], "-tm")
|| !strcmp(argv[i], "--theme")
|| (argtheme && !strcmp(argv[i], argtheme))
|| !strcmp(argv[i], "-bf")
|| !strcmp(argv[i], "--bind-file")
|| (argbinds && !strcmp(argv[i], argbinds))
#endif
))
continue;
@ -435,6 +450,10 @@ void readargs(int argc, char *argv[]) {
|| !strcmp(argv[i], "-nltm")
|| !strcmp(argv[i], "--load-theme")
|| !strcmp(argv[i], "--no-load-theme")
|| !strcmp(argv[i], "-lbi")
|| !strcmp(argv[i], "-nlbi")
|| !strcmp(argv[i], "--load-binds")
|| !strcmp(argv[i], "--no-load-binds")
|| !strcmp(argv[i], "-gbc")
|| !strcmp(argv[i], "-ngbc")
|| !strcmp(argv[i], "--global-colors")
@ -446,6 +465,9 @@ void readargs(int argc, char *argv[]) {
|| !strcmp(argv[i], "-tm")
|| !strcmp(argv[i], "--theme")
|| (argtheme && !strcmp(argv[i], argtheme))
|| !strcmp(argv[i], "-bf")
|| !strcmp(argv[i], "--bind-file")
|| (argbinds && !strcmp(argv[i], argbinds))
#endif
))
continue;
@ -528,7 +550,7 @@ void usage(int status) {
"spmenu -t, --top Position spmenu at the top of the screen\n"
"spmenu -b, --bottom Position spmenu at the bottom of the screen\n"
"spmenu -c, --center Position spmenu at the center of the screen\n"
"\n", status ? stderr : stdout);
, status ? stderr : stdout);
// more args
fputs("spmenu -hm, --hide-mode Hide mode indicator\n"
@ -582,8 +604,11 @@ void usage(int status) {
fputs("spmenu -wm, --managed, --x11-client Spawn spmenu as a window manager controlled client/window. Useful for testing\n"
"spmenu -nwm, --unmanaged Don't spawn spmenu as a window manager controlled client/window. Useful for testing\n"
"spmenu -cf, --config-file <file> Set config file to load to <file>\n"
"spmenu -lcfg, --load-config Load spmenu configuration (~/.spmenu.conf or ~/.config/spmenu/spmenu.conf)\n"
"spmenu -ncfg, --no-load-config Don't load spmenu configuration (~/.spmenu.conf or ~/.config/spmenu/spmenu.conf)\n"
"spmenu -lcfg, --load-config Load spmenu configuration (~/.config/spmenu/spmenu.conf)\n"
"spmenu -ncfg, --no-load-config Don't load spmenu configuration (~/.config/spmenu/spmenu.conf)\n"
"spmenu -bf, --bind-file <file> Exclusively load binds from <file>\n"
"spmenu -lbi, --load-binds Load spmenu binds (~/.config/spmenu/binds.conf)\n"
"spmenu -nlbi, --no-load-binds Don't load spmenu binds (~/.config/spmenu/binds.conf)\n"
"spmenu -tm, --theme <theme> Load theme <theme>\n"
"spmenu -ltm, --load-theme Load theme\n"
"spmenu -nltm, --no-load-theme Don't load theme\n"
@ -624,7 +649,7 @@ void usage(int status) {
"spmenu -cfc, --caret-foreground <color> Set the caret foreground color\n"
"spmenu -cbc, --caret-background <color> Set the caret background color\n"
"spmenu -bc, --border-background <color> Set the border color\n"
"\n", status ? stderr : stdout);
, status ? stderr : stdout);
// sgr sequences
fputs("spmenu -sgr0, --sgr0 <color> Set the SGR 0 color\n"

View file

@ -5,14 +5,14 @@
void conf_init(void) {
char *xdg_conf;
char *cfgfile = NULL;
char *bindfile = NULL;
char *home = NULL;
const char *dest;
// don't load configuration
if (!loadconfig) return;
if (loadconfig) {
// get path for configuration file
if (!cconf || !argconf) {
if (!argconf) {
if (!(xdg_conf = getenv("XDG_CONFIG_HOME"))) {
// ~/.config/spmenu/spmenu.conf
home = getenv("HOME");
@ -418,6 +418,7 @@ void conf_init(void) {
// look up
config_setting_lookup_int(conf, "theme", &loadtheme); // spmenu.file.theme
config_setting_lookup_int(conf, "binds", &loadbinds); // spmenu.file.binds
config_setting_lookup_int(conf, "global", &globalcolors); // spmenu.file.global
config_setting_lookup_int(conf, "xresources", &xresources); // spmenu.file.xresources
}
@ -609,6 +610,156 @@ void conf_init(void) {
for (unsigned int i = 0; i < config_setting_length(mouse_setting); ++i) {
config_setting_t *conf = config_setting_get_elem(mouse_setting, i);
for (int j = 0; j < LENGTH(ctp); j++) {
if (!strcmp(ctp[j].tclick, strdup(dest))) {
cbuttons[i].click = ctp[j].click;
}
}
// look up
config_setting_lookup_string(conf, "modifier", &dest);
for (int j = 0; j < LENGTH(ml); j++) {
if (!strcmp(ml[j].mod, strdup(dest))) {
cbuttons[i].mask = ml[j].modifier;
}
}
config_setting_lookup_string(conf, "button", &dest);
for (int j = 0; j < LENGTH(btp); j++) {
if (!strcmp(btp[j].click, strdup(dest))) {
cbuttons[i].button = btp[j].button;
}
}
config_setting_lookup_string(conf, "function", &dest);
for (int j = 0; j < LENGTH(fl); j++) {
if (!strcmp(fl[j].function, strdup(dest))) {
cbuttons[i].func = fl[j].func;
}
}
config_setting_lookup_string(conf, "argument", &dest);
for (int j = 0; j < LENGTH(al); j++) {
if (!strcmp(al[j].argument, strdup(dest))) {
cbuttons[i].arg = al[j].arg;
}
}
config_setting_lookup_int(conf, "ignoreglobalmouse", &ignoreglobalmouse);
}
}
// we're done with this config
config_destroy(&cfg);
}
// load the theme now
if (loadtheme) {
theme_load();
}
if (loadbinds) {
if (!argbinds) {
if (!(xdg_conf = getenv("XDG_CONFIG_HOME"))) {
home = getenv("HOME");
if (!(bindfile = malloc(snprintf(NULL, 0, "%s/%s", home, ".config/spmenu/binds.conf") + 1))) {
die("spmenu: failed to malloc bindfile");
}
sprintf(bindfile, "%s/%s", home, ".config/spmenu/binds.conf");
} else {
if (!(bindfile = malloc(snprintf(NULL, 0, "%s/%s", xdg_conf, "spmenu/binds.conf") + 1))) {
die("spmenu: failed to malloc bindfile");
}
sprintf(bindfile, "%s/%s", xdg_conf, "spmenu/binds.conf");
}
} else { // custom keys path
if (!(bindfile = malloc(snprintf(NULL, 0, "%s", argbinds) + 1))) {
die("spmenu: failed to malloc bindfile");
}
sprintf(bindfile, "%s", argbinds);
}
// don't bother trying to load if it doesn't exist.
if (access(bindfile, F_OK) != 0) {
return;
}
// init config
config_t bind;
config_init(&bind);
// attempt to read config file to cfg
if (!config_read_file(&bind, bindfile)) {
// invalid configuration, but let's try to read it anyway
fprintf(stderr, "spmenu: Invalid keys file.\n");
}
// load options binds.keys
config_setting_t *key_bind = config_lookup(&bind, "bind.keys");
if (key_bind != NULL) {
int nmode = 0;
memset(ckeys, '\0', LENGTH(ckeys)-1);
for (unsigned int i = 0; i < config_setting_length(key_bind); ++i) {
config_setting_t *conf = config_setting_get_elem(key_bind, i);
// look up
config_setting_lookup_string(conf, "modifier", &dest);
for (int j = 0; j < LENGTH(ml); j++) {
if (!strcmp(ml[j].mod, strdup(dest))) {
ckeys[i].mod = ml[j].modifier;
}
}
if (config_setting_lookup_int(conf, "mode", &nmode)) {
ckeys[i].mode = nmode;
}
config_setting_lookup_string(conf, "key", &dest);
for (int j = 0; j < LENGTH(kl); j++) {
if (!strcmp(kl[j].key, strdup(dest))) {
ckeys[i].keysym = kl[j].keysym;
}
}
config_setting_lookup_string(conf, "function", &dest);
for (int j = 0; j < LENGTH(fl); j++) {
if (!strcmp(fl[j].function, strdup(dest))) {
ckeys[i].func = fl[j].func;
}
}
config_setting_lookup_string(conf, "argument", &dest);
for (int j = 0; j < LENGTH(al); j++) {
if (!strcmp(al[j].argument, strdup(dest))) {
ckeys[i].arg = al[j].arg;
}
}
config_setting_lookup_int(conf, "ignoreglobalkeys", &ignoreglobalkeys);
}
}
// load options binds.mouse
config_setting_t *mouse_bind = config_lookup(&bind, "bind.mouse");
if (mouse_bind != NULL) {
memset(cbuttons, '\0', LENGTH(cbuttons)-1);
for (unsigned int i = 0; i < config_setting_length(mouse_bind); ++i) {
config_setting_t *conf = config_setting_get_elem(mouse_bind, i);
// look up
config_setting_lookup_string(conf, "click", &dest);
@ -655,8 +806,9 @@ void conf_init(void) {
}
}
// we're done here
config_destroy(&cfg);
if (loadtheme) theme_load();
// finally done
config_destroy(&bind);
}
return;
}

View file

@ -10,7 +10,7 @@ void theme_load(void) {
if (!loadconfig) return;
// get path for configuration file
if (!ctheme || !argtheme) {
if (!argtheme) {
if (!(xdg_conf = getenv("XDG_CONFIG_HOME"))) {
// ~/.config/spmenu/theme.conf
home = getenv("HOME");

View file

@ -9,8 +9,9 @@ static char *class = "spmenu"; /* Class for spmenu */
static int fast = 0; /* Grab keyboard first */
static int xresources = 1; /* Enable .Xresources support */
static int globalcolors = 1; /* Recognize global colors (such as colors generated by Pywal) */
static int loadconfig = 1; /* Load configuration (~/.spmenu.conf or ~/.config/spmenu/spmenu.conf) on runtime */
static int loadconfig = 1; /* Load configuration (~/.config/spmenu/spmenu.conf) on runtime */
static int loadtheme = 1; /* Load theme (~/.theme.conf or ~/.config/spmenu/theme.conf) on runtime */
static int loadbinds = 1; /* Load keybind file (~/.config/spmenu/binds.conf) on runtime */
static int mon = -1; /* Monitor to run spmenu on */
/* Window options */

View file

@ -36,8 +36,8 @@ DMENU_COMPAT="${DMENU_COMPAT:-false}"
AUTOREFRESH="${AUTOREFRESH:-false}"
MULTISELECT="${MULTISELECT:-true}"
DESKTOP_DIR="${DESKTOP_DIR:-${DESTDIR}${PREFIX}/share/applications}"
ICON_DIR="${ICON_DIR:-${DESTDIR}${PREFIX}/share/icons/hicolor ${DESTDIR}${PREFIX}/share/pixmaps}"
DESKTOP_DIR="${DESKTOP_DIR:-${DESTDIR}${PREFIX}/share/applications ${HOME}/.local/share/applications}"
ICON_DIR="${ICON_DIR:-${DESTDIR}${PREFIX}/share/icons/hicolor ${HOME}/.local/share/icons/hicolor ${DESTDIR}${PREFIX}/share/pixmaps}"
TEMPORARY_DIR="${TEMPORARY_DIR:-$CONFDIR/spmenu/run/cache}"
IMAGE="${IMAGE:-true}"
LOGFILE="${LOGFILE:-/tmp/spmenu_run.log}"
@ -247,8 +247,8 @@ DEFAULT_FEATURE="run" # spmenu_run default feature (run/fm/desktop/help)
HELP_COLOR="#FFFF00"
# .desktop options
DESKTOP_DIR="\${DESTDIR}\${PREFIX}/share/applications" # Directories for .desktop entries
ICON_DIR="\${DESTDIR}\${PREFIX}/share/icons/hicolor \${DESTDIR}\${PREFIX}/share/pixmaps" # Directories for icons defined in the entries
DESKTOP_DIR="\${DESTDIR}\${PREFIX}/share/applications \${HOME}/.local/share/applications" # Directories for .desktop entries
ICON_DIR="\${DESTDIR}\${PREFIX}/share/icons/hicolor \${HOME}/.local/share/icons/hicolor \${DESTDIR}\${PREFIX}/share/pixmaps" # Directories for icons defined in the entries
TEMPORARY_DIR="\$CONFDIR/spmenu/run/cache" # Directory used to store cached entries
HIDDEN_ENTRY_KEYWORDS="\$HIDDEN_KEYWORDS" # Keywords that will be ignored, needs to be in grep -vE syntax.
ENTRY_KEYWORDS="\$KEYWORDS" # Keywords that will be matched, needs to be in grep -E syntax.

View file

@ -362,21 +362,31 @@ Useful for testing
Set config file to load to file
.TP
\f[V]-lcfg, --load-config\f[R]
Load spmenu configuration (\[ti]/.spmenu.conf or
\[ti]/.config/spmenu/spmenu.conf)
Load spmenu configuration (\[ti]/.config/spmenu/spmenu.conf) on runtime
.TP
\f[V]-ncfg, --no-load-config\f[R]
Don\[cq]t load spmenu configuration (\[ti]/.spmenu.conf or
\[ti]/.config/spmenu/spmenu.conf)
Don\[cq]t load spmenu configuration (\[ti]/.config/spmenu/spmenu.conf)
on runtime
.TP
\f[V]-bf, --bind-file file\f[R]
Set bind file to load to file
.TP
\f[V]-lbi, --load-binds\f[R]
Exclusively load binds from file (\[ti]/.config/spmenu/binds.conf) on
runtime
.TP
\f[V]-nlbi, --no-load-binds\f[R]
Don\[cq]t exclusively load binds from file
(\[ti]/.config/spmenu/binds.conf) on runtime
.TP
\f[V]-tm, --theme theme\f[R]
Load theme `theme' on runtime.
Load theme `theme' on runtime
.TP
\f[V]-ltm, --load-theme\f[R]
Load theme
Load theme (\[ti]/.config/spmenu/theme.conf) on runtime
.TP
\f[V]-nltm, --no-load-theme\f[R]
Don\[cq]t load theme
Don\[cq]t load theme (\[ti]/.config/spmenu/theme.conf) on runtime
.TP
\f[V]-v, --version\f[R]
Print spmenu version to stdout
@ -1538,3 +1548,9 @@ me.
.SS See also
.IP \[bu] 2
spmenu_run(1)
.IP \[bu] 2
spmenu wiki (https://spmenu.speedie.site)
.IP \[bu] 2
spmenu git repository (https://git.speedie.site/spmenu)
.IP \[bu] 2
spmenu GitHub mirror (https://github.com/speediegq/spmenu)

View file

@ -191,10 +191,9 @@ static int fullscreen = 0;
// config file
#if USECONFIG
static int cconf = 0; // use custom config path?
static int ctheme = 0; // use custom theme path?
static char *argconf = NULL; // arg config path
static char *argtheme = NULL; // arg theme path
static char *argbinds = NULL; // arg binds path
#endif
// set an integer to 1 if we have rtl enabled, this saves a lot of lines and duplicate code

View file

@ -602,25 +602,38 @@ Set config file to load to file
</dd>
<dt><code>-lcfg, --load-config</code></dt>
<dd>
Load spmenu configuration (~/.spmenu.conf or
~/.config/spmenu/spmenu.conf)
Load spmenu configuration (~/.config/spmenu/spmenu.conf) on runtime
</dd>
<dt><code>-ncfg, --no-load-config</code></dt>
<dd>
Dont load spmenu configuration (~/.spmenu.conf or
~/.config/spmenu/spmenu.conf)
Dont load spmenu configuration (~/.config/spmenu/spmenu.conf) on
runtime
</dd>
<dt><code>-bf, --bind-file file</code></dt>
<dd>
Set bind file to load to file
</dd>
<dt><code>-lbi, --load-binds</code></dt>
<dd>
Exclusively load binds from file (~/.config/spmenu/binds.conf) on
runtime
</dd>
<dt><code>-nlbi, --no-load-binds</code></dt>
<dd>
Dont exclusively load binds from file (~/.config/spmenu/binds.conf) on
runtime
</dd>
<dt><code>-tm, --theme theme</code></dt>
<dd>
Load theme theme on runtime.
Load theme theme on runtime
</dd>
<dt><code>-ltm, --load-theme</code></dt>
<dd>
Load theme
Load theme (~/.config/spmenu/theme.conf) on runtime
</dd>
<dt><code>-nltm, --no-load-theme</code></dt>
<dd>
Dont load theme
Dont load theme (~/.config/spmenu/theme.conf) on runtime
</dd>
<dt><code>-v, --version</code></dt>
<dd>
@ -1541,6 +1554,11 @@ alternatively email me.</p>
<h2 id="see-also">See also</h2>
<ul>
<li>spmenu_run(1)</li>
<li><a href="https://spmenu.speedie.site">spmenu wiki</a></li>
<li><a href="https://git.speedie.site/spmenu">spmenu git
repository</a></li>
<li><a href="https://github.com/speediegq/spmenu">spmenu GitHub
mirror</a></li>
</ul>
</body>
</html>

View file

@ -196,3 +196,9 @@ me.
.SS See also
.IP \[bu] 2
spmenu(1)
.IP \[bu] 2
spmenu wiki (https://spmenu.speedie.site)
.IP \[bu] 2
spmenu git repository (https://git.speedie.site/spmenu)
.IP \[bu] 2
spmenu GitHub mirror (https://github.com/speediegq/spmenu)