Compare commits
19 Commits
zcurses/bu
...
34965bb98d
| Author | SHA1 | Date | |
|---|---|---|---|
| 34965bb98d | |||
| 2740f9bc8d | |||
| 2589b63023 | |||
| 6a4531423e | |||
| 8819cd4d18 | |||
| 585925df38 | |||
| 2ac97afdd1 | |||
| f24253b8c1 | |||
| df819f58a8 | |||
| c636dd078c | |||
| 0992b65d17 | |||
| 9e9c43a0cf | |||
| 0ab04406ec | |||
| e17ff47d5e | |||
| ff8bb3e4ab | |||
| 31d06e0f19 | |||
| 7bb6a459ee | |||
| 9e4c984822 | |||
| 9af452a8e2 |
@@ -6,8 +6,8 @@
|
|||||||
- brew:
|
- brew:
|
||||||
- zsh
|
- zsh
|
||||||
- command:
|
- command:
|
||||||
- install: sudo chsh $USER -s `which zsh`
|
- install: sudo chsh -s `which zsh` $USER
|
||||||
remove: sudo chsh $USER -s `which bash`
|
remove: sudo chsh -s `which bash` $USER
|
||||||
- symlink:
|
- symlink:
|
||||||
- {src: zlogin, dst: ~/.zlogin}
|
- {src: zlogin, dst: ~/.zlogin}
|
||||||
- {src: zlogout, dst: ~/.zlogout}
|
- {src: zlogout, dst: ~/.zlogout}
|
||||||
|
|||||||
22
README.md
22
README.md
@@ -51,10 +51,26 @@ display. This results in no noticeable lag when redrawing the prompt.
|
|||||||
Plugins are sourced manually and their git repositories tracked by
|
Plugins are sourced manually and their git repositories tracked by
|
||||||
[conduit][conduit], no plugin manager is used.
|
[conduit][conduit], no plugin manager is used.
|
||||||
|
|
||||||
* [zsh-syntax-highlighting][syntax] Fish shell like syntax highlighting for Zsh.
|
* [zsh-autosuggestions][zsh-autosuggestions] Fish-like autosuggestions for zsh.
|
||||||
|
* [fast-syntax-highlighting][syntax] Optimized and extended
|
||||||
|
zsh-syntax-highlighting - Fish shell like syntax highlighting for Zsh.
|
||||||
* [zsh-history-substring-search][search] Zsh port of the Fish shell's history
|
* [zsh-history-substring-search][search] Zsh port of the Fish shell's history
|
||||||
search.
|
search.
|
||||||
|
|
||||||
|
In addition to third party plugins the following are custom plugins residing in
|
||||||
|
this repository.
|
||||||
|
|
||||||
|
* [autoenv](autoenv/autoenv.zsh) is a inspired by [zsh-autoenv][zsh-autoenv] but
|
||||||
|
simplified by removing customization points and using a less intrusive UI.
|
||||||
|
* [build](build/build.plugin.zsh) is a collection of commands to make it easier
|
||||||
|
to build projects focuses on C/C++ development.
|
||||||
|
* [sandbox](sandbox/sandbox.plugin.zsh) is a command which sets up a throw away
|
||||||
|
directory for quickly testing ideas.
|
||||||
|
* [layout](layout/layout.plugin.zsh) is a command which setups up `tmux` panes
|
||||||
|
in a window with scripts.
|
||||||
|
* [notes](notes/notes.plugin.zsh) is a command to quickly edit markdown note
|
||||||
|
files.
|
||||||
|
|
||||||
## Environment & Settings
|
## Environment & Settings
|
||||||
|
|
||||||
The bulk of, if not all, configuration occurs in [`zshenv`](zshenv) and
|
The bulk of, if not all, configuration occurs in [`zshenv`](zshenv) and
|
||||||
@@ -135,7 +151,9 @@ Various aliases are defined at the end of [zshrc](zshrc) for convenience.
|
|||||||
[zsh]: https://www.zsh.org/
|
[zsh]: https://www.zsh.org/
|
||||||
[git]: https://git-scm.com/
|
[git]: https://git-scm.com/
|
||||||
[git-prompt]: https://github.com/olivierverdier/zsh-git-prompt
|
[git-prompt]: https://github.com/olivierverdier/zsh-git-prompt
|
||||||
[syntax]: https://github.com/zsh-users/zsh-syntax-highlighting
|
[zsh-autosuggestions]: https://github.com/zdharma/fast-syntax-highlighting
|
||||||
|
[zsh-autoenv]: https://github.com/Tarrasch/zsh-autoenv
|
||||||
|
[syntax]: https://github.com/zdharma/fast-syntax-highlighting
|
||||||
[search]: https://github.com/zsh-users/zsh-history-substring-search
|
[search]: https://github.com/zsh-users/zsh-history-substring-search
|
||||||
[vim-mode]: https://github.com/sharat87/zsh-vim-mode
|
[vim-mode]: https://github.com/sharat87/zsh-vim-mode
|
||||||
[tmux]: https://tmux.github.io
|
[tmux]: https://tmux.github.io
|
||||||
|
|||||||
@@ -75,6 +75,9 @@ commands:
|
|||||||
# Global entered directories array.
|
# Global entered directories array.
|
||||||
_autoenv_entered=()
|
_autoenv_entered=()
|
||||||
|
|
||||||
|
# Load zstat from stat module for inspecting modified time.
|
||||||
|
zmodload -F zsh/stat b:zstat
|
||||||
|
|
||||||
# Check if the given file is authorized, if not prompt the user to authorize,
|
# 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
|
# 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 ~/.cache/autoenv/authorized file to make authorization
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
"""The pick_build_dir command selects a build directory
|
|
||||||
|
|
||||||
The pick_build_dir command scans the current directory for directories starting
|
|
||||||
with ``build`` and prompts the user to select one from the list.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
from argparse import ArgumentParser
|
|
||||||
from os import listdir
|
|
||||||
from os.path import curdir, isdir
|
|
||||||
from sys import stderr
|
|
||||||
|
|
||||||
from pick import Picker
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Main entry point to build-dir.py script."""
|
|
||||||
parser = ArgumentParser()
|
|
||||||
parser.add_argument('output')
|
|
||||||
parser.add_argument('--default', action='store_true')
|
|
||||||
args = parser.parse_args()
|
|
||||||
directories = []
|
|
||||||
for directory in listdir(curdir):
|
|
||||||
if isdir(directory) and directory.startswith('build'):
|
|
||||||
directories.append(directory)
|
|
||||||
if len(directories) == 0:
|
|
||||||
print('no build directories found', file=stderr)
|
|
||||||
exit(1)
|
|
||||||
build_dirs = sorted(directories)
|
|
||||||
if args.default:
|
|
||||||
build_dir = build_dirs[0]
|
|
||||||
else:
|
|
||||||
picker = Picker(build_dirs, 'Select a build directory:')
|
|
||||||
picker.register_custom_handler(ord(''), lambda _: exit(1))
|
|
||||||
build_dir, _ = picker.start()
|
|
||||||
with open(args.output, 'w') as output:
|
|
||||||
output.write(build_dir)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
try:
|
|
||||||
main()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
exit(130)
|
|
||||||
@@ -37,15 +37,18 @@ optional arguments:
|
|||||||
EOF
|
EOF
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
error() { echo "\e[31merror:\e[0m $1"; return 1 }
|
error() { echo "\e[31merror:\e[0m $1" }
|
||||||
|
warning() { echo "\e[33mwarning:\e[0m $1" }
|
||||||
local build_dir
|
local build_dir
|
||||||
if [[ ${#*} -gt 1 ]]; then
|
if [[ ${#*} -gt 1 ]]; then
|
||||||
echo $usage
|
echo $usage
|
||||||
error "unexpected position arguments: ${*[2,${#*}]}"
|
error "unexpected position arguments: ${*[2,${#*}]}"; return 1
|
||||||
elif [[ ${#*} -eq 1 ]]; then
|
elif [[ ${#*} -eq 1 ]]; then
|
||||||
|
if [[ ! -d ${*[1]} ]]; then
|
||||||
|
warning "directory not found: ${*[1]}"
|
||||||
|
else
|
||||||
build_dir=${*[1]}
|
build_dir=${*[1]}
|
||||||
[[ ! -d $build_dir ]] && \
|
fi
|
||||||
error "directory not found: $build_dir"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# If <directory> was not set begin selection
|
# If <directory> was not set begin selection
|
||||||
@@ -60,7 +63,7 @@ EOF
|
|||||||
# Interactively select a build directory if more than 1 found
|
# Interactively select a build directory if more than 1 found
|
||||||
integer index=0
|
integer index=0
|
||||||
if [[ ${#build_dirs} -eq 0 ]]; then
|
if [[ ${#build_dirs} -eq 0 ]]; then
|
||||||
error "no build directories found"
|
error "no build directories found"; return 1
|
||||||
elif [[ ${#build_dirs} -gt 1 ]]; then
|
elif [[ ${#build_dirs} -gt 1 ]]; then
|
||||||
zmodload zsh/curses && {
|
zmodload zsh/curses && {
|
||||||
# Get the size of the terminal
|
# Get the size of the terminal
|
||||||
@@ -139,7 +142,7 @@ EOF
|
|||||||
|
|
||||||
# If the build variable is not defined the command could not be determined
|
# If the build variable is not defined the command could not be determined
|
||||||
if [ -z $build ]; then
|
if [ -z $build ]; then
|
||||||
echo "\e[33mwarning:\e[0m build command detection failed: $build_dir"
|
warning "build command detection failed: $build_dir"
|
||||||
# Prompt user to enter a build command
|
# Prompt user to enter a build command
|
||||||
vared -p 'enter comand: ' build
|
vared -p 'enter comand: ' build
|
||||||
fi
|
fi
|
||||||
@@ -149,7 +152,9 @@ EOF
|
|||||||
hash -d build=$build_dir
|
hash -d build=$build_dir
|
||||||
|
|
||||||
# If `--build` is specified then evaluate the command.
|
# If `--build` is specified then evaluate the command.
|
||||||
[[ -n $do_build ]] && eval build
|
if [[ -n $do_build ]]; then
|
||||||
|
eval build
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
201
git-prompt.c
Normal file
201
git-prompt.c
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#if __linux__
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define check(CONDITION) \
|
||||||
|
if (CONDITION) { \
|
||||||
|
fprintf(stderr, "error: %s: %d: %s\n", __FILE__, __LINE__, #CONDITION); \
|
||||||
|
exit(0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct process {
|
||||||
|
pid_t pid;
|
||||||
|
FILE* out;
|
||||||
|
} process_t;
|
||||||
|
|
||||||
|
process_t process_open(char* command) {
|
||||||
|
int fds[2];
|
||||||
|
check(pipe(fds));
|
||||||
|
int pid = fork();
|
||||||
|
check(pid == -1);
|
||||||
|
if (pid == 0) { // child process
|
||||||
|
close(fds[0]);
|
||||||
|
dup2(fds[1], STDOUT_FILENO);
|
||||||
|
dup2(STDOUT_FILENO, STDERR_FILENO);
|
||||||
|
char* argv[] = {"sh", "-c", command, NULL};
|
||||||
|
exit(execvp(argv[0], argv));
|
||||||
|
} else { // parent process
|
||||||
|
close(fds[1]);
|
||||||
|
process_t process = {pid, fdopen(fds[0], "rb")};
|
||||||
|
return process;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int process_close(process_t process) {
|
||||||
|
fclose(process.out);
|
||||||
|
int status;
|
||||||
|
check(process.pid != waitpid(process.pid, &status, 0));
|
||||||
|
if (WIFEXITED(status)) {
|
||||||
|
return WEXITSTATUS(status);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* trim(char* str) {
|
||||||
|
char* end;
|
||||||
|
while (isspace((unsigned char)*str)) str++;
|
||||||
|
if (*str == 0) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
end = str + strlen(str) - 1;
|
||||||
|
while (end > str && isspace((unsigned char)*end)) {
|
||||||
|
end--;
|
||||||
|
}
|
||||||
|
end[1] = '\0';
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* append(char* buffer, int count, ...) {
|
||||||
|
va_list list;
|
||||||
|
int i;
|
||||||
|
va_start(list, count);
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
strcat(buffer, va_arg(list, char*));
|
||||||
|
}
|
||||||
|
va_end(list);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* inttostr(char* buffer, int value) {
|
||||||
|
sprintf(buffer, "%d", value);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
process_t process;
|
||||||
|
// check we are in a git repo
|
||||||
|
process = process_open("git rev-parse --git-dir");
|
||||||
|
check(process_close(process));
|
||||||
|
|
||||||
|
// get the current branch name
|
||||||
|
process = process_open("git symbolic-ref --short HEAD");
|
||||||
|
char branch_buf[256] = {};
|
||||||
|
fread(branch_buf, 1, sizeof(branch_buf), process.out);
|
||||||
|
if (process_close(process)) {
|
||||||
|
// current HEAD is not a symbolic ref
|
||||||
|
process = process_open("git rev-parse --abbrev-ref HEAD");
|
||||||
|
memset(branch_buf, 0, sizeof(branch_buf));
|
||||||
|
fread(branch_buf, 1, sizeof(branch_buf), process.out);
|
||||||
|
check(process_close(process));
|
||||||
|
if (strcmp("HEAD", trim(branch_buf)) == 0) {
|
||||||
|
// get the commit hash
|
||||||
|
process = process_open("git rev-parse --short HEAD");
|
||||||
|
memset(branch_buf, 0, sizeof(branch_buf));
|
||||||
|
fread(branch_buf, 1, sizeof(branch_buf), process.out);
|
||||||
|
check(process_close(process));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char* branch = trim(branch_buf);
|
||||||
|
char prompt[1024] = {};
|
||||||
|
append(prompt, 3, " %{%F{66}%}", branch, "%{%f%}");
|
||||||
|
|
||||||
|
// get the upstream remote if one exists
|
||||||
|
char command[1024] = {};
|
||||||
|
append(command, 3, "git config branch.", branch, ".remote");
|
||||||
|
process = process_open(command);
|
||||||
|
char remote_buf[256] = {};
|
||||||
|
fread(remote_buf, 1, sizeof(remote_buf), process.out);
|
||||||
|
if (process_close(process) == 0) {
|
||||||
|
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,
|
||||||
|
"git rev-list --right-only refs/remotes/",
|
||||||
|
remote, "/", branch, "...HEAD --count"));
|
||||||
|
char count[32] = {};
|
||||||
|
fread(count, 1, sizeof(count), process.out);
|
||||||
|
if(process_close(process) == 0 && strcmp("0", trim(count))) {
|
||||||
|
append(prompt, 2, "↑", trim(count));
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the number of commits behind the remote
|
||||||
|
memset(command, 0, sizeof(command));
|
||||||
|
process = process_open(append(command, 5,
|
||||||
|
"git rev-list --left-only refs/remotes/",
|
||||||
|
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))) {
|
||||||
|
append(prompt, 2, "↓", trim(count));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
append(prompt, 1, " ");
|
||||||
|
|
||||||
|
// get the status and parse it
|
||||||
|
process = process_open("git status --porcelain");
|
||||||
|
char status[2048];
|
||||||
|
int indexed = 0, modified = 0, deleted = 0, untracked = 0, unmerged = 0;
|
||||||
|
while (NULL != fgets(status, sizeof(status) - 1, process.out)) {
|
||||||
|
char X = status[0];
|
||||||
|
char Y = status[1];
|
||||||
|
|
||||||
|
if (X == '?' && Y == '?') {
|
||||||
|
++untracked;
|
||||||
|
} else if ((X == 'A' && (Y == 'A' || Y == 'U')) ||
|
||||||
|
(X == 'D' && (Y == 'D' || Y == 'U')) ||
|
||||||
|
(X == 'U' && (Y == 'A' || Y == 'D' || Y == 'D' || Y == 'U'))) {
|
||||||
|
++unmerged;
|
||||||
|
} else {
|
||||||
|
switch (X) {
|
||||||
|
case ' ':
|
||||||
|
switch (Y) {
|
||||||
|
case 'M': ++modified; break;
|
||||||
|
case 'D': ++deleted; break;
|
||||||
|
} break;
|
||||||
|
case 'D': ++indexed;
|
||||||
|
switch (Y) {
|
||||||
|
case ' ': break;
|
||||||
|
case 'M': ++modified; break;
|
||||||
|
} break;
|
||||||
|
case 'M': case 'A': case 'R': case 'C': ++indexed;
|
||||||
|
switch (Y) {
|
||||||
|
case ' ': break;
|
||||||
|
case 'M': ++modified; break;
|
||||||
|
case 'D': ++deleted; break;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
check(process_close(process));
|
||||||
|
|
||||||
|
if (indexed || modified || deleted || unmerged || untracked) { // modified
|
||||||
|
char int_buf[32];
|
||||||
|
if (indexed) {
|
||||||
|
append(prompt, 3, "%{%F{2}%}*", inttostr(int_buf, indexed), "%{%f%}");
|
||||||
|
}
|
||||||
|
if (modified) {
|
||||||
|
append(prompt, 3, "%{%F{1}%}+", inttostr(int_buf, modified), "%{%f%}");
|
||||||
|
}
|
||||||
|
if (deleted) {
|
||||||
|
append(prompt, 3, "%{%F{1}%}-", inttostr(int_buf, deleted), "%{%f%}");
|
||||||
|
}
|
||||||
|
if (unmerged) {
|
||||||
|
append(prompt, 3, "%{%B%F{1}%}×", inttostr(int_buf, unmerged), "%{%f%}");
|
||||||
|
}
|
||||||
|
if (untracked) {
|
||||||
|
append(prompt, 1, "%{%F{1}%}…%{%f%}");
|
||||||
|
}
|
||||||
|
} else { // clean
|
||||||
|
append(prompt, 1, "%{%B%F{2}%}✓%{%f%b%}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the prompt
|
||||||
|
puts(prompt);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#compdef layout
|
#compdef layout
|
||||||
|
|
||||||
__get_layouts() {
|
__get_layouts() {
|
||||||
ls -1 ~/.config/tmux/layouts 2>/dev/null | \
|
ls -1 ~/.local/share/tmux/layouts 2>/dev/null | \
|
||||||
while read -r layout; do echo $layout; done
|
while read -r layout; do echo $layout; done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ layout() {
|
|||||||
if [[ "$1" == "" ]]; then
|
if [[ "$1" == "" ]]; then
|
||||||
echo "usage: layout <layout> [name]"
|
echo "usage: layout <layout> [name]"
|
||||||
else
|
else
|
||||||
tmux source-file ~/.config/tmux/layouts/$1
|
tmux source-file ~/.local/share/tmux/layouts/$1
|
||||||
if [[ "$2" != "" ]]; then
|
if [[ "$2" != "" ]]; then
|
||||||
tmux rename-window $2
|
tmux rename-window $2
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
prompt_fresh_help() {
|
prompt_fresh_help() {
|
||||||
echo "\
|
echo "\
|
||||||
options:
|
options:
|
||||||
-a enable almostontop like behaviour"
|
-a enable almostontop like behaviour
|
||||||
|
-r recompile git-prompt executable"
|
||||||
}
|
}
|
||||||
|
|
||||||
prompt_fresh_setup() {
|
prompt_fresh_setup() {
|
||||||
fresh_compile_git_prompt
|
|
||||||
|
|
||||||
# Parse options
|
# Parse options
|
||||||
local almostontop=0
|
local almostontop=0
|
||||||
while getopts 'a' opt; do
|
local recompile=0
|
||||||
|
while getopts 'ar' opt; do
|
||||||
case $opt in
|
case $opt in
|
||||||
a) local almostontop=1 ;;
|
a) local almostontop=1 ;;
|
||||||
|
r) local recompile=1 ;;
|
||||||
*) prompt -h fresh; return 1 ;;
|
*) prompt -h fresh; return 1 ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
@@ -19,8 +20,8 @@ prompt_fresh_setup() {
|
|||||||
autoload -U add-zsh-hook
|
autoload -U add-zsh-hook
|
||||||
|
|
||||||
# Hook to print the first line of the "two line" prompt, this line is not
|
# Hook to print the first line of the "two line" prompt, this line is not
|
||||||
# actually part of the prompt so does not get redrawn which can sometimes
|
# actually part of the prompt so does not get redrawn, this is preferable
|
||||||
# cause lines before the prompt to disappear.
|
# since sometimes lines before the prompt can disappear.
|
||||||
add-zsh-hook precmd fresh_line_one
|
add-zsh-hook precmd fresh_line_one
|
||||||
|
|
||||||
if [ $almostontop -eq 1 ]; then
|
if [ $almostontop -eq 1 ]; then
|
||||||
@@ -31,28 +32,29 @@ prompt_fresh_setup() {
|
|||||||
add-zsh-hook -d preexec fresh_almostontop
|
add-zsh-hook -d preexec fresh_almostontop
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$USERNAME" = "root" ]; then
|
[ $recompile -eq 1 ] && prompt_cleanup
|
||||||
local user="%{%F{9}%}%n%{%f%}"
|
fresh_compile_git_prompt
|
||||||
|
|
||||||
|
if [ "$USER" = "root" ]; then
|
||||||
|
local user="%{%F{1}%}%n%{%f%}"
|
||||||
else
|
else
|
||||||
local user="%{%F{35}%}%n%{%f%}"
|
local user="%{%F{35}%}%n%{%f%}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
local userhost=$USER
|
||||||
if [ "$SSH_CONNECTION" != "" ]; then
|
if [ "$SSH_CONNECTION" != "" ]; then
|
||||||
local user="%{%F{35}%}$user%{%f%}@%{%F{244}%}%M%{%f%}"
|
local user="$user@%{%F{244}%}%M%{%f%}"
|
||||||
|
local userhost="$userhost@`hostname`"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local length=`fresh_visible_length "$user"`
|
|
||||||
|
|
||||||
PS1="«$user» "
|
PS1="«$user» "
|
||||||
PS2="${(l:$length + 1:: :)}» "
|
PS2="«${(l:${#userhost}:: :)}» "
|
||||||
|
|
||||||
RPS1='$(fresh_rprompt)'
|
prompt_opts=(percent sp subst)
|
||||||
|
|
||||||
prompt_opts=(cr percent sp subst)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prompt_cleanup() {
|
prompt_cleanup() {
|
||||||
if [ -f ~/.cache/zsh/git-prompt ]; then rm ~/.cache/zsh/git-prompt; fi
|
[ -f ~/.cache/zsh/git-prompt ] && rm ~/.cache/zsh/git-prompt
|
||||||
}
|
}
|
||||||
|
|
||||||
fresh_line_one() {
|
fresh_line_one() {
|
||||||
@@ -61,85 +63,30 @@ fresh_line_one() {
|
|||||||
|
|
||||||
# Construct the time and directory portions of the prompt
|
# Construct the time and directory portions of the prompt
|
||||||
local time_stamp="%{%F{244}%}%D{%H:%M:%S}%{%f%}"
|
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{37}%}%~%{%f%}"
|
local directory="%{%F{37}%}%~%{%f%}"
|
||||||
|
|
||||||
# Check we are in a git repository
|
# Check we are in a git repository
|
||||||
if `git rev-parse --git-dir > /dev/null 2>&1`; then
|
local git=`~/.cache/zsh/git-prompt`
|
||||||
# Get git branch name & exit early if not found
|
|
||||||
local branch="`git symbolic-ref HEAD 2> /dev/null`"
|
# If the last command failed, display its error code at the right
|
||||||
if [ "" = "$branch" ]; then
|
if [[ $exit_code -ne 0 ]]; then
|
||||||
local branch="`git rev-parse --abbrev-ref HEAD`"
|
local result=" %{%B%F{1}%}$exit_code%{%f%b%}"
|
||||||
if [ "HEAD" = "$branch" ]; then
|
|
||||||
local branch="`git rev-parse --short $branch`"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$branch" != "" ]; then
|
# If a virtualenv is enabled, display it's basename
|
||||||
local branch=${branch#refs/heads/}
|
if [[ ! -z "$VIRTUAL_ENV" ]]; then
|
||||||
# Get the number of commits ahead/behind from the remote branch
|
local py=" %{%F{4}%}py%{%f%}%{%F{3}%}$(basename $VIRTUAL_ENV)%{%f%}"
|
||||||
local remote="`git config branch.$branch.remote 2> /dev/null`"
|
|
||||||
if [ "" != "remote" ]; then
|
|
||||||
local branches="refs/remotes/$remote/$branch...HEAD"
|
|
||||||
local nahead=`git rev-list --right-only $branches --count 2> /dev/null`
|
|
||||||
if [ "0" -ne "$nahead" ]; then local ahead="↑$nahead"; fi
|
|
||||||
local nbehind=`git rev-list --left-only $branches --count 2> /dev/null`
|
|
||||||
if [ "0" -ne "$nbehind" ]; then local behind="↓$nbehind"; fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Construct the git prompt
|
# If docker-machine env is active, display the machines name
|
||||||
local git="%{%F{66}%}$branch%{%f%}$ahead$behind "
|
if [[ ! -z "$DOCKER_MACHINE_NAME" ]]; then
|
||||||
|
local docker=" %{%F{6}%}$DOCKER_MACHINE_NAME%{%f%}"
|
||||||
if [ -f ~/.cache/zsh/git-prompt ]; then
|
|
||||||
# Get the change counts from git-prompt
|
|
||||||
local counts=(`~/.cache/zsh/git-prompt`)
|
|
||||||
|
|
||||||
# Parse the results from git-prompt
|
|
||||||
if [ 0 -eq ${#counts[@]} ]; then # clean
|
|
||||||
local git="$git%{%B%F{2}%}✓%{%f%b%}";
|
|
||||||
else
|
|
||||||
if [ 0 != $counts[1] ]; then # indexed
|
|
||||||
local git="$git%{%F{2}%}*$counts[1]%{%f%}"
|
|
||||||
fi
|
fi
|
||||||
if [ 0 != $counts[2] ]; then # modified
|
|
||||||
local git="$git%{%F{1}%}+$counts[2]%{%f%}";
|
|
||||||
fi
|
|
||||||
if [ 0 != $counts[3] ]; then # deleted
|
|
||||||
local git="$git%{%F{1}%}-$counts[3]%{%f%}";
|
|
||||||
fi
|
|
||||||
if [ 0 != $counts[4] ]; then # unmerged
|
|
||||||
local git="$git%{%B%F{1}%}×$counts[4]%{%f%b%}";
|
|
||||||
fi
|
|
||||||
if [ 0 != $counts[5] ]; then # untracked
|
|
||||||
local git="$git%{%F{1}%}…%{%f%}";
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Construct the prompt string
|
|
||||||
local line="$time_stamp $directory $git"
|
|
||||||
|
|
||||||
# Print the first line of the prompt
|
# Print the first line of the prompt
|
||||||
if [[ $exit_code -eq 0 ]]; then
|
print -P "$time_stamp $directory$git$py$docker$result"
|
||||||
print -P "$line"
|
|
||||||
else
|
|
||||||
# The last command failed, display its error code at the right
|
|
||||||
local result="%{%B%F{1}%}$exit_code%{%f%b%}"
|
|
||||||
local length=`fresh_visible_length "$line$result"`
|
|
||||||
print -P "$line${(l:COLUMNS - $length - 1:: :)}$result"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
fresh_rprompt() {
|
|
||||||
rprompt=""
|
|
||||||
if [[ ! -z "$DOCKER_MACHINE_NAME" ]]; then
|
|
||||||
rprompt="$rprompt %{%F{3}%}$DOCKER_MACHINE_NAME%{%f%}"
|
|
||||||
fi
|
|
||||||
if [[ ! -z "$VIRTUAL_ENV" ]]; then
|
|
||||||
rprompt="$rprompt %{%F{3}%}$(basename $VIRTUAL_ENV)%{%f%}"
|
|
||||||
fi
|
|
||||||
echo $rprompt
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fresh_almostontop() {
|
fresh_almostontop() {
|
||||||
@@ -148,70 +95,14 @@ fresh_almostontop() {
|
|||||||
print -P "$PROMPT"'$1'
|
print -P "$PROMPT"'$1'
|
||||||
}
|
}
|
||||||
|
|
||||||
fresh_visible_length() {
|
|
||||||
echo $(( ${#${(S%%)1//(\%(KF1]|)\{*\}|\%[Bbkf])}} ))
|
|
||||||
}
|
|
||||||
|
|
||||||
fresh_compile_git_prompt() {
|
fresh_compile_git_prompt() {
|
||||||
# Compile a simple C executable which parses the output of `git status
|
# Compile a simple C program which parses the output of `git status
|
||||||
# --procelain` to greatly decrease the time taken to render the prompt
|
# --procelain` to greatly decrease the time taken to draw the prompt
|
||||||
local cache=~/.cache/zsh
|
[ ! -d ~/.cache/zsh ] && mkdir -p ~/.cache/zsh
|
||||||
if [ ! -d $cache ]; then mkdir -p $cache; fi
|
if [ ! -f ~/.cache/zsh/git-prompt ]; then
|
||||||
if [ ! -f $cache/git-prompt ]; then
|
cc -std=gnu99 -O3 -DNDEBUG ~/.config/zsh/git-prompt.c -o ~/.cache/zsh/git-prompt
|
||||||
cc -x c -std=gnu99 -O3 -DNDEBUG -o $cache/git-prompt - 2> /dev/null << EOF
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
FILE *file = popen("git status --porcelain", "r");
|
|
||||||
if (NULL == file) { return 0; }
|
|
||||||
|
|
||||||
char status[2048];
|
|
||||||
int indexed = 0, modified = 0, deleted = 0, untracked = 0, unmerged = 0;
|
|
||||||
|
|
||||||
while (NULL != fgets(status, sizeof(status) - 1, file)) {
|
|
||||||
char X = status[0];
|
|
||||||
char Y = status[1];
|
|
||||||
|
|
||||||
if (X == '?' && Y == '?') {
|
|
||||||
++untracked;
|
|
||||||
} else if ((X == 'A' && (Y == 'A' || Y == 'U')) ||
|
|
||||||
(X == 'D' && (Y == 'D' || Y == 'U')) ||
|
|
||||||
(X == 'U' && (Y == 'A' || Y == 'D' || Y == 'D' || Y == 'U'))) {
|
|
||||||
++unmerged;
|
|
||||||
} else {
|
|
||||||
switch (X) {
|
|
||||||
case ' ':
|
|
||||||
switch (Y) {
|
|
||||||
case 'M': ++modified; break;
|
|
||||||
case 'D': ++deleted; break;
|
|
||||||
} break;
|
|
||||||
case 'D': ++indexed;
|
|
||||||
switch (Y) {
|
|
||||||
case ' ': break;
|
|
||||||
case 'M': ++modified; break;
|
|
||||||
} break;
|
|
||||||
case 'M': case 'A': case 'R': case 'C': ++indexed;
|
|
||||||
switch (Y) {
|
|
||||||
case ' ': break;
|
|
||||||
case 'M': ++modified; break;
|
|
||||||
case 'D': ++deleted; break;
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pclose(file);
|
|
||||||
|
|
||||||
if (indexed || modified || deleted || unmerged || untracked) {
|
|
||||||
printf("%d %d %d %d %d", indexed, modified, deleted, unmerged, untracked);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "git prompt disabled, are the system development headers installed?"
|
echo "git-prompt was not compiled, is a C99 toolchain installed?"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
if [[ "" == $SANDBOX_ENV_IN_FILE ]]; then
|
|
||||||
export SANDBOX_ENV_IN_FILE=$AUTOENV_IN_FILE
|
|
||||||
fi
|
|
||||||
if [[ "" == $SANDBOX_ENV_OUT_FILE ]]; then
|
|
||||||
export SANDBOX_ENV_OUT_FILE=$AUTOENV_OUT_FILE
|
|
||||||
fi
|
|
||||||
if [[ "" == $SANDBOX_ROOT ]]; then
|
if [[ "" == $SANDBOX_ROOT ]]; then
|
||||||
export SANDBOX_ROOT=$HOME/Sandbox
|
export SANDBOX_ROOT=$HOME/Sandbox
|
||||||
fi
|
fi
|
||||||
@@ -33,11 +27,11 @@ sandbox() {
|
|||||||
begin=$PWD
|
begin=$PWD
|
||||||
cd $sandbox
|
cd $sandbox
|
||||||
|
|
||||||
echo "SANDBOX_HOME=\$(dirname -- "\$0:a")" >> $SANDBOX_ENV_IN_FILE
|
echo "SANDBOX_HOME=\$(dirname -- "\$0:a")" >> .enter
|
||||||
echo "SANDBOX_NAME=$2" >> $SANDBOX_ENV_IN_FILE
|
echo "SANDBOX_NAME=$2" >> .enter
|
||||||
|
|
||||||
echo "unset SANDBOX_NAME" >> $SANDBOX_ENV_OUT_FILE
|
echo "unset SANDBOX_NAME" >> .exit
|
||||||
echo "unset SANDBOX_HOME" >> $SANDBOX_ENV_OUT_FILE
|
echo "unset SANDBOX_HOME" >> .exit
|
||||||
|
|
||||||
git init &> /dev/null
|
git init &> /dev/null
|
||||||
|
|
||||||
@@ -73,7 +67,7 @@ sandbox() {
|
|||||||
rm -rf $sandbox
|
rm -rf $sandbox
|
||||||
;;
|
;;
|
||||||
list)
|
list)
|
||||||
/bin/ls -1 $SANDBOX_ROOT
|
/bin/ls -1 $SANDBOX_ROOT | less -F -K -R -X
|
||||||
;;
|
;;
|
||||||
enable)
|
enable)
|
||||||
if [[ "" == $2 ]]; then
|
if [[ "" == $2 ]]; then
|
||||||
|
|||||||
5
zprofile
5
zprofile
@@ -1,2 +1,7 @@
|
|||||||
# .zprofile [1] Used for executing user's commands at start, will be sourced
|
# .zprofile [1] Used for executing user's commands at start, will be sourced
|
||||||
# when starting as a login shell.
|
# when starting as a login shell.
|
||||||
|
|
||||||
|
# macOS is obnoxious and overwrites the PATH from a users ~/.zshenv, which is
|
||||||
|
# sourced first, in /etc/zprofile by calling `/usr/libexec/path_helper -s` so
|
||||||
|
# this is required so that PATH is once again set to the desired value.
|
||||||
|
[ `uname` = Darwin ] && source ~/.zshenv
|
||||||
|
|||||||
25
zshenv
25
zshenv
@@ -5,22 +5,35 @@
|
|||||||
# Enable saving command history to file
|
# Enable saving command history to file
|
||||||
[ ! -d $HOME/.cache/zsh ] && mkdir -p $HOME/.cache/zsh
|
[ ! -d $HOME/.cache/zsh ] && mkdir -p $HOME/.cache/zsh
|
||||||
HISTFILE=$HOME/.cache/zsh/histfile
|
HISTFILE=$HOME/.cache/zsh/histfile
|
||||||
HISTSIZE=5000
|
HISTSIZE=20000
|
||||||
SAVEHIST=5000
|
SAVEHIST=20000
|
||||||
|
|
||||||
|
# Remove vi mode switch delay
|
||||||
|
KEYTIMEOUT=1
|
||||||
|
|
||||||
# Enable time stats for long lasting commands
|
# Enable time stats for long lasting commands
|
||||||
REPORTTIME=5
|
REPORTTIME=5
|
||||||
|
|
||||||
# Add Homebrew python to PATH on macOS if present
|
|
||||||
[ "`uname`" = "Darwin" ] && [ -d /usr/local/opt/python/libexec/bin ] &&
|
|
||||||
PATH=/usr/local/opt/python/libexec/bin:$PATH
|
|
||||||
|
|
||||||
# Add ~/.local to the environment
|
# Add ~/.local to the environment
|
||||||
fpath+=$HOME/.local/share/zsh/site-functions
|
fpath+=$HOME/.local/share/zsh/site-functions
|
||||||
PATH=$HOME/.local/bin:$PATH
|
PATH=$HOME/.local/bin:$PATH
|
||||||
MANPATH=$HOME/.local/share/man:$MANPATH
|
MANPATH=$HOME/.local/share/man:$MANPATH
|
||||||
INFOPATH=$HOME/.local/share/info:$INFOPATH
|
INFOPATH=$HOME/.local/share/info:$INFOPATH
|
||||||
|
|
||||||
|
if [ `uname` = Darwin ]; then
|
||||||
|
[ -f /usr/local/bin/ccache ] && \
|
||||||
|
PATH=/usr/local/opt/ccache/libexec:$PATH
|
||||||
|
else
|
||||||
|
[ -f /usr/bin/ccache ] && \
|
||||||
|
PATH=/usr/lib/ccache:$PATH
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove duplicates from environment variables
|
||||||
|
typeset -U fpath
|
||||||
|
typeset -U PATH; export PATH
|
||||||
|
typeset -U MANPATH; export MANPATH
|
||||||
|
typeset -U INFOPATH; export INFOPATH
|
||||||
|
|
||||||
# Use ~/.local for pip installs on macOS
|
# Use ~/.local for pip installs on macOS
|
||||||
[ "`uname`" = "Darwin" ] && export PYTHONUSERBASE=$HOME/.local
|
[ "`uname`" = "Darwin" ] && export PYTHONUSERBASE=$HOME/.local
|
||||||
|
|
||||||
|
|||||||
37
zshrc
37
zshrc
@@ -32,18 +32,19 @@ source-plugin build
|
|||||||
source-plugin sandbox
|
source-plugin sandbox
|
||||||
|
|
||||||
# Layout tmux window commands
|
# Layout tmux window commands
|
||||||
source-plugin layout
|
[ "$TMUX" != "" ] && source-plugin layout
|
||||||
|
|
||||||
# Note taking commands
|
# Note taking commands
|
||||||
source-plugin notes
|
source-plugin notes
|
||||||
|
|
||||||
# Remove duplicates from history
|
# Remove duplicates from history
|
||||||
setopt hist_ignore_all_dups
|
setopt histignoredups
|
||||||
setopt hist_reduce_blanks
|
|
||||||
setopt hist_save_no_dups
|
|
||||||
|
|
||||||
# Enable multi-terminal history
|
# Enable multi-terminal history
|
||||||
setopt inc_append_history
|
setopt share_history
|
||||||
|
|
||||||
|
# Disable error when no glob matches are found
|
||||||
|
setopt nonomatch
|
||||||
|
|
||||||
# Enable comments in the prompt
|
# Enable comments in the prompt
|
||||||
setopt interactive_comments
|
setopt interactive_comments
|
||||||
@@ -52,10 +53,13 @@ setopt interactive_comments
|
|||||||
setopt ignore_eof
|
setopt ignore_eof
|
||||||
|
|
||||||
# Disable sound
|
# Disable sound
|
||||||
unsetopt beep
|
setopt nobeep
|
||||||
|
|
||||||
# Disable tty flow control, allows vim to use '<Ctrl>S'
|
# Disable tty flow control, allows vim to use '<Ctrl>S'
|
||||||
unsetopt flow_control && stty -ixon
|
setopt noflowcontrol; stty -ixon
|
||||||
|
|
||||||
|
# Enable completions in the middle of a word
|
||||||
|
setopt completeinword
|
||||||
|
|
||||||
# Initialize completions
|
# Initialize completions
|
||||||
autoload -U compinit
|
autoload -U compinit
|
||||||
@@ -82,6 +86,9 @@ prompt fresh
|
|||||||
# Enable vi mode line editor keymap
|
# Enable vi mode line editor keymap
|
||||||
bindkey -v
|
bindkey -v
|
||||||
|
|
||||||
|
# Enable backspace after returning to viins from vicmd mode
|
||||||
|
bindkey '^?' backward-delete-char
|
||||||
|
|
||||||
# Enable yank, change, and delete whole line with 'Y', 'cc', and 'dd'
|
# Enable yank, change, and delete whole line with 'Y', 'cc', and 'dd'
|
||||||
bindkey -M vicmd 'Y' vi-yank-whole-line
|
bindkey -M vicmd 'Y' vi-yank-whole-line
|
||||||
|
|
||||||
@@ -158,22 +165,6 @@ fi
|
|||||||
# Load work related config
|
# Load work related config
|
||||||
[ -f ~/.config/work/zshrc ] && source ~/.config/work/zshrc
|
[ -f ~/.config/work/zshrc ] && source ~/.config/work/zshrc
|
||||||
|
|
||||||
# Remove duplicates from environment variables
|
|
||||||
typeset -U PATH
|
|
||||||
typeset -U MANPATH
|
|
||||||
typeset -U INFOPATH
|
|
||||||
|
|
||||||
# Add ccache symlink directory to start of PATH, this must be after
|
|
||||||
# `typeset -U PATH` because on macOS this reorders the list so ccache's
|
|
||||||
# symlinks will no longer be at the start of PATH rendering it unusable.
|
|
||||||
if [ `uname` = Darwin ]; then
|
|
||||||
[ -f /usr/local/bin/ccache ] && \
|
|
||||||
PATH=/usr/local/opt/ccache/libexec:$PATH
|
|
||||||
else
|
|
||||||
[ -f /usr/bin/ccache ] && \
|
|
||||||
PATH=/usr/lib/ccache:$PATH
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Aliases
|
# Aliases
|
||||||
alias grep='grep --color=always'
|
alias grep='grep --color=always'
|
||||||
which cmake &> /dev/null && \
|
which cmake &> /dev/null && \
|
||||||
|
|||||||
Reference in New Issue
Block a user