diff options
| -rw-r--r-- | API.md | 34 | ||||
| -rw-r--r-- | bb.c | 66 | ||||
| -rw-r--r-- | bb.h | 2 | ||||
| -rw-r--r-- | bindings.bb | 18 |
4 files changed, 59 insertions, 61 deletions
@@ -29,33 +29,33 @@ environment variables: - `$@` (the list of arguments): the full paths of the selected files - `$BBCURSOR`: the full path of the file under the cursor -- `$BBDOTFILES`: "1" if files beginning with "." are visible in bb, otherwise "" -- `$BB_DEPTH`: the number of `bb` instances deep (in case you want to run a +- `$BBDEPTH`: the number of `bb` instances deep (in case you want to run a shell and have that shell print something special in the prompt) - `$BBCMD`: a file to which `bb` commands can be written (used internally) +- `$BBGLOB`: the glob pattern `bb` is using to determine which files to show ## BB Internal State Commands In order to modify bb's internal state, you can call `bbcmd <cmd>`, where "cmd" is one of the following commands (or a unique prefix of one): -- `.:[01]` Whether to show "." in each directory -- `..:[01]` Whether to show ".." in each directory +- `bind:<keys>:<script>` Bind the given key presses to run the given script - `cd:<path>` Navigate to <path> - `columns:<columns>` Change which columns are visible, and in what order -- `deselect:<filename>` Deselect <filename> -- `dotfiles:[01]` Whether dotfiles are visible -- `fg:[num]` Send a background process to the foreground +- `deselect[:<filename>]` Deselect <filename> (default: all selected files) +- `fg[:num]` Send a background process to the foreground (default: most recent process) +- `glob:<glob pattern>` The glob pattern for which files to show (default: `*`) - `goto:<filename>` Move the cursor to <filename> (changing directory if needed) -- `interleave:[01]` Whether or not directories should be interleaved with files in the display +- `help` Show the help menu +- `interleave[:01]` Whether or not directories should be interleaved with files in the display (default: toggle) - `move:<num*>` Move the cursor a numeric amount -- `quit` Quit bb +- `quit` Quit `bb` - `refresh` Refresh the file listing - `scroll:<num*>` Scroll the view a numeric amount -- `select:<filename>` Select <filename> -- `sort:([+-]method)+` Set sorting method (+: normal, -: reverse), additional methods act as tiebreaker +- `select[:<filename>]` Select <filename> (default: all visible files) +- `sort:([+-]method)+` Set sorting method (+: normal, -: reverse, default: toggle), additional methods act as tiebreaker - `spread:<num*>` Spread the selection state at the cursor -- `toggle:<filename>` Toggle the selection status of <filename> +- `toggle[:<filename>]` Toggle the selection status of <filename> (default: all visible files) For any of these commands (e.g. `select`), an empty parameter followed by additional arguments (e.g. `bbcmd select: <file1> <file2> ...`) is equivalent to @@ -68,6 +68,16 @@ absolute value or a relative value (starting with `+` or `-`), and/or a percent and `%n` means percent of number of files (e.g. `+50%` means half a screen height down, and `100%n` means the last file) +## Globbing + +`bb` uses glob patterns to determine which files are visible. By default, the +pattern is `*`, which means all files except those starting with a `.` (dot). +`bb`'s globs are POSIX-compliant and do not support bash-style extensions like +`**` for recursive matches. `bb` supports multiple, space-separated globs, so +for example, you can display all files including dotfiles with the glob: `.* *` +(by default, pressing the `.` key will toggle this behavior). The current `bb` +glob is available in `$BBGLOB`, which can be used in scripts if left unquoted. + ## Final Notes Internally, `bbcmd` writes the commands (NUL terminated) to a file whose path is @@ -537,13 +537,7 @@ void run_bbcmd(bb_t *bb, const char *cmd) const char *value = strchr(cmd, ':'); if (value) ++value; #define set_bool(target) do { if (!value) { target = !target; } else { target = value[0] == '1'; } } while (0) - if (matches_cmd(cmd, ".")) { // +. - set_globs(bb, ". *"); - populate_files(bb, bb->path); - } else if (matches_cmd(cmd, "..")) { // +.. - set_globs(bb, ".. *"); - populate_files(bb, bb->path); - } else if (matches_cmd(cmd, "bind:")) { // +bind:<keys>:<script> + if (matches_cmd(cmd, "bind:")) { // +bind:<keys>:<script> char *value_copy = memcheck(strdup(value)); char *keys = trim(value_copy); if (!keys[0]) { free(value_copy); return; } @@ -587,7 +581,10 @@ void run_bbcmd(bb_t *bb, const char *cmd) } else if (matches_cmd(cmd, "columns:")) { // +columns: strncpy(bb->columns, value, MAX_COLS); dirty = 1; - } else if (matches_cmd(cmd, "deselect:")) { // +deselect + } else if (matches_cmd(cmd, "deselect")) { // +deselect + while (bb->selected) + set_selected(bb, bb->selected, 0); + } else if (matches_cmd(cmd, "deselect:")) { // +deselect:<file> char pbuf[PATH_MAX]; normalize_path(bb->path, value, pbuf); entry_t *e = load_entry(bb, pbuf); @@ -599,20 +596,10 @@ void run_bbcmd(bb_t *bb, const char *cmd) for (e = bb->selected; e; e = e->selected.next) { if (strcmp(e->fullname, pbuf) == 0) { set_selected(bb, e, 0); - break; + return; } } - } else if (matches_cmd(cmd, "deselect")) { // +deselect - while (bb->selected) - set_selected(bb, bb->selected, 0); - } else if (matches_cmd(cmd, "dotfiles:") || matches_cmd(cmd, "dotfiles")) { // +dotfiles: - int dotfiles = strstr(bb->globpats, ".*") != NULL; - set_bool(dotfiles); - if (dotfiles) - set_globs(bb, ".* *"); - else - set_globs(bb, "*"); - populate_files(bb, bb->path); + warn("Could not find file to deselect: \"%s\"", value); } else if (matches_cmd(cmd, "fg:") || matches_cmd(cmd, "fg")) { // +fg: int nprocs = 0; for (proc_t *p = running_procs; p; p = p->running.next) ++nprocs; @@ -640,7 +627,7 @@ void run_bbcmd(bb_t *bb, const char *cmd) } else if (matches_cmd(cmd, "goto:")) { // +goto: entry_t *e = load_entry(bb, value); if (!e) { - warn("Could not find file to go to: \"%s\".", value); + warn("Could not find file to go to: \"%s\"", value); return; } if (IS_VIEWED(e)) { @@ -700,30 +687,27 @@ void run_bbcmd(bb_t *bb, const char *cmd) set_scroll(bb, bb->scroll + n); else set_scroll(bb, n); - } else if (matches_cmd(cmd, "select:") || matches_cmd(cmd, "select")) { // +select: - if (!value) { - for (int i = 0; i < bb->nfiles; i++) - set_selected(bb, bb->files[i], 1); - } else { - entry_t *e = load_entry(bb, value); - if (e) set_selected(bb, e, 1); - } + } else if (matches_cmd(cmd, "select")) { // +select + for (int i = 0; i < bb->nfiles; i++) + set_selected(bb, bb->files[i], 1); + } else if (matches_cmd(cmd, "select:")) { // +select:<file> + entry_t *e = load_entry(bb, value); + if (e) set_selected(bb, e, 1); + else warn("Could not find file to select: \"%s\"", value); } else if (matches_cmd(cmd, "sort:")) { // +sort: set_sort(bb, value); sort_files(bb); } else if (matches_cmd(cmd, "spread:")) { // +spread: goto move; - } else if (matches_cmd(cmd, "toggle:") || matches_cmd(cmd, "toggle")) { // +toggle - if (!value && !bb->nfiles) return; - if (!value) value = bb->files[bb->cursor]->fullname; + } else if (matches_cmd(cmd, "toggle")) { // +toggle + for (int i = 0; i < bb->nfiles; i++) + set_selected(bb, bb->files[i], !IS_SELECTED(bb->files[i])); + } else if (matches_cmd(cmd, "toggle:")) { // +toggle:<file> entry_t *e = load_entry(bb, value); - if (!e) { - warn("Could not find file to toggle: \"%s\".", value); - return; - } - set_selected(bb, e, !IS_SELECTED(e)); + if (e) set_selected(bb, e, !IS_SELECTED(e)); + else warn("Could not find file to toggle: \"%s\"", value); } else { - warn("Invalid bb command: +%s.", cmd); + warn("Invalid bb command: %s", cmd); } } @@ -1013,7 +997,7 @@ void set_globs(bb_t *bb, const char *globs) { free(bb->globpats); bb->globpats = memcheck(strdup(globs)); - setenv("BBGLOBS", bb->globpats, 1); + setenv("BBGLOB", bb->globpats, 1); } /* @@ -1214,11 +1198,11 @@ int main(int argc, char *argv[]) setenv("sysconfdir", "/etc", 0); setenv("SHELL", "bash", 0); setenv("EDITOR", "nano", 0); - char *curdepth = getenv("BB_DEPTH"); + char *curdepth = getenv("BBDEPTH"); int depth = curdepth ? atoi(curdepth) : 0; char depthstr[16]; sprintf(depthstr, "%d", depth + 1); - setenv("BB_DEPTH", depthstr, 1); + setenv("BBDEPTH", depthstr, 1); setenv("BBSHELLFUNC", bbcmdfn, 1); char full_initial_path[PATH_MAX]; getcwd(full_initial_path, PATH_MAX); @@ -26,7 +26,7 @@ #include "bterm.h" // Macros: -#define BB_VERSION "0.22.1" +#define BB_VERSION "0.24.0" #ifndef PATH_MAX #define PATH_MAX 4096 diff --git a/bindings.bb b/bindings.bb index fa38614..5e3a232 100644 --- a/bindings.bb +++ b/bindings.bb @@ -23,14 +23,14 @@ l,Right: # Enter directory if [ -d "$BBCURSOR" ]; then bbcmd cd:"$BBCURSOR"; fi Ctrl-f: # Search for file file="$( - find $BBGLOBS -mindepth 1 -printf '%P\0' | pick "Find: " + find $BBGLOB -mindepth 1 -printf '%P\0' | pick "Find: " )" && bbcmd goto:"$file" /: # Pick a file - file="$(printf "%s\0" $BBGLOBS | pick "Pick: ")" || exit + file="$(printf "%s\0" $BBGLOB | pick "Pick: ")" || exit bbcmd goto:"$file" *: # Set the glob - ask BBGLOBS "Show files matching: " - bbcmd glob:"$BBGLOBS" + ask BBGLOB "Show files matching: " + bbcmd glob:"$BBGLOB" Ctrl-g: # Go to directory ask goto "Go to directory: " && bbcmd cd:"$goto" m: # Mark this directory @@ -66,11 +66,11 @@ Mouse wheel up: # Scroll up Section: File Selection v,V,Space: # Toggle selection at cursor - bbcmd toggle + bbcmd toggle:"$BBCURSOR" Escape: # Clear selection bbcmd deselect S: # Select pattern - ask patt "Select: " && eval bbcmd select: "$patt" + ask patt "Select: " && bbcmd select: $patt U: # Unselect pattern ask patt "Unselect: " && eval bbcmd deselect: "$patt" Ctrl-s: # Save the selection @@ -197,7 +197,11 @@ s: # Sort by... ask columns "Set columns (*)selected (a)ccessed (c)reated (m)odified (n)ame (p)ermissions (r)andom (s)ize: " && bbcmd col:"$columns" .: # Toggle dotfile visibility - bbcmd dotfiles + if [ "$BBGLOB" = ".* *" ]; then + bbcmd glob:"*" + else + bbcmd glob:".* *" + fi i: # Toggle interleaving files and directories bbcmd interleave F5,Ctrl-l: # Refresh view |
