Compare commits

...

82 Commits

Author SHA1 Message Date
fb2d270e2d Print build directory once selected 2025-04-09 16:50:35 +01:00
a0468b7842 Always enable CMake color diagnostics 2025-02-07 12:22:28 +00:00
8ff71513b2 Add completions for session command 2024-09-17 20:36:09 +01:00
2fea9a3795 Update build usage and error message 2024-09-17 19:43:57 +01:00
ee2dac70db Only migrate histfile if target doesn't exist 2024-09-11 20:30:01 +01:00
Kenneth Benzie (Benie)
8812ef8544 Use XDG base dir vars instead of defaults 2024-09-10 07:39:51 -07:00
1e53581d17 Add configurable session host shortnames 2024-08-23 21:40:31 +01:00
6c86d1c0cc Add session command 2024-08-21 23:00:52 +01:00
4ff10eb05e Use neovim as man pager 2024-08-03 00:09:45 +01:00
0ad3647ddc Make prompt also detect running in a container 2024-07-13 10:13:21 +00:00
b5dedf6d56 Also notify ignore fg 2024-07-08 13:41:17 +01:00
c401ecfb86 Also export BUILD_DIR to an absolute path 2024-06-21 14:16:10 +01:00
e7da727896 Also ignore watch commands 2024-06-17 19:37:57 +01:00
192659fd84 Also ignore cat & bat 2024-05-25 17:45:07 +01:00
6632715529 Teach golang xdg manners 2024-05-17 21:44:04 +01:00
37fd8b00e3 Also ignore podman notifications 2024-05-17 17:22:52 +01:00
3be19a22a0 Fix fresh prompt cleanup when options were specified 2024-05-11 22:43:27 +01:00
fda79768b7 Also ignore [i]python 2024-05-09 12:06:33 +01:00
88fdfe7a84 Properly cleanup fresh prompt theme
If `prompt <theme>` is used, prior to this patch the `fresh_line_one`
precmd hook would not be removed. This is no longer the case and cleanup
is correctly performed.
2024-05-08 23:36:21 +01:00
d0cf713a02 Also ignore zsh & bash 2024-05-08 23:00:13 +01:00
e1f16b56b0 Also notify ignore slides 2024-05-08 22:52:34 +01:00
f983c1e205 Also ignore top like tools in notify complete 2024-05-08 14:42:21 +01:00
52a9552bf7 Don't edit an autoenv on init 2024-05-06 21:52:19 +01:00
96a1272506 Remove zcurses build-dir selector 2024-05-04 10:39:10 +01:00
f7bca0102a Tweak .build-dir widget and only enable during build-dir 2024-05-04 10:31:08 +01:00
dcacb1de42 Add .build-var zle widget
Press Ctrl-B to fuzzy find all configuration CMake variables for the
current build directory. Once a variable is selected, rewrite the
command-line to set the selected CMake variable.
2024-05-03 22:44:30 +01:00
766ac3c5bf Move fzf-history-search to utilities
Also rename to .fzf-history-search to avoid it turning up in normal
command completion as an option.
2024-05-03 22:38:19 +01:00
2d56207f1e Stop disabling Ex mode 2024-05-03 22:31:32 +01:00
c20d18e62d More tweaks for build-dir fzf invocation 2024-05-03 15:59:54 +01:00
6388b076bd Add ping to notify ignore list 2024-05-03 15:06:25 +01:00
a3ca92e2a6 Search entire history with fzf in Ctrl-R 2024-05-02 23:57:44 +01:00
d12bc6f756 Make C-r work more like build-dir 2024-05-01 21:41:49 +01:00
e269e6ff8d Swap fzf args in build-dir to make more sense 2024-05-01 21:41:25 +01:00
b4ce10f1bd Tweak build-dir fzf invocation 2024-05-01 21:29:00 +01:00
1bdaa8ac08 Fix bug in build-dir with single build dir 2024-05-01 21:28:26 +01:00
47082002f9 Define fzf theme based on Kanagawa 2024-05-01 21:27:44 +01:00
ba9eba596f Limit the max size of the build-dir fzf window 2024-05-01 17:33:53 +01:00
0efb635f02 Use fzf by default for build-dir selector 2024-05-01 14:27:19 +01:00
f50db402af Also ignore man on notify command completed 2024-04-24 20:35:32 +01:00
bc3fcea5dd Also don't notify if cmatrix exits 2024-04-24 00:46:00 +01:00
29b232527a Fix sandbox create (but how did it break?!?) 2024-04-23 22:23:41 +01:00
eae2e82bdb Add glab to the list if commands to notify ignore 2024-04-20 16:58:39 +01:00
0951c445f4 Expand frequent-directory & check dir exists 2024-04-18 21:59:29 +01:00
b9373430b0 Also ignore gh for long command notifications 2024-04-16 17:40:05 +01:00
6280d90bd9 Make notify command threshold 60 seconds again 2024-04-13 16:43:57 +01:00
3accfe0bec Add install.zsh for standalone installs 2024-04-13 16:10:41 +01:00
a9fb5104ac Don't notify when select commands exit 2024-04-12 22:51:42 +01:00
6678fe0aaf Assume layouts are executable not tmux scripts 2024-04-12 20:58:25 +01:00
1ca9e4f6ae Use a bit of clang-format on git-prompt.c 2024-04-08 20:33:26 +01:00
7aa78e94d1 Notify via OSC 9 after long running command completes 2024-04-07 23:24:50 +01:00
42260925a0 Fix tmux-dcs-passthrough & notify utilities
These two have been sitting in a broken state for quite a while but I
findally RTFM and realised that the escape characters in the escape
sequence need to be doubled up in order for tmux to properly pass
through the escape sequence.
2024-04-07 23:01:02 +01:00
a6d97c1eac Add fuzzy history search with fzf 2024-04-07 19:29:01 +01:00
1bf5d10b74 Don't underline precommands 2024-04-04 21:31:43 +01:00
edf37ebf07 Use vimdebug in build-debug if nvim is available 2024-04-02 16:09:31 +01:00
18bcb6ccde Add CMAKE_EXPORT_COMPILE_COMMANDS env var 2024-03-09 13:18:25 +00:00
8a9e66db32 Add ls-iommu utility 2023-12-22 13:11:39 +00:00
1e60a5ddd5 Add hashes for ~/.config ~/.local and ~/.cache 2023-12-21 16:15:34 +00:00
4b0425b2d4 Add url command to {en,de}code text 2023-10-19 18:05:04 +01:00
5c62ff219c Remove unused tasks.yaml 2023-10-19 17:47:46 +01:00
1121b9a193 Alias wol to wakeonlan 2023-10-05 19:59:28 +01:00
0c4cd8880b Add sourcing of local ignored file 2023-06-21 22:05:57 +01:00
e30f86800d Don't check for vim when using $EDITOR 2023-06-17 15:15:00 +01:00
ad5dc95e4d Add script to list completions available for instlled commands 2023-02-18 15:06:04 +00:00
d226ac7097 Also load ~/.config/private/zshrc if present 2023-02-16 10:26:38 +00:00
e7750cb0a9 Remove chevrons from prompt 2023-02-03 11:20:21 +00:00
Benie
efbfa23241 Add new homebrew install locaiton to PATH 2022-12-10 15:59:39 +00:00
b95b365276 Don't attempt to set invalid environment variable names 2022-11-25 13:28:49 +00:00
501353a534 Add sandbox error message for invalid commands 2022-11-09 16:42:46 +00:00
02abb0960c Always use nvim for vimdebug command 2022-11-06 22:05:49 +00:00
a81465daad Only set WGETRC if $HOME/.config/wget/rc exists 2022-11-06 14:56:49 +00:00
5a33d2b5ac Add autoenv add=local subcommand
The `add=local` subcommand creates `.local/bin` if it doesn't exit and
then updates the autoenv to add it to `PATH`.
2022-10-26 20:31:51 +01:00
c691d335c0 Disable zsh-history-substring-search highlights 2022-10-11 17:16:23 +01:00
715014ed3d Specify compdump file location to compinit 2022-09-20 22:45:54 +01:00
efcea9e8a5 Change value of WGETRC 2022-09-20 22:45:42 +01:00
ea61bde858 Change sandbox prompt highlight color 2022-07-29 17:45:12 +01:00
a96aa50fbe Add --show option to build-dir command
The new option shows the current build directory, if present.
2022-07-11 13:47:05 +01:00
c61c86e979 Add ~Sandbox hashed directory 2022-06-12 21:03:54 +01:00
8790bc0c4e Use $EDITOR rather the vim directory 2022-03-31 22:13:26 +01:00
b349befbf4 Be explicit about python absolute path
One some distros `virtualenv` still uses a Python 2 executable, I always
set `python` to point to Python 3 so be explicit about getting the
absolute path to `python` when creating a `virtualenv` with `autoenv
add=py`.
2022-03-22 13:29:33 +00:00
74f2dd7dae Fix autoenv add=py .enter when run in subdirectory 2022-03-22 13:29:33 +00:00
a362ab0e04 Prefer nvim over vim for EDITOR, don't use which 2022-02-26 17:22:51 +00:00
a422ab1125 Also install ag 2022-02-19 11:13:39 +00:00
21 changed files with 653 additions and 338 deletions

