aboutsummaryrefslogtreecommitdiff
path: root/config.def.h
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2019-09-30 15:46:24 -0700
committerBruce Hill <bruce@bruce-hill.com>2019-09-30 15:46:24 -0700
commit7a666d519556e9c7bf510d71565793978e7beba0 (patch)
treede0fdab0d45729219e7ba40c0c325df050bd2e83 /config.def.h
parente341f51dc62af41494a8618ad8e8c31632e93053 (diff)
Overhaul of how binding commands works. It's now all handled through
bbstartup.sh, which loads bindings.bb and parses it to +bind:<keys>:<script> commands.
Diffstat (limited to 'config.def.h')
-rw-r--r--config.def.h247
1 files changed, 5 insertions, 242 deletions
diff --git a/config.def.h b/config.def.h
index f4ae750..f8f431e 100644
--- a/config.def.h
+++ b/config.def.h
@@ -7,66 +7,15 @@
This file contains:
- Global options, like which colors are used
- Column formatting (width and title)
- - Startup commands
- - User key bindings
-
- 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 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
- shell and have that shell print something special in the prompt)
- $BBCMD: a file to which `bb` commands can be written (used internally)
-
- In order to modify bb's internal state, you can call `bb +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
- 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
- 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
- move:<num*> Move the cursor a numeric amount
- 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
- spread:<num*> Spread the selection state at the cursor
- toggle:<filename> Toggle the selection status of <filename>
-
- 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 *script;
- const char *description;
+ int key;
+ char *script;
+ char *description;
} binding_t;
typedef struct {
@@ -93,58 +42,9 @@ typedef struct {
#define SH "sh"
#endif
-// Used for STRINGIFY(__COUNTER__) to embed the line number as a string
-// (as in "ask --history=bb."STRINGIFY(__COUNTER__)")
-#define STRINGIFY2(x) #x
-#define STRINGIFY(x) STRINGIFY2(x)
-
-// Some handy macros for common shell script behaviors:
-// Bold text:
-#define B(s) "\033[1m" s "\033[22m"
-
-// Macro for getting user input:
-#ifndef ASK
-#define ASK(var, prompt, initial) " read -p \"" B(prompt) "\" " var " </dev/tty >/dev/tty "
-#endif
-
-#ifndef ASK1
-#define ASK1(var, prompt) " { printf \""prompt"\"; stty -icanon -echo; "var"=$(dd bs=1 count=1 2> /dev/null); stty icanon echo; } "
-#endif
-
-#define PAUSE ASK1("REPLY", "\033[2mPress any key to continue...\033[0m\033[?25l")
-
-// Macro for picking from a list of options:
-#ifndef PICK
-#define PICK(prompt) " { "ASK("query", prompt)" && awk '{print length, $1}' | sort -n | cut -d' ' -f2- | "\
- "grep -i -m1 \"$(echo \"$query\" | sed 's;.;[^/&]*[&];g')\"; } "
-#endif
-
-// 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; "\
- "wait $pid; }"
-#endif
-
-#ifndef CONFIRM
-#define CONFIRM(action, files) " { printf '%s\\n' \""B(action)"\" \""files"\" | more; " \
- ASK1("REPLY", B("Is that okay? [y/N] "))"; [ \"$REPLY\" = 'y' ]; } "
-#endif
-
-#define SECTION(name) {{0}, NULL, name}
-
-
// These commands will run at startup (before command-line arguments)
-extern const char *startupcmds[];
extern const column_t columns[128];
-extern binding_t bindings[];
+extern binding_t bindings[1024];
// Column widths and titles:
const column_t columns[128] = {
@@ -158,20 +58,6 @@ const column_t columns[128] = {
['s'] = {9, " Size"},
};
-// This is a list of commands that runs when `bb` launches:
-const char *startupcmds[] = {
- // Set some default marks:
- "mkdir -p ~/.config/bb/marks",
- "ln -sT ~/.config/bb/marks ~/.config/bb/marks/marks 2>/dev/null",
- "ln -sT ~ ~/.config/bb/marks/home 2>/dev/null",
- "ln -sT / ~/.config/bb/marks/root 2>/dev/null",
- "ln -sT ~/.config ~/.config/bb/marks/config 2>/dev/null",
- "ln -sT ~/.local ~/.config/bb/marks/local 2>/dev/null",
- // 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>"}
@@ -183,129 +69,6 @@ const char *startupcmds[] = {
* `vim -c 'set t_ti= t_te=' "$@"` to prevent momentarily seeing the shell
* after editing.
*****************************************************************************/
-binding_t bindings[] = {
- SECTION("Key Bindings"),
- {{'?', KEY_F1}, "+help", B("Help")" menu"},
- {{'q', 'Q'}, "+quit", B("Quit")},
-
- SECTION("Navigation"),
- {{'j', KEY_ARROW_DOWN}, "+move:+1", B("Next")" file"},
- {{'k', KEY_ARROW_UP}, "+move:-1", B("Previous")" file"},
- {{'h', KEY_ARROW_LEFT}, "+cd:..", B("Parent")" directory"},
- {{'l', KEY_ARROW_RIGHT}, "[ -d \"$BBCURSOR\" ] && bb \"+cd:$BBCURSOR\"", B("Enter")" a directory"},
- {{KEY_CTRL_F}, "bb \"+goto:$(if [ $BBDOTFILES ]; then find -mindepth 1; else find -mindepth 1 ! -path '*/.*'; fi "
- "| "PICK("Find: ")")\"", B("Search")" for file"},
- {{'/'}, "bb \"+goto:$(if [ $BBDOTFILES ]; then find -mindepth 1 -maxdepth 1; else find -mindepth 1 -maxdepth 1 ! -path '*/.*'; fi "
- "| "PICK("Pick: ")")\"", B("Pick")" file"},
- {{KEY_CTRL_G}, ASK("goto", "Go to directory: ", "")" && bb +cd:\"$goto\"", B("Go to")" directory"},
- {{'m'}, ASK("mark", "Mark: ", "")" && ln -s \"$PWD\" ~/.config/bb/marks/\"$mark\"", B("Mark")" this directory"},
- {{'\''}, "mark=\"$(ls ~/.config/bb/marks | " PICK("Jump to: ") ")\" "
- "&& bb +cd:\"$(readlink -f ~/.config/bb/marks/\"$mark\")\"",
- "Go to a "B("marked")" directory"},
- {{'-', KEY_BACKSPACE, KEY_BACKSPACE2},
- "[ $BBPREVPATH ] && bb +cd:\"$BBPREVPATH\"", "Go to "B("previous")" directory"},
- {{';'}, "bb +cd:'<selection>'", "Show "B("selected files")},
- {{'0'}, "bb +cd:\"$BBINITIALPATH\"", "Go to "B("initial directory")},
- {{'g', KEY_HOME}, "+move:0", "Go to "B("first")" file"},
- {{'G', KEY_END}, "+move:100%n", "Go to "B("last")" file"},
- {{KEY_PGDN}, "+scroll:+100%", B("Page down")},
- {{KEY_PGUP}, "+scroll:-100%", B("Page up")},
- {{KEY_CTRL_D}, "+scroll:+50%", B("Half page down")},
- {{KEY_CTRL_U}, "+scroll:-50%", B("Half page up")},
- {{KEY_MOUSE_WHEEL_DOWN}, "+scroll:+3", B("Scroll down")},
- {{KEY_MOUSE_WHEEL_UP}, "+scroll:-3", B("Scroll up")},
-
- SECTION("File Selection"),
- {{' ','v','V'}, "+toggle", B("Toggle")" selection at cursor"},
- {{KEY_ESC}, "bb +deselect: \"$@\"", B("Clear")" selection"},
- {{KEY_CTRL_S}, "[ $# -gt 0 ] && "ASK("savename", "Save selection as: ", "") " && printf '%s\\0' \"$@\" > ~/.config/bb/\"$savename\"",
- B("Save")" the selection"},
- {{KEY_CTRL_O}, "loadpath=\"$(find ~/.config/bb -maxdepth 1 -type f | " PICK("Load selection: ") ")\" "
- "&& [ -e \"$loadpath\" ] && bb +deselect:'*' "
- "&& while IFS= read -r -d $'\\0'; do bb +select:\"$REPLY\"; done < \"$loadpath\"",
- B("Open")" a saved selection"},
- {{'J'}, "+spread:+1", B("Spread")" selection down"},
- {{'K'}, "+spread:-1", B("Spread")" selection up"},
- {{KEY_CTRL_A},
- "if [ $BBDOTFILES ]; then find -mindepth 1 -maxdepth 1 -print0; "
- "else find -mindepth 1 -maxdepth 1 ! -path '*/.*' -print0; fi | bb +sel:",
- B("Select all")" files here"},
-
- SECTION("Actions"),
- {{'\r', KEY_MOUSE_DOUBLE_LEFT},
- "if [ -d \"$BBCURSOR\" ]; then bb \"+cd:$BBCURSOR\"; "
-#ifdef __APPLE__
- "elif file -bI \"$BBCURSOR\" | grep -q '^\\(text/\\|inode/empty\\)'; then $EDITOR \"$BBCURSOR\"; "
- "else open \"$BBCURSOR\"; fi",
-#else
- "elif file -bi \"$BBCURSOR\" | grep -q '^\\(text/\\|inode/empty\\)'; then $EDITOR \"$BBCURSOR\"; "
- "else xdg-open \"$BBCURSOR\"; fi",
-#endif
- B("Open")" file/directory"},
- {{'e'}, "$EDITOR \"$BBCURSOR\" || "PAUSE, B("Edit")" file in $EDITOR"},
- {{'E'}, "[ $# -gt 0 ] && $EDITOR \"$@\" || "PAUSE, B("Edit")" selected files in $EDITOR"},
- {{'d'}, CONFIRM("The following will be deleted:", "$BBCURSOR") " && rm -rf \"$BBCURSOR\" && bb +refresh && bb +deselect: \"$BBCURSOR\"",
- B("Delete")" a file"},
- {{'D', KEY_DELETE},
- "[ $# -gt 0 ] && "CONFIRM("The following will be deleted:", "$@") " && rm -rf \"$@\" && bb +refresh && bb +deselect: \"$@\"",
- B("Delete")" selected files"},
- {{KEY_CTRL_V}, "[ $# -gt 0 ] && "
- CONFIRM("The following will be moved here:", "$@") " && { "
- SPIN("mv -i \"$@\" . && bb +refresh && bb +deselect: \"$@\" && for f; do bb \"+sel:$(basename \"$f\")\"; done")" || "PAUSE"; }",
- B("Move")" files here"},
- {{'c'}, CONFIRM("Copy file:", "$BBCURSOR")" && cp -ri \"$BBCURSOR\" \"$BBCURSOR.copy\" && bb +refresh",
- B("Copy")" a file"},
- {{'C'}, "[ $# -gt 0 ] && "CONFIRM("The following will be copied here:", "$@")
- " && for f; do if [ \"./$(basename \"$f\")\" -ef \"$f\" ]; then "
- SPIN("cp -ri \"$f\" \"$(basename \"$f\").copy\"")"; "
- "else "SPIN("cp -ri \"$f\" .")"; fi; done; bb +refresh",
- B("Copy")" the selected files here"},
- {{KEY_CTRL_N}, "type=\"$(printf '%s\\n' File Directory | "PICK("Create new: ")")\" "
- "&& "ASK("name", "New $type: ", "")" && "
- "{ if [ $type = File ]; then touch \"$name\"; else mkdir \"$name\"; fi "
- "&& bb \"+goto:$name\" +r || "PAUSE"; }", B("New")" file/directory"},
- {{'p'}, "$PAGER \"$BBCURSOR\"", B("Page")" through a file in $PAGER"},
- {{'P'}, "[ $# -gt 0 ] && $PAGER \"$@\"", B("Page")" through selected files in $PAGER"},
- {{'|'}, ASK("cmd", "|", "") " && printf '%s\\n' \"$@\" | "SH" -c \"$BBSHELLFUNC$cmd\"; " PAUSE "; bb +r",
- B("Pipe")" selected files to a command"},
- {{':'}, ASK("cmd", ":", "")" && "SH" -c \"$BBSHELLFUNC$cmd\" -- \"$@\"; " PAUSE "; bb +refresh",
- B("Run")" a command"},
- {{'>'}, "tput rmcup >/dev/tty; $SHELL; bb +r", "Open a "B("shell")},
- {{'r', KEY_F2},
- ASK("newname", "Rename \033[33m$(basename \"$BBCURSOR\")\033[39m: ", "$(basename \"$BBCURSOR\")")" && "
- "r=\"$(dirname \"$BBCURSOR\")/$newname\" && "
- "[ \"$r\" != \"$BBCURSOR\" ] && mv -i \"$BBCURSOR\" \"$r\" && bb +refresh && "
- "while [ $# -gt 0 ]; do [ \"$1\" = \"$BBCURSOR\" ] && bb \"+deselect:$BBCURSOR\" \"+select:$r\"; shift; done && "
- "bb +goto:\"$r\"",
- B("Rename")" a file"},
- {{'R'},
- "bb +refresh; "
- "for f; do "
- " "ASK("newname", "Rename \033[33m$(basename \"$f\")\033[39m: ", "$(basename \"$f\")")" || break; "
- " r=\"$(dirname \"$f\")/$newname\"; "
- " [ \"$r\" != \"$f\" ] && mv -i \"$f\" \"$r\" && bb \"+deselect:$f\" \"+select:$r\"; "
- " [ \"$f\" = \"$BBCURSOR\" ] && bb +goto:\"$r\"; "
- "done", B("Rename")" selected files"},
- {{KEY_CTRL_R},
- "command -v rename >/dev/null || { echo 'The `rename` command is not installed. Please install it to use this key binding.'; "PAUSE"; exit; }; "
- ASK("patt", "Replace pattern: ", "")" && "ASK("rep", "Replacement: ", "")" && "
- CONFIRM("Renaming:", "$(if [ $# -gt 0 ]; then rename -nv \"$patt\" \"$rep\" \"$@\"; else rename -nv \"$patt\" \"$rep\" *; fi)")" && "
- "if [ $# -gt 0 ]; then rename -i \"$patt\" \"$rep\" \"$@\"; else rename -i \"$patt\" \"$rep\" *; fi; bb +refresh",
- B("Regex rename")" files"},
-
- SECTION("File Display"),
- {{'s'},
- ASK1("sort", B("Sort (n)ame (s)ize (m)odification (c)reation (a)ccess (r)andom (p)ermissions: "))
- " && bb +sort:\"~$sort\" +refresh",
- B("Sort")" by..."},
- {{'#'}, ASK("columns", "Set columns (*)selected (a)ccessed (c)reated (m)odified (n)ame (p)ermissions (r)andom (s)ize: ", "")
- " && bb +col:\"$columns\"",
- "Set "B("columns")},
- {{'.'}, "+dotfiles", "Toggle "B("dotfile")" visibility"},
- {{'i'}, "+interleave", "Toggle "B("interleaving")" files and directories"},
- {{KEY_F5}, "+refresh", B("Refresh")},
-
- {{-1}} // Array must be -1-terminated
-};
+binding_t bindings[1024];
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1