Initial working version using globbing.
This commit is contained in:
parent
d7e6159eb8
commit
9636042858
1
Makefile
1
Makefile
@ -81,7 +81,6 @@ uninstall:
|
|||||||
fi; \
|
fi; \
|
||||||
[ ! "$$prefix" ] && prefix="/usr/local"; \
|
[ ! "$$prefix" ] && prefix="/usr/local"; \
|
||||||
[ ! "$$sysconfdir" ] && sysconfdir=/etc; \
|
[ ! "$$sysconfdir" ] && sysconfdir=/etc; \
|
||||||
[ ! "$$XDG_CONFIG_HOME" ] && XDG_CONFIG_HOME=~/.config; \
|
|
||||||
echo "Deleting..."; \
|
echo "Deleting..."; \
|
||||||
rm -rvf "$$prefix/bin/$(NAME)" "$$prefix/share/man/man1/$(NAME).1" "$$sysconfdir/xdg/bb"; \
|
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"
|
printf "\033[1mIf you created any config files in ~/.config/bb, you may want to delete them manually.\033[0m"
|
||||||
|
73
bb.c
73
bb.c
@ -460,27 +460,21 @@ int populate_files(bb_t *bb, const char *path)
|
|||||||
bb->files[bb->nfiles++] = e;
|
bb->files[bb->nfiles++] = e;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DIR *dir = opendir(bb->path);
|
glob_t globbuf = {0};
|
||||||
if (!dir)
|
char *pat, *tmpglob = memcheck(strdup(bb->globpats));
|
||||||
err("Couldn't open dir: %s", bb->path);
|
while ((pat = strsep(&tmpglob, " ")) != NULL)
|
||||||
|
glob(pat, GLOB_NOSORT|GLOB_APPEND, NULL, &globbuf);
|
||||||
for (struct dirent *dp; (dp = readdir(dir)) != NULL; ) {
|
free(tmpglob);
|
||||||
if (dp->d_name[0] == '.') {
|
for (size_t i = 0; i < globbuf.gl_pathc; i++) {
|
||||||
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;
|
|
||||||
}
|
|
||||||
if ((size_t)bb->nfiles + 1 > space)
|
if ((size_t)bb->nfiles + 1 > space)
|
||||||
bb->files = memcheck(realloc(bb->files, (space += 100)*sizeof(void*)));
|
bb->files = memcheck(realloc(bb->files, (space += 100)*sizeof(void*)));
|
||||||
// Don't normalize path so we can get "." and ".."
|
// Don't normalize path so we can get "." and ".."
|
||||||
entry_t *entry = load_entry(bb, dp->d_name);
|
entry_t *entry = load_entry(bb, globbuf.gl_pathv[i]);
|
||||||
if (!entry) err("Failed to load entry: '%s'", dp->d_name);
|
if (!entry) err("Failed to load entry: '%s'", globbuf.gl_pathv[i]);
|
||||||
entry->index = bb->nfiles;
|
entry->index = bb->nfiles;
|
||||||
bb->files[bb->nfiles++] = entry;
|
bb->files[bb->nfiles++] = entry;
|
||||||
}
|
}
|
||||||
closedir(dir);
|
globfree(&globbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < bb->nfiles; i++) {
|
for (int i = 0; i < bb->nfiles; i++) {
|
||||||
@ -551,10 +545,10 @@ void run_bbcmd(bb_t *bb, const char *cmd)
|
|||||||
if (value) ++value;
|
if (value) ++value;
|
||||||
#define set_bool(target) do { if (!value) { target = !target; } else { target = value[0] == '1'; } } while (0)
|
#define set_bool(target) do { if (!value) { target = !target; } else { target = value[0] == '1'; } } while (0)
|
||||||
if (matches_cmd(cmd, ".")) { // +.
|
if (matches_cmd(cmd, ".")) { // +.
|
||||||
set_bool(bb->show_dot);
|
set_globs(bb, ". *");
|
||||||
populate_files(bb, bb->path);
|
populate_files(bb, bb->path);
|
||||||
} else if (matches_cmd(cmd, "..")) { // +..
|
} else if (matches_cmd(cmd, "..")) { // +..
|
||||||
set_bool(bb->show_dotdot);
|
set_globs(bb, ".. *");
|
||||||
populate_files(bb, bb->path);
|
populate_files(bb, bb->path);
|
||||||
} else if (matches_cmd(cmd, "bind:")) { // +bind:<keys>:<script>
|
} else if (matches_cmd(cmd, "bind:")) { // +bind:<keys>:<script>
|
||||||
char *value_copy = memcheck(strdup(value));
|
char *value_copy = memcheck(strdup(value));
|
||||||
@ -619,8 +613,12 @@ void run_bbcmd(bb_t *bb, const char *cmd)
|
|||||||
while (bb->selected)
|
while (bb->selected)
|
||||||
set_selected(bb, bb->selected, 0);
|
set_selected(bb, bb->selected, 0);
|
||||||
} else if (matches_cmd(cmd, "dotfiles:") || matches_cmd(cmd, "dotfiles")) { // +dotfiles:
|
} else if (matches_cmd(cmd, "dotfiles:") || matches_cmd(cmd, "dotfiles")) { // +dotfiles:
|
||||||
set_bool(bb->show_dotfiles);
|
int dotfiles = strstr(bb->globpats, ".*") != NULL;
|
||||||
setenv("BBDOTFILES", bb->show_dotfiles ? "1" : "", 1);
|
set_bool(dotfiles);
|
||||||
|
if (dotfiles)
|
||||||
|
set_globs(bb, ".* *");
|
||||||
|
else
|
||||||
|
set_globs(bb, "*");
|
||||||
populate_files(bb, bb->path);
|
populate_files(bb, bb->path);
|
||||||
} else if (matches_cmd(cmd, "fg:") || matches_cmd(cmd, "fg")) { // +fg:
|
} else if (matches_cmd(cmd, "fg:") || matches_cmd(cmd, "fg")) { // +fg:
|
||||||
int nprocs = 0;
|
int nprocs = 0;
|
||||||
@ -643,6 +641,9 @@ void run_bbcmd(bb_t *bb, const char *cmd)
|
|||||||
init_term();
|
init_term();
|
||||||
set_title(bb);
|
set_title(bb);
|
||||||
dirty = 1;
|
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:
|
} else if (matches_cmd(cmd, "goto:")) { // +goto:
|
||||||
entry_t *e = load_entry(bb, value);
|
entry_t *e = load_entry(bb, value);
|
||||||
if (!e) {
|
if (!e) {
|
||||||
@ -765,6 +766,7 @@ void render(bb_t *bb)
|
|||||||
} else {
|
} else {
|
||||||
fputs_escaped(tty_out, bb->path, color);
|
fputs_escaped(tty_out, bb->path, color);
|
||||||
}
|
}
|
||||||
|
fprintf(tty_out, "\033[0;2m[%s]", bb->globpats);
|
||||||
fputs(" \033[K\033[0m", tty_out);
|
fputs(" \033[K\033[0m", tty_out);
|
||||||
|
|
||||||
static const char *help = "Press '?' to see key bindings ";
|
static const char *help = "Press '?' to see key bindings ";
|
||||||
@ -862,17 +864,17 @@ void render(bb_t *bb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case COL_MTIME:
|
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);
|
fputs(buf, tty_out);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COL_CTIME:
|
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);
|
fputs(buf, tty_out);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COL_ATIME:
|
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);
|
fputs(buf, tty_out);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1069,6 +1071,17 @@ void set_scroll(bb_t *bb, int newscroll)
|
|||||||
if (bb->cursor < 0) bb->cursor = 0;
|
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.
|
* Select or deselect a file.
|
||||||
*/
|
*/
|
||||||
@ -1321,8 +1334,9 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
bb_t bb = {
|
bb_t bb = {
|
||||||
.columns = "*smpn",
|
.columns = "*smpn",
|
||||||
.sort = "+n"
|
.sort = "+n",
|
||||||
};
|
};
|
||||||
|
set_globs(&bb, "*");
|
||||||
init_term();
|
init_term();
|
||||||
bb_browse(&bb, full_initial_path);
|
bb_browse(&bb, full_initial_path);
|
||||||
fputs(T_LEAVE_BBMODE, tty_out);
|
fputs(T_LEAVE_BBMODE, tty_out);
|
||||||
@ -1335,6 +1349,18 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
fflush(stdout);
|
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)
|
if (print_dir)
|
||||||
printf("%s\n", bb.path);
|
printf("%s\n", bb.path);
|
||||||
|
|
||||||
@ -1342,6 +1368,7 @@ int main(int argc, char *argv[])
|
|||||||
populate_files(&bb, NULL);
|
populate_files(&bb, NULL);
|
||||||
while (bb.selected)
|
while (bb.selected)
|
||||||
set_selected(&bb, bb.selected, 0);
|
set_selected(&bb, bb.selected, 0);
|
||||||
|
free(bb.globpats);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
bb.h
17
bb.h
@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <glob.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -25,12 +26,13 @@
|
|||||||
#include "bterm.h"
|
#include "bterm.h"
|
||||||
|
|
||||||
// Macros:
|
// Macros:
|
||||||
#define BB_VERSION "0.21.2"
|
#define BB_VERSION "0.22.0"
|
||||||
|
|
||||||
#ifndef PATH_MAX
|
#ifndef PATH_MAX
|
||||||
#define PATH_MAX 4096
|
#define PATH_MAX 4096
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define BB_TIME_FMT " %I:%M%p %D "
|
||||||
#define MAX_COLS 12
|
#define MAX_COLS 12
|
||||||
#define MAX_SORT (2*MAX_COLS)
|
#define MAX_SORT (2*MAX_COLS)
|
||||||
#define HASH_SIZE 1024
|
#define HASH_SIZE 1024
|
||||||
@ -142,11 +144,9 @@ typedef struct bb_s {
|
|||||||
int nfiles, nselected;
|
int nfiles, nselected;
|
||||||
int scroll, cursor;
|
int scroll, cursor;
|
||||||
|
|
||||||
|
char *globpats;
|
||||||
char sort[MAX_SORT+1];
|
char sort[MAX_SORT+1];
|
||||||
char columns[MAX_COLS+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 interleave_dirs : 1;
|
||||||
unsigned int should_quit : 1;
|
unsigned int should_quit : 1;
|
||||||
} bb_t;
|
} bb_t;
|
||||||
@ -182,9 +182,9 @@ static binding_t bindings[MAX_BINDINGS];
|
|||||||
// Column widths and titles:
|
// Column widths and titles:
|
||||||
static const column_t columns[] = {
|
static const column_t columns[] = {
|
||||||
['*'] = {2, "*"},
|
['*'] = {2, "*"},
|
||||||
['a'] = {21, " Accessed"},
|
['a'] = {18, " Accessed"},
|
||||||
['c'] = {21, " Created"},
|
['c'] = {18, " Created"},
|
||||||
['m'] = {21, " Modified"},
|
['m'] = {18, " Modified"},
|
||||||
['n'] = {40, "Name"},
|
['n'] = {40, "Name"},
|
||||||
['p'] = {5, "Permissions"},
|
['p'] = {5, "Permissions"},
|
||||||
['r'] = {2, "Random"},
|
['r'] = {2, "Random"},
|
||||||
@ -217,6 +217,7 @@ static void render(bb_t *bb);
|
|||||||
static void restore_term(const struct termios *term);
|
static void restore_term(const struct termios *term);
|
||||||
static int run_script(bb_t *bb, const char *cmd);
|
static int run_script(bb_t *bb, const char *cmd);
|
||||||
static void set_cursor(bb_t *bb, int i);
|
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_selected(bb_t *bb, entry_t *e, int selected);
|
||||||
static void set_scroll(bb_t *bb, int i);
|
static void set_scroll(bb_t *bb, int i);
|
||||||
static void set_sort(bb_t *bb, const char *sort);
|
static void set_sort(bb_t *bb, const char *sort);
|
||||||
@ -330,8 +331,6 @@ PICK ";\n"
|
|||||||
;
|
;
|
||||||
|
|
||||||
static const char *runstartup =
|
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"
|
"for path in \"$XDG_CONFIG_HOME/bb\" \"$sysconfdir/xdg/bb\" .; do\n"
|
||||||
" if [ -e \"$path/bbstartup.sh\" ]; then\n"
|
" if [ -e \"$path/bbstartup.sh\" ]; then\n"
|
||||||
" . \"$path/bbstartup.sh\";\n"
|
" . \"$path/bbstartup.sh\";\n"
|
||||||
|
@ -4,11 +4,14 @@
|
|||||||
|
|
||||||
# Load key bindings
|
# Load key bindings
|
||||||
# first check ~/.config/bb/bindings.bb, then /etc/xdg/bb/bindings.bb, then ./bindings.bb
|
# 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
|
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
|
else
|
||||||
for path in "$sysconfdir/xdg/bb" "$XDG_CONFIG_HOME/bb"; do
|
for path in "$sysconfdir/xdg/bb" "$XDG_CONFIG_HOME/bb"; do
|
||||||
cat "$path/bindings.bb" 2>/dev/null
|
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
|
fi
|
||||||
printf '\0' >> "$BBCMD"
|
|
||||||
|
10
bindings.bb
10
bindings.bb
@ -23,14 +23,14 @@ l,Right: # Enter directory
|
|||||||
if [ -d "$BBCURSOR" ]; then bbcmd cd:"$BBCURSOR"; fi
|
if [ -d "$BBCURSOR" ]; then bbcmd cd:"$BBCURSOR"; fi
|
||||||
Ctrl-f: # Search for file
|
Ctrl-f: # Search for file
|
||||||
file="$(
|
file="$(
|
||||||
if [ $BBDOTFILES ]; then find -mindepth 1 -printf '%P\0';
|
find $BBGLOBS -mindepth 1 -printf '%P\0' | pick "Find: "
|
||||||
else find -mindepth 1 ! -path '*/.*' -printf '%P\0';
|
|
||||||
fi | pick "Find: "
|
|
||||||
)" && bbcmd goto:"$file"
|
)" && bbcmd goto:"$file"
|
||||||
/: # Pick a file
|
/: # Pick a file
|
||||||
file="$(find -mindepth 1 -maxdepth 1 -printf '%P\0' | pick "Pick: ")" || exit
|
file="$(printf "%s\0" $BBGLOBS | pick "Pick: ")" || exit
|
||||||
expr "$file" : "\..*" >/dev/null && ! [ "$BBDOTFILES" ] && bbcmd dotfiles
|
|
||||||
bbcmd goto:"$file"
|
bbcmd goto:"$file"
|
||||||
|
*: # Set the glob
|
||||||
|
ask BBGLOBS "Show files matching: "
|
||||||
|
bbcmd glob:"$BBGLOBS"
|
||||||
Ctrl-g: # Go to directory
|
Ctrl-g: # Go to directory
|
||||||
ask goto "Go to directory: " && bbcmd cd:"$goto"
|
ask goto "Go to directory: " && bbcmd cd:"$goto"
|
||||||
m: # Mark this directory
|
m: # Mark this directory
|
||||||
|
Loading…
Reference in New Issue
Block a user