Skip to content

Commit

Permalink
Sheet edit open (#223)
Browse files Browse the repository at this point in the history
* added edit/open cmd
* TO DO: support multiple nested row_filters. show file name in status bar. add menus. etc
* TO DO: add tests for this feature
  • Loading branch information
liquidaty authored Oct 12, 2024
1 parent d074e7a commit eb3a20c
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 110 deletions.
147 changes: 86 additions & 61 deletions app/sheet.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <errno.h>

#include <zsv.h>
#include "sheet/sheet_internal.h"
Expand All @@ -31,6 +32,9 @@
#include <pthread.h>
#endif

#define ZSV_COMMAND sheet
#include "zsv_command.h"

#include "sheet/buffer.h"
#include "sheet/buffer.c"

Expand Down Expand Up @@ -98,12 +102,11 @@ size_t zsvsheet_get_input_raw_row(struct zsvsheet_rowcol *input_offset, struct z
#include "sheet/cursor.c"

// zsvsheet_handle_find_next: return non-zero if a result was found
char zsvsheet_handle_find_next(struct zsvsheet_ui_buffer *uib, const char *filename, const char *needle,
struct zsv_opts *zsv_opts, struct zsvsheet_opts *zsvsheet_opts, size_t header_span,
char zsvsheet_handle_find_next(struct zsvsheet_ui_buffer *uib, const char *needle, const struct zsv_opts *zsv_opts,
struct zsvsheet_opts *zsvsheet_opts, size_t header_span,
struct zsvsheet_display_dimensions *ddims, int *update_buffer,
struct zsv_prop_handler *custom_prop_handler, const char *opts_used) {
if (zsvsheet_find_next(uib, filename, needle, zsv_opts, zsvsheet_opts, header_span, custom_prop_handler, opts_used) >
0) {
if (zsvsheet_find_next(uib, needle, zsv_opts, zsvsheet_opts, header_span, custom_prop_handler, opts_used) > 0) {
*update_buffer = zsvsheet_goto_input_raw_row(uib, zsvsheet_opts->found_rownum, header_span, ddims, (size_t)-1);
return 1;
}
Expand Down Expand Up @@ -153,8 +156,32 @@ void zsvsheet_set_status(struct zsvsheet_display_dimensions *ddims, int overwrit

#include "sheet/terminfo.c"

#define ZSV_COMMAND sheet
#include "zsv_command.h"
int zsvsheet_ui_buffer_open_file(const char *filename, const struct zsv_opts *zsv_optsp, const char *row_filter,
struct zsv_prop_handler *custom_prop_handler, const char *opts_used,
struct zsvsheet_ui_buffer **ui_buffer_stack_bottom,
struct zsvsheet_ui_buffer **ui_buffer_stack_top) {
struct zsvsheet_buffer_opts bopts = {0};
struct zsvsheet_ui_buffer_opts uibopts = {0};
uibopts.filename = filename;
uibopts.buff_opts = &bopts;
struct zsvsheet_opts zsvsheet_opts = {0};
struct zsv_opts opts = *zsv_optsp;
int err = 0;
struct zsvsheet_ui_buffer *tmp_ui_buffer = NULL;
uibopts.row_filter = row_filter;
if ((err = read_data(&tmp_ui_buffer, &uibopts, &opts, 0, 0, 0, NULL, &zsvsheet_opts, custom_prop_handler,
opts_used)) != 0 ||
!tmp_ui_buffer || !tmp_ui_buffer->buff_used_rows) {
zsvsheet_ui_buffer_delete(tmp_ui_buffer);
if (err)
return err;
return -1;
}
tmp_ui_buffer->cursor_row = 1; // first row is header
zsvsheet_ui_buffer_push(ui_buffer_stack_bottom, ui_buffer_stack_top, tmp_ui_buffer);
return 0;
}

#include "sheet/usage.c"

int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *optsp,
Expand All @@ -164,11 +191,6 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op
return zsv_status_ok;
}

if (argc < 2) {
fprintf(stderr, "Please specify an input file\n");
return 1;
}

const char *locale = setlocale(LC_ALL, "C.UTF-8");
if (!locale || strstr(locale, "UTF-8") == NULL)
locale = setlocale(LC_ALL, "");
Expand All @@ -182,31 +204,33 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op
return 1;
}

const char *filename = argv[1];
char *find = NULL;
struct zsvsheet_ui_buffer *ui_buffers = NULL;
struct zsvsheet_ui_buffer *current_ui_buffer = NULL;
struct zsvsheet_ui_buffer *tmp_ui_buffer;
struct zsv_opts opts = *optsp;

size_t header_span = 0; // number of rows that comprise the header
struct zsvsheet_opts zsvsheet_opts = {0};
int err;
struct zsvsheet_buffer_opts bopts = {0};
tmp_ui_buffer = NULL;
struct zsvsheet_ui_buffer_opts uibopts = {0};
uibopts.buff_opts = &bopts;
if ((err = read_data(&tmp_ui_buffer, &uibopts, filename, &opts, 0, 0, 0, NULL, &zsvsheet_opts, custom_prop_handler,
opts_used)) != 0 ||
!tmp_ui_buffer || !tmp_ui_buffer->buff_used_rows) {
if (err)
perror(filename);
else
fprintf(stderr, "%s: no data found", filename);
zsvsheet_ui_buffer_delete(tmp_ui_buffer);
return -1;
{
struct zsvsheet_ui_buffer *tmp_ui_buffer;
zsvsheet_ui_buffer_new_blank(&tmp_ui_buffer);
if (!tmp_ui_buffer) {
fprintf(stderr, "Out of memory!\n");
return ENOMEM;
}
zsvsheet_ui_buffer_push(&ui_buffers, &current_ui_buffer, tmp_ui_buffer);
}

if (argc > 1) {
const char *filename = argv[1];
if ((err = zsvsheet_ui_buffer_open_file(filename, optsp, NULL, custom_prop_handler, opts_used, &ui_buffers,
&current_ui_buffer))) {
if (err > 0)
perror(filename);
else
fprintf(stderr, "%s: no data found", filename); // to do: change this to a base-buff status msg
return -1;
}
}
zsvsheet_ui_buffer_push(&ui_buffers, &current_ui_buffer, tmp_ui_buffer);

header_span = 1;
initscr();
Expand All @@ -216,7 +240,6 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op
struct zsvsheet_display_dimensions display_dims = get_display_dimensions(1, 1);

int zsvsheetch;
current_ui_buffer->cursor_row = 1; // first row is header
size_t rownum_col_offset = 1;
display_buffer_subtable(current_ui_buffer, rownum_col_offset, header_span, &display_dims);
char cmdbuff[256]; // subcommand buffer
Expand Down Expand Up @@ -316,18 +339,19 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op
: current_ui_buffer->dimensions.col_count + rownum_col_offset,
&current_ui_buffer->cursor_col, &current_ui_buffer->buff_offset.col);
break;
case zsvsheet_key_escape: // escape
tmp_ui_buffer = zsvsheet_ui_buffer_pop(&ui_buffers, &current_ui_buffer);
if (tmp_ui_buffer) {
zsvsheet_ui_buffer_delete(tmp_ui_buffer);
update_buffer = 1;
break;
case zsvsheet_key_escape: // escape
if (current_ui_buffer->prior) { // current_ui_buffer is not the base/blank buffer
if (zsvsheet_ui_buffer_pop(&ui_buffers, &current_ui_buffer, NULL)) {
update_buffer = 1;
break;
}
}
continue;
case zsvsheet_key_find_next:
if (find) {
if (!zsvsheet_handle_find_next(current_ui_buffer, filename, find, &opts, &zsvsheet_opts, header_span,
&display_dims, &update_buffer, custom_prop_handler, opts_used))
struct zsvsheet_opts zsvsheet_opts = {0};
if (!zsvsheet_handle_find_next(current_ui_buffer, find, optsp, &zsvsheet_opts, header_span, &display_dims,
&update_buffer, custom_prop_handler, opts_used))
continue;
}
break;
Expand All @@ -336,44 +360,45 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op
if (*cmdbuff != '\0') {
free(find);
find = strdup(cmdbuff);
if (!zsvsheet_handle_find_next(current_ui_buffer, filename, find, &opts, &zsvsheet_opts, header_span,
&display_dims, &update_buffer, custom_prop_handler, opts_used))
struct zsvsheet_opts zsvsheet_opts = {0};
if (!zsvsheet_handle_find_next(current_ui_buffer, find, optsp, &zsvsheet_opts, header_span, &display_dims,
&update_buffer, custom_prop_handler, opts_used))
continue;
}
break;
case zsvsheet_key_open_file:
case zsvsheet_key_filter:
get_subcommand("Filter", cmdbuff, sizeof(cmdbuff), (int)(display_dims.rows - display_dims.footer_span));
if (*cmdbuff != '\0') {
tmp_ui_buffer = NULL;
uibopts.row_filter = cmdbuff;
if ((err = read_data(&tmp_ui_buffer, &uibopts, filename, &opts, 0, 0, 0, NULL, // header_span, NULL,
&zsvsheet_opts, custom_prop_handler, opts_used)) != 0) {
zsvsheet_set_status(&display_dims, 1, "Unexpected error!"); // to do: better error message
zsvsheet_ui_buffer_delete(tmp_ui_buffer);
continue;
} else if (tmp_ui_buffer->buff_used_rows > 1) {
zsvsheet_ui_buffer_push(&ui_buffers, &current_ui_buffer, tmp_ui_buffer);
current_ui_buffer->cursor_row = 1;
// not sure why but using ncurses, erase() and refresh() needed for screen to properly redraw
erase();
refresh();
} else {
zsvsheet_ui_buffer_delete(tmp_ui_buffer);
get_subcommand(zsvsheetch == zsvsheet_key_filter ? "Filter" : "File to open", cmdbuff, sizeof(cmdbuff),
(int)(display_dims.rows - display_dims.footer_span));
if (*cmdbuff == '\0')
continue;

if ((err = zsvsheet_ui_buffer_open_file(zsvsheetch == zsvsheet_key_filter ? current_ui_buffer->filename : cmdbuff,
optsp, zsvsheetch == zsvsheet_key_filter ? cmdbuff : NULL,
custom_prop_handler, opts_used, &ui_buffers, &current_ui_buffer))) {
if (err > 0)
zsvsheet_set_status(&display_dims, 1, "%s: %s", current_ui_buffer->filename, strerror(err));
else if (err < 0)
zsvsheet_set_status(&display_dims, 1, "Unexpected error");
else
zsvsheet_set_status(&display_dims, 1, "Not found: %s", cmdbuff);
continue;
}
continue;
} else if (zsvsheetch == zsvsheet_key_filter && current_ui_buffer->dimensions.row_count < 2) {
zsvsheet_ui_buffer_pop(&ui_buffers, &current_ui_buffer, NULL);
zsvsheet_set_status(&display_dims, 1, "Not found: %s", cmdbuff);
}
break;
}
if (update_buffer) {
if (read_data(&current_ui_buffer, NULL, filename, &opts, current_ui_buffer->input_offset.row,
struct zsvsheet_opts zsvsheet_opts = {0};
if (read_data(&current_ui_buffer, NULL, optsp, current_ui_buffer->input_offset.row,
current_ui_buffer->input_offset.col, header_span, current_ui_buffer->dimensions.index,
&zsvsheet_opts, custom_prop_handler, opts_used)) {
zsvsheet_set_status(&display_dims, 1, "Unexpected error!"); // to do: better error message
continue;
}
}
if (current_ui_buffer->status) // filter_dimensions.row_count)
if (current_ui_buffer->status)
zsvsheet_set_status(&display_dims, 1, current_ui_buffer->status);
display_buffer_subtable(current_ui_buffer, rownum_col_offset, header_span, &display_dims);
}
Expand Down
28 changes: 15 additions & 13 deletions app/sheet/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,11 @@ void zsvsheet_buffer_delete(zsvsheet_buffer_t buff) {
}
}

zsvsheet_buffer_t zsvsheet_buffer_new(size_t cols, struct zsvsheet_buffer_opts *opts,
enum zsvsheet_buffer_status *stat) {
*stat = zsvsheet_buffer_status_ok;
zsvsheet_buffer_t zsvsheet_buffer_new(size_t cols, struct zsvsheet_buffer_opts *opts, enum zsvsheet_status *stat) {
struct zsvsheet_buffer_opts bopts = {0};
if (!opts)
opts = &bopts;
*stat = zsvsheet_status_ok;
if (opts->rows == 0)
opts->rows = ZSVSHEET_BUFFER_DEFAULT_ROW_COUNT;
else if (opts->rows < 256)
Expand All @@ -73,17 +75,17 @@ zsvsheet_buffer_t zsvsheet_buffer_new(size_t cols, struct zsvsheet_buffer_opts *
if (opts->max_cell_len == 0)
opts->max_cell_len = ZSVSHEET_BUFFER_DEFAULT_MAX_CELL_LEN;
if (opts->cell_buff_len < sizeof(void *) * 2)
*stat = zsvsheet_buffer_status_error;
*stat = zsvsheet_status_error;
else {
if (!opts->no_rownum_column)
cols++;
void *data = calloc(opts->rows, cols * opts->cell_buff_len);
if (!data)
*stat = zsvsheet_buffer_status_memory;
*stat = zsvsheet_status_memory;
else {
struct zsvsheet_buffer *buff = calloc(1, sizeof(*buff));
if (!buff)
*stat = zsvsheet_buffer_status_memory;
*stat = zsvsheet_status_memory;
else {
buff->opts.rows = opts->rows;
buff->cols = cols;
Expand All @@ -101,9 +103,9 @@ zsvsheet_buffer_t zsvsheet_buffer_new(size_t cols, struct zsvsheet_buffer_opts *
#define UTF8_NOT_FIRST_CHAR(x) ((x & 0xC0) == 0x80)
#endif

enum zsvsheet_buffer_status zsvsheet_buffer_write_cell_w_len(zsvsheet_buffer_t buff, size_t row, size_t col,
const unsigned char *value, size_t len) {
enum zsvsheet_buffer_status stat = zsvsheet_buffer_status_ok;
enum zsvsheet_status zsvsheet_buffer_write_cell_w_len(zsvsheet_buffer_t buff, size_t row, size_t col,
const unsigned char *value, size_t len) {
enum zsvsheet_status stat = zsvsheet_status_ok;
size_t offset = buffer_data_offset(buff, row, col);
free_long_cell(buff, offset);
if (len < buff->opts.cell_buff_len) {
Expand All @@ -120,7 +122,7 @@ enum zsvsheet_buffer_status zsvsheet_buffer_write_cell_w_len(zsvsheet_buffer_t b
len--;
}
if (!len) // the only reason len could be 0 is if our input was not valid utf8, but check to make sure anyway
stat = zsvsheet_buffer_status_utf8;
stat = zsvsheet_status_utf8;
else {
char *value_copy = malloc(1 + len);
if (value_copy) {
Expand All @@ -129,14 +131,14 @@ enum zsvsheet_buffer_status zsvsheet_buffer_write_cell_w_len(zsvsheet_buffer_t b
set_long_cell(buff, offset, value_copy);
buff->long_cell_count++;
} else
stat = zsvsheet_buffer_status_memory;
stat = zsvsheet_status_memory;
}
}
return stat;
}

enum zsvsheet_buffer_status zsvsheet_buffer_write_cell(zsvsheet_buffer_t buff, size_t row, size_t col,
const unsigned char *value) {
enum zsvsheet_status zsvsheet_buffer_write_cell(zsvsheet_buffer_t buff, size_t row, size_t col,
const unsigned char *value) {
return zsvsheet_buffer_write_cell_w_len(buff, row, col, value, strlen((void *)value));
}

Expand Down
18 changes: 5 additions & 13 deletions app/sheet/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,20 @@

typedef struct zsvsheet_buffer *zsvsheet_buffer_t;

enum zsvsheet_buffer_status {
zsvsheet_buffer_status_ok = 0,
zsvsheet_buffer_status_memory,
zsvsheet_buffer_status_error, // generic error
zsvsheet_buffer_status_utf8
};

struct zsvsheet_buffer_opts {
size_t cell_buff_len; // default = 16. must be >= 2 * sizeof(void *)
size_t max_cell_len; // length in bytes; defaults to 32767
size_t rows; // rows to buffer. cannot be < 256
char no_rownum_column; // reserved. TO DO: if set, omit row num column
};

zsvsheet_buffer_t zsvsheet_buffer_new(size_t cols, struct zsvsheet_buffer_opts *opts,
enum zsvsheet_buffer_status *stat);
zsvsheet_buffer_t zsvsheet_buffer_new(size_t cols, struct zsvsheet_buffer_opts *opts, enum zsvsheet_status *stat);

enum zsvsheet_buffer_status zsvsheet_buffer_write_cell(zsvsheet_buffer_t buff, size_t row, size_t col,
const unsigned char *value);
enum zsvsheet_status zsvsheet_buffer_write_cell(zsvsheet_buffer_t buff, size_t row, size_t col,
const unsigned char *value);

enum zsvsheet_buffer_status zsvsheet_buffer_write_cell_w_len(zsvsheet_buffer_t buff, size_t row, size_t col,
const unsigned char *value, size_t len);
enum zsvsheet_status zsvsheet_buffer_write_cell_w_len(zsvsheet_buffer_t buff, size_t row, size_t col,
const unsigned char *value, size_t len);

const unsigned char *zsvsheet_buffer_cell_display(zsvsheet_buffer_t buff, size_t row, size_t col);

Expand Down
2 changes: 2 additions & 0 deletions app/sheet/key-bindings.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
static enum zsvsheet_key zsvsheet_key_binding(int ch) {
if (ch == 27) // escape
return zsvsheet_key_escape;
if (ch == 'e') // edit / open
return zsvsheet_key_open_file;
if (ch == KEY_SF) // shift + down
return zsvsheet_key_move_bottom;
if (ch == KEY_SR) // shift + up
Expand Down
3 changes: 2 additions & 1 deletion app/sheet/key-bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ enum zsvsheet_key {
zsvsheet_key_move_right,
zsvsheet_key_filter,
zsvsheet_key_find,
zsvsheet_key_find_next
zsvsheet_key_find_next,
zsvsheet_key_open_file
};

#endif
Loading

0 comments on commit eb3a20c

Please sign in to comment.