4
.gitignore vendored
View File

@ -1,2 +1,4 @@
# Ignore all plugin files in subdirectories
*/
zsh-*/
local
zsh*.local

View File

@ -17,6 +17,7 @@ _autoenv() {
edit:'edit .enter and .exit scripts in current directory'
deinit:'remove .enter and .exit scripts in current directory'
reload:'reload the current environment'
add=local:'add .local/bin to PATH'
add=py:'add Python virtualenv to the autoenv'
)
_describe -t commands command commands && ret=0 ;;

View File

@ -22,6 +22,7 @@ commands:
edit edit .enter and .exit scripts in current directory
deinit remove .enter and .exit scripts in current directory
reload reload the current environment
add=local add .local/bin to PATH
add=py add Python virtualenv to the autoenv"
;;
@ -35,8 +36,6 @@ commands:
[ -f $PWD/.enter ] && _autoenv_authorized $PWD/.enter yes
# If exit script exists, authorize it.
[ -f $PWD/.exit ] && _autoenv_authorized $PWD/.exit yes
# Edit the autoenv.
autoenv edit
# Enter the autoenv.
_autoenv_enter $PWD
;;
@ -45,21 +44,16 @@ commands:
if ! [ -f $PWD/.enter ] || ! [ -f $PWD/.exit ]; then
echo '.enter or .exit not found'; return 1
fi
# If vim exists, edit enter and exit scripts.
if which vim &> /dev/null; then
# Exit the autoenv before editing.
_autoenv_exit $PWD
if vim -p $PWD/.enter $PWD/.exit; then
# If enter script exists, authorize it.
[ -f $PWD/.enter ] && _autoenv_authorized $PWD/.enter yes
# If exit script exists, authorize it.
[ -f $PWD/.exit ] && _autoenv_authorized $PWD/.exit yes
fi
# Enter the autoenv.
_autoenv_enter $PWD
else
echo 'vim not found'; return 1
# Exit the autoenv before editing.
_autoenv_exit $PWD
if $EDITOR -p $PWD/.enter $PWD/.exit; then
# If enter script exists, authorize it.
[ -f $PWD/.enter ] && _autoenv_authorized $PWD/.enter yes
# If exit script exists, authorize it.
[ -f $PWD/.exit ] && _autoenv_authorized $PWD/.exit yes
fi
# Enter the autoenv.
_autoenv_enter $PWD
;;
deinit) # Remove .enter and .exit scripts in current directory.
@ -92,13 +86,34 @@ commands:
_autoenv_enter $PWD
;;
add=local) # Add .local/bin to PATH
if ! [ -f $PWD/.enter ] || ! [ -f $PWD/.exit ]; then
echo '.enter or .exit not found'; return 1
fi
_autoenv_exit $PWD
# Create .local/bin if not present
if ! [ -d $PWD/.local/bin ]; then
mkdir -p $PWD/.local/bin
fi
# On enter: store PATH and insert .local/bin
echo 'OLDPATH=$PATH' >> .enter
echo 'PATH=$PWD/.local/bin:$PATH' >> .enter
# On exit: reset PATH
echo 'PATH=$OLDPATH' >> .exit
echo 'unset OLDPATH' >> .exit
# Authorize modified autoenv
_autoenv_authorized $PWD/.enter yes
_autoenv_authorized $PWD/.exit yes
_autoenv_enter $PWD
;;
add=py) # Add Python virtualenv to the sandbox
if ! [ -f $PWD/.enter ] || ! [ -f $PWD/.exit ]; then
echo '.enter or .exit not found'; return 1
fi
_autoenv_exit $PWD
virtualenv .local
echo 'source .local/bin/activate' >> .enter
virtualenv -p `command -v python` .local
echo 'source ${0:a:h}/.local/bin/activate' >> .enter
echo 'deactivate' >> .exit
_autoenv_authorized $PWD/.enter yes
_autoenv_authorized $PWD/.exit yes
@ -122,16 +137,22 @@ zmodload -F zsh/stat b:zstat
# Check if the given file is authorized, if not prompt the user to authorize,
# ignore, or view the file. Authorized files and their modified times are
# stored in the ~/.cache/autoenv/authorized file to make authorization
# stored in the $XDG_STATE_HOME/autoenv/authorized file to make authorization
# persistent.
_autoenv_authorized() {
local file=$1 yes=$2
# If autoenv cache directory does not exist, create it.
! [ -d ~/.cache/autoenv ] && mkdir -p ~/.cache/autoenv
# If autoenv state directory does not exist, create it.
! [ -d ${XDG_STATE_HOME:-$HOME/.local/state}/autoenv ] && \
mkdir -p ${XDG_STATE_HOME:-$HOME/.local/state}/autoenv
# Migrate from cache to state directory
[ -f $HOME/.cache/autoenv/authorized ] && \
mv $HOME/.cache/autoenv/authorized \
${XDG_STATE_HOME:-$HOME/.local/state}/autoenv/authorized
# If the authorized file does not exist, create it.
! [ -f ~/.cache/autoenv/authorized ] && touch ~/.cache/autoenv/authorized
! [ -f ${XDG_STATE_HOME:-$HOME/.local/state}/autoenv/authorized ] && \
touch ${XDG_STATE_HOME:-$HOME/.local/state}/autoenv/authorized
# Load the authorized file into a map of authorized key value pairs.
typeset -A authorized=(`cat ~/.cache/autoenv/authorized`)
typeset -A authorized=(`cat ${XDG_STATE_HOME:-$HOME/.local/state}/autoenv/authorized`)
# If the file has been removed, return.
! [ -f $file ] && return 1
# If the given file has been authorized, i.e. the modified time matches that
@ -153,7 +174,7 @@ _autoenv_authorized() {
# Add file to the authorized map.
authorized[$file]=$modified_time
# Store authorized map in authorized file.
echo ${(kv)authorized} > ~/.cache/autoenv/authorized
echo ${(kv)authorized} > ${XDG_STATE_HOME:-$HOME/.local/state}/autoenv/authorized
}
# Source an enter script and add its directory to the global entered

View File

@ -1,6 +1,7 @@
#compdef build-dir
_arguments \
'(-h --help)'{-h,--help}'[]' \
'(-h --help)'{-h,--help}'[show this help message and exit]' \
'(-s --show)'{-s,--show}'[show the current build directory]' \
'--build[invoke a build after selection]' \
'1:directory:_files'

View File

@ -7,33 +7,31 @@ alias build="build-dir --build"
# Detect installed debugger and set the `debug` alias to debug a program with
# command line arguments.
if [ `uname` = Linux ]; then
if [[ "`vim --version|head -1|cut -c 19-21`" =~ "^8\.[123456789]$" ]]; then
autoload -U regexp-replace
function vimdebug() {
# For each item in $* replace * and \* and then replace \ with \\
local args=()
for arg in "$@"; do
regexp-replace arg '\*' '\\*'
args+=($arg)
done
vim "+packadd termdebug" "+TermdebugCommand $args"
}
alias debug='vimdebug'
elif which cgdb &> /dev/null; then
alias debug='cgdb --args'
elif which gdb &> /dev/null; then
autoload -U regexp-replace
function vimdebug() {
# For each item in $* replace * and \* and then replace \ with \\
local args=()
for arg in "$@"; do
regexp-replace arg '\*' '\\*'
args+=($arg)
done
nvim "+packadd termdebug" "+TermdebugCommand $args"
}
if command -v nvim &> /dev/null; then
alias debug=vimdebug
elif command -v gdb &> /dev/null; then
alias debug='gdb --args'
fi
elif [ `uname` = Darwin ]; then
which lldb &> /dev/null && \
command -v lldb &> /dev/null && \
alias debug='lldb --'
fi
# Interactively choose a `~build` directory for `build` to build.
build-dir() {
local usage='usage: build-dir [-h] [--build] [<directory>]'
local -a help do_build
zparseopts -D h=help -help=help -build=do_build
local usage='usage: build-dir [-h] [-s] [--build] [<directory>]'
local -a help show do_build
zparseopts -D h=help -help=help s=show -show=show -build=do_build
if [[ -n $help ]]; then
cat << EOF
$usage
@ -45,16 +43,26 @@ positional arguments:
optional arguments:
-h, --help show this help message and exit
-s, --show show the current build directory
--build invoke a build after selection
EOF
return
fi
error() { echo "\e[31merror:\e[0m $1" }
warning() { echo "\e[33mwarning:\e[0m $1" }
if [[ -n $show ]]; then
if [[ ! -n $build_dir ]]; then
error "build directory not set"
return 1
else
echo "$build_dir"
return
fi
fi
local local_build_dir
if [[ ${#*} -gt 1 ]]; then
echo $usage
error "unexpected position arguments: ${*[2,${#*}]}"; return 1
error "unexpected positional arguments: ${*[2,${#*}]}"; return 1
elif [[ ${#*} -eq 1 ]]; then
if [[ ! -d ${*[1]} ]]; then
warning "directory not found: ${*[1]}"
@ -76,99 +84,58 @@ EOF
integer index=0
if [[ ${#local_build_dirs} -eq 0 ]]; then
error "no build directories found"; return 1
elif [[ ${#local_build_dirs} -eq 1 ]]; then
local_build_dir=${local_build_dirs[1]}
elif [[ ${#local_build_dirs} -gt 1 ]]; then
zmodload zsh/curses && {
# Get the size of the terminal
local size=`stty size`
integer height=${size% *}
integer width=${size#* }
# Create the window and hide the cursor
zcurses init
zcurses addwin build-dir $height $width 0 0
# Hide the cursor for zcurses, trap SIGINT to ensure cleanup in
# always-list occurs below
tput civis; trap 'return 130' INT
# Enter display loop
local key keypad
while (( 1 )); do
zcurses clear build-dir
# Add the prompt text
zcurses move build-dir 1 1
zcurses string build-dir 'Select a build directory:'
# Add the selections text
for (( i = 0; i < ${#local_build_dirs}; i++ )); do
integer line=$i+3
zcurses move build-dir $line 1
[[ $index -eq $i ]] &&
zcurses string build-dir "* " ||
zcurses string build-dir " "
zcurses string build-dir ${local_build_dirs[$i+1]}
done
# Display the text the and wait for input
zcurses refresh build-dir
zcurses input build-dir key keypad
# Handle user input
case $key in
(UP|k|$'\C-P')
[[ $index -gt 0 ]] && index=$index-1 ;;
(DOWN|j|$'\C-N')
[[ $index -lt ${#local_build_dirs}-1 ]] && index=$index+1 ;;
(ENTER|$'\n')
break ;;
esac
done
} always {
# Restore the cursor and cleanup zcurses
tput cvvis; tput cnorm
zcurses delwin build-dir
zcurses end
}
# Use fzf to select a build directory
local max=$(( $( tput lines ) / 2 ))
local best=$(( ${#local_build_dirs} + 4 ))
local_build_dir=$(
printf '%s\n' "${local_build_dirs[@]}" |
fzf --layout=reverse --tac --info=hidden --border=rounded \
--cycle --height=$(( $best < $max ? $best : $max ))
)
if [[ $? -ne 0 ]]; then
return 1
fi
fi
fi
# On success setup the build directory for use
if [[ $? -eq 0 ]]; then
# Set the build directory from selection if empty
[[ -z $local_build_dir ]] && \
local_build_dir=${local_build_dirs[$index+1]}
# If `build.ninja` exists in alias `ninja`, return.
local build
[ -f $local_build_dir/build.ninja ] && \
build="ninja -C $local_build_dir"
# If `build.ninja` exists in alias `ninja`, return.
local build
[ -f $local_build_dir/build.ninja ] && \
build="ninja -C $local_build_dir"
# If `Makefile` exists in alias `make`, return.
if [ -f $local_build_dir/Makefile ]; then
[ `uname` = Darwin ] && \
local cpu_count=`sysctl -n hw.ncpu` ||
local cpu_count=`grep -c '^processor' /proc/cpuinfo`
build="make -j $cpu_count -C $local_build_dir"
fi
# If the build variable is not defined the command could not be determined
if [ -z $build ]; then
warning "build command detection failed: $local_build_dir"
# Prompt user to enter a build command
vared -p 'enter comand: ' build
fi
# Redefine the `build` alias and update the `~build` hash directory
alias build="$build"
hash -d build=$local_build_dir
export build_dir=$local_build_dir
# If `--build` is specified then evaluate the command.
if [[ -n $do_build ]]; then
eval build
fi
# If `Makefile` exists in alias `make`, return.
if [ -f $local_build_dir/Makefile ]; then
[ `uname` = Darwin ] && \
local cpu_count=`sysctl -n hw.ncpu` ||
local cpu_count=`grep -c '^processor' /proc/cpuinfo`
build="make -j $cpu_count -C $local_build_dir"
fi
# If the build variable is not defined the command could not be determined
if [ -z $build ]; then
warning "build command detection failed: $local_build_dir"
# Prompt user to enter a build command
vared -p 'enter comand: ' build
fi
# Redefine the `build` alias and update the `~build` hash directory
alias build="$build"
hash -d build=$local_build_dir
export build_dir=$local_build_dir
export BUILD_DIR=$PWD/$local_build_dir
echo "$build_dir"
# If `--build` is specified then evaluate the command.
if [[ -n $do_build ]]; then
eval build
fi
# Bind C-B to fuzzy find & complete cmake variables.
zle -N .build-var
bindkey '^B' .build-var
}
# Build then run a target residing in `~build/bin`.
@ -182,3 +149,22 @@ build-debug() {
local target=$1; shift 1
eval build $target && debug ~build/bin/$target "$@"
}
# Fuzzy find CMake variables, select one to set the variable via a command.
.build-var() {
local var=$(
cat $build_dir/CMakeCache.txt |
grep --color=never -Ex '^\w+:\w+=.*$' |
fzf --layout=reverse --info=hidden --border=rounded \
--cycle --height=50%
)
if [[ -n "$var" ]]; then
if [[ "$BUFFER" = "cmake"* ]]; then
BUFFER="$BUFFER-D$var"
else
BUFFER="cmake -B\$build_dir -D$var"
fi
zle end-of-line
fi
zle reset-prompt
}

View File

@ -9,24 +9,24 @@
#endif
#ifdef DEBUG
#define check(CONDITION) \
if (CONDITION) { \
fprintf(stderr, "error: %s: %d: %s\n", __FILE__, __LINE__, #CONDITION); \
exit(0); \
#define check(CONDITION) \
if (CONDITION) { \
fprintf(stderr, "error: %s: %d: %s\n", __FILE__, __LINE__, #CONDITION); \
exit(0); \
}
#else
#define check(CONDITION) \
if (CONDITION) { \
exit(0); \
#define check(CONDITION) \
if (CONDITION) { \
exit(0); \
}
#endif
typedef struct process {
pid_t pid;
FILE* out;
FILE *out;
} process_t;
process_t process_open(char* command) {
process_t process_open(char *command) {
int fds[2];
check(pipe(fds));
int pid = fork();
@ -35,7 +35,7 @@ process_t process_open(char* command) {
close(fds[0]);
dup2(fds[1], STDOUT_FILENO);
dup2(STDOUT_FILENO, STDERR_FILENO);
char* argv[] = {"sh", "-c", command, NULL};
char *argv[] = {"sh", "-c", command, NULL};
exit(execvp(argv[0], argv));
} else { // parent process
close(fds[1]);
@ -54,9 +54,11 @@ int process_close(process_t process) {
return 0;
}
char* trim(char* str) {
char* end;
while (isspace((unsigned char)*str)) str++;
char *trim(char *str) {
char *end;
while (isspace((unsigned char)*str)) {
str++;
}
if (*str == 0) {
return str;
}
@ -68,17 +70,17 @@ char* trim(char* str) {
return str;
}
char* append(char* buffer, int count, ...) {
char *append(char *buffer, int count, ...) {
va_list list;
va_start(list, count);
for (int i = 0; i < count; i++) {
strcat(buffer, va_arg(list, char*));
strcat(buffer, va_arg(list, char *));
}
va_end(list);
return buffer;
}
char* inttostr(char* buffer, int value) {
char *inttostr(char *buffer, int value) {
sprintf(buffer, "%d", value);
return buffer;
}
@ -102,7 +104,7 @@ int main() {
check(process_close(process));
}
}
char* branch = trim(branch_buf);
char *branch = trim(branch_buf);
char prompt[1024] = {};
append(prompt, 3, " %{%F{66}%}", branch, "%{%f%}");
@ -113,7 +115,7 @@ int main() {
char remote_buf[256] = {};
fread(remote_buf, 1, sizeof(remote_buf), process.out);
if (process_close(process) == 0) {
char* remote = trim(remote_buf);
char *remote = trim(remote_buf);
// get the number of commits ahead of the remote
memset(command, 0, sizeof(command));
process = process_open(append(command, 5,
@ -121,7 +123,7 @@ int main() {
remote, "/", branch, "...HEAD --count"));
char count[32] = {};
fread(count, 1, sizeof(count), process.out);
if(process_close(process) == 0 && strcmp("0", trim(count))) {
if (process_close(process) == 0 && strcmp("0", trim(count))) {
append(prompt, 2, "", trim(count));
}
@ -132,7 +134,7 @@ int main() {
remote, "/", branch, "...HEAD --count"));
memset(count, 0, sizeof(count));
fread(count, 1, sizeof(count), process.out);
if(process_close(process) == 0 && strcmp("0", trim(count))) {
if (process_close(process) == 0 && strcmp("0", trim(count))) {
append(prompt, 2, "", trim(count));
}
}
@ -157,7 +159,7 @@ int main() {
case ' ':
switch (Y) {
case 'M': ++modified; break;
case 'D': ++deleted; break;
case 'D': ++deleted; break;
} break;
case 'D': ++indexed;
switch (Y) {
@ -168,14 +170,14 @@ int main() {
switch (Y) {
case ' ': break;
case 'M': ++modified; break;
case 'D': ++deleted; break;
case 'D': ++deleted; break;
} break;
}
}
}
check(process_close(process));
if (indexed || modified || deleted || unmerged || untracked) { // modified
if (indexed || modified || deleted || unmerged || untracked) { // modified
char int_buf[32];
if (indexed) {
append(prompt, 3, "%{%F{2}%}*", inttostr(int_buf, indexed), "%{%f%}");
@ -192,7 +194,7 @@ int main() {
if (untracked) {
append(prompt, 1, "%{%F{1}%}…%{%f%}");
}
} else { // clean
} else { // clean
append(prompt, 1, "%{%B%F{2}%}✓%{%f%b%}");
}

92
install.zsh Executable file
View File

@ -0,0 +1,92 @@
#!/usr/bin/env zsh
error() {
echo "error: $*"
exit 1
}
directories=(
~/.cache/zsh
~/.local/bin
~/.local/share/zsh/plugins
~/.local/share/zsh/site-functions
)
for directory in $directories; do
mkdir -p $directory
done
plugins=(
zsh-users/zsh-autosuggestions
zsh-users/zsh-history-substring-search
zsh-users/zsh-syntax-highlighting
zsh-users/zsh-completions
)
for plugin in $plugins; do
plugin_name=${plugin/*\//}
plugin_directory=~/.local/share/zsh/plugins/$plugin_name
if [ -d $plugin_directory ]; then
if ! git -C $plugin_directory diff-index --quiet HEAD --; then
error $plugin_directory contains unstaged changes
fi
pull=`git -C $plugin_directory pull`
if [ "$pull" != "Already up to date." ] && \
[ "$pull" != "Already up-to-date." ]; then
echo changed pulled $plugin_directory
fi
else
git clone https://github.com/$plugin.git $plugin_directory > /dev/null
echo changed cloned $plugin_directory
fi
old_plugin_directory=~/.config/zsh/$plugin_name
if [ -d $old_plugin_directory ]; then
rm -rf $old_plugin_directory
echo changed removed $old_plugin_directory
fi
done
declare -A symlinks
symlinks=(
~/.config/zsh/zlogin ~/.zlogin
~/.config/zsh/zlogout ~/.zlogout
~/.config/zsh/zprofile ~/.zprofile
~/.config/zsh/zshenv ~/.zshenv
~/.config/zsh/zshrc ~/.zshrc
~/.config/zsh/prompt_fresh_setup
~/.local/share/zsh/site-functions/prompt_fresh_setup
~/.config/zsh/cmake-uninstall ~/.local/bin/cmake-uninstall
~/.config/zsh/$ ~/.local/bin/$
~/.config/zsh/url/url ~/.local/bin/url
)
for completion in ~/.config/zsh/**/_*; do
filename=`basename $completion`
symlinks[$completion]=~/.local/share/zsh/site-functions/$filename
done
completions=( ~/.local/share/zsh/plugins/zsh-completions/src/* )
for completion in $completions; do
filename=`basename $completion`
name=${filename:1}
if command -v $name > /dev/null; then
symlinks[$completion]=~/.local/share/zsh/site-functions/$filename
fi
done
for source in ${(k)symlinks}; do
dest=$symlinks[$source]
if [ -L $dest ]; then
target=`readlink $dest`
if [ "$target" != "$source" ]; then
rm $dest
ln -s $source $dest
echo changed replace incorrect symlink $dest
fi
elif [ -f $dest ]; then
error symlink failed $dest exists but is a regular file
else
ln -s $source $dest
echo changed created symlink $dest
fi
done

View File

@ -2,7 +2,7 @@ layout() {
if [[ "$1" == "" ]]; then
echo "usage: layout <layout> [name]"
else
tmux source-file ~/.local/share/tmux/layouts/$1
~/.local/share/tmux/layouts/$1
if [[ "$2" != "" ]]; then
tmux rename-window $2
fi

View File

@ -0,0 +1,22 @@
#!/usr/bin/env zsh
# Loop over available completions and add existing commands to array.
local -a completions
completions=(~/.config/zsh/zsh-completions/src/*)
local -a command_list
for completion in $completions; do
local filename=$(basename $completion)
local name=${filename:1}
if command -v $name &> /dev/null; then
command_list+=($name)
fi
done
# Print JSON array of commands Ansible can consume.
echo '['
local length=${#command_list[@]}
for (( i = 1; i < $length; i++ )); do
echo " \"${command_list[$i]}\","
done
echo " \"${command_list[-1]}\""
echo ']'

6
ls-iommu.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
for d in /sys/kernel/iommu_groups/*/devices/*; do
n=${d#*/iommu_groups/*}; n=${n%%/*}
printf '%s ' "$n"
lspci -nns "${d##*/}"
done

View File

@ -44,33 +44,40 @@ prompt_fresh_setup() {
fi
local userhost=$USER
if [ "$SSH_CONNECTION" != "" ] || [ "$DISTROBOX_ENTER_PATH" != "" ]; then
if [ "$SSH_CONNECTION" != "" ] || [ "$container" != "" ]; then
local user="$user@%{%F{244}%}%M%{%f%}"
local userhost="$userhost@`hostname`"
fi
PS1="«$user» "
PS2="«${(l:${#userhost}:: :)}» "
PS1="$user "
PS2="${(l:${#userhost}:: :)} "
prompt_opts=(percent sp subst)
}
prompt_cleanup() {
[ -f ~/.cache/zsh/git-prompt ] && rm ~/.cache/zsh/git-prompt
[ -f ${XDG_CACHE_HOME:-$HOME/.cache}/zsh/git-prompt ] && \
rm ${XDG_CACHE_HOME:-$HOME/.cache}/zsh/git-prompt
}
fresh_line_one() {
# First get the last commands exit code before doing anything
local exit_code=$?
# Clean up if fresh is no longer the current prompt theme
if [[ "`prompt -c | tail -1 | xargs`" != "fresh"* ]]; then
add-zsh-hook -d precmd fresh_line_one
return
fi
# Construct the time and directory portions of the prompt
local time_stamp="%{%F{244}%}%D{%H:%M:%S}%{%f%}"
[[ -n $SANDBOX_HOME ]] && \
local directory="%{%F{3}%}$SANDBOX_NAME${PWD#$SANDBOX_HOME}%{%f%}" || \
local directory="%{%F{220}%}$SANDBOX_NAME${PWD#$SANDBOX_HOME}%{%f%}" || \
local directory="%{%F{37}%}%~%{%f%}"
# Check we are in a git repository
local git=`~/.cache/zsh/git-prompt`
local git=`${XDG_CACHE_HOME:-$HOME/.cache}/zsh/git-prompt`
# If the last command failed, display its error code at the right
if [[ $exit_code -ne 0 ]]; then
@ -172,10 +179,12 @@ fresh_almostontop_preexec() {
fresh_compile_git_prompt() {
# Compile a simple C program which parses the output of `git status
# --procelain` to greatly decrease the time taken to draw the prompt
[ ! -d ~/.cache/zsh ] && mkdir -p ~/.cache/zsh
if [ ! -f ~/.cache/zsh/git-prompt ]; then
[ ! -d ${XDG_CACHE_HOME:-$HOME/.cache}/zsh ] && \
mkdir -p ${XDG_CACHE_HOME:-$HOME/.cache}/zsh
if [ ! -f ${XDG_CACHE_HOME:-$HOME/.cache}/zsh/git-prompt ]; then
cc -std=gnu99 -O3 -DNDEBUG -Wno-unused-result \
~/.config/zsh/git-prompt.c -o ~/.cache/zsh/git-prompt
${XDG_CONFIG_HOME:-$HOME/.config}/zsh/git-prompt.c \
-o ${XDG_CACHE_HOME:-$HOME/.cache}/zsh/git-prompt
if [ $? -ne 0 ]; then
echo "git-prompt was not compiled, is a C99 toolchain installed?"
fi

View File

@ -36,7 +36,7 @@ usage: sandbox [-h] {create,rename,destroy,enable,disable,list} ..
if [ "$git" = true ]; then
local repo=$arg
git=false
elif [[ -n "$name" ]]; then
elif [[ -z "$name" ]]; then
error "invalid argument $arg\n$usage" && return 1
else
local name=$arg
@ -44,14 +44,11 @@ usage: sandbox [-h] {create,rename,destroy,enable,disable,list} ..
fi
done
unset git
[[ -z "$name" ]] && \
error "missing argument <name>\n$usage" && return 1
local sandbox=$SANDBOX_ROOT/$name
[[ -d "$sandbox" ]] && \
error "sandbox already exists $name" && return 1
if [[ -n "$repo" ]]; then
mkdir -p $SANDBOX_ROOT &> /dev/null
git clone $repo $sandbox
@ -61,55 +58,49 @@ usage: sandbox [-h] {create,rename,destroy,enable,disable,list} ..
cd $sandbox
git init &> /dev/null
fi
echo "SANDBOX_HOME=\$(dirname -- "\$0:a")" >> $sandbox/.enter
echo "SANDBOX_NAME=$name" >> $sandbox/.enter
_autoenv_authorized $sandbox/.enter yes
echo "unset SANDBOX_NAME" >> $sandbox/.exit
echo "unset SANDBOX_HOME" >> $sandbox/.exit
_autoenv_authorized $sandbox/.exit yes
_autoenv_enter $sandbox
;;
rename)
local old_name=$1 new_name=$2
[[ -z "$old_name" ]] && \
error "missing argument <old-name>\n$usage" && return 1
[[ -z "$new_name" ]] && \
error "missing argument <new-name>\n$usage" && return 1
local old=$SANDBOX_ROOT/$old_name new=$SANDBOX_ROOT/$new_name
[[ ! -d "$old" ]] && \
error "sandbox does not exist $old_name" && return 1
[[ -d "$new" ]] && \
error "sandbox already exists $new_name" && return 1
[[ "$PWD" = "$old"* ]] && _autoenv_exit $PWD
mv $old $new
sed -i "s/$old_name/$new_name/g" $new/.enter
_autoenv_authorized $new/.enter yes
_autoenv_authorized $new/.exit yes
[[ "$PWD" = "$old"* ]] && cd $new
;;
destroy)
local name=$1
[[ -z "$name" ]] && \
error "missing argument <name>\n$usage" && return 1
local sandbox=$SANDBOX_ROOT/$name
[[ ! -d $sandbox ]] && \
error "sandbox does not exist $name" && return 1
[[ "$PWD" = "$sandbox"* ]] && cd ~
rm -rf $sandbox
;;
list)
ls -1 $SANDBOX_ROOT | less -F -K -R -X
;;
enable)
local name=$1
[[ -z "$name" ]] && \
@ -118,16 +109,19 @@ usage: sandbox [-h] {create,rename,destroy,enable,disable,list} ..
local sandbox=$SANDBOX_ROOT/$name
[[ ! -d $sandbox ]] && \
error "sandbox does not exist $name" && return 1
export SANDBOX_RETURN=$PWD
cd $sandbox
;;
disable)
[[ -z "$SANDBOX_RETURN" ]] && \
error "sandbox is not currently active" && return 1
cd $SANDBOX_RETURN
unset SANDBOX_RETURN
;;
*)
error "invalid sandbox command: $cmd" && return 1
;;
esac
}

32
session/_session Normal file
View File

@ -0,0 +1,32 @@
#compdef session
__session_sessions() {
list() {
for item in $HOME/.local/share/tmux/layouts/session-*; do
item=${item#$HOME/.local/share/tmux/layouts/}
echo ${item#session-}
done
}
local -a sessions
sessions=(${(fo)"$(list)"})
_describe 'session' sessions
}
__session_hosts() {
list() {
declare -A hosts
if [ -f ~/.config/session ]; then
source ~/.config/session
for key val in "${(@kv)hosts}"; do
echo $key
done
fi
}
local -a hosts
hosts=(${(fo)"$(list)"})
_describe 'host' hosts
}
_arguments \
':session:__session_sessions' \
':host:__session_hosts'

View File

@ -0,0 +1,33 @@
session() {
if [[ "$1" == "" ]]; then
echo "usage: session <name> [<host>]"
else
local name=$1
local host=$2
if [[ "$3" != "" ]]; then
echo "$fg[red]error:$reset_color invalid argument: $3"
return 1
fi
declare -A hosts
if [ -f ~/.config/session ]; then
source ~/.config/session
fi
local url=$hosts[$host]
host=${url:-$host}
if [[ "$TMUX" == "" ]]; then
local cmd="tmux new-session -As $name"
if [[ "$host" != "" ]]; then
cmd="ssh $host -t $cmd"
fi
eval $cmd
else
if [[ "$host" != "" ]]; then
echo "$fg[red]error:$reset_color <host> not allowed inside tmux session"
return 1
fi
tmux list-sessions | grep "$name:" &> /dev/null || \
tmux new-session -Ads $name -c $HOME
tmux switch-client -t $name
fi
fi
}

View File

@ -1,91 +0,0 @@
---
- name: zsh install packages
become: '{{package_become}}'
package:
name: zsh
state: present
- name: zsh install Debian packages
when: ansible_os_family == "Debian"
become: true
apt:
name:
- zsh-doc
- pinentry-curses
- unzip
state: present
- name: zsh clone plugin repos
git:
repo: '{{item.repo}}'
dest: '{{item.dest}}'
with_items:
- repo: https://github.com/zsh-users/zsh-autosuggestions.git
dest: ~/.config/zsh/zsh-autosuggestions
- repo: https://github.com/zsh-users/zsh-history-substring-search.git
dest: ~/.config/zsh/zsh-history-substring-search
- repo: https://github.com/zsh-users/zsh-syntax-highlighting.git
dest: ~/.config/zsh/zsh-syntax-highlighting
- repo: https://github.com/zsh-users/zsh-completions.git
dest: ~/.config/zsh/zsh-completions
- repo: https://github.com/junegunn/fzf.git
dest: ~/.config/zsh/fzf
- name: zsh install fzf binaries
command:
cmd: ~/.config/zsh/fzf/install --bin
creates: ~/.config/zsh/fzf/bin/fzf
- name: zsh create directories
file:
state: directory
dest: '{{item}}'
with_items:
- ~/.local/bin
- ~/.local/share/zsh/site-functions
- name: zsh create symbolic links
file:
state: link
src: '{{item.src}}'
dest: '{{item.dest}}'
with_items:
- src: ~/.config/zsh/zlogin
dest: ~/.zlogin
- src: ~/.config/zsh/zlogout
dest: ~/.zlogout
- src: ~/.config/zsh/zprofile
dest: ~/.zprofile
- src: ~/.config/zsh/zshenv
dest: ~/.zshenv
- src: ~/.config/zsh/zshrc
dest: ~/.zshrc
- src: ~/.config/zsh/prompt_fresh_setup
dest: ~/.local/share/zsh/site-functions/prompt_fresh_setup
- src: ~/.config/zsh/build/_build-dir
dest: ~/.local/share/zsh/site-functions/_build-dir
- src: ~/.config/zsh/sandbox/_sandbox
dest: ~/.local/share/zsh/site-functions/_sandbox
- src: ~/.config/zsh/layout/_layout
dest: ~/.local/share/zsh/site-functions/_layout
- src: ~/.config/zsh/notes/_note
dest: ~/.local/share/zsh/site-functions/_note
- src: ~/.config/zsh/fzf/bin/fzf
dest: ~/.local/bin/fzf
- src: ~/.config/zsh/fzf/bin/fzf-tmux
dest: ~/.local/bin/fzf-tmux
- src: ~/.config/zsh/cmake-uninstall
dest: ~/.local/bin/cmake-uninstall
- src: ~/.config/zsh/$
dest: ~/.local/bin/$
- name: zsh get absolute path
shell: command -v zsh
register: zsh
changed_when: false
- name: zsh set default shell
user:
name: '{{lookup("env", "USER")}}'
shell: '{{zsh.stdout}}'
become: true

View File

@ -1,19 +0,0 @@
#!/usr/bin/env zsh
# Check if third party completions are present.
local zsh_completions=~/.config/zsh/zsh-completions
[ ! -d $zsh_completions ] && return 0
# Loop over all completions.
for completion in $zsh_completions/src/_*; do
local name=`basename $completion`
local symlink=~/.local/share/zsh/site-functions/$name
# Remove existing completion file if it exists.
[ -f $symlink ] && rm $symlink
# Check if the command exists on the PATH.
if which ${name:1} &> /dev/null; then
# Symlink the completion for the existing command.
[ `uname` = Darwin ] && \
ln -s $completion $symlink || ln -sr $completion $symlink
fi
done

22
url/_url Normal file
View File

@ -0,0 +1,22 @@
#compdef url
_url() {
local ret=1 context curcontext="$curcontext" state line
typeset -A opt_args
_arguments -C -w -s \
'(-h --help)'{-h,--help}'[show this help message and exit]' \
'1: :->command'
case $state in
(command)
declare -a commands
local commands=(
encode:'encode unencoded text'
decode:'decode encoded text'
)
_describe -t commands command commands && ret=0 ;;
esac
return ret
}

27
url/url Executable file
View File

@ -0,0 +1,27 @@
#!/usr/bin/env python
"""URL encode or decode text."""
from argparse import ArgumentParser
from urllib import parse
def main():
cli = ArgumentParser(description=__doc__)
cli.add_argument('command',
choices=['encode', 'decode'],
help='type of processing to perform on text')
cli.add_argument('text',
nargs='?',
help='optional text read from stdin when omitted')
args = cli.parse_args()
print({
'encode': parse.quote_plus,
'decode': parse.unquote_plus,
}[args.command](args.text if args.text else input()))
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
exit(130)

View File

@ -26,18 +26,86 @@ fi
# Passthrough an escape sequences tmux doesn't know about.
tmux-dcs-passthrough() {
local escape_sequence=$1
if [ -n "$TMUX" ]; then
printf "\x1bPtmux;\x1b$1\x1b\\"
# Replace single \x1b or \033 with two, this is required for tmux to
# properly pass-through the escape sequence.
escape_sequence=${escape_sequence//\\x1b/\\x1b\\x1b}
escape_sequence=${escape_sequence//\\033/\\x1b\\x1b}
printf '\x1bPtmux;\x1b'"$escape_sequence"'\x1b\\'
else
printf "$1"
printf "$escape_sequence"
fi
}
# OSC 9 - Post a notification - supported by iTerm2, maybe others?
# OSC 9 - Post a notification - supported by iTerm2, kitty, WezTerm, others?
notify() {
tmux-dcs-passthrough "\x1b]9;$*\x7"
tmux-dcs-passthrough '\x1b]9;'"$*"'\x7'
}
# Send a desktop notification when long running commands complete.
notify_command_threshold=60
notify_ignore_list=(
bash
bat
btop
cat
cmatrix
fg
gh
git
glab
htop
ipython
man
nvim
ping
podman
python
session
slides
ssh
sudo
sudoedit
tmux
top
vi
vim
watch
zsh
)
notify-ignore() {
for ignore in $notify_ignore_list; do
if [[ "$1" = "$ignore"* ]]; then
return 0
fi
done
return 1
}
notify-preexec() {
if notify-ignore $1; then
return
fi
notify_command_start=`date +%s`
notify_command=$1
}
add-zsh-hook preexec notify-preexec
notify-precmd() {
if ! [[ -z $notify_command_start ]]; then
local notify_command_end=`date +%s`
local notify_command_time=$(($notify_command_end - $notify_command_start))
if [[ $notify_command_time -gt $notify_command_threshold ]]; then
notify "completed: $notify_command"
fi
unset notify_command
unset notify_command_start
fi
}
add-zsh-hook precmd notify-precmd
# Detect the type and extract an archive file.
extract() {
if [ -f $1 ]; then
@ -102,3 +170,26 @@ if which docker-machine &> /dev/null; then
fi
}
fi
ls-iommu() {
$HOME/.config/zsh/ls-iommu.sh | sort -n
}
# Fuzzy history search with fzf
function .fzf-history-search() {
local selected
selected=$(
cat $HISTFILE | # get entire history
sed 's/ *[0-9]* *//' | # remove cruft
awk '!seen[$0]++' | # remove duplicates
fzf --layout=reverse --tac --cycle --info=hidden \
--border=rounded --height=50%
)
if [[ -n "$selected" ]]; then
BUFFER="$selected"
zle end-of-line
fi
zle reset-prompt
}
zle -N .fzf-history-search
bindkey '^R' .fzf-history-search

92
zshenv
View File

@ -2,12 +2,24 @@
# contain commands that produce output or assume the shell is attached to a
# tty. This file will always be sourced.
[ -f ~/.config/zsh/zshenv.local ] && source ~/.config/zsh/zshenv.local
# Ensure cache and state directories exist
[ ! -d -${XDG_CACHE_HOME:-$HOME/.cache}/zsh ] && \
mkdir -p ${XDG_CACHE_HOME:-$HOME/.cache}/zsh
[ ! -d -${XDG_STATE_HOME:-$HOME/.local/state}/zsh ] && \
mkdir -p ${XDG_STATE_HOME:-$HOME/.local/state}/zsh
# Enable saving command history to file
[ ! -d $HOME/.cache/zsh ] && mkdir -p $HOME/.cache/zsh
HISTFILE=$HOME/.cache/zsh/histfile
HISTFILE=${XDG_STATE_HOME:-$HOME/.local/state}/zsh/histfile
HISTSIZE=20000
SAVEHIST=20000
# Migrate histfile from cache to state directory
! [ -f $HISTFILE ] && [ -f $HOME/.cache/zsh/histfile ] && \
mv $HOME/.cache/zsh/histfile \
${XDG_STATE_HOME:-$HOME/.local/state}/zsh/histfile
# Remove vi mode switch delay
KEYTIMEOUT=1
@ -22,10 +34,17 @@ INFOPATH=$HOME/.local/share/info:$INFOPATH
# Add ccache compiler aliases to PATH and use XDG base dir paths
if [ `uname` = Darwin ]; then
[ -d /usr/local/opt/python/libexec/bin ] && \
PATH=/usr/local/opt/python/libexec/bin:$PATH
[ -f /usr/local/bin/ccache ] && \
PATH=/usr/local/opt/ccache/libexec:$PATH
if [ `uname -m` = arm64 ]; then
homebrew_root=/opt/homebrew
[ -d /opt/homebrew/bin ] && \
PATH=$homebrew_root/bin:$PATH
else
homebrew_root=/usr/local
fi
[ -d $homebrew_root/opt/python/libexec/bin ] && \
PATH=$homebrew_root/opt/python/libexec/bin:$PATH
[ -f $homebrew_root/bin/ccache ] && \
PATH=$homebrew_root/opt/ccache/libexec:$PATH
elif [ -f /usr/bin/ccache ]; then
if [ -d /usr/lib/ccache/bin ]; then
PATH=/usr/lib/ccache/bin:$PATH
@ -33,12 +52,14 @@ elif [ -f /usr/bin/ccache ]; then
PATH=/usr/lib/ccache:$PATH
fi
fi
export CCACHE_CONFIGPATH=$HOME/.config/ccache
export CCACHE_DIR=$HOME/.cache/ccache
export CCACHE_CONFIGPATH=${XDG_CONFIG_HOME:-$HOME/.config}/ccache
export CCACHE_DIR=${XDG_CACHE_HOME:-$HOME/.cache}/ccache
# Add default CMake generator
which ninja &> /dev/null && \
# Add default CMake options
command -v ninja &> /dev/null && \
export CMAKE_GENERATOR=Ninja
export CMAKE_EXPORT_COMPILE_COMMANDS=ON
export CMAKE_COLOR_DIAGNOSTICS=ON
# Remove duplicates from environment variables
typeset -U fpath
@ -47,8 +68,22 @@ typeset -U MANPATH; export MANPATH
typeset -U INFOPATH; export INFOPATH
# Set default editor.
which vim &> /dev/null && \
export EDITOR=`which vim`
if command -v nvim &> /dev/null; then
export EDITOR=`command -v nvim`
# Also use nvim for man pages
export MANPAGER='nvim +Man!'
elif command -v vim &> /dev/null; then
export EDITOR=`command -v vim`
fi
export GIT_EDITOR=$EDITOR
if command -v fzf &> /dev/null; then
export FZF_DEFAULT_OPTS='--no-bold
--color=fg:#c5c9c5,fg+:#c5c9c5,bg:#000000,bg+:#393836
--color=hl:#8ea4a2,hl+:#8ea4a2,info:#afaf87,marker:#C8C093
--color=prompt:#C8C093,spinner:#8992a7,pointer:#FF9E3B,header:#87afaf
--color=gutter:#000000,border:#54546D,label:#aeaeae,query:#c5c9c5'
fi
# Use ~/.local for pip installs on macOS
[ "`uname`" = "Darwin" ] && export PYTHONUSERBASE=$HOME/.local
@ -77,26 +112,31 @@ export PYLINTHOME=~/.local/share/pylint
export VIRTUAL_ENV_DISABLE_PROMPT=1
# If pinentry-curses exists, use it for lastpass-cli
which pinentry-curses &> /dev/null && \
command -v pinentry-curses &> /dev/null && \
export LPASS_PINENTRY=pinentry-curses
# Teach these some XDG Base Directory Spec manners
export IPYTHONDIR=$HOME/.config/ipython
which cargo &> /dev/null && \
export IPYTHONDIR=${XDG_CONFIG_HOME:-$HOME/.config}/ipython
command -v cargo &> /dev/null && \
export CARGO_HOME=$HOME/.local/share/cargo
if which ccache &> /dev/null; then
export CCACHE_CONFIGPATH=$HOME/.config/ccache.conf
export CCACHE_DIR=$HOME/.cache/ccache
if command -v ccache &> /dev/null; then
export CCACHE_CONFIGPATH=${XDG_CONFIG_HOME:-$HOME/.config}/ccache.conf
export CCACHE_DIR=${XDG_CACHE_HOME:-$HOME/.cache}/ccache
fi
which conan &> /dev/null && \
command -v conan &> /dev/null && \
export CONAN_USER_HOME=$HOME/.local/share/conan
which docker &> /dev/null && \
command -v docker &> /dev/null && \
export DOCKER_CONFIG=$HOME/.local/share/docker
export GTK_RC_FILES=$HOME/.config/gtk/gtkrc
export GTK2_RC_FILES=$HOME/.config/gtk-2.0/gtkrc
which rustup &> /dev/null && \
export GTK_RC_FILES=${XDG_CONFIG_HOME:-$HOME/.config}/gtk/gtkrc
export GTK2_RC_FILES=${XDG_CONFIG_HOME:-$HOME/.config}/gtk-2.0/gtkrc
export PYLINTHOME=${XDG_CACHE_HOME:-$HOME/.cache}/pylint
command -v rustup &> /dev/null && \
export RUSTUP_HOME=$HOME/.local/share/rustup
export PYLINTHOME=$HOME/.cache/pylint
[ -f ${XDG_CONFIG_HOME:-$HOME/.config}/wget/rc ] && \
export WGETRC=${XDG_CONFIG_HOME:-$HOME/.config}/wget/rc
# TODO: terminfo
[ -f $HOME/.config/wgetrc ] &&
export WGETRC=$HOME/.config/wgetrc
export GOBIN=$HOME/.local/bin
export GOPATH=$HOME/.local/share/go
export GOCACHE=${XDG_CACHE_HOME:-$HOME/.cache}/go/build
export GOMODCACHE=${XDG_CACHE_HOME:-$HOME/.cache}/go/pkg/mod
export GOTMPDIR=${XDG_CACHE_HOME:-$HOME/.cache}/go/tmp

74
zshrc
View File

@ -3,8 +3,12 @@
# Load plugin scripts
source-plugin() {
if [ -d ~/.config/zsh/$1 ]; then
source ~/.config/zsh/$1/$1.plugin.zsh
local shared_plugin=${XDG_DATA_HOME:-$HOME/.local/share}/zsh/plugins/$1/$1.plugin.zsh
local local_plugin=${XDG_CONFIG_HOME:-$HOME/.config}/zsh/$1/$1.plugin.zsh
if [ -f $shared_plugin ]; then
source $shared_plugin
elif [ -f $local_plugin ]; then
source $local_plugin
else
echo "zsh plugin not found: $1"
fi
@ -17,9 +21,13 @@ ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(end-of-line vi-end-of-line)
# Search history with a command substring
source-plugin zsh-history-substring-search
HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND=
HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND=
# Command syntax highlighting
source-plugin zsh-syntax-highlighting
(( ${+ZSH_HIGHLIGHT_STYLES} )) || typeset -A ZSH_HIGHLIGHT_STYLES
ZSH_HIGHLIGHT_STYLES[precommand]=fg=green
# Build system helper commands
source-plugin build
@ -33,6 +41,9 @@ source-plugin utilities
# Automatically source .enter and .exit scripts on cd
source-plugin autoenv
# Session manager
source-plugin session
# Layout tmux window commands
[ "$TMUX" != "" ] && source-plugin layout
@ -65,10 +76,10 @@ setopt completeinword
# Initialize completions
autoload -U compinit
compinit
compinit -d ${XDG_CACHE_HOME:-$HOME/.cache}/zsh/compdump
# Add pip to the old completion engine if present
if which pip &> /dev/null; then
if command -v pip &> /dev/null; then
function _pip_completion {
local words cword
read -Ac words
@ -118,9 +129,6 @@ bindkey -M vicmd 'j' history-substring-search-down
bindkey -r '^[h'
bindkey -M vicmd 'K' run-help
# Disable Ex mode with ':'
bindkey -rM vicmd ':'
# Enable '<Shirt><Tab>' reverse order completions
bindkey '^[[Z' reverse-menu-complete
@ -170,17 +178,39 @@ if [[ ! -z "$cursor_block" && ! -z "$cursor_line" ]]; then
fi
# Frequntly used directories
function frequent-directory() { export $1; hash -d $1 }
frequent-directory Projects="$HOME/Projects"
function frequent-directory() {
if [ -d "$2" ]; then
# Replace - with _ in environment variable name.
local name=${1//-/_}
local value=$2
export $name=$value
hash -d $1
fi
}
frequent-directory Desktop "$HOME/Desktop"
frequent-directory Documents "$HOME/Documents"
frequent-directory Downloads "$HOME/Downloads"
frequent-directory Projects "$HOME/Projects"
frequent-directory Sandbox "$HOME/Sandbox"
frequent-directory cache "${XDG_CACHE_HOME:-$HOME/.cache}"
frequent-directory config "${XDG_CONFIG_HOME:-$HOME/.config}"
frequent-directory local "$HOME/.local"
# Load work related config
[ -f ~/.config/work/zshrc ] && source ~/.config/work/zshrc
[ -f ${XDG_CONFIG_HOME:-$HOME/.config}/work/zshrc ] && \
source ${XDG_CONFIG_HOME:-$HOME/.config}/work/zshrc
[ -f ${XDG_CONFIG_HOME:-$HOME/.config}/private/zshrc ] && \
source ${XDG_CONFIG_HOME:-$HOME/.config}/private/zshrc
[ -f ${XDG_CONFIG_HOME:-$HOME/.config}/zsh/local ] && \
source ${XDG_CONFIG_HOME:-$HOME/.config}/zsh/local
[ -f ${XDG_CONFIG_HOME:-$HOME/.config}/zsh/zshrc.local ] && \
source ${XDG_CONFIG_HOME:-$HOME/.config}/zsh/zshrc.local
# Aliases
alias grep='grep --color=always'
which cmake &> /dev/null && \
command -v cmake &> /dev/null && \
alias cninja='cmake -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON'
which ssh &> /dev/null && \
command -v ssh &> /dev/null && \
alias ssh='TERM=xterm-256color ssh'
alias weather="curl wttr.in"
alias cls="clear && printf '\e[3J'"
@ -188,15 +218,29 @@ alias cls="clear && printf '\e[3J'"
case `uname` in
Linux)
alias ls='ls -F --color=auto'
if which cgdb &> /dev/null; then
if command -v cgdb &> /dev/null; then
alias debug='cgdb --args'
elif which gdb &> /dev/null; then
elif command -v gdb &> /dev/null; then
alias debug='gdb --args'
fi
;;
Darwin)
alias ls='ls -GFh'
which lldb &> /dev/null && \
command -v lldb &> /dev/null && \
alias debug='lldb --'
;;
esac
command -v wol > /dev/null && \
alias wakeonlan='wol'
# Append any aliases to notify_ignore_list if they contain any ignore commands
# NOTE: Keep this at the end of ~/.zshrc so all aliases are processed
for name in ${(k)aliases}; do
cmd=${${${$(alias $name)#${name}=}#\'}#\"}
for ignore in $notify_ignore_list; do
if [[ "$cmd" = "$ignore"* ]]; then
notify_ignore_list+=( $name )
fi
done
done