Skip to content

Commit

Permalink
Fix configuration loader
Browse files Browse the repository at this point in the history
Allows to override default configuration.
Resolves #203.

Signed-off-by: Artem Senichev <[email protected]>
  • Loading branch information
artemsen committed Oct 20, 2024
1 parent 2edcc83 commit 41f63ea
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 160 deletions.
157 changes: 145 additions & 12 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,137 @@
#include <stdlib.h>
#include <string.h>

/** Default configuration. */
struct config_default {
const char* section;
const char* key;
const char* value;
};
static const struct config_default defaults[] = {
{ "general", "mode", "viewer" },
{ "general", "position", "parent" },
{ "general", "size", "parent" },
{ "general", "sigusr1", "reload" },
{ "general", "sigusr2", "next_file" },
{ "general", "app_id", "swayimg" },

{ "viewer", "window", "#00000000" },
{ "viewer", "transparency", "grid" },
{ "viewer", "scale", "optimal" },
{ "viewer", "fixed", "yes" },
{ "viewer", "antialiasing", "no" },
{ "viewer", "slideshow", "no" },
{ "viewer", "slideshow_time", "3" },
{ "viewer", "history", "1" },
{ "viewer", "preload", "1" },

{ "gallery", "size", "200" },
{ "gallery", "cache", "100" },
{ "gallery", "fill", "yes" },
{ "gallery", "antialiasing", "no" },
{ "gallery", "window", "#00000000" },
{ "gallery", "background", "#202020ff" },
{ "gallery", "select", "#404040ff" },
{ "gallery", "border", "#000000ff" },
{ "gallery", "shadow", "#000000ff" },

{ "list", "order", "alpha" },
{ "list", "loop", "yes" },
{ "list", "recursive", "no" },
{ "list", "all", "yes" },

{ "font", "name", "monospace" },
{ "font", "size", "14" },
{ "font", "color", "#ccccccff" },
{ "font", "shadow", "#000000a0" },

{ "info", "show", "yes" },
{ "info", "info_timeout", "5" },
{ "info", "status_timeout", "3" },

{ "info.viewer", "top_left", "+name,+format,+filesize,+imagesize,+exif" },
{ "info.viewer", "top_right", "index" },
{ "info.viewer", "bottom_left", "scale,frame" },
{ "info.viewer", "bottom_right", "status" },

{ "info.gallery", "top_left", "none" },
{ "info.gallery", "top_right", "none" },
{ "info.gallery", "bottom_left", "none" },
{ "info.gallery", "bottom_right", "name,status" },

{ "keys.viewer", "F1", "help" },
{ "keys.viewer", "Home", "first_file" },
{ "keys.viewer", "End", "last_file" },
{ "keys.viewer", "Prior", "prev_file" },
{ "keys.viewer", "Next", "next_file" },
{ "keys.viewer", "Space", "next_file" },
{ "keys.viewer", "Shift+d", "prev_dir" },
{ "keys.viewer", "d", "next_dir" },
{ "keys.viewer", "Shift+o", "prev_frame" },
{ "keys.viewer", "o", "next_frame" },
{ "keys.viewer", "c", "skip_file" },
{ "keys.viewer", "Shift+s", "slideshow" },
{ "keys.viewer", "s", "animation" },
{ "keys.viewer", "f", "fullscreen" },
{ "keys.viewer", "Return", "mode" },
{ "keys.viewer", "Left", "step_left 10" },
{ "keys.viewer", "Right", "step_right 10" },
{ "keys.viewer", "Up", "step_up 10" },
{ "keys.viewer", "Down", "step_down 10" },
{ "keys.viewer", "Equal", "zoom +10" },
{ "keys.viewer", "Plus", "zoom +10" },
{ "keys.viewer", "Minus", "zoom -10" },
{ "keys.viewer", "w", "zoom width" },
{ "keys.viewer", "Shift+w", "zoom height" },
{ "keys.viewer", "z", "zoom fit" },
{ "keys.viewer", "Shift+z", "zoom fill" },
{ "keys.viewer", "0", "zoom real" },
{ "keys.viewer", "BackSpace", "zoom optimal" },
{ "keys.viewer", "bracketleft", "rotate_left" },
{ "keys.viewer", "bracketright", "rotate_right" },
{ "keys.viewer", "m", "flip_vertical" },
{ "keys.viewer", "Shift+m", "flip_horizontal" },
{ "keys.viewer", "a", "antialiasing" },
{ "keys.viewer", "r", "reload" },
{ "keys.viewer", "i", "info" },
{ "keys.viewer", "Shift+Delete", "exec rm '%'; skip_file" },
{ "keys.viewer", "Escape", "exit" },
{ "keys.viewer", "q", "exit" },
{ "keys.viewer", "ScrollLeft", "step_right 5" },
{ "keys.viewer", "ScrollRight", "step_left 5" },
{ "keys.viewer", "ScrollUp", "step_up 5" },
{ "keys.viewer", "ScrollDown", "step_down 5" },
{ "keys.viewer", "Ctrl+ScrollUp", "zoom +10" },
{ "keys.viewer", "Ctrl+ScrollDown", "zoom -10" },
{ "keys.viewer", "Shift+ScrollUp", "prev_file" },
{ "keys.viewer", "Shift+ScrollDown", "next_file" },
{ "keys.viewer", "Alt+ScrollUp", "prev_frame" },
{ "keys.viewer", "Alt+ScrollDown", "next_frame" },

{ "keys.gallery", "F1", "help" },
{ "keys.gallery", "Home", "first_file" },
{ "keys.gallery", "End", "last_file" },
{ "keys.gallery", "Left", "step_left" },
{ "keys.gallery", "Right", "step_right" },
{ "keys.gallery", "Up", "step_up" },
{ "keys.gallery", "Down", "step_down" },
{ "keys.gallery", "Prior", "page_up" },
{ "keys.gallery", "Next", "page_down" },
{ "keys.gallery", "c", "skip_file" },
{ "keys.gallery", "f", "fullscreen" },
{ "keys.gallery", "Return", "mode" },
{ "keys.gallery", "a", "antialiasing" },
{ "keys.gallery", "r", "reload" },
{ "keys.gallery", "i", "info" },
{ "keys.gallery", "Shift+Delete", "exec rm '%'; skip_file" },
{ "keys.gallery", "Escape", "exit" },
{ "keys.gallery", "q", "exit" },
{ "keys.gallery", "ScrollLeft", "step_right" },
{ "keys.gallery", "ScrollRight", "step_left" },
{ "keys.gallery", "ScrollUp", "step_up" },
{ "keys.gallery", "ScrollDown", "step_down" },
};

