aboutsummaryrefslogtreecommitdiff
path: root/config.def.h
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2019-06-10 20:37:34 -0700
committerBruce Hill <bruce@bruce-hill.com>2019-06-10 20:37:34 -0700
commit5a5f9afa05a1f4dfdcd559c0f28691a65bfc6b46 (patch)
treef7c03498ce9fd6dd86ae3c9386349b1fbb73eebe /config.def.h
parent86c8bed803356d6855e75bd364085f9cf8717b9e (diff)
Updated with some cleaner behavior for PICK and added SPIN. Also removed
command line flags in favor of manually using `tput rmcup`. Updated the documentation.
Diffstat (limited to 'config.def.h')
-rw-r--r--config.def.h163
1 files changed, 96 insertions, 67 deletions
diff --git a/config.def.h b/config.def.h
index cd187cf..77fdd26 100644
--- a/config.def.h
+++ b/config.def.h
@@ -1,19 +1,22 @@
/*
- BB Key Bindings
+ BB Configuration, Startup Commands, and Key Bindings
- User-defined key bindings go in config.h, which is created by running `make`
+ User customization goes in config.h, which is created by running `make`
(config.def.h is for keeping the defaults around, just in case)
- The basic structure is:
- <list of keys to bind>
- <program to run>
- <description> (for the help menu)
- <flags> (whether to run in a full terminal window or silently, etc.)
+ This file contains:
+ - Global options, like which colors are used
+ - Column formatting (width and title)
+ - Startup commands
+ - User key bindings
- When the scripts are run, the following values are provided as environment variables:
+ For startup commands and key bindings, the following values are provided as
+ environment variables:
- $@ (the list of arguments): the full paths of the selected files
- $BBCURSOR: the full name of the file under the cursor
+ $@ (the list of arguments): the full paths of the selected files, or if
+ no files are selected, the full path of the file under the cursor
+ $BBCURSOR: the full path of the file under the cursor
+ $BBSELECTED: "1" if any files are selected, otherwise ""
$BB_DEPTH: 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)
@@ -40,31 +43,49 @@
spread:<num*> Spread the selection state at the cursor
toggle:<filename> Toggle the selection status of <filename>
- Internally, bb will write the commands (NUL terminated) to $BBCMD, if
- $BBCMD is set, and read the file when file browsing resumes. These commands
- can also be passed to bb at startup, and will run immediately.
- E.g. `bb +col:n +sort:r .` will launch `bb` only showing the name column, randomly sorted.
-
- *Note: for numeric-based commands (like scroll), the number can be either
+ Note: for numeric-based commands (like scroll), the number can be either
an absolute value or a relative value (starting with '+' or '-'), and/or
a percent (ending with '%'). Scrolling and moving, '%' means percent of
screen height, and '%n' means percent of number of files (e.g. +50% means
half a screen height down, and 100%n means the last file)
+ Internally, bb will write the commands (NUL terminated) to $BBCMD, if
+ $BBCMD is set, and read the file when file browsing resumes. These commands
+ can also be passed to bb at startup, and will run immediately.
+ E.g. `bb '+col:n' '+sort:+r' .` will launch `bb` only showing the name column, randomly sorted.
+
+ As a shorthand and performance optimization, commands that don't rely on any
+ shell variables or scripting can be written as "+move:+1" instead of "bb '+move:+1'",
+ which is a bit faster because internally it avoids writing to and reading from
+ the $BBCMD file.
+
*/
#include "bterm.h"
+// Constants:
+#define MAX_REBINDINGS 8
+
+// Types:
+typedef struct {
+ int keys[MAX_REBINDINGS+1];
+ const char *command;
+ const char *description;
+} binding_t;
+
+typedef struct {
+ int width;
+ const char *name;
+} column_t;
+
// Configurable options:
#define KEY_DELAY 50
-#define SCROLLOFF MIN(5, (termheight-4)/2)
-
+#define SCROLLOFF MIN(5, (termheight-4)/2)
#define CMDFILE_FORMAT "/tmp/bb.XXXXXX"
-
#define SORT_INDICATOR "↓"
#define RSORT_INDICATOR "↑"
#define SELECTED_INDICATOR " \033[31;7m \033[0m"
#define NOT_SELECTED_INDICATOR " "
-
+// Colors (using ANSI escape sequences):
#define TITLE_COLOR "\033[37;1m"
#define NORMAL_COLOR "\033[37m"
#define CURSOR_COLOR "\033[43;30;1m"
@@ -72,13 +93,18 @@
#define DIR_COLOR "\033[34m"
#define EXECUTABLE_COLOR "\033[31m"
+// Some handy macros for common shell script behaviors:
#define PAUSE " read -n1 -p '\033[2mPress any key to continue...\033[0m\033[?25l'"
+// Bold text:
+#define B(s) "\033[1m" s "\033[22m"
+
+// Macros for getting user input:
#ifndef ASK
#ifdef ASKECHO
#define ASK(var, prompt, initial) var "=\"$(" ASKECHO(prompt, initial) ")\""
#else
-#define ASK(var, prompt, initial) "read -p \"" prompt "\" " var
+#define ASK(var, prompt, initial) "read -p \"" prompt "\" " var " </dev/tty >/dev/tty"
#endif
#endif
@@ -86,43 +112,33 @@
#define ASKECHO(prompt, initial) ASK("REPLY", prompt, initial) " && echo \"$REPLY\""
#endif
+// Get user input to choose an option (piped in). If you want to use
+// a fuzzy finder like fzy or fzf, then this should be something like:
+// "fzy --prompt=\"" prompt "\" --query=\"" initial "\""
#ifndef PICK
-#define PICK(prompt, initial) "true && " ASKECHO(prompt, initial)
+#define PICK(prompt, initial) "grep -i -m1 \"^$(" ASKECHO(prompt, initial) " | sed 's/./[^&]*[&]/g')\""
#endif
-#define NORMAL_TERM (1<<0)
-
-#define MAX_REBINDINGS 8
-
-typedef struct {
- int keys[MAX_REBINDINGS+1];
- const char *command;
- const char *description;
- int flags;
-} binding_t;
+// Display a spinning indicator if command takes longer than 10ms:
+#ifndef SPIN
+#define SPIN(cmd) "{ " cmd "; } & " \
+ "pid=$!; "\
+ "spinner='-\\|/'; "\
+ "sleep 0.01; "\
+ "while kill -0 $pid 2>/dev/null; do "\
+ " printf '%c\\033[D' \"$spinner\" >/dev/tty; "\
+ " spinner=\"`echo $spinner | sed 's/\\(.\\)\\(.*\\)/\\2\\1/'`\"; "\
+ " sleep 0.1; "\
+ "done"
+#endif
-typedef struct {
- int width;
- const char *name;
-} column_t;
// These commands will run at startup (before command-line arguments)
extern const char *startupcmds[];
extern const column_t columns[128];
+extern binding_t bindings[];
-const char *startupcmds[] = {
- //////////////////////////////////////////////
- // User-defined startup commands can go here
- //////////////////////////////////////////////
- // Set some default marks:
- "+mark:0", "+mark:~=~", "+mark:h=~", "+mark:/=/", "+mark:c=~/.config",
- "+mark:l=~/.local", "+mark:s=<selection>",
- // Default column and sorting options:
- "+sort:+n", "+col:*smpn", "+..",
- NULL, // NULL-terminated array
-};
-
-// Column widths:
+// Column widths and titles:
const column_t columns[128] = {
['*'] = {2, "*"},
['a'] = {21, " Accessed"},
@@ -134,17 +150,29 @@ const column_t columns[128] = {
['s'] = {9, "Size"},
};
-extern binding_t bindings[];
-#define B(s) "\033[1m" s "\033[22m"
+// This is a list of commands that runs when `bb` launches:
+const char *startupcmds[] = {
+ // Set some default marks:
+ "+mark:0", "+mark:~=~", "+mark:h=~", "+mark:/=/", "+mark:c=~/.config",
+ "+mark:l=~/.local", "+mark:s=<selection>",
+ // Default column and sorting options:
+ "+sort:+n", "+col:*smpn", "+..",
+ NULL, // NULL-terminated array
+};
+
+/******************************************************************************
+ * These are all the key bindings for bb.
+ * The format is: {{keys,...}, "<script>", "<description>"}
+ *
+ * Please note that these are sh scripts, not bash scripts, so bash-isms
+ * won't work unless you make your script use `bash -c "<your bash script>"`
+ *
+ * If your editor is vim (and not neovim), you can replace `$EDITOR` below with
+ * `vim -c 'set t_ti= t_te=' "$@"` to prevent momentarily seeing the shell
+ * after editing.
+ *****************************************************************************/
binding_t bindings[] = {
- /*************************************************************************
- * User-defined custom scripts can go here
- * Format is: {{keys}, "script", "help text", flags}
- *
- * Please note that these are sh scripts, not bash scripts, so bash-isms
- * won't work unless you make your script use `bash -c "<your script>"`
- ************************************************************************/
- {{'?', KEY_F1}, "bb -b | $PAGER -r", B("Help")" menu", NORMAL_TERM},
+ {{'?', KEY_F1}, "bb -b | $PAGER -rX", B("Help")" menu"},
{{'q', 'Q'}, "+quit", B("Quit")},
{{'j', KEY_ARROW_DOWN}, "+move:+1", B("Next")" file"},
{{'k', KEY_ARROW_UP}, "+move:-1", B("Previous")" file"},
@@ -161,18 +189,19 @@ binding_t bindings[] = {
"elif file -bi \"$BBCURSOR\" | grep '^\\(text/\\|inode/empty\\)' >/dev/null; then $EDITOR \"$BBCURSOR\"; "
"else xdg-open \"$BBCURSOR\"; fi",
#endif
- B("Open")" file/directory", NORMAL_TERM},
+ B("Open")" file/directory"},
{{' ','v','V'}, "+toggle", B("Toggle")" selection"},
{{KEY_ESC}, "+deselect:*", B("Clear")" selection"},
- {{'e'}, "$EDITOR \"$@\" || "PAUSE, B("Edit")" file in $EDITOR", NORMAL_TERM},
+ {{'e'}, "$EDITOR \"$@\" || "PAUSE, B("Edit")" file in $EDITOR"},
{{KEY_CTRL_F}, "bb \"+g:`find | "PICK("Find: ", "")"`\"", B("Search")" for file"},
- {{'/'}, "bb \"+g:`ls -a | "PICK("Pick: ", "")"`\"", B("Pick")" file"},
+ {{'/'}, "bb \"+g:`ls -pa | "PICK("Pick: ", "")"`\"", B("Pick")" file"},
{{'d', KEY_DELETE}, "rm -rfi \"$@\" && bb '+deselect:*' +r ||" PAUSE, B("Delete")" files"},
- {{'D'}, "rm -rf \"$@\" && bb '+deselect:*' +r ||" PAUSE, B("Delete")" files (without confirmation)"},
- {{'M'}, "mv -i \"$@\" . && bb '+deselect:*' +r && for f; do bb \"+sel:`pwd`/`basename \"$f\"`\"; done || "PAUSE,
+ {{'D'}, SPIN("rm -rf \"$@\"")" && bb '+deselect:*' +r ||" PAUSE, B("Delete")" files (without confirmation)"},
+ {{'M'}, SPIN("mv -i \"$@\" .")" && bb '+deselect:*' +r && for f; do bb \"+sel:`pwd`/`basename \"$f\"`\"; done || "PAUSE,
B("Move")" files to current directory"},
- {{'c'}, "cp -ri \"$@\" . && bb +r || "PAUSE, B("Copy")" files to current directory"},
- {{'C'}, "bb '+de:*' && for f; do cp \"$f\" \"$f.copy\" && bb \"+sel:$f.copy\"; done && bb +r || "PAUSE, B("Clone")" files"},
+ {{'c'}, SPIN("cp -ri \"$@\" .")" && bb +r || "PAUSE, B("Copy")" files to current directory"},
+ {{'C'}, "bb '+de:*' && for f; do "SPIN("cp \"$f\" \"$f.copy\"")" && bb \"+sel:$f.copy\"; done && bb +r || "PAUSE,
+ B("Clone")" files"},
{{'n'}, ASK("name", "New file: ", "")" && touch \"$name\" && bb \"+goto:$name\" +r || "PAUSE, B("New file")},
{{'N'}, ASK("name", "New dir: ", "")" && mkdir \"$name\" && bb \"+goto:$name\" +r || "PAUSE, B("New directory")},
{{KEY_CTRL_G}, "bb \"+cd:`" ASKECHO("Go to directory: ", "") "`\"", B("Go to")" directory"},
@@ -180,7 +209,7 @@ binding_t bindings[] = {
B("Pipe")" selected files to a command"},
{{':'}, "sh -c \"`" ASKECHO(":", "") "`\" -- \"$@\"; " PAUSE "; bb +refresh",
B("Run")" a command"},
- {{'>'}, "$SHELL; bb +r", "Open a "B("shell"), NORMAL_TERM},
+ {{'>'}, "tput rmcup >/dev/tty; $SHELL; bb +r", "Open a "B("shell")},
{{'m'}, "read -n1 -p 'Mark: ' m && bb \"+mark:$m;$PWD\"", "Set "B("mark")},
{{'\''}, "read -n1 -p 'Jump: ' j && bb \"+jump:$j\"", B("Jump")" to mark"},
{{'r'},