diff options
-rw-r--r-- | examples/skhdrc | 23 | ||||
-rw-r--r-- | src/hotkey.c | 30 | ||||
-rw-r--r-- | src/hotload.c | 48 | ||||
-rw-r--r-- | src/hotload.h | 2 | ||||
-rw-r--r-- | src/parse.c | 66 |
5 files changed, 126 insertions, 43 deletions
diff --git a/examples/skhdrc b/examples/skhdrc index f752f60..e6864e7 100644 --- a/examples/skhdrc +++ b/examples/skhdrc @@ -60,14 +60,14 @@ shift + cmd - j : chunkc tiling::window --warp south shift + cmd - k : chunkc tiling::window --warp north shift + cmd - l : chunkc tiling::window --warp east -# move floating windows / windows on a floating space -shift + alt - up : chunkc tiling::window --warp-floating fullscreen -shift + alt - left : chunkc tiling::window --warp-floating left -shift + alt - right : chunkc tiling::window --warp-floating right -shift + cmd - left : chunkc tiling::window --warp-floating top-left -shift + cmd - right : chunkc tiling::window --warp-floating top-right -shift + ctrl - left : chunkc tiling::window --warp-floating bottom-left -shift + ctrl - right : chunkc tiling::window --warp-floating bottom-right +# make floating window fill screen +shift + alt - up : chunkc tiling::window --grid-layout 1:1:0:0:1:1 + +# make floating window fill left-half of screen +shift + alt - left : chunkc tiling::window --grid-layout 1:2:0:0:1:1 + +# make floating window fill right-half of screen +shift + alt - right : chunkc tiling::window --grid-layout 1:2:1:0:1:1 # send window to desktop shift + alt - x : chunkc tiling::window --send-to-desktop $(chunkc get _last_active_desktop) @@ -137,12 +137,13 @@ alt - d : chunkc tiling::window --toggle parent # toggle window split type alt - e : chunkc tiling::window --toggle split -# float / unfloat window -alt - t : chunkc tiling::window --toggle float +# float / unfloat window and center on screen +alt - t : chunkc tiling::window --toggle float;\ + chunkc tiling::window --grid-layout 4:4:1:1:2:2 # toggle sticky, float and resize to picture-in-picture size alt - s : chunkc tiling::window --toggle sticky;\ - chunkc tiling::window --warp-floating pip-right + chunkc tiling::window --grid-layout 5:5:4:0:1:1 # float next window to be tiled shift + alt - t : chunkc set window_float_next 1 diff --git a/src/hotkey.c b/src/hotkey.c index fae753b..af1e410 100644 --- a/src/hotkey.c +++ b/src/hotkey.c @@ -123,17 +123,21 @@ bool find_and_exec_hotkey(struct hotkey *eventkey, struct table *mode_map, struc } internal void -free_hotkeys(struct table *hotkey_map) +free_hotkeys(struct table *hotkey_map, struct table *freed_pointers) { int count; void **hotkeys = table_reset(hotkey_map, &count); + for (int index = 0; index < count; ++index) { struct hotkey *hotkey = (struct hotkey *) hotkeys[index]; - // the same hotkey can be added for multiple modes - // we need to know if this pointer was already freed - // by a mode that was destroyed before us - // free(hotkey->command); - // free(hotkey); + if (table_find(freed_pointers, hotkey)) { + // we have already freed this pointer, do nothing! + // printf("info: %p has already been freed!\n", hotkey); + } else { + table_add(freed_pointers, hotkey, hotkey); + free(hotkey->command); + free(hotkey); + } } if (count) { @@ -141,20 +145,32 @@ free_hotkeys(struct table *hotkey_map) } } +unsigned long hash_pointer(struct hotkey *a) { return (unsigned long)a; } +bool same_pointer(struct hotkey *a, struct hotkey *b) { return a == b; } + void free_mode_map(struct table *mode_map) { int count; + struct table freed_pointers; void **modes = table_reset(mode_map, &count); + + if (count) { + table_init(&freed_pointers, 13, + (table_hash_func) hash_pointer, + (table_compare_func) same_pointer); + } + for (int index = 0; index < count; ++index) { struct mode *mode = (struct mode *) modes[index]; if (mode->command) free(mode->command); if (mode->name) free(mode->name); - free_hotkeys(&mode->hotkey_map); + free_hotkeys(&mode->hotkey_map, &freed_pointers); free(mode); } if (count) { free(modes); + table_free(&freed_pointers); } } diff --git a/src/hotload.c b/src/hotload.c index 8677cc2..ad02d21 100644 --- a/src/hotload.c +++ b/src/hotload.c @@ -1,4 +1,5 @@ #include "hotload.h" +#include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -40,6 +41,31 @@ file_name(const char *file) return name; } +internal char * +resolve_symlink(char *file) +{ + struct stat buffer; + if (lstat(file, &buffer) != 0) { + return NULL; + } + + if (!S_ISLNK(buffer.st_mode)) { + return file; + } + + ssize_t size = buffer.st_size + 1; + char *result = malloc(size); + ssize_t read = readlink(file, result, size); + + if (read != -1) { + result[read] = '\0'; + return result; + } + + free(result); + return NULL; +} + internal struct watched_file * hotloader_watched_file(struct hotloader *hotloader, char *absolutepath) { @@ -78,14 +104,24 @@ internal FSEVENT_CALLBACK(hotloader_handler) } } -void hotloader_add_file(struct hotloader *hotloader, const char *file) +void hotloader_add_file(struct hotloader *hotloader, char *file) { if (!hotloader->enabled) { - struct watched_file watch_info; - watch_info.directory = file_directory(file); - watch_info.filename = file_name(file); - hotloader->watch_list[hotloader->watch_count++] = watch_info; - printf("hotload: watching file '%s' in directory '%s'\n", watch_info.filename, watch_info.directory); + char *real_path = resolve_symlink(file); + if (real_path) { + struct watched_file watch_info; + watch_info.directory = file_directory(real_path); + watch_info.filename = file_name(real_path); + + if (real_path != file) { + free(real_path); + } + + hotloader->watch_list[hotloader->watch_count++] = watch_info; + printf("hotload: watching file '%s' in directory '%s'\n", watch_info.filename, watch_info.directory); + } else { + fprintf(stderr, "hotload: could not watch file '%s'\n", file); + } } } diff --git a/src/hotload.h b/src/hotload.h index 5948a21..ad782fb 100644 --- a/src/hotload.h +++ b/src/hotload.h @@ -27,6 +27,6 @@ struct hotloader bool hotloader_begin(struct hotloader *hotloader, hotloader_callback *callback); void hotloader_end(struct hotloader *hotloader); -void hotloader_add_file(struct hotloader *hotloader, const char *file); +void hotloader_add_file(struct hotloader *hotloader, char *file); #endif diff --git a/src/parse.c b/src/parse.c index bf5a48d..e807b8a 100644 --- a/src/parse.c +++ b/src/parse.c @@ -12,6 +12,23 @@ #define internal static +internal void +init_default_mode(struct parser *parser) +{ + struct mode *default_mode = malloc(sizeof(struct mode)); + + default_mode->line = -1; + default_mode->cursor = -1; + default_mode->name = copy_string("default"); + + table_init(&default_mode->hotkey_map, 131, + (table_hash_func) hash_hotkey, + (table_compare_func) same_hotkey); + + default_mode->command = NULL; + table_add(parser->mode_map, default_mode->name, default_mode); +} + internal char * read_file(const char *file) { @@ -153,6 +170,11 @@ parse_mode(struct parser *parser, struct hotkey *hotkey) struct mode *mode = table_find(parser->mode_map, name); free(name); + if (!mode && token_equals(identifier, "default")) { + init_default_mode(parser); + mode = table_find(parser->mode_map, "default"); + } + if (!mode) { parser_report_error(parser, Error_Undeclared_Ident, "undeclared identifier"); return; @@ -178,35 +200,40 @@ parse_hotkey(struct parser *parser) memset(hotkey, 0, sizeof(struct hotkey)); bool found_modifier; - printf("(#%d) hotkey :: {\n", parser->current_token.line); + printf("hotkey :: #%d {\n", parser->current_token.line); if (parser_match(parser, Token_Identifier)) { parse_mode(parser, hotkey); if (parser->error) { - return NULL; + goto err; } } if (hotkey->mode_count > 0) { if (!parser_match(parser, Token_Insert)) { parser_report_error(parser, Error_Unexpected_Token, "expected '<'"); - return NULL; + goto err; } } else { - hotkey->mode_list[hotkey->mode_count++] = table_find(parser->mode_map, "default"); + hotkey->mode_list[hotkey->mode_count] = table_find(parser->mode_map, "default"); + if (!hotkey->mode_list[hotkey->mode_count]) { + init_default_mode(parser); + hotkey->mode_list[hotkey->mode_count] = table_find(parser->mode_map, "default"); + } + hotkey->mode_count++; } if ((found_modifier = parser_match(parser, Token_Modifier))) { hotkey->flags = parse_modifier(parser); if (parser->error) { - return NULL; + goto err; } } if (found_modifier) { if (!parser_match(parser, Token_Dash)) { parser_report_error(parser, Error_Unexpected_Token, "expected '-'"); - return NULL; + goto err; } } @@ -218,7 +245,7 @@ parse_hotkey(struct parser *parser) parse_key_literal(parser, hotkey); } else { parser_report_error(parser, Error_Unexpected_Token, "expected key-literal"); - return NULL; + goto err; } if (parser_match(parser, Token_Arrow)) { @@ -232,16 +259,20 @@ parse_hotkey(struct parser *parser) hotkey->command = parse_command(parser); if (!table_find(parser->mode_map, hotkey->command)) { parser_report_error(parser, Error_Undeclared_Ident, "undeclared identifier"); - return NULL; + goto err; } } else { parser_report_error(parser, Error_Unexpected_Token, "expected ':' followed by command or ';' followed by mode"); - return NULL; + goto err; } printf("}\n"); return hotkey; + +err: + free(hotkey); + return NULL; } internal struct mode * @@ -295,16 +326,15 @@ void parse_config(struct parser *parser) (parser_check(parser, Token_Literal)) || (parser_check(parser, Token_Key_Hex)) || (parser_check(parser, Token_Key))) { - hotkey = parse_hotkey(parser); - if (parser->error) { + if ((hotkey = parse_hotkey(parser))) { + for (int i = 0; i < hotkey->mode_count; ++i) { + mode = hotkey->mode_list[i]; + table_add(&mode->hotkey_map, hotkey, hotkey); + } + } else if (parser->error) { free_mode_map(parser->mode_map); return; } - - for (int i = 0; i < hotkey->mode_count; ++i) { - mode = hotkey->mode_list[i]; - table_add(&mode->hotkey_map, hotkey, hotkey); - } } else { parser_report_error(parser, Error_Unexpected_Token, "expected decl, modifier or key-literal"); return; @@ -362,11 +392,11 @@ void parser_report_error(struct parser *parser, enum parse_error_type error_type va_start(args, format); if (error_type == Error_Unexpected_Token) { - fprintf(stderr, "(#%d:%d) ", parser->current_token.line, parser->current_token.cursor); + fprintf(stderr, "#%d:%d: ", parser->current_token.line, parser->current_token.cursor); vfprintf(stderr, format, args); fprintf(stderr, ", but got '%.*s'\n", parser->current_token.length, parser->current_token.text); } else if (error_type == Error_Undeclared_Ident) { - fprintf(stderr, "(#%d:%d) ", parser->previous_token.line, parser->previous_token.cursor); + fprintf(stderr, "#%d:%d: ", parser->previous_token.line, parser->previous_token.cursor); vfprintf(stderr, format, args); fprintf(stderr, " '%.*s'\n", parser->previous_token.length, parser->previous_token.text); } else if (error_type == Error_Duplicate_Ident) { |