/** Config file location. */
struct location {
const char* prefix; ///< Environment variable name
Expand Down Expand Up @@ -104,9 +235,8 @@ static char* expand_path(const char* prefix_env, const char* postfix)
* @param path full path to the file
* @return loaded config instance or NULL on errors
*/
static struct config* load(const char* path)
static bool load(const char* path, struct config** cfg)
{
struct config* cfg = NULL;
FILE* fd = NULL;
char* buff = NULL;
size_t buff_sz = 0;
Expand All @@ -116,7 +246,7 @@ static struct config* load(const char* path)

fd = fopen(path, "r");
if (!fd) {
return NULL;
return false;
}

while ((nread = getline(&buff, &buff_sz, fd)) != -1) {
Expand Down Expand Up @@ -186,32 +316,35 @@ static struct config* load(const char* path)
}

// save configuration parameter
config_set(&cfg, section, line, value);
config_set(cfg, section, line, value);
}

free(buff);
free(section);
fclose(fd);

return cfg;
return true;
}

struct config* config_load(void)
{
struct config* cfg = NULL;

// set defaults
for (size_t i = 0; i < ARRAY_SIZE(defaults); ++i) {
const struct config_default* def = &defaults[i];
config_set(&cfg, def->section, def->key, def->value);
}

// find and load first available config file
for (size_t i = 0; i < ARRAY_SIZE(config_locations); ++i) {
const struct location* cl = &config_locations[i];
char* path = expand_path(cl->prefix, cl->postfix);
if (path) {
cfg = load(path);
if (cfg) {
free(path);
break;
}
}
const bool loaded = path && load(path, &cfg);
free(path);
if (loaded) {
break;
}
}

return cfg;
Expand Down
135 changes: 0 additions & 135 deletions src/keybind.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,94 +10,6 @@
#include <stdlib.h>
#include <string.h>

// Default key bindings
struct keybind_default {
xkb_keysym_t key; ///< Keyboard key
uint8_t mods; ///< Key modifiers
struct action action; ///< Action
};

// clang-format off

/** Default key bindings for viewer mode. */
static const struct keybind_default default_viewer[] = {
{ .key = XKB_KEY_F1, .action = { action_help, NULL } },
{ .key = XKB_KEY_Home, .action = { action_first_file, NULL } },
{ .key = XKB_KEY_End, .action = { action_last_file, NULL } },
{ .key = XKB_KEY_space, .action = { action_next_file, NULL } },
{ .key = XKB_KEY_SunPageDown, .action = { action_next_file, NULL } },
{ .key = XKB_KEY_SunPageUp, .action = { action_prev_file, NULL } },
{ .key = XKB_KEY_c, .action = { action_skip_file, NULL } },
{ .key = XKB_KEY_d, .action = { action_next_dir, NULL } },
{ .key = XKB_KEY_d, .mods = KEYMOD_SHIFT, .action = { action_prev_dir, NULL } },
{ .key = XKB_KEY_o, .action = { action_next_frame, NULL } },
{ .key = XKB_KEY_o, .mods = KEYMOD_SHIFT, .action = { action_prev_frame, NULL } },
{ .key = XKB_KEY_s, .action = { action_animation, NULL } },
{ .key = XKB_KEY_s, .mods = KEYMOD_SHIFT, .action = { action_slideshow, NULL } },
{ .key = XKB_KEY_f, .action = { action_fullscreen, NULL } },
{ .key = XKB_KEY_Left, .action = { action_step_left, NULL } },
{ .key = XKB_KEY_Right, .action = { action_step_right, NULL } },
{ .key = XKB_KEY_Up, .action = { action_step_up, NULL } },
{ .key = XKB_KEY_Down, .action = { action_step_down, NULL } },
{ .key = XKB_KEY_equal, .action = { action_zoom, "+10" } },
{ .key = XKB_KEY_plus, .action = { action_zoom, "+10" } },
{ .key = XKB_KEY_minus, .action = { action_zoom, "-10" } },
{ .key = XKB_KEY_w, .action = { action_zoom, "width" } },
{ .key = XKB_KEY_w, .mods = KEYMOD_SHIFT, .action = { action_zoom, "height" } },
{ .key = XKB_KEY_z, .action = { action_zoom, "fit" } },
{ .key = XKB_KEY_z, .mods = KEYMOD_SHIFT, .action = { action_zoom, "fill" } },
{ .key = XKB_KEY_0, .action = { action_zoom, "real" } },
{ .key = XKB_KEY_BackSpace, .action = { action_zoom, "optimal" } },
{ .key = XKB_KEY_bracketleft, .action = { action_rotate_left, NULL } },
{ .key = XKB_KEY_bracketright, .action = { action_rotate_right, NULL } },
{ .key = XKB_KEY_m, .action = { action_flip_vertical, NULL } },
{ .key = XKB_KEY_m, .mods = KEYMOD_SHIFT, .action = { action_flip_horizontal, NULL } },
{ .key = XKB_KEY_a, .action = { action_antialiasing, NULL } },
{ .key = XKB_KEY_r, .action = { action_reload, NULL } },
{ .key = XKB_KEY_i, .action = { action_info, NULL } },
{ .key = XKB_KEY_Return, .action = { action_mode, NULL } },
{ .key = XKB_KEY_Escape, .action = { action_exit, NULL } },
{ .key = XKB_KEY_q, .action = { action_exit, NULL } },
{ .key = VKEY_SCROLL_LEFT, .action = { action_step_right, "5" } },
{ .key = VKEY_SCROLL_RIGHT, .action = { action_step_left, "5" } },
{ .key = VKEY_SCROLL_UP, .action = { action_step_up, "5" } },
{ .key = VKEY_SCROLL_DOWN, .action = { action_step_down, "5" } },
{ .key = VKEY_SCROLL_UP, .mods = KEYMOD_CTRL, .action = { action_zoom, "+10" } },
{ .key = VKEY_SCROLL_DOWN, .mods = KEYMOD_CTRL, .action = { action_zoom, "-10" } },
{ .key = VKEY_SCROLL_UP, .mods = KEYMOD_SHIFT, .action = { action_prev_file, NULL } },
{ .key = VKEY_SCROLL_DOWN, .mods = KEYMOD_SHIFT, .action = { action_next_file, NULL } },
{ .key = VKEY_SCROLL_UP, .mods = KEYMOD_ALT, .action = { action_prev_frame, NULL } },
{ .key = VKEY_SCROLL_DOWN, .mods = KEYMOD_ALT, .action = { action_next_frame, NULL } },
{ .key = XKB_KEY_Delete, .mods = KEYMOD_SHIFT, .action = { action_none, NULL } },
};

/** Default key bindings for gallery mode. */
static const struct keybind_default default_gallery[] = {
{ .key = XKB_KEY_F1, .action = { action_help, NULL } },
{ .key = XKB_KEY_Home, .action = { action_first_file, NULL } },
{ .key = XKB_KEY_End, .action = { action_last_file, NULL } },
{ .key = XKB_KEY_f, .action = { action_fullscreen, NULL } },
{ .key = XKB_KEY_Left, .action = { action_step_left, NULL } },
{ .key = XKB_KEY_Right, .action = { action_step_right, NULL } },
{ .key = XKB_KEY_Up, .action = { action_step_up, NULL } },
{ .key = XKB_KEY_Down, .action = { action_step_down, NULL } },
{ .key = XKB_KEY_Prior, .action = { action_page_up, NULL } },
{ .key = XKB_KEY_Next, .action = { action_page_down, NULL } },
{ .key = XKB_KEY_c, .action = { action_skip_file, NULL } },
{ .key = XKB_KEY_a, .action = { action_antialiasing, NULL } },
{ .key = XKB_KEY_r, .action = { action_reload, NULL } },
{ .key = XKB_KEY_i, .action = { action_info, NULL } },
{ .key = XKB_KEY_Return, .action = { action_mode, NULL } },
{ .key = XKB_KEY_Escape, .action = { action_exit, NULL } },
{ .key = XKB_KEY_q, .action = { action_exit, NULL } },
{ .key = VKEY_SCROLL_LEFT, .action = { action_step_right, NULL } },
{ .key = VKEY_SCROLL_RIGHT, .action = { action_step_left, NULL } },
{ .key = VKEY_SCROLL_UP, .action = { action_step_up, NULL } },
{ .key = VKEY_SCROLL_DOWN, .action = { action_step_down, NULL } },
{ .key = XKB_KEY_Delete, .mods = KEYMOD_SHIFT, .action = { action_none, NULL } },
};
// clang-format on

// Names of virtual keys
struct virtual_keys {
xkb_keysym_t key;
Expand Down Expand Up @@ -259,44 +171,6 @@ static void set_binding(struct keybind** head, xkb_keysym_t key, uint8_t mods,
}
}

/**
* Create default binding.
* @param head head of binding list
* @param kb default key binding description
*/
static void set_default(struct keybind** head, const struct keybind_default* kb)
{
struct action_seq actions;

if (kb->action.type == action_none && kb->key == XKB_KEY_Delete &&
kb->mods == KEYMOD_SHIFT) {
// special action: Shift+Del
actions.num = 2;
actions.sequence = malloc(actions.num * sizeof(struct action));
if (actions.sequence) {
actions.sequence[0].type = action_exec;
actions.sequence[0].params = str_dup("rm \"%\"", NULL);
actions.sequence[1].type = action_skip_file;
actions.sequence[1].params = NULL;
}
} else {
actions.num = 1;
actions.sequence = malloc(actions.num * sizeof(struct action));
if (actions.sequence) {
actions.sequence[0].type = kb->action.type;
if (kb->action.params) {
actions.sequence[0].params = str_dup(kb->action.params, NULL);
} else {
actions.sequence[0].params = NULL;
}
}
}

if (actions.sequence) {
set_binding(head, kb->key, kb->mods, &actions);
}
}

/**
* Load binding from config parameters.
* @param kb head of binding list
Expand Down Expand Up @@ -336,15 +210,6 @@ static void load_binding(struct keybind** head, struct config* cfg,

void keybind_init(struct config* cfg)
{
// create default bindings
for (size_t i = 0; i < ARRAY_SIZE(default_viewer); ++i) {
set_default(&kb_viewer, &default_viewer[i]);
}
for (size_t i = 0; i < ARRAY_SIZE(default_gallery); ++i) {
set_default(&kb_gallery, &default_gallery[i]);
}

// load bindings from config
load_binding(&kb_viewer, cfg, "keys.viewer");
load_binding(&kb_gallery, cfg, "keys.gallery");
}
Expand Down
Loading

0 comments on commit 41f63ea

Please sign in to comment.