Cleaned up the command parsing code a bit to be slightly more correct
and more compact. Now uses if-else-if chain instead of nested switch statements. This may be very slightly less performant, but probably not noticeable and much cleaner code.
This commit is contained in:
parent
e2152a57a3
commit
e40feed849
120
bb.c
120
bb.c
@ -59,7 +59,7 @@ void bb_browse(bb_t *bb, const char *path)
|
||||
while (cmdfile && getdelim(&cmd, &space, '\0', cmdfile) >= 0) {
|
||||
cmdpos = ftell(cmdfile);
|
||||
if (!cmd[0]) continue;
|
||||
process_cmd(bb, cmd);
|
||||
run_bbcmd(bb, cmd);
|
||||
if (bb->dirty) {
|
||||
free(cmd);
|
||||
fclose(cmdfile);
|
||||
@ -121,7 +121,7 @@ void bb_browse(bb_t *bb, const char *path)
|
||||
if (cmdpos != 0)
|
||||
err("Command file still open");
|
||||
if (is_simple_bbcmd(binding->script)) {
|
||||
process_cmd(bb, binding->script);
|
||||
run_bbcmd(bb, binding->script);
|
||||
} else {
|
||||
move_cursor(tty_out, 0, termheight-1);
|
||||
restore_term(&default_termios);
|
||||
@ -405,6 +405,16 @@ entry_t* load_entry(bb_t *bb, const char *path, int clear_dots)
|
||||
return entry;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return whether a string matches a command
|
||||
* e.g. matches_cmd("cd:..", "cd") == 1, matches_cmd("q", "quit") == 1
|
||||
*/
|
||||
static inline int matches_cmd(const char *str, const char *cmd)
|
||||
{
|
||||
while (*str == *cmd && *cmd) ++str, ++cmd;
|
||||
return *str == '\0' || *str == ':';
|
||||
}
|
||||
|
||||
/*
|
||||
* Memory allocation failures are unrecoverable in bb, so this wrapper just
|
||||
* prints an error message and exits if that happens.
|
||||
@ -565,23 +575,20 @@ void print_bindings(int fd)
|
||||
* Run a bb internal command (e.g. "+refresh") and return an indicator of what
|
||||
* needs to happen next.
|
||||
*/
|
||||
bb_result_t process_cmd(bb_t *bb, const char *cmd)
|
||||
bb_result_t run_bbcmd(bb_t *bb, const char *cmd)
|
||||
{
|
||||
if (cmd[0] == '+') ++cmd;
|
||||
else if (strncmp(cmd, "bb +", 4) == 0) cmd = &cmd[4];
|
||||
const char *value = strchr(cmd, ':');
|
||||
if (value) ++value;
|
||||
#define set_bool(target) do { if (!value) { target = !target; } else { target = value[0] == '1'; } } while (0)
|
||||
switch (cmd[0]) {
|
||||
case '.': { // +..:, +.:
|
||||
if (cmd[1] == '.') // +..:
|
||||
if (matches_cmd(cmd, "..")) { // +..
|
||||
set_bool(bb->show_dotdot);
|
||||
else // +.:
|
||||
populate_files(bb, 1);
|
||||
} else if (matches_cmd(cmd, ".")) { // +.
|
||||
set_bool(bb->show_dot);
|
||||
populate_files(bb, 1);
|
||||
return BB_OK;
|
||||
}
|
||||
case 'b': { // +bind:<keys>:<script>
|
||||
} else if (matches_cmd(cmd, "bind")) { // +bind:<keys>:<script>
|
||||
if (!value || !value[0])
|
||||
return BB_INVALID;
|
||||
char *value_copy = memcheck(strdup(value));
|
||||
@ -617,27 +624,14 @@ bb_result_t process_cmd(bb_t *bb, const char *cmd)
|
||||
}
|
||||
}
|
||||
free(value_copy);
|
||||
return BB_OK;
|
||||
}
|
||||
case 'c': { // +cd:, +columns:
|
||||
switch (cmd[1]) {
|
||||
case 'd': { // +cd:
|
||||
} else if (matches_cmd(cmd, "cd")) { // +cd:
|
||||
if (!value) return BB_INVALID;
|
||||
if (cd_to(bb, value)) return BB_INVALID;
|
||||
return BB_OK;
|
||||
}
|
||||
case 'o': { // +columns:
|
||||
} else if (matches_cmd(cmd, "columns")) { // +columns:
|
||||
if (!value) return BB_INVALID;
|
||||
strncpy(bb->columns, value, MAX_COLS);
|
||||
bb->dirty = 1;
|
||||
return BB_OK;
|
||||
}
|
||||
}
|
||||
return BB_INVALID;
|
||||
}
|
||||
case 'd': { // +deselect:, +dotfiles:
|
||||
switch (cmd[1]) {
|
||||
case 'e': { // +deselect:
|
||||
} else if (matches_cmd(cmd, "deselect")) { // +deselect
|
||||
if (!value) {
|
||||
while (bb->firstselected)
|
||||
set_selected(bb, bb->firstselected, 0);
|
||||
@ -657,25 +651,17 @@ bb_result_t process_cmd(bb_t *bb, const char *cmd)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return BB_OK;
|
||||
}
|
||||
case 'o': { // +dotfiles:
|
||||
} else if (matches_cmd(cmd, "dotfiles")) { // +dotfiles:
|
||||
set_bool(bb->show_dotfiles);
|
||||
populate_files(bb, 1);
|
||||
return BB_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
case 'e': { // +execute:
|
||||
} else if (matches_cmd(cmd, "execute")) { // +execute:
|
||||
if (!value || !value[0]) return BB_INVALID;
|
||||
move_cursor(tty_out, 0, termheight-1);
|
||||
fputs(T_ON(T_SHOW_CURSOR), tty_out);
|
||||
restore_term(&default_termios);
|
||||
run_script(bb, value);
|
||||
init_term();
|
||||
return BB_OK;
|
||||
}
|
||||
case 'g': { // +goto:
|
||||
} else if (matches_cmd(cmd, "goto")) { // +goto:
|
||||
if (!value) return BB_INVALID;
|
||||
entry_t *e = load_entry(bb, value, 1);
|
||||
if (!e) return BB_INVALID;
|
||||
@ -689,13 +675,10 @@ bb_result_t process_cmd(bb_t *bb, const char *cmd)
|
||||
if (!lastslash) return BB_INVALID;
|
||||
*lastslash = '\0'; // Split in two
|
||||
cd_to(bb, pbuf);
|
||||
if (IS_VIEWED(e)) {
|
||||
if (IS_VIEWED(e))
|
||||
set_cursor(bb, e->index);
|
||||
return BB_OK;
|
||||
} else try_free_entry(e);
|
||||
return BB_OK;
|
||||
}
|
||||
case 'h': { // +help
|
||||
else try_free_entry(e);
|
||||
} else if (matches_cmd(cmd, "help")) { // +help
|
||||
restore_term(&default_termios);
|
||||
int fds[2];
|
||||
pipe(fds);
|
||||
@ -715,16 +698,12 @@ bb_result_t process_cmd(bb_t *bb, const char *cmd)
|
||||
init_term();
|
||||
signal(SIGINT, old_handler);
|
||||
bb->dirty = 1;
|
||||
return BB_OK;
|
||||
}
|
||||
case 'i': { // +interleave
|
||||
} else if (matches_cmd(cmd, "interleave")) { // +interleave
|
||||
set_bool(bb->interleave_dirs);
|
||||
sort_files(bb);
|
||||
return BB_OK;
|
||||
}
|
||||
case 'k': // +kill
|
||||
} else if (matches_cmd(cmd, "kill")) { // +kill
|
||||
cleanup_and_exit(SIGINT);
|
||||
case 'm': { // +move:
|
||||
} else if (matches_cmd(cmd, "move")) { // +move:
|
||||
int oldcur, isdelta, n;
|
||||
move:
|
||||
if (!value) return BB_INVALID;
|
||||
@ -736,22 +715,16 @@ bb_result_t process_cmd(bb_t *bb, const char *cmd)
|
||||
n = (n * (value[1] == 'n' ? bb->nfiles : termheight)) / 100;
|
||||
if (isdelta) set_cursor(bb, bb->cursor + n);
|
||||
else set_cursor(bb, n);
|
||||
if (cmd[0] == 's') { // +spread:
|
||||
if (matches_cmd(cmd, "spread")) { // +spread:
|
||||
int sel = IS_SELECTED(bb->files[oldcur]);
|
||||
for (int i = bb->cursor; i != oldcur; i += (oldcur > i ? 1 : -1))
|
||||
set_selected(bb, bb->files[i], sel);
|
||||
}
|
||||
return BB_OK;
|
||||
}
|
||||
case 'q': // +quit
|
||||
} else if (matches_cmd(cmd, "quit")) { // +quit
|
||||
bb->should_quit = 1;
|
||||
return BB_OK;
|
||||
case 'r': // +refresh
|
||||
} else if (matches_cmd(cmd, "refresh")) { // +refresh
|
||||
populate_files(bb, 1);
|
||||
return BB_OK;
|
||||
case 's': // +scroll:, +select:, +sort:, +spread:
|
||||
switch (cmd[1]) {
|
||||
case 'c': { // scroll:
|
||||
} else if (matches_cmd(cmd, "scroll")) { // +scroll:
|
||||
if (!value) return BB_INVALID;
|
||||
// TODO: figure out the best version of this
|
||||
int isdelta = value[0] == '+' || value[0] == '-';
|
||||
@ -762,41 +735,29 @@ bb_result_t process_cmd(bb_t *bb, const char *cmd)
|
||||
set_scroll(bb, bb->scroll + n);
|
||||
else
|
||||
set_scroll(bb, n);
|
||||
return BB_OK;
|
||||
}
|
||||
|
||||
case '\0': case 'e': { // +select:
|
||||
} else if (matches_cmd(cmd, "select")) { // +select:
|
||||
if (!value && !bb->nfiles) return BB_INVALID;
|
||||
if (!value) value = bb->files[bb->cursor]->fullname;
|
||||
entry_t *e = load_entry(bb, value, 1);
|
||||
if (e) set_selected(bb, e, 1);
|
||||
return BB_OK;
|
||||
}
|
||||
case 'o': // +sort:
|
||||
} else if (matches_cmd(cmd, "sort")) { // +sort:
|
||||
if (!value) return BB_INVALID;
|
||||
set_sort(bb, value);
|
||||
sort_files(bb);
|
||||
return BB_OK;
|
||||
|
||||
case 'p': // +spread:
|
||||
} else if (matches_cmd(cmd, "spread")) { // +spread:
|
||||
goto move;
|
||||
|
||||
case 'u': // +suspend
|
||||
} else if (matches_cmd(cmd, "suspend")) { // +suspend
|
||||
fputs(T_LEAVE_BBMODE, tty_out);
|
||||
restore_term(&orig_termios);
|
||||
raise(SIGTSTP);
|
||||
init_term();
|
||||
bb->dirty = 1;
|
||||
break;
|
||||
}
|
||||
case 't': { // +toggle:
|
||||
} else if (matches_cmd(cmd, "toggle")) { // +toggle
|
||||
if (!value && !bb->nfiles) return BB_INVALID;
|
||||
if (!value) value = bb->files[bb->cursor]->fullname;
|
||||
entry_t *e = load_entry(bb, value, 1);
|
||||
if (e) set_selected(bb, e, !IS_SELECTED(e));
|
||||
return BB_OK;
|
||||
}
|
||||
default: {
|
||||
} else {
|
||||
fputs(T_LEAVE_BBMODE, tty_out);
|
||||
restore_term(&orig_termios);
|
||||
const char *msg = "Invalid bb command: ";
|
||||
@ -806,8 +767,7 @@ bb_result_t process_cmd(bb_t *bb, const char *cmd)
|
||||
init_term();
|
||||
return BB_INVALID;
|
||||
}
|
||||
}
|
||||
return BB_INVALID;
|
||||
return BB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
3
bb.h
3
bb.h
@ -178,11 +178,12 @@ static int fputs_escaped(FILE *f, const char *str, const char *color);
|
||||
static void init_term(void);
|
||||
static int is_simple_bbcmd(const char *s);
|
||||
static entry_t* load_entry(bb_t *bb, const char *path, int clear_dots);
|
||||
static inline int matches_cmd(const char *str, const char *cmd);
|
||||
static void* memcheck(void *p);
|
||||
static void normalize_path(const char *root, const char *path, char *pbuf, int clear_dots);
|
||||
static void populate_files(bb_t *bb, int samedir);
|
||||
static void print_bindings(int fd);
|
||||
static bb_result_t process_cmd(bb_t *bb, const char *cmd);
|
||||
static bb_result_t run_bbcmd(bb_t *bb, const char *cmd);
|
||||
static void render(bb_t *bb);
|
||||
static void restore_term(const struct termios *term);
|
||||
static int run_script(bb_t *bb, const char *cmd);
|
||||
|
Loading…
Reference in New Issue
Block a user