aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/skhdrc23
-rw-r--r--src/hotkey.c30
-rw-r--r--src/hotload.c48
-rw-r--r--src/hotload.h2
-rw-r--r--src/parse.c66
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) {