diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2020-02-22 16:05:05 -0800 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2020-02-22 16:05:05 -0800 |
| commit | 96360428586f3d5722bb9fdc9baf1b1cc0b5dbc6 (patch) | |
| tree | c2df717d1dfdf75ec649e673f9f80ad6533df66e | |
| parent | d7e6159eb855578142b19d4becadadc5c55e32ca (diff) | |
Initial working version using globbing.
| -rw-r--r-- | Makefile | 1 | ||||
| -rw-r--r-- | bb.c | 73 | ||||
| -rw-r--r-- | bb.h | 17 | ||||
| -rwxr-xr-x | bbstartup.sh | 9 | ||||
| -rw-r--r-- | bindings.bb | 10 |
5 files changed, 69 insertions, 41 deletions
@@ -81,7 +81,6 @@ uninstall: fi; \ [ ! "$$prefix" ] && prefix="/usr/local"; \ [ ! "$$sysconfdir" ] && sysconfdir=/etc; \ - [ ! "$$XDG_CONFIG_HOME" ] && XDG_CONFIG_HOME=~/.config; \ echo "Deleting..."; \ rm -rvf "$$prefix/bin/$(NAME)" "$$prefix/share/man/man1/$(NAME).1" "$$sysconfdir/xdg/bb"; \ printf "\033[1mIf you created any config files in ~/.config/bb, you may want to delete them manually.\033[0m" @@ -460,27 +460,21 @@ int populate_files(bb_t *bb, const char *path) bb->files[bb->nfiles++] = e; } } else { - DIR *dir = opendir(bb->path); - if (!dir) - err("Couldn't open dir: %s", bb->path); - - for (struct dirent *dp; (dp = readdir(dir)) != NULL; ) { - if (dp->d_name[0] == '.') { - if (dp->d_name[1] == '.' && dp->d_name[2] == '\0') { - if (!bb->show_dotdot || strcmp(bb->path, "/") == 0) continue; - } else if (dp->d_name[1] == '\0') { - if (!bb->show_dot) continue; - } else if (!bb->show_dotfiles) continue; - } + glob_t globbuf = {0}; + char *pat, *tmpglob = memcheck(strdup(bb->globpats)); + while ((pat = strsep(&tmpglob, " ")) != NULL) + glob(pat, GLOB_NOSORT|GLOB_APPEND, NULL, &globbuf); + free(tmpglob); + for (size_t i = 0; i < globbuf.gl_pathc; i++) { if ((size_t)bb->nfiles + 1 > space) bb->files = memcheck(realloc(bb->files, (space += 100)*sizeof(void*))); // Don't normalize path so we can get "." and ".." - entry_t *entry = load_entry(bb, dp->d_name); - if (!entry) err("Failed to load entry: '%s'", dp->d_name); + entry_t *entry = load_entry(bb, globbuf.gl_pathv[i]); + if (!entry) err("Failed to load entry: '%s'", globbuf.gl_pathv[i]); entry->index = bb->nfiles; bb->files[bb->nfiles++] = entry; } - closedir(dir); + globfree(&globbuf); } for (int i = 0; i < bb->nfiles; i++) { @@ -551,10 +545,10 @@ void run_bbcmd(bb_t *bb, const char *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_bool(bb->show_dot); + set_globs(bb, ". *"); populate_files(bb, bb->path); } else if (matches_cmd(cmd, "..")) { // +.. - set_bool(bb->show_dotdot); + set_globs(bb, ".. *"); populate_files(bb, bb->path); } else if (matches_cmd(cmd, "bind:")) { // +bind:<keys>:<script> char *value_copy = memcheck(strdup(value)); @@ -619,8 +613,12 @@ void run_bbcmd(bb_t *bb, const char *cmd) while (bb->selected) set_selected(bb, bb->selected, 0); } else if (matches_cmd(cmd, "dotfiles:") || matches_cmd(cmd, "dotfiles")) { // +dotfiles: - set_bool(bb->show_dotfiles); - setenv("BBDOTFILES", bb->show_dotfiles ? "1" : "", 1); + int dotfiles = strstr(bb->globpats, ".*") != NULL; + set_bool(dotfiles); + if (dotfiles) + set_globs(bb, ".* *"); + else + set_globs(bb, "*"); populate_files(bb, bb->path); } else if (matches_cmd(cmd, "fg:") || matches_cmd(cmd, "fg")) { // +fg: int nprocs = 0; @@ -643,6 +641,9 @@ void run_bbcmd(bb_t *bb, const char *cmd) init_term(); set_title(bb); dirty = 1; + } else if (matches_cmd(cmd, "glob:")) { // +glob: + set_globs(bb, value[0] ? value : "*"); + populate_files(bb, bb->path); } else if (matches_cmd(cmd, "goto:")) { // +goto: entry_t *e = load_entry(bb, value); if (!e) { @@ -765,6 +766,7 @@ void render(bb_t *bb) } else { fputs_escaped(tty_out, bb->path, color); } + fprintf(tty_out, "\033[0;2m[%s]", bb->globpats); fputs(" \033[K\033[0m", tty_out); static const char *help = "Press '?' to see key bindings "; @@ -862,17 +864,17 @@ void render(bb_t *bb) } case COL_MTIME: - strftime(buf, sizeof(buf), " %I:%M%p %b %e %Y ", localtime(&(entry->info.st_mtime))); + strftime(buf, sizeof(buf), BB_TIME_FMT, localtime(&(entry->info.st_mtime))); fputs(buf, tty_out); break; case COL_CTIME: - strftime(buf, sizeof(buf), " %I:%M%p %b %e %Y ", localtime(&(entry->info.st_ctime))); + strftime(buf, sizeof(buf), BB_TIME_FMT, localtime(&(entry->info.st_ctime))); fputs(buf, tty_out); break; case COL_ATIME: - strftime(buf, sizeof(buf), " %I:%M%p %b %e %Y ", localtime(&(entry->info.st_atime))); + strftime(buf, sizeof(buf), BB_TIME_FMT, localtime(&(entry->info.st_atime))); fputs(buf, tty_out); break; @@ -1069,6 +1071,17 @@ void set_scroll(bb_t *bb, int newscroll) if (bb->cursor < 0) bb->cursor = 0; } + +/* + * Set the glob pattern(s) used by bb. Patterns are ' ' delimited + */ +void set_globs(bb_t *bb, const char *globs) +{ + free(bb->globpats); + bb->globpats = memcheck(strdup(globs)); + setenv("BBGLOBS", bb->globpats, 1); +} + /* * Select or deselect a file. */ @@ -1321,8 +1334,9 @@ int main(int argc, char *argv[]) bb_t bb = { .columns = "*smpn", - .sort = "+n" + .sort = "+n", }; + set_globs(&bb, "*"); init_term(); bb_browse(&bb, full_initial_path); fputs(T_LEAVE_BBMODE, tty_out); @@ -1335,6 +1349,18 @@ int main(int argc, char *argv[]) } fflush(stdout); } + + { + char path[PATH_MAX + strlen("/bb/state.sh")]; + sprintf(path, "%s/bb/state.sh", xdg_data_home); + FILE *f = fopen(path, "w"); + fprintf(f, "bbcmd glob:'%s'\n", bb.globpats); + fprintf(f, "bbcmd sort:'%s'\n", bb.sort); + fprintf(f, "bbcmd columns:'%s'\n", bb.columns); + if (bb.interleave_dirs) fprintf(f, "bbcmd interleave\n"); + fclose(f); + } + if (print_dir) printf("%s\n", bb.path); @@ -1342,6 +1368,7 @@ int main(int argc, char *argv[]) populate_files(&bb, NULL); while (bb.selected) set_selected(&bb, bb.selected, 0); + free(bb.globpats); return 0; } @@ -7,6 +7,7 @@ */ #include <dirent.h> #include <fcntl.h> +#include <glob.h> #include <limits.h> #include <signal.h> #include <stdio.h> @@ -25,12 +26,13 @@ #include "bterm.h" // Macros: -#define BB_VERSION "0.21.2" +#define BB_VERSION "0.22.0" #ifndef PATH_MAX #define PATH_MAX 4096 #endif +#define BB_TIME_FMT " %I:%M%p %D " #define MAX_COLS 12 #define MAX_SORT (2*MAX_COLS) #define HASH_SIZE 1024 @@ -142,11 +144,9 @@ typedef struct bb_s { int nfiles, nselected; int scroll, cursor; + char *globpats; char sort[MAX_SORT+1]; char columns[MAX_COLS+1]; - unsigned int show_dotdot : 1; - unsigned int show_dot : 1; - unsigned int show_dotfiles : 1; unsigned int interleave_dirs : 1; unsigned int should_quit : 1; } bb_t; @@ -182,9 +182,9 @@ static binding_t bindings[MAX_BINDINGS]; // Column widths and titles: static const column_t columns[] = { ['*'] = {2, "*"}, - ['a'] = {21, " Accessed"}, - ['c'] = {21, " Created"}, - ['m'] = {21, " Modified"}, + ['a'] = {18, " Accessed"}, + ['c'] = {18, " Created"}, + ['m'] = {18, " Modified"}, ['n'] = {40, "Name"}, ['p'] = {5, "Permissions"}, ['r'] = {2, "Random"}, @@ -217,6 +217,7 @@ static void render(bb_t *bb); static void restore_term(const struct termios *term); static int run_script(bb_t *bb, const char *cmd); static void set_cursor(bb_t *bb, int i); +static void set_globs(bb_t *bb, const char *globs); static void set_selected(bb_t *bb, entry_t *e, int selected); static void set_scroll(bb_t *bb, int i); static void set_sort(bb_t *bb, const char *sort); @@ -330,8 +331,6 @@ PICK ";\n" ; static const char *runstartup = -"[ ! \"$XDG_CONFIG_HOME\" ] && XDG_CONFIG_HOME=~/.config;\n" -"[ ! \"$sysconfdir\" ] && sysconfdir=/etc;\n" "for path in \"$XDG_CONFIG_HOME/bb\" \"$sysconfdir/xdg/bb\" .; do\n" " if [ -e \"$path/bbstartup.sh\" ]; then\n" " . \"$path/bbstartup.sh\";\n" diff --git a/bbstartup.sh b/bbstartup.sh index 80615fb..9058169 100755 --- a/bbstartup.sh +++ b/bbstartup.sh @@ -4,11 +4,14 @@ # Load key bindings # first check ~/.config/bb/bindings.bb, then /etc/xdg/bb/bindings.bb, then ./bindings.bb +[ ! -d "$XDG_DATA_HOME/bb" ] && mkdir -p "$XDG_DATA_HOME/bb" if [ ! -e "$XDG_CONFIG_HOME/bb/bindings.bb" ] && [ ! -e "$sysconfdir/xdg/bb/bindings.bb" ]; then - cat "./bindings.bb" 2>/dev/null | sed -e '/^#/d' -e "s/^\([^ ]\)/$(printf '\034')bind:\\1/" | tr '\034' '\0' >> "$BBCMD" + cat "./bindings.bb" 2>/dev/null | awk '/^#/ {next} /^[^ ]/ {printf "\0bind:"} {print $0} END {printf "\0"}' >> "$BBCMD" else for path in "$sysconfdir/xdg/bb" "$XDG_CONFIG_HOME/bb"; do cat "$path/bindings.bb" 2>/dev/null - done | sed -e '/^#/d' -e "s/^\([^ ]\)/$(printf '\034')bind:\\1/" | tr '\034' '\0' >> "$BBCMD" + done | awk '/^#/ {next} /^[^ ]/ {printf "\0bind:"} {print $0} END {printf "\0"}' >> "$BBCMD" +fi +if [ -e "$XDG_DATA_HOME/bb/state.sh" ]; then + . "$XDG_DATA_HOME/bb/state.sh" fi -printf '\0' >> "$BBCMD" diff --git a/bindings.bb b/bindings.bb index 55b9ad4..fa38614 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="$( - if [ $BBDOTFILES ]; then find -mindepth 1 -printf '%P\0'; - else find -mindepth 1 ! -path '*/.*' -printf '%P\0'; - fi | pick "Find: " + find $BBGLOBS -mindepth 1 -printf '%P\0' | pick "Find: " )" && bbcmd goto:"$file" /: # Pick a file - file="$(find -mindepth 1 -maxdepth 1 -printf '%P\0' | pick "Pick: ")" || exit - expr "$file" : "\..*" >/dev/null && ! [ "$BBDOTFILES" ] && bbcmd dotfiles + file="$(printf "%s\0" $BBGLOBS | pick "Pick: ")" || exit bbcmd goto:"$file" +*: # Set the glob + ask BBGLOBS "Show files matching: " + bbcmd glob:"$BBGLOBS" Ctrl-g: # Go to directory ask goto "Go to directory: " && bbcmd cd:"$goto" m: # Mark this directory |
