# ============================================= #
# ------------------ Helpers ------------------ #
# ============================================= #
_split_flags() {
args=() flags=()
local arg wants_value=0
for arg in "$@"; do
if [ "$wants_value" -eq 1 ]; then
flags+=("$arg")
wants_value=0
elif [[ $arg == -* ]]; then
flags+=("$arg")
if [[ $arg != *=* && " ${value_flags:-} " == *" $arg "* ]];then
wants_value=1
fi
else
args+=("$arg")
fi
done
}
_value_flags_from_help() {
awk '
/^[[:space:]]+-/ {
opt = $0
sub(/^[[:space:]]+/, "", opt)
if (match(opt, / +/))
opt = substr(opt, 1, RSTART - 1)
if (opt !~ /=[A-Z<]/ && opt !~ /-[[:alnum:]-]+[[:space:]]+([A-Z][A-Z]+|<)/)
next
n = split(opt, tok, /[ ,]+/)
for (i = 1; i <= n; i++) {
f = tok[i]
sub(/=.*/, "", f)
if (f ~ /^--?[[:alnum:]]/ && !(f in seen)) {
seen[f] = 1
out = out (out ? " " : "") f
}
}
}
END { print out }
'
}
_value_flags_cached() {
local key=$1 witness=$2; shift 2
local CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/split_flags"
local cache="$CACHE_DIR/$key"
if [ ! -f "$cache" ] || { [ -n "$witness" ] && [ "$witness" -nt "$cache" ]; } || [ -n "$(find "$cache" -mtime +7 2>/dev/null)" ]; then
mkdir -p "$CACHE_DIR"
if "$@" 2>/dev/null | _value_flags_from_help > "$cache.tmp" && [ -s "$cache.tmp" ]; then
mv "$cache.tmp" "$cache"
else
rm -f "$cache.tmp"
fi
fi
cat "$cache" 2>/dev/null
}
_limit_to_window_width() {
if [ "$1" != -f ] && [ ! -t 1 ]; then
cat
return
fi
local columns
columns=$(stty size </dev/tty 2>/dev/null | awk '{ print $2 }')
if ! [ "${columns:-0}" -gt 0 ] 2>/dev/null; then
columns=${COLUMNS:-0}
fi
if ! [ "$columns" -gt 0 ] 2>/dev/null; then
cat
return
fi
awk -v columns="$columns" '
function width(text, stripped) {
stripped = text
gsub(/\033\[[0-9;]*m/, "", stripped)
return length(stripped)
}
function ellipsize(text, limit, result, pos, len, char, visible, escape) {
if (width(text) <= limit)
return text
if (limit < 2)
limit = 2
result = ""
visible = 0
len = length(text)
for (pos = 1; pos <= len; pos++) {
char = substr(text, pos, 1)
if (char == "\033") {
escape = char
while (++pos <= len) {
char = substr(text, pos, 1)
escape = escape char
if (char == "m")
break
}
result = result escape
} else {
if (visible >= limit - 2)
break
result = result char
visible++
}
}
return result ".." "\033[m"
}
{ print ellipsize($0, columns) }
'
}
_run_notify() {
local title=$1 bin=$2; shift 2
"$bin" "$@"
local status=$?
osascript - "$title" "$* $status" <<'END'
on run argv
tell application "System Events"
set activeApp to name of first application process whose frontmost is true
if "Terminal" is not in activeApp then
display notification (item 2 of argv) with title (item 1 of argv) sound name "Morse"
end if
end tell
end run
END
return $status
}
_git_get_default_branch_name() {
local ref
ref=$(git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null)
if [ -n "$ref" ]; then
echo "${ref#origin/}"
elif git show-ref --verify --quiet refs/remotes/origin/main; then
echo "main"
elif git show-ref --verify --quiet refs/remotes/origin/master; then
echo "master"
else
git rev-parse --abbrev-ref HEAD 2>/dev/null
fi
}
_git_get_current_branch_name() {
git symbolic-ref --short HEAD 2>/dev/null
}
_git_get_revision_count() {
local branch=${1:-HEAD}
git rev-list --count "$branch" "^$(_git_get_base_ref "$branch")" 2>/dev/null
}
_git_get_touched_files() {
git status --porcelain --untracked-files=all | sed s/^...//
}
_git_get_modified_files() {
echo -e "$(_git_get_touched_files)\n$(git diff --name-only origin/HEAD...HEAD)" | sort | uniq
}
_git_does_branch_exist() {
git show-ref --verify --quiet "refs/heads/$1"
}
_git_get_base_ref() {
if ! git rev-parse --abbrev-ref "$1@{upstream}" 2>/dev/null; then
echo "origin/HEAD"
fi
}
# ============================================= #
# ------------------ Aliases ------------------ #
# ============================================= #
# Important
alias s="subl"
alias x="xargs"
alias xs="x subl"
alias v="ls -abGHhlOT"
# General
alias ..="cd .."
alias ...="cd ../.."
alias ....="cd ../../.."
alias f="find . | g"
alias g="grep"
alias mkdir="mkdir -p"
# Git
alias gd="git diff --binary --color=auto"
alias gf="git fetch"
alias gr="git rebase"
alias gs="git status"
alias gv="git ls-files"
# Node
alias nr="npm run"
# ============================================= #
# ----------------- Functions ----------------- #
# ============================================= #
# Permissions
p644() {
find "${1:-.}" -type f -exec chmod 644 {} +
}
p755() {
find "${1:-.}" -type d -exec chmod 755 {} +
}
# Management
make() {
_run_notify make /usr/bin/make "$@"
}
xcodebuild() {
_run_notify xcodebuild /usr/bin/xcodebuild "$@"
}
rd() {
if [ -n "$1" ]; then
find . -name "$1" -type f -delete
else
echo "Usage: rd filename.xyz"
fi
}
o() {
open "${1:-.}"
}
path() {
if [ -n "$1" ]; then
echo "$PWD/$1"
else
pwd
fi
}
extract() {
if [ -f "$1" ]; then
case "$1" in
*.tar.bz2) tar xvjf "$1" ;;
*.tar.gz) tar xvzf "$1" ;;
*.bz2) bunzip2 "$1" ;;
*.gz) gunzip "$1" ;;
*.jar) jar xf "$1" ;;
*.tar) tar xvf "$1" ;;
*.tbz2) tar xvjf "$1" ;;
*.tgz) tar xvzf "$1" ;;
*.zip) unzip "$1" ;;
*.Z) uncompress "$1" ;;
*) echo "\"$1\" cannot be extracted via >extract<" ;;
esac
else
echo "\"$1\" is not a valid file"
fi
}
# Git
gl() {
local color=never columns=0
if [ -t 1 ]; then
color=always
columns=$(stty size </dev/tty 2>/dev/null | awk '{ print $2 }')
if ! [ "${columns:-0}" -gt 0 ] 2>/dev/null; then
columns=${COLUMNS:-0}
fi
fi
local args flags
local value_flags="-n --max-count --skip --since --after --until --before --author --committer --grep -S -G -L --min-parents --max-parents --pretty --format --date --abbrev --encoding --decorate-refs --decorate-refs-exclude"
_split_flags "$@"
local base
if [[ ${#args[@]} -eq 0 ]]; then
base=$(_git_get_default_branch_name)
if ! git rev-parse --verify --quiet "$base" >/dev/null 2>&1; then
base="origin/$base"
fi
if ! git rev-parse --verify --quiet "$base" >/dev/null 2>&1; then
base=$(_git_get_base_ref)
fi
else
base=$(_git_get_base_ref "${args[0]}")
fi
local count=$(git rev-list --count "${args[0]:-HEAD}" "^$base" 2>/dev/null) limit=10
if [[ $count != "0" && -n $count ]]; then
limit=$((count + 5))
fi
git log --color=$color -$limit --pretty='format:%C(yellow)%h %C(cyan)%cd %C(magenta)%an%x09%C(white)%s%Creset%x09%C(yellow)%d%Creset' "${flags[@]}" "${args[@]}" | awk -F'\t' -v columns="$columns" '
function width(text, stripped) {
stripped = text
gsub(/\033\[[0-9;]*m/, "", stripped)
return length(stripped)
}
function ellipsize(text, limit, result, pos, len, char, visible, escape) {
if (width(text) <= limit)
return text
if (limit < 2)
limit = 2
result = ""
visible = 0
len = length(text)
for (pos = 1; pos <= len; pos++) {
char = substr(text, pos, 1)
if (char == "\033") {
escape = char
while (++pos <= len) {
char = substr(text, pos, 1)
escape = escape char
if (char == "m")
break
}
result = result escape
} else {
if (visible >= limit - 2)
break
result = result char
visible++
}
}
return result ".." "\033[m"
}
{
prefixes[NR] = $1
subjects[NR] = $2
decorations[NR] = $3
if (width($1) > prefix_width)
prefix_width = width($1)
}
END {
for (row = 1; row <= NR; row++) {
prefix = prefixes[row]
subject = subjects[row]
decoration = decorations[row]
if (width(decoration) > 0)
sub(/ /, "", decoration)
else
decoration = ""
if (columns > 0) {
budget = columns - prefix_width - 1
if (decoration != "")
budget -= width(decoration) + 1
if (width(subject) > budget) {
if (budget < 2)
subject = ""
else
subject = ellipsize(subject, budget)
}
}
line = sprintf("%s%*s %s", prefix, prefix_width - width(prefix), "", subject)
if (decoration != "")
line = line " " decoration
print line
}
}
' | if [ -t 1 ]; then
less -RFX
else
cat
fi
}
ga() {
if [ -n "$1" ]; then
if [ -f "$1" ]; then
git apply -v "$1" "${@:2}"
else
curl -L "$1" | git apply -v "${@:2}"
fi
else
echo "Usage: ga path [...flags]"
fi
}
gp() {
if [ "$#" -ne 0 ]; then
git pull --rebase "$@"
return
fi
local branch=$(_git_get_current_branch_name)
if [ -n "$branch" ] && git remote get-url upstream >/dev/null 2>&1 && git show-ref --verify --quiet "refs/remotes/upstream/$branch"; then
git pull --rebase upstream "$branch" && git push origin "$branch"
else
git pull --rebase
fi
}
gu() {
local branch=$(_git_get_current_branch_name)
git push origin "$branch" "$@"
}
gc() {
if [ "$#" -eq 0 ]; then
git switch "$(_git_get_default_branch_name)"
elif [ "$#" -eq 1 ] && _git_does_branch_exist "$1"; then
local default=$(_git_get_default_branch_name)
if [ "$1" = "$default" ]; then
git switch "$1"
else
git rebase "$default" "$1"
fi
else
git checkout "$@"
fi
}
gb() {
local refs=() color=auto
while [ $# -gt 0 ]; do
case $1 in
-a|--all) refs+=(refs/heads refs/remotes) ;;
-r|--remotes) refs+=(refs/remotes) ;;
--no-color) color=never ;;
--color) color=always ;;
--color=*) color=${1#--color=} ;;
--) shift; refs+=("$@"); break ;;
-?*) git branch "$@"; return ;;
*) refs+=("$1") ;;
esac
shift
done
if [ ${#refs[@]} -eq 0 ]; then
refs=(refs/heads)
fi
case $color in
always|never) ;;
*)
color=never
if [ -t 1 ]; then
color=always
fi
;;
esac
local default=$(_git_get_default_branch_name)
local marker='%(if)%(HEAD)%(then)*%(else)%(if)%(worktreepath)%(then)+%(else) %(end)%(end)'
local branch_name='%(color:yellow)%(refname:short)%(color:reset)'
local commit_date='%(color:cyan)%(committerdate:format-local:%Y-%m-%d %H:%M:%S)%(color:reset)'
local base_branch='%(if)%(upstream)%(then)%(color:green)%(upstream:short)%(color:reset)%(end)'
local ahead_behind='%(if)%(upstream)%(then)U:%(upstream:track,nobracket)%(else)C:%(ahead-behind:'"$default"')%(end)'
local commit_title='%(color:white)%(contents:subject)%(color:reset)'
git for-each-ref --color=$color --format="$marker%09$branch_name%09$commit_date%09$base_branch%09$ahead_behind%09%(worktreepath)%09$commit_title" "${refs[@]}" | awk -F'\t' -v color="$color" -v default="$default" '
function width(text, stripped) {
stripped = text
gsub(/\033\[[0-9;]*m/, "", stripped)
gsub(/↑|↓/, ".", stripped)
return length(stripped)
}
function max(a, b) {
return a > b ? a : b
}
function bold(text) {
return (color == "always" ? "\033[1m" text : text)
}
function cell(value, column_width) {
return (column_width > 0 ? sprintf(" %s%*s", value, column_width - width(value), "") : "")
}
{
if ($1 == "*")
current_row = NR
branch_plain = $2
gsub(/\033\[[0-9;]*m/, "", branch_plain)
if (branch_plain == default)
default_row = NR
base_branch = $4
plain = base_branch
gsub(/\033\[[0-9;]*m/, "", plain)
if (plain == default || plain == "origin/" default || plain == "upstream/" default)
base_branch = ""
base_branches[NR] = base_branch
ahead_behind = $5
gsub(/\033\[[0-9;]*m/, "", ahead_behind)
if (substr(ahead_behind, 1, 2) == "U:") {
ahead_behind = substr(ahead_behind, 3)
gsub(/ahead /, "↑", ahead_behind)
gsub(/behind /, "↓", ahead_behind)
gsub(/, /, "", ahead_behind)
} else if (substr(ahead_behind, 1, 2) == "C:") {
split(substr(ahead_behind, 3), parts, " ")
ahead_behind = ""
if (parts[1] + 0 > 0)
ahead_behind = ahead_behind "↑" parts[1]
if (parts[2] + 0 > 0)
ahead_behind = ahead_behind "↓" parts[2]
} else {
ahead_behind = ""
}
if (color == "always" && ahead_behind != "")
ahead_behind = "\033[90m" ahead_behind "\033[m"
ahead_behinds[NR] = ahead_behind
worktree = ""
if ($1 == "+") {
worktree = $6
sub(/.*\//, "", worktree)
worktree = (color == "always" ? "\033[35m" worktree "\033[m" : worktree)
}
worktrees[NR] = worktree
rows[NR] = $0
branch_name_width = max(branch_name_width, width($2))
base_branch_width = max(base_branch_width, width(base_branch))
ahead_behind_width = max(ahead_behind_width, width(ahead_behind))
worktree_width = max(worktree_width, width(worktree))
}
END {
order_count = 0
if (current_row) order[++order_count] = current_row
if (default_row && default_row != current_row) order[++order_count] = default_row
for (row = 1; row <= NR; row++) {
if (row != current_row && row != default_row)
order[++order_count] = row
}
for (i = 1; i <= order_count; i++) {
row = order[i]
split(rows[row], field, "\t")
name = (row == current_row ? bold(field[2]) : field[2])
printf "%s%*s %s%s%s%s %s\n", \
name, branch_name_width - width(field[2]), "", \
field[3], \
cell(ahead_behinds[row], ahead_behind_width), \
cell(base_branches[row], base_branch_width), \
cell(worktrees[row], worktree_width), \
field[7]
}
}' | if [ -t 1 ]; then
_limit_to_window_width -f | less -RFX
else
cat
fi
}
gri() {
if [ "$#" -gt 0 ]; then
git rebase -i --autostash "$@"
return
fi
local base=$(_git_get_base_ref)
local first_ahead=$(git rev-list --reverse "$base..HEAD" 2>/dev/null | head -n 1)
if [ -n "$first_ahead" ]; then
git rebase -i --autostash "$first_ahead~2" "$@"
else
git rebase -i --autostash "HEAD~10" "$@"
fi
}
gdf() {
local branch=$(_git_get_current_branch_name)
if _git_does_branch_exist "$1"; then
gd "$(_git_get_base_ref "$1")...$1" > "$DATA/${2:-$1}.diff"
elif [ -n "$1" ]; then
if [ -n "$2" ]; then
gd "${@:1:$#-1}" > "$DATA/${!#}.diff"
else
if git cat-file -e "$1" 2>/dev/null >&2; then
gd "$1" > "$DATA/$branch.diff"
else
gd > "$DATA/$1.diff"
fi
fi
else
gd > "$DATA/$branch.diff"
fi
}
gds() {
local branch=$(_git_get_current_branch_name)
if _git_does_branch_exist "$1"; then
gd "$(_git_get_base_ref "$1")...$1" | s
elif [ -n "$1" ]; then
if [ -n "$2" ]; then
gd "${@:1:$#-1}" | s
else
if git cat-file -e "$1" 2>/dev/null >&2; then
gd "$1" | s
else
gd | s
fi
fi
else
gd | s
fi
}
gh() {
if [ "$#" -eq 1 ] && _git_does_branch_exist "$1"; then
local base=$(_git_get_base_ref "$1")
local count=$(git rev-list --count "$base..$1" 2>/dev/null)
if [ "${count:-0}" -gt 1 ]; then
git show --binary --color=auto --format=medium "$base..$1"
return
fi
fi
git show --binary --color=auto --format=medium "$@"
}
ghf() {
local branch=$(_git_get_current_branch_name)
if _git_does_branch_exist "$1"; then
git format-patch --stdout "$(_git_get_base_ref "$1")..$1" > "$DATA/${2:-$1}.patch"
elif [ -n "$1" ]; then
if [ -n "$2" ]; then
gh "${@:1:$#-1}" > "$DATA/${!#}.patch"
else
if git cat-file -e "$1" 2>/dev/null >&2; then
gh "$1" > "$DATA/$branch.patch"
else
gh > "$DATA/$1.patch"
fi
fi
else
gh > "$DATA/$branch.patch"
fi
}
ghs() {
local branch=$(_git_get_current_branch_name)
if _git_does_branch_exist "$1"; then
git format-patch --stdout "$(_git_get_base_ref "$1")..$1" | s
elif [ -n "$1" ]; then
if [ -n "$2" ]; then
gh "${@:1:$#-1}" | s
else
if git cat-file -e "$1" 2>/dev/null >&2; then
gh "$1" | s
else
gh | s
fi
fi
else
gh | s
fi
}
# Bazel
_bazel() {
local subcommand=$1; shift
local args flags
local value_flags="-c --compilation_mode -j --jobs --config --platforms --cpu --define --copt --cxxopt --linkopt --test_filter --test_arg --test_output --test_timeout --test_tag_filters --runs_per_test --flaky_test_attempts --build_tag_filters --local_cpu_resources --local_ram_resources --output_groups"
_split_flags "$@"
if [ ${#args[@]} -eq 0 ]; then
args=("...")
fi
_run_notify "bazel $subcommand" bazel "$subcommand" "${flags[@]}" "${args[@]}"
}
bb() {
_bazel build "$@"
}
bt() {
_bazel test --test_output=streamed --nocache_test_results --nozip_undeclared_test_outputs "$@"
}
br() {
_bazel run "$@"
}
# Web Development
u() {
local server=$(basename "$(dirname "$PWD")")
local folder=$(basename "$PWD")
for path in "$@"; do
if [[ $folder == "site" ]]; then
scp -r "$path" "$server:/var/www/html/$path"
else
scp -r "$path" "$server:$path"
fi
done
}
# ============================================= #
# ------------------ WebKit+ ------------------ #
# ============================================= #
_webkit_dir() {
local dir
dir=$(git rev-parse --show-toplevel 2>/dev/null)
if [ -n "$dir" ] && [ -e "$dir/Tools/Scripts/webkitdirs.pm" ]; then
echo "$dir"
else
echo "$WebKit"
fi
}
alias mc="make-filtered clean"
alias mr="make-filtered release"
alias md="make-filtered debug"
make-filtered() {
local WebKit=$(_webkit_dir)
make "$@" | "$WebKit/Tools/Scripts/filter-build-webkit"
}
xcodebuild-filtered() {
local WebKit=$(_webkit_dir)
xcodebuild "$@" | "$WebKit/Tools/Scripts/filter-build-webkit"
}
ml() {
local WebKit=$(_webkit_dir)
"$WebKit/Tools/Scripts/extract-localizable-js-strings" --utf8 "$WebKit/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js" "$WebKit/Source/WebInspectorUI/UserInterface" "$@"
}
sr() {
local WebKit=$(_webkit_dir)
"$WebKit/Tools/Scripts/run-safari" --release "$@"
}
sd() {
local WebKit=$(_webkit_dir)
"$WebKit/Tools/Scripts/run-safari" --debug "$@"
}
wtl() {
local WebKit=$(_webkit_dir)
local args flags
local value_flags=$(_value_flags_cached run-webkit-tests "$WebKit/Tools/Scripts/run-webkit-tests" "$WebKit/Tools/Scripts/run-webkit-tests" --help)
_split_flags "$@"
if [ ${#args[@]} -eq 0 ]; then
local file
while IFS= read -r file; do
if [ -n "$file" ]; then
args+=("$file")
fi
done < <(_git_get_modified_files | grep LayoutTests | sed -E -e 's#(LayoutTests/)platform/[^/]+/#\1#' -e 's#-expected\.[^./]+$#.html#' | grep -E '\.html$' | sort -u)
fi
"$WebKit/Tools/Scripts/run-webkit-tests" --no-build --no-sample --no-retry-failures --time-out-ms=5000 --verbose "${flags[@]}" "${args[@]}"
}
wta() {
local WebKit=$(_webkit_dir)
"$WebKit/Tools/Scripts/run-api-tests" --no-build --timestamps --verbose "$@"
}
wtjs() {
local WebKit=$(_webkit_dir)
"$WebKit/Tools/Scripts/run-jsc-stress-tests" --verbose "$WebKit/JSTests/stress" --filter "$@"
}
run-minibrowser() {
"$(_webkit_dir)/Tools/Scripts/run-minibrowser" "$@"
}
gw() {
local WebKit=$(_webkit_dir)
"$WebKit/Tools/Scripts/git-webkit" "$@"
}
# ============================================= #
# ---------------- Completions ---------------- #
# ============================================= #
completion_aliases=()
_color_red="\001\033[31m\002"
_color_green="\001\033[32m\002"
_color_blue="\001\033[34m\002"
_color_cyan="\001\033[36m\002"
_color_reset="\001\033[0m\002"
_ps1_color_git() {
local status
if ! status=$(git status --porcelain --branch 2>/dev/null); then
return 0
fi
local git_dir common_dir
{ read -r git_dir; read -r common_dir; } < <(git rev-parse --git-dir --git-common-dir 2>/dev/null)
local header=${status%%$'\n'*}
local branch operation=
if [[ $header == "## "*"No commits yet on "* ]]; then
branch=${header##*on }
elif [[ $header == "## HEAD (no branch)" ]]; then
local rebase_dir=
if [[ -d $git_dir/rebase-merge ]]; then
rebase_dir=$git_dir/rebase-merge
elif [[ -d $git_dir/rebase-apply ]]; then
rebase_dir=$git_dir/rebase-apply
fi
if [[ -n $rebase_dir && -f $rebase_dir/onto ]]; then
local onto onto_name step total
read -r onto < "$rebase_dir/onto"
onto_name=$(git describe --all --exact-match "$onto" 2>/dev/null)
onto_name=${onto_name#*/}
if [[ -z $onto_name ]]; then
onto_name=$(git rev-parse --short "$onto" 2>/dev/null)
fi
branch="(rebasing onto ${onto_name}"
if [[ -f $rebase_dir/msgnum && -f $rebase_dir/end ]]; then
read -r step < "$rebase_dir/msgnum"
read -r total < "$rebase_dir/end"
branch="${branch} ${step}/${total}"
elif [[ -f $rebase_dir/next && -f $rebase_dir/last ]]; then
read -r step < "$rebase_dir/next"
read -r total < "$rebase_dir/last"
branch="${branch} ${step}/${total}"
fi
branch="${branch})"
operation=rebasing
else
branch=$(git rev-parse --short HEAD 2>/dev/null)
fi
else
branch=${header:3}
branch=${branch%%...*}
fi
if [[ -z $branch ]]; then
return 0
fi
if [[ -z $operation ]]; then
if [[ -f $git_dir/MERGE_HEAD ]]; then
operation=merging
elif [[ -f $git_dir/CHERRY_PICK_HEAD ]]; then
operation=cherry-picking
elif [[ -f $git_dir/REVERT_HEAD ]]; then
operation=reverting
elif [[ -f $git_dir/BISECT_LOG ]]; then
operation=bisecting
fi
if [[ -n $operation ]]; then
branch="${branch} (${operation})"
fi
fi
local ahead=""
if [[ $header == *"ahead "* ]]; then
ahead=${header##*ahead }
ahead="↑${ahead%%[],]*}"
fi
local behind=""
if [[ $header == *"behind "* ]]; then
behind=${header##*behind }
behind="↓${behind%%]*}"
fi
local count=""
if [[ -z $operation ]]; then
local revisions=$(_git_get_revision_count)
if [[ -n $revisions && $revisions != 0 ]]; then
count="+${revisions}"
fi
fi
local tracking=""
if [[ -n $ahead$behind$count ]]; then
tracking=" ${ahead}${behind}${count}"
fi
local stash=
if [[ -f $common_dir/logs/refs/stash ]]; then
local stash_count=0 stash_line
while IFS= read -r stash_line || [[ -n $stash_line ]]; do
stash_count=$((stash_count + 1))
done < "$common_dir/logs/refs/stash"
if [[ $stash_count -gt 0 ]]; then
stash=" ≡${stash_count}"
fi
elif [[ -f $common_dir/refs/stash ]]; then
stash=" ≡"
fi
local unpushed=$_color_reset unstaged=$_color_reset
if [[ $status == *$'\n'* ]]; then
unpushed=$_color_red
local line
while IFS= read -r line; do
case $line in
'## '*|'?? '*|'!! '*) continue ;;
esac
if [[ ${line:1:1} != ' ' ]]; then
unstaged=$_color_red
break
fi
done <<< "$status"
fi
echo -ne "${unpushed}[${unstaged}${branch}${_color_reset}${tracking}${stash}${unpushed}]${_color_reset}"
}
if [ "$SSH_CONNECTION" ] || [ "$SSH_TTY" ] || [ "$SSH_CLIENT" ]; then
export PS1="[\u@${_color_blue}\h${_color_reset}] ${_color_cyan}(\t) ${_color_green}\w${_color_reset} \$(_ps1_color_git): "
else
export PS1="${_color_cyan}(\t) ${_color_green}\w${_color_reset} \$(_ps1_color_git): "
fi
# General
complete -cf sudo
complete -cf man
complete -c which
complete -a type
_complete_ssh()
{
COMPREPLY=()
local cur="${COMP_WORDS[COMP_CWORD]}"
local comp_ssh_hosts="$(
{
cut -f 1 -d ' ' "$HOME/.ssh/known_hosts" 2>/dev/null | \
grep -v '^#' | \
grep -v '\[' ;
grep '^Host ' "$HOME/.ssh/config" 2>/dev/null | \
awk '{print $2}' ;
} | sort -u
)"
COMPREPLY=( $(compgen -W "${comp_ssh_hosts}" -- $cur))
return 0
}
complete -F _complete_ssh ssh
# Bash
if [ -f /opt/homebrew/etc/bash_completion ]; then
source /opt/homebrew/etc/bash_completion
fi
# Git
if [ -f "$HOME/.git-completion.sh" ]; then
source "$HOME/.git-completion.sh"
# Aliases
completion_aliases+=("gd")
completion_aliases+=("gf")
completion_aliases+=("gr")
completion_aliases+=("gv")
# Functions
completion_aliases+=("gp=git pull")
completion_aliases+=("gl=git log")
completion_aliases+=("ga=git apply")
completion_aliases+=("gu=git push")
completion_aliases+=("gc=git checkout")
completion_aliases+=("gb=git branch")
completion_aliases+=("gri=git rebase -i")
completion_aliases+=("gdf=git diff")
completion_aliases+=("gds=git diff")
completion_aliases+=("gh=git show")
completion_aliases+=("ghf=git show")
completion_aliases+=("ghs=git show")
fi
# Bazel
if [ -r "$HOME/.cache/bash-completion/bazel.sh" ]; then
source "$HOME/.cache/bash-completion/bazel.sh"
# Functions
completion_aliases+=("bb=bazel build")
completion_aliases+=("bt=bazel test")
completion_aliases+=("br=bazel run")
fi
# Node
if [ -f /opt/homebrew/etc/bash_completion.d/npm ]; then
source /opt/homebrew/etc/bash_completion.d/npm
# Aliases
completion_aliases+=("nr=npm run")
fi
# WebKit
if [ -f "$WebKit/Tools/Scripts/webkit-tools-completion.sh" ]; then
source "$WebKit/Tools/Scripts/webkit-tools-completion.sh"
complete -o default -W "--platform --ios-simulator --iphone-simulator --ipad-simulator --simulator --gtk --wpe --win --maccatalyst -t --target --debug --release --64-bit --32-bit --arm --architecture --model -q --quiet -v --verbose --timestamps --json-output -g --guard-malloc --root --wtf-only --webkit-only --web-core-only --webkit-legacy-only --ipc-only --wgsl-only -d --dump --build --no-build --timeout --no-timeout --iterations --repeat-each --child-processes --run-singly --force --additional-env-var" wta
complete -o default -W "--add-platform-exceptions --complex-text --debug --exit-after-n-crashes-or-timeouts --exit-after-n-failures --force --guard-malloc --help --http --ignore-tests --iterations --leaks --no-build --no-http --no-show-results --no-new-test-results --no-retry-failures --no-sample-on-timeout --pixel-tests --platform --quiet --order --release --reset-results --results-directory --root --run-singly --child-processes --skipped --threaded --time-out-ms --timeout --tolerance --verbose -1 -g -h -i -l -p -q -t -v" wtl
complete -o default -W "--help -h --jsc -j --no-copy --cloop --platform --memory-limited --no-jit --force-collectContinuously --output-dir -o --run-bundle --tarball --force-vm-copy --arch --force-architecture --ldd --artifact-exec-wrapper --os --shell-runner --make-runner --ruby-runner --gnu-parallel-runner --gnu-parallel-chunk-size --test-writer --treat-failing-as-flaky --remote --remote-config-file --report-execution-time --model --child-processes -c --max-timeout --filter --verbose -v --env-vars --debug --release --quick -q --basic --no-slow --jitless-wasm --no-retry" wtjs
fi
# worktrees
if [ -r "$HOME/Developer/worktrees/.pool/bin/wt-completion.bash" ]; then
source "$HOME/Developer/worktrees/.pool/bin/wt-completion.bash"
fi
# Aliases
_complete_alias() {
local completion_alias_name=$1
local completion_alias_value=${@:2:$#-1}
local completion_alias_value_array
read -r -a completion_alias_value_array <<< "$completion_alias_value"
local comp_words=() word
for word in "${COMP_WORDS[@]}"; do
if [[ $word == "$completion_alias_name" ]]; then
comp_words+=("${completion_alias_value_array[@]}")
else
comp_words+=("$word")
fi
done
COMP_WORDS=("${comp_words[@]}")
COMP_LINE=${COMP_LINE
//${completion_alias_name}/${completion_alias_value}}
COMP_CWORD=$(( ${#COMP_WORDS[@]} - 1 ))
COMP_POINT=${#COMP_LINE}
local current_word=${COMP_WORDS[$COMP_CWORD]}
local previous_word
if [[ ${#COMP_WORDS[@]} -ge 2 ]]; then
previous_word=${COMP_WORDS[$(( COMP_CWORD - 1 ))]}
fi
local command=${COMP_WORDS[0]}
local comp_definition=$(complete -p "$command")
local comp_function=$(sed -n "s/^complete .* -F \(.*\) ${command}/\1/p" <<< "$comp_definition")
"$comp_function" "${command}" "${current_word}" "${previous_word}"
}
for ((completion_index = 0; completion_index < ${#completion_aliases[@]}; ++completion_index)); do
IFS="=" read -r -a completion_alias <<< "${completion_aliases[$completion_index]}"
completion_alias_name=${completion_alias[0]}
completion_alias_value=""
if [[ ${#completion_alias[@]} == 1 ]]; then
completion_alias_definition=$(alias "$completion_alias_name")
completion_alias_value=$(dequote
"${completion_alias_definition
//alias ${completion_alias_name}=}")
else
completion_alias_value=${completion_alias[1]}
fi
eval "_complete_$completion_alias_name() {
_complete_alias ${completion_alias_name} ${completion_alias_value}
}"
eval "complete -o default -o nospace -F _complete_$completion_alias_name $completion_alias_name"
done
unset -v completion_aliases completion_index completion_alias completion_alias_name completion_alias_value completion_alias_definition