Skip to content

Commit

Permalink
Add help buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
richiejp committed Nov 15, 2024
1 parent 5dfe914 commit 2b6edca
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 34 deletions.
127 changes: 105 additions & 22 deletions app/sheet.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,10 +355,13 @@ static zsvsheet_status zsvsheet_find(struct zsvsheet_builtin_proc_state *state,
struct zsvsheet_opts zsvsheet_opts = {0};
int prompt_footer_row = (int)(di->dimensions->rows - di->dimensions->footer_span);

if (!current_ui_buffer->filename)
goto out;

if (!next) {
get_subcommand("Find", prompt_buffer, sizeof(prompt_buffer), prompt_footer_row);
if (*prompt_buffer == '\0') {
goto no_input;
goto out;
} else {
free(state->find);
state->find = strdup(prompt_buffer);
Expand All @@ -370,7 +373,7 @@ static zsvsheet_status zsvsheet_find(struct zsvsheet_builtin_proc_state *state,
&di->update_buffer, state->custom_prop_handler, state->opts_used);
}

no_input:
out:
return zsvsheet_status_ok;
}

Expand Down Expand Up @@ -413,9 +416,12 @@ static zsvsheet_status zsvsheet_filter_handler(struct zsvsheet_proc_context *ctx
int prompt_footer_row = (int)(di->dimensions->rows - di->dimensions->footer_span);
int err;

if (!current_ui_buffer->filename)
goto out;

get_subcommand("Filter", prompt_buffer, sizeof(prompt_buffer), prompt_footer_row);
if (*prompt_buffer == '\0')
goto no_input;
goto out;

const char *data_filename = zsvsheet_buffer_data_filename(current_ui_buffer);
char is_filtered_file = !(data_filename == current_ui_buffer->filename);
Expand Down Expand Up @@ -444,10 +450,85 @@ static zsvsheet_status zsvsheet_filter_handler(struct zsvsheet_proc_context *ctx
free(new_ui_buffer->filename);
new_ui_buffer->filename = strdup(current_ui_buffer->filename);
}
no_input:
out:
return zsvsheet_status_ok;
}

static zsvsheet_status zsvsheet_help_handler(struct zsvsheet_proc_context *ctx) {
struct zsvsheet_builtin_proc_state *state = (struct zsvsheet_builtin_proc_state *)ctx->subcommand_context;
struct zsvsheet_display_info *di = &state->display_info;
struct zsvsheet_screen_buffer_opts bopts = {
.no_rownum_column = 1,
.cell_buff_len = 64,
.max_cell_len = 0,
.rows = 256,
};
struct zsvsheet_ui_buffer_opts uibopts = {
.buff_opts = &bopts,
.filename = NULL,
.no_rownum_col_offset = 1,
};
struct zsvsheet_ui_buffer *uib;
zsvsheet_screen_buffer_t buffer;
enum zsvsheet_priv_status pstat;
enum zsvsheet_status stat = zsvsheet_status_error;
const size_t cols = 3;

buffer = zsvsheet_screen_buffer_new(cols, &bopts, &pstat);
if (pstat != zsvsheet_priv_status_ok)
goto free_buffer;

uib = zsvsheet_ui_buffer_new(buffer, &uibopts);
if (!uib)
goto free_buffer;

const char *head[3] = {"Key(s)", "Action", "Description"};
for (size_t j = 0; j < sizeof(head) / sizeof(head[0]); j++) {
pstat = zsvsheet_screen_buffer_write_cell(buffer, 0, j, (const unsigned char *)head[j]);
if (pstat != zsvsheet_priv_status_ok)
goto free_buffer;
}

size_t row = 1;
for (size_t i = 0; zsvsheet_get_key_binding(i) != NULL; i++) {
struct zsvsheet_key_binding *kb = zsvsheet_get_key_binding(i);
struct zsvsheet_procedure *proc = zsvsheet_find_procedure(kb->proc_id);

if (proc == NULL || kb->hidden)
continue;

const char *desc[3] = {
zsvsheet_key_binding_ch_name(kb),
proc->name,
proc->description,
};

for (size_t j = 0; j < cols; j++) {
pstat = zsvsheet_screen_buffer_write_cell(buffer, row, j, (const unsigned char *)desc[j]);
if (pstat != zsvsheet_priv_status_ok)
goto free_buffer;
}

row++;
}

uib->dimensions.col_count = cols;
uib->dimensions.row_count = row;
uib->buff_used_rows = row;

if (asprintf(&uib->status, "<esc> to exit help ") == -1)
goto free_buffer;

zsvsheet_ui_buffer_push(di->ui_buffers.base, di->ui_buffers.current, uib);
stat = zsvsheet_status_ok;
goto out;

free_buffer:
zsvsheet_screen_buffer_delete(buffer);
out:
return stat;
}

/* We do most procedures in one handler. More complex procedures can be
* separated into their own handlers.
*/
Expand Down Expand Up @@ -510,32 +591,34 @@ zsvsheet_status zsvsheet_builtin_proc_handler(struct zsvsheet_proc_context *ctx)
struct builtin_proc_desc {
int proc_id;
const char *name;
const char *description;
zsvsheet_proc_fn handler;
} builtin_procedures[] = {
{ zsvsheet_builtin_proc_quit, "quit", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_escape, NULL, zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_move_bottom, NULL, zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_move_top, NULL, zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_move_first_col, NULL, zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_pg_down, "pageup", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_pg_up, "pagedn", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_move_last_col, NULL, zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_move_up, NULL, zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_move_down, NULL, zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_move_left, NULL, zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_move_right, NULL, zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_find, NULL, zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_find_next, NULL, zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_resize, NULL, zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_open_file, "open", zsvsheet_open_file_handler },
{ zsvsheet_builtin_proc_filter, "filter", zsvsheet_filter_handler },
{ zsvsheet_builtin_proc_quit, "quit", "Exit the application", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_escape, "escape", "Leave the current view or cancel a subcommand", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_move_bottom, "bottom", "Jump to the last row", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_move_top, "top", "Jump to the first row", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_move_first_col, "first", "Jump to the first column", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_pg_down, "pagedown", "Move down one page", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_pg_up, "pageup", "Move up one page", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_move_last_col, "last", "Jump to the last column", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_move_up, "up", "Move up one row", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_move_down, "down", "Move down one row", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_move_left, "left", "Move left one column", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_move_right, "right", "Move right one column", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_find, "find", "Set a search term and jump to the first result after the cursor", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_find_next, "next", "Jump to the next search result", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_resize, "resize", "Resize the layout to fit new terminal dimensions", zsvsheet_builtin_proc_handler },
{ zsvsheet_builtin_proc_open_file, "open", "Open a another CSV file", zsvsheet_open_file_handler },
{ zsvsheet_builtin_proc_filter, "filter", "Hide rows that do not contain the specified text", zsvsheet_filter_handler },
{ zsvsheet_builtin_proc_help, "help", "Display a list of actions and key-bindings", zsvsheet_help_handler },
{ -1, NULL, NULL }
};
/* clang-format on */

void zsvsheet_register_builtin_procedures(void) {
for (struct builtin_proc_desc *desc = builtin_procedures; desc->proc_id != -1; ++desc) {
if (zsvsheet_register_builtin_proc(desc->proc_id, desc->name, desc->handler) < 0) {
if (zsvsheet_register_builtin_proc(desc->proc_id, desc->name, desc->description, desc->handler) < 0) {
fprintf(stderr, "failed to register builtin procedure\n");
}
}
Expand Down
77 changes: 72 additions & 5 deletions app/sheet/key-bindings.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#include "procedure.h"
#include "key-bindings.h"

#include <curses.h>
#include <errno.h>
#include <stdio.h>
#include <assert.h>

#ifndef ZSVSHEET_CTRL
/* clang-format off */
Expand Down Expand Up @@ -51,6 +54,16 @@ int zsvsheet_register_proc_key_binding(char ch, zsvsheet_proc_id_t proc_id) {
return zsvsheet_register_key_binding(&binding);
}

struct zsvsheet_key_binding *zsvsheet_get_key_binding(size_t i) {
if (i >= MAX_KEY_BINDINGS)
return NULL;

if (key_bindings[i].ch != -1)
return &key_bindings[i];

return NULL;
}

struct zsvsheet_key_binding *zsvsheet_find_key_binding(int ch) {
for (int i = 0; i < MAX_KEY_BINDINGS; ++i) {
if (key_bindings[i].ch == ch)
Expand Down Expand Up @@ -111,8 +124,11 @@ struct zsvsheet_key_binding zsvsheet_vim_key_bindings[] = {
{ .ch = 'q', .proc_id = zsvsheet_builtin_proc_quit, },

{ .ch = 27, .proc_id = zsvsheet_builtin_proc_escape, },
{ .ch = KEY_RESIZE, .proc_id = zsvsheet_builtin_proc_resize, },

{
.ch = KEY_RESIZE,
.proc_id = zsvsheet_builtin_proc_resize,
.hidden = 1,
},
{ .ch = '^', .proc_id = zsvsheet_builtin_proc_move_first_col,},
{ .ch = '$', .proc_id = zsvsheet_builtin_proc_move_last_col, },
{ .ch = KEY_SLEFT, .proc_id = zsvsheet_builtin_proc_move_first_col,},
Expand All @@ -132,7 +148,12 @@ struct zsvsheet_key_binding zsvsheet_vim_key_bindings[] = {
{ .ch = KEY_NPAGE, .proc_id = zsvsheet_builtin_proc_pg_down, },
{ .ch = KEY_PPAGE, .proc_id = zsvsheet_builtin_proc_pg_up, },

{ .ch = 'g', .handler = zsvsheet_vim_g_key_binding_dmux_handler },
{
.ch = 'g',
.ch_name = "g g",
.proc_id = zsvsheet_builtin_proc_move_top,
.handler = zsvsheet_vim_g_key_binding_dmux_handler
},
{ .ch = 'G', .proc_id = zsvsheet_builtin_proc_move_bottom, },
/* Shift up/down also move you to the top/bottom of the page but have a
* slightly different behaviour in terms of what ends up in the view but
Expand All @@ -150,6 +171,7 @@ struct zsvsheet_key_binding zsvsheet_vim_key_bindings[] = {
/* Open is a subcommand only in vim. Keeping the binding for now */
{ .ch = 'e', .proc_id = zsvsheet_builtin_proc_open_file, },
{ .ch = 'f', .proc_id = zsvsheet_builtin_proc_filter, },
{ .ch = '?', .proc_id = zsvsheet_builtin_proc_help, },

{ .ch = -1 }
};
Expand Down Expand Up @@ -183,8 +205,11 @@ zsvsheet_status zsvsheet_emacs_Cs_key_binding_dmux_handler(struct zsvsheet_key_b
/* clang-format off */
struct zsvsheet_key_binding zsvsheet_emacs_key_bindings[] = {
{ .ch = 27, .proc_id = zsvsheet_builtin_proc_escape, },
{ .ch = KEY_RESIZE, .proc_id = zsvsheet_builtin_proc_resize, },

{
.ch = KEY_RESIZE,
.proc_id = zsvsheet_builtin_proc_resize,
.hidden = 1,
},
{ .ch = ZSVSHEET_CTRL('a'), .proc_id = zsvsheet_builtin_proc_move_first_col,},
{ .ch = ZSVSHEET_CTRL('e'), .proc_id = zsvsheet_builtin_proc_move_last_col,},

Expand All @@ -206,6 +231,8 @@ struct zsvsheet_key_binding zsvsheet_emacs_key_bindings[] = {
{ .ch = ZSVSHEET_CTRL('f'), .handler = zsvsheet_emacs_Cf_key_binding_dmux_handler, },
/* No such thing in emacs, find a more suitable binding */
{ .ch = 'f', .proc_id = zsvsheet_builtin_proc_filter, },
{ .ch = ZSVSHEET_CTRL('h'), .proc_id = zsvsheet_builtin_proc_help, },


{ .ch = -1 }
};
Expand All @@ -214,3 +241,43 @@ struct zsvsheet_key_binding zsvsheet_emacs_key_bindings[] = {
void zsvsheet_register_emacs_key_bindings(void) {
zsvsheet_register_builtin_key_bindings(zsvsheet_emacs_key_bindings);
}

struct zsvsheet_ch_name {
int ch;
const char *name;
};

/* clang-format off */
struct zsvsheet_ch_name zsvsheet_common_ch_names[] = {
{ .ch = KEY_RESIZE, .name = "<resize>" },
{ .ch = 27, .name = "<esc>" },
{ .ch = KEY_SLEFT, .name = "<shift><left>" },
{ .ch = KEY_SRIGHT, .name = "<shift><right>" },
{ .ch = KEY_UP, .name = "<up>" },
{ .ch = KEY_DOWN, .name = "<down>" },
{ .ch = KEY_LEFT, .name = "<left>" },
{ .ch = KEY_RIGHT, .name = "<right>" },
{ .ch = ZSVSHEET_CTRL('a'), .name = "<ctrl>a" },
{ .ch = ZSVSHEET_CTRL('d'), .name = "<ctrl>d" },
{ .ch = ZSVSHEET_CTRL('e'), .name = "<ctrl>e" },
{ .ch = ZSVSHEET_CTRL('f'), .name = "<ctrl>f" },
{ .ch = ZSVSHEET_CTRL('h'), .name = "<ctrl>f" },
{ .ch = ZSVSHEET_CTRL('u'), .name = "<ctrl>u" },
{ .ch = ZSVSHEET_CTRL('v'), .name = "<ctrl>v" },
{ .ch = KEY_NPAGE, .name = "<page up>" },
{ .ch = KEY_PPAGE, .name = "<page down>" },
{ .ch = -1 },
};
/* clang-format on */

const char *zsvsheet_key_binding_ch_name(struct zsvsheet_key_binding *binding) {
if (binding->ch_name)
return binding->ch_name;

for (int i = 0; zsvsheet_common_ch_names[i].ch != -1; i++) {
if (zsvsheet_common_ch_names[i].ch == binding->ch)
return zsvsheet_common_ch_names[i].name;
}

return keyname(binding->ch);
}
8 changes: 7 additions & 1 deletion app/sheet/key-bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ enum zsvsheet_key {
zsvsheet_key_find,
zsvsheet_key_find_next,
zsvsheet_key_open_file,
zsvsheet_key_resize
zsvsheet_key_resize,
zsvsheet_key_question,
};

struct zsvsheet_key_binding_context;
Expand All @@ -32,6 +33,8 @@ typedef zsvsheet_status (*zsvsheet_key_binding_fn)(struct zsvsheet_key_binding_c
* be implemented if need be by defining a custom handler */
struct zsvsheet_key_binding {
int ch;
const char *ch_name;
char hidden;
zsvsheet_key_binding_fn handler;
zsvsheet_proc_id_t proc_id;
};
Expand All @@ -51,6 +54,7 @@ int zsvsheet_register_key_binding(struct zsvsheet_key_binding *binding);

zsvsheet_status zsvsheet_key_press(int ch, void *subcommand_context);

struct zsvsheet_key_binding *zsvsheet_get_key_binding(size_t i);
struct zsvsheet_key_binding *zsvsheet_find_key_binding(int ch);

/*
Expand All @@ -61,4 +65,6 @@ void zsvsheet_register_vim_key_bindings(void);

void zsvsheet_register_emacs_key_bindings(void);

const char *zsvsheet_key_binding_ch_name(struct zsvsheet_key_binding *binding);

#endif
11 changes: 7 additions & 4 deletions app/sheet/procedure.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
struct zsvsheet_procedure {
zsvsheet_proc_id_t id;
const char *name;
const char *description;
zsvsheet_proc_fn handler;
};

Expand Down Expand Up @@ -75,12 +76,14 @@ static zsvsheet_proc_id_t zsvsheet_do_register_proc(struct zsvsheet_procedure *p
return proc->id;
}

zsvsheet_proc_id_t zsvsheet_register_builtin_proc(zsvsheet_proc_id_t id, const char *name, zsvsheet_proc_fn handler) {
struct zsvsheet_procedure procedure = {.id = id, .name = name, .handler = handler};
zsvsheet_proc_id_t zsvsheet_register_builtin_proc(zsvsheet_proc_id_t id, const char *name, const char *description,
zsvsheet_proc_fn handler) {
struct zsvsheet_procedure procedure = {.id = id, .name = name, .description = description, .handler = handler};
return zsvsheet_do_register_proc(&procedure);
}

zsvsheet_proc_id_t zsvsheet_register_proc(const char *name, zsvsheet_proc_fn handler) {
struct zsvsheet_procedure procedure = {.id = zsvsheet_generate_proc_id(), .name = name, .handler = handler};
zsvsheet_proc_id_t zsvsheet_register_proc(const char *name, const char *description, zsvsheet_proc_fn handler) {
struct zsvsheet_procedure procedure = {
.id = zsvsheet_generate_proc_id(), .name = name, .description = description, .handler = handler};
return zsvsheet_do_register_proc(&procedure);
}
7 changes: 5 additions & 2 deletions app/sheet/procedure.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ enum {
zsvsheet_builtin_proc_open_file,
zsvsheet_builtin_proc_resize,
zsvsheet_builtin_proc_prompt,
zsvsheet_builtin_proc_help,
zsvsheet_builtin_proc_vim_g_key_binding_dmux,
};

#define ZSVSHEET_PROC_INVALID 0
Expand Down Expand Up @@ -73,9 +75,10 @@ zsvsheet_status zsvsheet_proc_invoke_from_keypress(zsvsheet_proc_id_t proc_id, i
zsvsheet_status zsvsheet_proc_invoke(zsvsheet_proc_id_t proc_id, struct zsvsheet_proc_context *ctx);

/* Register builtin procedure with fixed id */
zsvsheet_proc_id_t zsvsheet_register_builtin_proc(zsvsheet_proc_id_t id, const char *name, zsvsheet_proc_fn handler);
zsvsheet_proc_id_t zsvsheet_register_builtin_proc(zsvsheet_proc_id_t id, const char *name, const char *description,
zsvsheet_proc_fn handler);

/* Dynamically register a procedure, returns a positive id or negative error */
zsvsheet_proc_id_t zsvsheet_register_proc(const char *name, zsvsheet_proc_fn handler);
zsvsheet_proc_id_t zsvsheet_register_proc(const char *name, const char *description, zsvsheet_proc_fn handler);

#endif /* ZSVSHEET_PROCEDURE_H */

0 comments on commit 2b6edca

Please sign in to comment.