aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarry Jeffery <harry@exec64.co.uk>2018-10-18 23:16:04 +0100
committerGitHub <noreply@github.com>2018-10-18 23:16:04 +0100
commit7e1c122027902f05934c1b700e3697d2451536dc (patch)
tree4c1e2390842c370aea555231d7914df5cc7b2d97
parent7221ef8319ad88c9ab81e7734e89b8debfe861b4 (diff)
parent51837d93572fe229275d239c7a8d4113ef81ea38 (diff)
downloadimv-7e1c122027902f05934c1b700e3697d2451536dc.tar.gz
Merge pull request #134 from Jeinzi/dev-jeinzi
Multiple commands per bind
-rw-r--r--AUTHORS1
-rw-r--r--README.md7
-rw-r--r--doc/imv.5.txt3
-rw-r--r--src/binds.c37
-rw-r--r--src/binds.h2
-rw-r--r--src/commands.c10
-rw-r--r--src/commands.h1
-rw-r--r--src/imv.c21
-rw-r--r--src/list.c1
9 files changed, 55 insertions, 28 deletions
diff --git a/AUTHORS b/AUTHORS
index 99eb671..b88acf6 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -6,6 +6,7 @@ People who have contributed to imv:
* Dmitrij D. Czarkoff
* Jose Diez
* Kenneth Hanley
+ * Julian Heinzel
* Hannes Körber
* Aleksandra Kosiacka
* Michal Koutenský
diff --git a/README.md b/README.md
index 12e3a1d..fd139d2 100644
--- a/README.md
+++ b/README.md
@@ -51,15 +51,16 @@ you like.
In your imv config:
[binds]
- <Shift+x> = exec rm $imv_current_file
+ <Shift+x> = exec rm "$imv_current_file"
+ <Shift+x> = close
-Then press 'X' within imv to delete the image.
+Then press 'X' within imv to delete the image and close it.
#### Rotate an image
In your imv config:
[binds]
- <Shift+r> = exec mogrify -rotate 90 $imv_current_file
+ <Shift+r> = exec mogrify -rotate 90 "$imv_current_file"
Then press 'R' within imv to rotate the image 90 degrees using imagemagick.
diff --git a/doc/imv.5.txt b/doc/imv.5.txt
index cb12eb3..8c376a6 100644
--- a/doc/imv.5.txt
+++ b/doc/imv.5.txt
@@ -96,7 +96,8 @@ Binds
The *[binds]* section allows custom key bindings to be added to imv.
Binds are in the format 'key combination = command'. A key combination can
-consist of multiple keys in succession.
+consist of multiple keys in succession. If there is more then one command
+defined for a given key combination, they are executed one after another.
Single keys such as 'q' are just that: 'q = quit' will bind the 'q' key to the
'quit' command.
diff --git a/src/binds.c b/src/binds.c
index 1649537..9e268b4 100644
--- a/src/binds.c
+++ b/src/binds.c
@@ -5,7 +5,7 @@
struct bind_node {
char *key; /* input key to reach this node */
- char *command; /* command to run for this node, or NULL if not leaf node */
+ struct list *commands; /* commands to run for this node, or NULL if not leaf node */
struct list *suffixes; /* list of bind_node* suffixes, or NULL if leaf node */
};
@@ -24,7 +24,7 @@ static int compare_node_key(const void* item, const void *key)
static void init_bind_node(struct bind_node *bn)
{
bn->key = NULL;
- bn->command = NULL;
+ bn->commands = NULL;
bn->suffixes = list_create();
}
@@ -34,7 +34,9 @@ static void destroy_bind_node(struct bind_node *bn)
destroy_bind_node(bn->suffixes->items[i]);
}
free(bn->key);
- free(bn->command);
+ if(bn->commands) {
+ list_deep_free(bn->commands);
+ }
list_deep_free(bn->suffixes);
}
@@ -49,6 +51,7 @@ struct imv_binds *imv_binds_create(void)
void imv_binds_free(struct imv_binds *binds)
{
destroy_bind_node(&binds->bind_tree);
+ list_deep_free(binds->keys);
free(binds);
}
@@ -69,7 +72,7 @@ enum bind_result imv_binds_add(struct imv_binds *binds, const struct list *keys,
struct bind_node *node = &binds->bind_tree;
for(size_t i = 0; i < keys->len; ++i) {
/* If we've reached a node that already has a command, there's a conflict */
- if(node->command) {
+ if(node->commands) {
result = BIND_INVALID_COMMAND;
break;
}
@@ -81,7 +84,7 @@ enum bind_result imv_binds_add(struct imv_binds *binds, const struct list *keys,
/* Create our new node */
next_node = malloc(sizeof(struct bind_node));
init_bind_node(next_node);
- next_node->key = strdup(keys->items[i]);
+ next_node->key = keys->items[i];
list_append(node->suffixes, next_node);
} else {
next_node = node->suffixes->items[child_index];
@@ -90,15 +93,14 @@ enum bind_result imv_binds_add(struct imv_binds *binds, const struct list *keys,
/* We've now found the correct node for this key */
/* Check if the node has a command */
- if(next_node->command) {
+ if(next_node->commands) {
if(i + 1 < keys->len) {
/* If we're not at the end, it's a conflict */
result = BIND_CONFLICTS;
break;
} else {
- /* Otherwise we just need to overwrite the existing bind. */
- free(next_node->command);
- next_node->command = strdup(command);
+ /* Otherwise we just need to append a new command to the existing bind. */
+ list_append(next_node->commands, strdup(command));
result = BIND_SUCCESS;
break;
}
@@ -110,7 +112,8 @@ enum bind_result imv_binds_add(struct imv_binds *binds, const struct list *keys,
if(next_node->suffixes->len > 0) {
result = BIND_CONFLICTS;
} else {
- next_node->command = strdup(command);
+ next_node->commands = list_create();
+ list_append(next_node->commands, strdup(command));
}
} else {
/* Otherwise, move down the trie */
@@ -133,7 +136,7 @@ enum lookup_result {
LOOKUP_MATCH,
};
-static enum lookup_result bind_lookup(struct bind_node *node, struct list *keys, const char **out_str)
+static enum lookup_result bind_lookup(struct bind_node *node, struct list *keys, struct list **out_list)
{
for(size_t part = 0; part < keys->len; ++part) {
const char* cur_key = keys->items[part];
@@ -151,8 +154,8 @@ static enum lookup_result bind_lookup(struct bind_node *node, struct list *keys,
}
}
- if(node->command) {
- *out_str = node->command;
+ if(node->commands) {
+ *out_list = node->commands;
return LOOKUP_MATCH;
}
return LOOKUP_PARTIAL;
@@ -216,7 +219,7 @@ void imv_bind_clear_input(struct imv_binds *binds)
binds->keys = list_create();
}
-const char *imv_bind_handle_event(struct imv_binds *binds, const SDL_Event *event)
+struct list *imv_bind_handle_event(struct imv_binds *binds, const SDL_Event *event)
{
if(event->key.keysym.sym == SDLK_ESCAPE) {
imv_bind_clear_input(binds);
@@ -230,13 +233,13 @@ const char *imv_bind_handle_event(struct imv_binds *binds, const SDL_Event *even
}
list_append(binds->keys, strdup(buffer));
- const char *command = NULL;
- enum lookup_result result = bind_lookup(&binds->bind_tree, binds->keys, &command);
+ struct list *commands = NULL;
+ enum lookup_result result = bind_lookup(&binds->bind_tree, binds->keys, &commands);
if(result == LOOKUP_PARTIAL) {
return NULL;
} else if(result == LOOKUP_MATCH) {
imv_bind_clear_input(binds);
- return command;
+ return commands;
} else if(result == LOOKUP_INVALID) {
imv_bind_clear_input(binds);
return NULL;
diff --git a/src/binds.h b/src/binds.h
index 05810d8..a720fe1 100644
--- a/src/binds.h
+++ b/src/binds.h
@@ -32,7 +32,7 @@ const struct list *imv_bind_input_buffer(struct imv_binds *binds);
void imv_bind_clear_input(struct imv_binds *binds);
/* Handle an input event, if a bind is triggered, return its command */
-const char *imv_bind_handle_event(struct imv_binds *binds, const SDL_Event *event);
+struct list *imv_bind_handle_event(struct imv_binds *binds, const SDL_Event *event);
/* Convert a string (such as from a config) to a key list */
struct list *imv_bind_parse_keys(const char *keys);
diff --git a/src/commands.c b/src/commands.c
index 7dfbc2c..0fb8b46 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -72,4 +72,14 @@ int imv_command_exec(struct imv_commands *cmds, const char *command, void *data)
return ret;
}
+int imv_command_exec_list(struct imv_commands *cmds, struct list *commands, void *data)
+{
+ int ret = 0;
+ for(size_t i = 0; i < commands->len; ++i) {
+ const char *command = commands->items[i];
+ ret += imv_command_exec(cmds, command, data);
+ }
+ return ret;
+}
+
/* vim:set ts=2 sts=2 sw=2 et: */
diff --git a/src/commands.h b/src/commands.h
index cf3a728..cf81f68 100644
--- a/src/commands.h
+++ b/src/commands.h
@@ -12,6 +12,7 @@ void imv_commands_free(struct imv_commands *cmds);
void imv_command_register(struct imv_commands *cmds, const char *command, void (*handler)(struct list*, const char*, void*));
void imv_command_alias(struct imv_commands *cmds, const char *command, const char *alias);
int imv_command_exec(struct imv_commands *cmds, const char *command, void *data);
+int imv_command_exec_list(struct imv_commands *cmds, struct list *commands, void *data);
#endif
diff --git a/src/imv.c b/src/imv.c
index dc3dedf..fd239bb 100644
--- a/src/imv.c
+++ b/src/imv.c
@@ -129,6 +129,7 @@ static const char *add_bind(struct imv *imv, const char *keys, const char *comma
}
enum bind_result result = imv_binds_add(imv->binds, list, command);
+ list_free(list);
if (result == BIND_SUCCESS) {
return NULL;
@@ -244,10 +245,14 @@ struct imv *imv_create(void)
void imv_free(struct imv *imv)
{
free(imv->font_name);
+ free(imv->title_text);
+ free(imv->overlay_text);
imv_binds_free(imv->binds);
imv_navigator_free(imv->navigator);
imv_loader_free(imv->loader);
imv_commands_free(imv->commands);
+ imv_viewport_free(imv->view);
+ imv_image_free(imv->image);
if(imv->stdin_image_data) {
free(imv->stdin_image_data);
}
@@ -763,7 +768,6 @@ static void handle_event(struct imv *imv, SDL_Event *event)
case SDL_QUIT:
imv_command_exec(imv->commands, "quit", imv);
break;
-
case SDL_TEXTINPUT:
strncat(imv->input_buffer, event->text.text, command_buffer_len - 1);
imv->need_redraw = true;
@@ -780,8 +784,11 @@ static void handle_event(struct imv *imv, SDL_Event *event)
imv->input_buffer = NULL;
imv->need_redraw = true;
} else if(event->key.keysym.sym == SDLK_RETURN) {
- imv_command_exec(imv->commands, imv->input_buffer, imv);
+ struct list *commands = list_create();
+ list_append(commands, imv->input_buffer);
+ imv_command_exec_list(imv->commands, commands, imv);
SDL_StopTextInput();
+ list_free(commands);
free(imv->input_buffer);
imv->input_buffer = NULL;
imv->need_redraw = true;
@@ -806,9 +813,9 @@ static void handle_event(struct imv *imv, SDL_Event *event)
}
break;
default: { /* braces to allow const char *cmd definition */
- const char *cmd = imv_bind_handle_event(imv->binds, event);
- if(cmd) {
- imv_command_exec(imv->commands, cmd, imv);
+ struct list *cmds = imv_bind_handle_event(imv->binds, event);
+ if(cmds) {
+ imv_command_exec_list(imv->commands, cmds, imv);
}
}
}
@@ -921,6 +928,7 @@ static char *get_config_path(void)
wordexp_t word;
if(wordexp(config_paths[i], &word, 0) == 0) {
if (!word.we_wordv[0]) {
+ wordfree(&word);
continue;
}
@@ -1066,7 +1074,7 @@ static int handle_ini_value(void *user, const char *section, const char *name,
bool imv_load_config(struct imv *imv)
{
- const char *path = get_config_path();
+ char *path = get_config_path();
if(!path) {
/* no config, no problem - we have defaults */
return true;
@@ -1080,6 +1088,7 @@ bool imv_load_config(struct imv *imv)
fprintf(stderr, "Error in config file: %s:%d\n", path, err);
return false;
}
+ free(path);
return true;
}
diff --git a/src/list.c b/src/list.c
index 0bc3b7e..4cd7f24 100644
--- a/src/list.c
+++ b/src/list.c
@@ -12,6 +12,7 @@ struct list *list_create(void)
void list_free(struct list *list)
{
free(list->items);
+ free(list);
}
void list_deep_free(struct list *list)