diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..d4de618b --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.gitsecret/keys/random_seed +!*.secret +zsh/secret diff --git a/.gitsecret/keys/pubring.kbx b/.gitsecret/keys/pubring.kbx new file mode 100644 index 00000000..06c20b9d Binary files /dev/null and b/.gitsecret/keys/pubring.kbx differ diff --git a/.gitsecret/keys/pubring.kbx~ b/.gitsecret/keys/pubring.kbx~ new file mode 100644 index 00000000..5857cd59 Binary files /dev/null and b/.gitsecret/keys/pubring.kbx~ differ diff --git a/.gitsecret/keys/trustdb.gpg b/.gitsecret/keys/trustdb.gpg new file mode 100644 index 00000000..8d715af5 Binary files /dev/null and b/.gitsecret/keys/trustdb.gpg differ diff --git a/.gitsecret/paths/mapping.cfg b/.gitsecret/paths/mapping.cfg new file mode 100644 index 00000000..70315088 --- /dev/null +++ b/.gitsecret/paths/mapping.cfg @@ -0,0 +1 @@ +zsh/secret:63d3fba77f570fbb9e9f999303a2828c4a2d88990836e80ea08a48c48619da22 diff --git a/install.sh b/install.sh index 56026f7d..9c22e36f 100755 --- a/install.sh +++ b/install.sh @@ -35,4 +35,5 @@ ln -s ~/.dotfiles/zsh/antibody ~/.config/antibody ln -s ~/.dotfiles/zsh/zshrc ~/.zshrc ln -s ~/.dotfiles/zsh/cmds ~/.cmds ln -s ~/.dotfiles/zsh/aliases ~/.aliases +ln -s ~/.dotfiles/zsh/completions ~/.completions diff --git a/misc/tmate.conf b/misc/tmate.conf new file mode 100644 index 00000000..5804327b --- /dev/null +++ b/misc/tmate.conf @@ -0,0 +1,11 @@ +## tmate + +# Reassign prefix to not conflict with tmux +set -g prefix C-] +bind-key ] send-prefix + +# turn off status bar so tmate is invisible +set -g status off + +# Fix timeout for escape key +set -s escape-time 0 diff --git a/suckless/dwm/config.h b/suckless/dwm/config.h index afa7a16c..5aa73d72 100644 --- a/suckless/dwm/config.h +++ b/suckless/dwm/config.h @@ -76,6 +76,7 @@ static const Rule rules[] = { /* class instance title tags mask isfloating monitor */ { "discord", NULL, NULL, 1 << 8, 0, -1 }, { "Mailspring", NULL, NULL, 1 << 7, 0, -1 }, + { "Thunderbird", NULL, NULL, 1 << 7, 0, -1 }, { "Termite", NULL, NULL, 1 << 0, 0, -1 }, { "firefoxdeveloperedition", NULL, NULL, 1 << 1, 0, -1 }, { "Tor Browser", NULL, NULL, 1 << 1, 0, -1 }, diff --git a/tmux/tmux.conf b/tmux/tmux.conf index bc6dd904..bb7eca4e 100644 --- a/tmux/tmux.conf +++ b/tmux/tmux.conf @@ -1,6 +1,6 @@ # Bind escape to copy mode unbind [ -bind Escape copy-mode +bind v copy-mode # p = paste unbind p @@ -22,16 +22,15 @@ set -g clock-mode-style 12 # Renumber windows after removing one set -g renumber-windows on +# Set the thumbs key to f, I don't use find-window anyways +unbind f +set -g @thumbs-key f + # use 256 colors # set -g default-terminal 'tmux-256color-italic' set-option -ga terminal-overrides ",xterm-256color-italic:Tc" # set -g default-terminal "tmux-256color-italic" - -# change tmux bar colors -set -g status-bg '#B388FF' -set -g status-fg '#EEEEEE' - # Keep plenty of history for scrollback set -g history-limit 50000 @@ -43,6 +42,8 @@ set -g mouse on set -g status-keys vi setw -g mode-keys vi bind-key -Tcopy-mode-vi 'v' send -X begin-selection +bind-key -Tcopy-mode-vi 'y' send -X copy-selection +bind y run-shell "tmux show-buffer | xclip -sel clip -i" \; display-message "Copied tmux buffer to system clipboard" # Smart pane switching with awareness of Vim splits. # See: https://github.com/christoomey/vim-tmux-navigator @@ -66,11 +67,6 @@ set -g display-panes-time 1200 # status bar stuff set -g status-left-length 40 -# Simplify status bar display. -set -g status-left '[#S]' -set -g status-right "%I:%M %p " -# set -g status-right "#[fg=red][44%%]#[default] - %I:%M %p " - # Dismiss current pane to background window bind b break-pane -d bind-key j command-prompt -p "join pane from: " "join-pane -h -s '%%'" @@ -121,4 +117,33 @@ unbind '"' # Split panes bind | split-window -h -c "#{pane_current_path}" bind _ split-window -v -c "#{pane_current_path}" - +bind-key "\\" split-window -fh -c "#{pane_current_path}" +bind-key "_" split-window -fv -c "#{pane_current_path}" + +# Plugins +set -g @plugin 'tmux-plugins/tpm' +set -g @plugin 'tmux-plugins/tmux-sensible' +set -g @plugin 'tmux-plugins/tmux-resurrect' +set -g @plugin 'fcsonline/tmux-thumbs' +set -g @plugin 'wfxr/tmux-fzf-url' +set -g @plugin 'tmux-plugins/tmux-yank' +set -g @plugin 'Alkindi42/tmux-bitwarden' + +run '~/.tmux/plugins/tpm/tpm' + +set -as terminal-overrides ',*:indn@' # This fixes the clear bug on tmate + +# status bar theme + +set -g status-bg 'colour235' +set -g status-justify 'centre' +set -g status-left-length '100' +set -g status 'on' +set -g status-right-length '100' +set -g status-left '#[fg=colour232,bg=colour154] #S #[fg=colour154,bg=colour238,nobold,nounderscore,noitalics]#[fg=colour222,bg=colour238] #W #[fg=colour238,bg=colour235,nobold,nounderscore,noitalics]#[fg=colour121,bg=colour235] #(whoami)  #(uptime | cut -d " " -f 1,2,3) #[fg=colour235,bg=colour235,nobold,nounderscore,noitalics]' +set -g status-right '#[fg=colour235,bg=colour235,nobold,nounderscore,noitalics]#[fg=colour121,bg=colour235] %r  %a  %Y #[fg=colour238,bg=colour235,nobold,nounderscore,noitalics]#[fg=colour222,bg=colour238] #H #[fg=colour154,bg=colour238,nobold,nounderscore,noitalics]#[fg=colour232,bg=colour154] #(rainbarf --battery --remaining --no-rgb) ' +setw -g window-status-format '#[fg=colour235,bg=colour235,nobold,nounderscore,noitalics]#[default] #I  #W #[fg=colour235,bg=colour235,nobold,nounderscore,noitalics]' +setw -g window-status-current-format '#[fg=colour235,bg=colour238,nobold,nounderscore,noitalics]#[fg=colour222,bg=colour238] #I  #W  #F #[fg=colour238,bg=colour235,nobold,nounderscore,noitalics]' + +# Capture contents on tmux-ressurect save +set -g @resurrect-capture-pane-contents 'on' diff --git a/xorg/xinitrc b/xorg/xinitrc index 8f951c65..e07a1bf9 100755 --- a/xorg/xinitrc +++ b/xorg/xinitrc @@ -18,7 +18,7 @@ aw-server & aw-watcher-window & aw-watcher-afk & mconnect -d & -mailspring & +thunderbird & dbus-update-activation-environment --systemd DISPLAY export SSH_AUTH_SOCK export QT_QPA_PLATFORMTHEME="qt5ct" diff --git a/zsh/aliases b/zsh/aliases new file mode 100755 index 00000000..af20dbbd --- /dev/null +++ b/zsh/aliases @@ -0,0 +1,18 @@ +#!/usr/bin/zsh + +alias feh="feh --scale-down --auto-zoom" +alias idea="/home/yigit/.local/share/JetBrains/Toolbox/apps/IDEA-U/ch-0/201.7223.91/bin/idea.sh" +alias lights_off="curl 'http://yeetclock/setcolor?R=2000&G=10&B=000&O=0'" +alias open=xdg-open +alias rm="rm -i" +alias clip="xclip -selection clipboard" +alias g="git " +alias t="TERM=screen-256color-bce tmux" +alias tn="TERM=screen-256color-bce tmux new -s " +alias tat="TERM=screen-256color-bce tmux a -t " +alias yain="yay -Syu " +alias ls="ls --color" + +# Suffix aliases +alias -g G=" | rg" +alias gshh="gcloud cloud-shell ssh --authorize-session" diff --git a/zsh/antibody/zsh_plugins.txt b/zsh/antibody/zsh_plugins.txt index 1471da00..567dab33 100644 --- a/zsh/antibody/zsh_plugins.txt +++ b/zsh/antibody/zsh_plugins.txt @@ -8,4 +8,5 @@ zsh-users/zsh-syntax-highlighting zsh-users/zsh-history-substring-search zsh-users/zsh-autosuggestions le0me55i/zsh-extract +hcgraf/zsh-sudo diff --git a/zsh/cmds b/zsh/cmds index 11f49c73..673367f5 100644 --- a/zsh/cmds +++ b/zsh/cmds @@ -1,14 +1,5 @@ #!/usr/bin/zsh -alias backup="sudo borg create --progress --stats /mnt/hdd/backups::laptop_$(date +%m_%d_%Y) /home /usr /etc /var /opt /boot --exclude /var/lib --exclude /home/yigit/Projects/UltimateStudent/recordings" -alias metis_backup="mysqldump --no-tablespaces --single-transaction -u bcaa49b6f602ea -h eu-cdbr-west-03.cleardb.net heroku_a78e4b025f8259d -pdc691280 > ~/.db_backups/metis_$(date +%m_%d_%Y).sql" -alias feh="feh --scale-down --auto-zoom" -alias idea="/home/yigit/.local/share/JetBrains/Toolbox/apps/IDEA-U/ch-0/201.7223.91/bin/idea.sh" -alias lights_off="curl 'http://yeetclock/setcolor?R=2000&G=10&B=000&O=0'" -alias open=xdg-open -alias rm="rm -i" -alias clip="xclip -selection clipboard" - count() { echo -n $1 | wc -c } @@ -48,3 +39,64 @@ colors() { done echo "" } + + +# TMATE Functions + +TMATE_PAIR_NAME="$(whoami)-pair" +TMATE_SOCKET_LOCATION="/tmp/tmate-pair.sock" +TMATE_TMUX_SESSION="/tmp/tmate-tmux-session" + +# Get current tmate connection url +tmate-url() { + url="$(tmate -S $TMATE_SOCKET_LOCATION display -p '#{tmate_ssh}')" + echo "$url" | tr -d '\n' | xclip -selection clipboard + echo "Copied tmate url for $TMATE_PAIR_NAME:" + echo "$url" +} + +# Start a new tmate pair session if one doesn't already exist +# If creating a new session, the first argument can be an existing TMUX session to connect to automatically + +tmate-attach() { + if [ -n "$1" ]; then + echo "Attaching tmate to tmux session $1"; + echo $1 > $TMATE_TMUX_SESSION + tmate -S "$TMATE_SOCKET_LOCATION" send -t "$TMATE_PAIR_NAME" "TMUX='' tmux attach-session -t $1; tmate-unpair" ENTER + fi +} + + +tmate-pair() { + if [ ! -e "$TMATE_SOCKET_LOCATION" ]; then + tmate -S "$TMATE_SOCKET_LOCATION" -f "$HOME/.tmate.conf" new-session -d -s "$TMATE_PAIR_NAME" + + while [ -z "$url" ]; do + url="$(tmate -S $TMATE_SOCKET_LOCATION display -p '#{tmate_ssh_ro}')" + done + echo "$url" | tr -d '\n' | xclip -selection clipboard + echo "Copied tmate url for $TMATE_PAIR_NAME:" + echo "$url" + tmate -S "$TMATE_SOCKET_LOCATION" send -t "$TMATE_PAIR_NAME" "q" ENTER + sleep 1 + #tmate-attach $1 + sleep 2 + fi + tmate -S "$TMATE_SOCKET_LOCATION" attach-session -t "$TMATE_PAIR_NAME" +} + +# Close the pair because security +tmate-unpair() { + if [ -e "$TMATE_SOCKET_LOCATION" ]; then + if [ -e "$TMATE_SOCKET_LOCATION" ]; then + tmux detach -s $(cat $TMATE_TMUX_SESSION) + rm -f $TMATE_TMUX_SESSION + fi + + tmate -S "$TMATE_SOCKET_LOCATION" kill-session -t "$TMATE_PAIR_NAME" + echo "Killed session $TMATE_PAIR_NAME" + else + echo "Session already killed" + fi +} + diff --git a/zsh/completions/_gcloud b/zsh/completions/_gcloud new file mode 100644 index 00000000..350387f8 --- /dev/null +++ b/zsh/completions/_gcloud @@ -0,0 +1,439 @@ +#compdef gcloud +#------------------------------------------------------------ +# Description: +# +# Completion script for Google Cloud SDK +# +# Author: +# +# * Colin Su (https://github.com/littleq0903) +# +# Source Code: +# +# https://github.com/littleq0903/gcloud-zsh-completion +# +#------------------------------------------------------------ + +## Util functions + +# get authorized account list +__account_list () +{ + _wanted application expl 'Authorized Google Accounts' compadd $(command gcloud auth list 2> /dev/null | grep - | sed -e "s/^ - //g" | sed -e "s/(active)//g") +} + +# get config variable names +__variable_list () +{ + _wanted application expl 'gcloud :: config :: Configuration Variables' compadd $(command gcloud config list 2> /dev/null | grep "=" | sed -e "s/ = .*//g") +} + +## Common stuffs +local -a _first_arguments +_first_arguments=( + # these are command groups + 'auth:Manage oauth2 credentials for the Google Cloud SDK' + 'components:Install, update, or remove the tools in the Google Cloud SDK' + 'compute:Read and manipulate Google Compute Engine resources' + 'config:View and edit Google Cloud SDK properties' + 'sql:Manage Cloud SQL databases' + # these are just commands + 'init:Initialize a gcloud workspace in the current directory' + 'interactive:Use this tool in an interactive python shell' + 'version:Print version information for Cloud SDK components' +) + +# common options +common_ops=( + {--project+,-p+}":Google Cloud Platform project to use for this invocation:( )" + {--quiet,-q}"[Disable all interactive prompts when running gcloud commands. If input is required, defaults will be used, or an error will be raised.]" + "--user-output-enabled+:Control whether user intended output is printed to the console.:(true false)" + "--verbosity+:Override the default verbosity for this command. This must be a standard logging verbosity level:(debug info warning error critical none)" +) + +## for 'auth' command group +# Commands +local -a _auth_arguments +_auth_arguments=( + "activate-refresh-token:Get credentials via an existing refresh token" + "list:List the accounts for known credentials" + "login:Get credentials via Google's oauth2 web flow" + "revoke:Revoke authorization for credentials" +) + +__gcloud-auth () +{ + local curcontext="$curcontext" state line + local -A opt_args + + _arguments \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + _describe -t subcommand "gcloud :: auth Commands" _auth_arguments + return + ;; + (options) + case $line[1] in + (list) + _arguments \ + "--account+::List only credentials for one account:( )" + ;; + (login) + # TODO: make options repeatable + local args + args=( + "--account+:Override the account acquired from the web flow:( )" + "--do-not-activate[Do not set the new credentials as active]" + "--no-launch-browser[Print a URL to be copied instead of launching a web browser]" + ) + _arguments -C $args + ;; + (revoke) + _arguments \ + "--all[Revoke all known credentials]" + ;; + esac + ;; + esac +} + +## for 'components' command groups +local -a _components_arguments +_components_arguments=( + 'list:Command to list the current state of installed components' + 'remove:Command to remove installed components' + 'restore:Command to restore a backup of a Cloud SDK installation' + 'update:Command to update existing or install new components' +) + +__gcloud-components () +{ + local curcontext="$curcontext" state line + local -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + _describe -t commands "gcloud :: components Commands" _components_arguments + return + ;; + (options) + case $line[1] in + (list) + _arguments \ + "--show-versions[Show version information for all components]" + ;; + (remove) + ;; + (restore) + ;; + (update) + ;; + esac + ;; + esac +} + +## for 'compute' command groups +local -a _compute_arguments +_compute_arguments=( + "addresses:Read and manipulate Google Compute Engine addresses." + "backend-services:List, create, and delete backend services." + "disk-types:Read Google Compute Engine virtual disk types." + "disks:Read and manipulate Google Compute Engine disks." + "firewall-rules:List, create, and delete Google Compute Engine firewall rules." + "forwarding-rules:Read and manipulate forwarding rules to send traffic to load balancers." + "http-health-checks:Read and manipulate HTTP health checks for load balanced instances." + "images:List, create, and delete Google Compute Engine images." + "instances:Read and manipulate Google Compute Engine virtual machine instances." + "machine-types:Read Google Compute Engine virtual machine types." + "networks:List, create, and delete Google Compute Engine networks." + "operations:Read and manipulate Google Compute Engine operations." + "project-info:Read and manipulate project-level data like quotas and metadata." + "regions:List Google Compute Engine regions." + "routes:Read and manipulate routes." + "snapshots:List, describe, and delete Google Compute Engine snapshots." + "target-http-proxies:List, create, and delete target HTTP proxies." + "target-instances:Read and manipulate Google Compute Engine virtual target instances." + "target-pools:Read and manipulate Google Compute Engine target pools." + "url-maps:List, create, and delete URL maps." + "zones:List Google Compute Engine zones." + "config-ssh:Populate SSH config files with Host entries from each instance" + "copy-files:Copy files to and from Google Compute Engine virtual machines." + "ssh:SSH into a virtual machine instance." +) + +__gcloud-compute () +{ + local curcontext="$curcontext" state line + local -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + _describe -t commands "gcloud :: compute commands" _compute_arguments + return + ;; + esac + + + +} + +## for 'config' command groups +local -a _config_arguments +_config_arguments=( + 'list:View Google Cloud SDK properties' + 'set:Edit Google Cloud SDK properties' + 'unset:Erase Google Cloud SDK properties' +) + +__gcloud-config () +{ + local curcontext="$curcontext" state line + local -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + _describe -t commands "gcloud :: config Commands" _config_arguments + return + ;; + (options) + case $line[1] in + (list) + _arguments \ + "--all[List all set and unset properties that match the arguments]" \ + {--section+,-s+}":The section whose properties shall be listed:( )" + ;; + (set) + # FEATURE: gcloud config set , will complete the property names + local -a _config_set_arguments + _config_set_arguments=( + "--global-only[Set the option in the global properties file]" + {--section+,-s+}":The section containing the option to be set:( )" + ) + + _arguments -C \ + $_config_set_arguments \ + '1:feature:__variable_list' \ + '*:value:->value' + + case $state in + (value) + case $line[1] in + (account) + # FEATURE: gcloud config set account + # when `config set account `, completing by authroized accounts + _arguments -C \ + '2:feature:__account_list' + ;; + esac + ;; + esac + + ;; + (unset) + # FEATURE: gcloud config unset , will complete the property names + local -a _config_unset_arguments + _config_unset_arguments=( + "--global-only[Unset the option in the global properties file]" + {--section+,-s+}":The section containing the option to be unset:( )" + ) + _arguments \ + $_config_unset_arguments \ + '1:feature:__variable_list' + ;; + esac + ;; + esac +} + + +## for 'sql' command groups +local -a _sql_arguments +_sql_arguments=( + 'backups:Provide commands for working with backups of Cloud SQL instances' + 'instances:Provide commands for managing Cloud SQL instances' + 'operations:Provide commands for working with Cloud SQL instance operations' + 'ssl-certs:Provide commands for managing SSL certificates of Cloud SQL instances' + 'tiers:Provide a command to list tiers' +) + +__gcloud-sql () +{ + local curcontext="$curcontext" state line + local -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + _describe -t commands "gcloud :: sql Commands" _sql_arguments + return + ;; + (options) + case $line[1] in + (backups) + _sql_backups_arguments=( + "get:Retrieves information about a backup" + "list:Lists all backups associated with a given instance" + ) + + _arguments \ + ':command:->command' \ + {--instance+,-i+}":Cloud SQL instance ID:( )" \ + '*::options:->options' + + case $state in + (command) + local -a _sql_backups_arguments + _describe -t commands "gcloud :: sql :: backup Commands" _sql_backups_arguments + ;; + esac + ;; + (instances) + # too many optional options in here, cry ;( + _sql_instances_arguments=( + 'create:Creates a new Cloud SQL instance' + 'delete:Deletes a Cloud SQL instance' + 'export:Exports data from a Cloud SQL instance' + 'get:Retrieves information about a Cloud SQL instance' + 'import:Imports data into a Cloud SQL instance from Google Cloud Storage' + 'list:Lists Cloud SQL instances in a given project' + 'patch:Updates the settings of a Cloud SQL instance' + 'reset-ssl-config:Deletes all client certificates and generates a new server certificate' + 'restart:Restarts a Cloud SQL instance' + 'restore-backup:Restores a backup of a Cloud SQL instance' + 'set-root-password:Sets the password of the MySQL root user' + ) + + _arguments \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + _describe -t commands "gcloud :: sql :: instances Commands" _sql_instances_arguments + ;; + esac + ;; + (operations) + local -a _sql_operations_arguments + _sql_operations_arguments=( + "get:Retrieves information about a Cloud SQL instance operation." + "list:Lists all instance operations for the given Cloud SQL instance" + ) + + _arguments \ + ':command:->command' \ + {--instance+,-i+}":Cloud SQL instance ID:( )" \ + '*::options:->options' + + case $state in + (command) + _describe -t commands "gcloud :: sql :: operations Commands" _sql_backups_arguments + ;; + esac + ;; + (ssl-certs) + local -a _sql_sslcerts_arguments + _sql_sslcerts_arguments=( + 'create:Creates an SSL certificate for a Cloud SQL instance' + 'delete:Deletes an SSL certificate for a Cloud SQL instance' + 'get:Retrieves information about an SSL cert for a Cloud SQL instance' + 'list:Lists all SSL certs for a Cloud SQL instance' + ) + + _arguments \ + ':command:->command' \ + {--instance+,-i+}":Cloud SQL instance ID:( )" \ + '*::options:->options' + + case $state in + (command) + _describe -t commands "gcloud :: sql :: ssl-certs Commands" _sql_sslcerts_arguments + ;; + esac + ;; + (tiers) + local -a _sql_tiers_arguments + _sql_tiers_arguments=( + "list:Lists all available service tiers for Google Cloud SQL" + ) + + _arguments \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + _describe -t commands "gcloud :: sql :: tiers Commands" _sql_tiers_arguments + ;; + esac + ;; + esac + ;; + esac +} + +## Top-level completion function +local expl +local curcontext="$curcontext" state line +local -A opt_args + +_arguments -C \ + $common_ops \ + ':command:->command' \ + '*::options:->options' + +case $state in + (command) + _describe -t commands "Google Cloud SDK Commands" _first_arguments + ;; + + (options) + # subcommands + case $line[1] in + (auth) + __gcloud-auth + ;; + (compute) + __gcloud-compute + ;; + (components) + __gcloud-components + ;; + (config) + __gcloud-config + ;; + (sql) + __gcloud-sql + ;; + esac + ;; +esac + +return 0 + +# Local Variables: +# mode: Shell-Script +# sh-indentation: 2 +# indent-tabs-mode: nil +# sh-basic-offset: 2 +# End: +# vim: ft=zsh sw=2 ts=2 et diff --git a/zsh/completions/_git b/zsh/completions/_git new file mode 100644 index 00000000..6c562969 --- /dev/null +++ b/zsh/completions/_git @@ -0,0 +1,294 @@ +#compdef git gitk + +# zsh completion wrapper for git +# +# Copyright (c) 2012-2020 Felipe Contreras +# +# The recommended way to install this script is to make a copy of it as a +# file named '_git' inside any directory in your fpath. +# +# For example, create a directory '~/.zsh/', copy this file to '~/.zsh/_git', +# and then add the following to your ~/.zshrc file: +# +# fpath=(~/.zsh $fpath) +# +# You need git's bash completion script installed. By default bash-completion's +# location will be used (e.g. pkg-config --variable=completionsdir bash-completion). +# +# If your bash completion script is somewhere else, you can specify the +# location in your ~/.zshrc: +# +# zstyle ':completion:*:*:git:*' script ~/.git-completion.bash +# + +zstyle -T ':completion:*:*:git:*' tag-order && \ + zstyle ':completion:*:*:git:*' tag-order 'common-commands' + +zstyle -s ":completion:*:*:git:*" script script +if [ -z "$script" ]; then + local -a locations + local e bash_completion + + bash_completion=$(pkg-config --variable=completionsdir bash-completion 2>/dev/null) || + bash_completion='/usr/share/bash-completion/completions/' + + locations=( + "$(dirname ${funcsourcetrace[1]%:*})"/git-completion.bash + "$HOME/.local/share/bash-completion/completions/git" + "$bash_completion/git" + '/etc/bash_completion.d/git' # old debian + ) + for e in $locations; do + test -f $e && script="$e" && break + done +fi + +local old_complete="$functions[complete]" +functions[complete]=: +GIT_SOURCING_ZSH_COMPLETION=y . "$script" +functions[complete]="$old_complete" + +__gitcomp () +{ + emulate -L zsh + + local cur_="${3-$cur}" + + case "$cur_" in + --*=) + ;; + --no-*) + local c IFS=$' \t\n' + local -a array + for c in ${=1}; do + if [[ $c == "--" ]]; then + continue + fi + c="$c${4-}" + case $c in + --*=|*.) ;; + *) c="$c " ;; + esac + array+=("$c") + done + compset -P '*[=:]' + compadd -Q -S '' -p "${2-}" -a -- array && _ret=0 + ;; + *) + local c IFS=$' \t\n' + local -a array + for c in ${=1}; do + if [[ $c == "--" ]]; then + c="--no-...${4-}" + array+=("$c ") + break + fi + c="$c${4-}" + case $c in + --*=|*.) ;; + *) c="$c " ;; + esac + array+=("$c") + done + compset -P '*[=:]' + compadd -Q -S '' -p "${2-}" -a -- array && _ret=0 + ;; + esac +} + +__gitcomp_direct () +{ + emulate -L zsh + + compset -P '*[=:]' + compadd -Q -S '' -- ${(f)1} && _ret=0 +} + +__gitcomp_nl () +{ + emulate -L zsh + + compset -P '*[=:]' + compadd -Q -S "${4- }" -p "${2-}" -- ${(f)1} && _ret=0 +} + +__gitcomp_file () +{ + emulate -L zsh + + compset -P '*[=:]' + compadd -f -p "${2-}" -- ${(f)1} && _ret=0 +} + +__gitcomp_direct_append () +{ + __gitcomp_direct "$@" +} + +__gitcomp_nl_append () +{ + __gitcomp_nl "$@" +} + +__gitcomp_file_direct () +{ + __gitcomp_file "$1" "" +} + +_git_zsh () +{ + __gitcomp "v1.1" +} + +__git_complete_command () +{ + emulate -L zsh + + local command="$1" + local completion_func="_git_${command//-/_}" + if (( $+functions[$completion_func] )); then + emulate ksh -c $completion_func + return 0 + else + return 1 + fi +} + +__git_zsh_bash_func () +{ + emulate -L ksh + + local command=$1 + + __git_complete_command "$command" && return + + local expansion=$(__git_aliased_command "$command") + if [ -n "$expansion" ]; then + words[1]=$expansion + __git_complete_command "$expansion" + fi +} + +__git_zsh_cmd_common () +{ + local -a list + list=( + add:'add file contents to the index' + bisect:'find by binary search the change that introduced a bug' + branch:'list, create, or delete branches' + checkout:'checkout a branch or paths to the working tree' + clone:'clone a repository into a new directory' + commit:'record changes to the repository' + diff:'show changes between commits, commit and working tree, etc' + fetch:'download objects and refs from another repository' + grep:'print lines matching a pattern' + init:'create an empty Git repository or reinitialize an existing one' + log:'show commit logs' + merge:'join two or more development histories together' + mv:'move or rename a file, a directory, or a symlink' + pull:'fetch from and merge with another repository or a local branch' + push:'update remote refs along with associated objects' + rebase:'forward-port local commits to the updated upstream head' + reset:'reset current HEAD to the specified state' + restore:'restore working tree files' + rm:'remove files from the working tree and from the index' + show:'show various types of objects' + status:'show the working tree status' + switch:'switch branches' + tag:'create, list, delete or verify a tag object signed with GPG') + _describe -t common-commands 'common commands' list && _ret=0 +} + +__git_zsh_cmd_alias () +{ + local -a list + list=(${${(0)"$(git config -z --get-regexp '^alias\.*')"}#alias.}) + list=(${(f)"$(printf "%s:alias for '%s'\n" ${(f@)list})"}) + _describe -t alias-commands 'aliases' list && _ret=0 +} + +__git_zsh_cmd_all () +{ + local -a list + emulate ksh -c __git_compute_all_commands + list=( ${=__git_all_commands} ) + _describe -t all-commands 'all commands' list && _ret=0 +} + +__git_zsh_main () +{ + local curcontext="$curcontext" state state_descr line + typeset -A opt_args + local -a orig_words + + orig_words=( ${words[@]} ) + + _arguments -C \ + '(-p --paginate --no-pager)'{-p,--paginate}'[pipe all output into ''less'']' \ + '(-p --paginate)--no-pager[do not pipe git output into a pager]' \ + '--git-dir=-[set the path to the repository]: :_directories' \ + '--bare[treat the repository as a bare repository]' \ + '(- :)--version[prints the git suite version]' \ + '--exec-path=-[path to where your core git programs are installed]:: :_directories' \ + '--html-path[print the path where git''s HTML documentation is installed]' \ + '--info-path[print the path where the Info files are installed]' \ + '--man-path[print the manpath (see `man(1)`) for the man pages]' \ + '--work-tree=-[set the path to the working tree]: :_directories' \ + '--namespace=-[set the git namespace]' \ + '--no-replace-objects[do not use replacement refs to replace git objects]' \ + '(- :)--help[prints the synopsis and a list of the most commonly used commands]: :->arg' \ + '(-): :->command' \ + '(-)*:: :->arg' && return + + case $state in + (command) + _tags common-commands alias-commands all-commands + while _tags; do + _requested common-commands && __git_zsh_cmd_common + _requested alias-commands && __git_zsh_cmd_alias + _requested all-commands && __git_zsh_cmd_all + let _ret || break + done + ;; + (arg) + local command="${words[1]}" __git_dir + + if (( $+opt_args[--bare] )); then + __git_dir='.' + else + __git_dir=${opt_args[--git-dir]} + fi + + (( $+opt_args[--help] )) && command='help' + + words=( ${orig_words[@]} ) + + __git_zsh_bash_func $command + ;; + esac +} + +_git () +{ + local _ret=1 + local cur cword prev + + cur=${words[CURRENT]} + prev=${words[CURRENT-1]} + let cword=CURRENT-1 + + if (( $+functions[__${service}_zsh_main] )); then + __${service}_zsh_main + elif (( $+functions[__${service}_main] )); then + emulate ksh -c __${service}_main + elif (( $+functions[_${service}] )); then + emulate ksh -c _${service} + elif (( $+functions[_${service//-/_}] )); then + emulate ksh -c _${service//-/_} + fi + + let _ret && _default && _ret=0 + return _ret +} + +_git diff --git a/zsh/completions/_spt b/zsh/completions/_spt new file mode 100644 index 00000000..b6cb1e5e --- /dev/null +++ b/zsh/completions/_spt @@ -0,0 +1,348 @@ +#compdef spt + +autoload -U is-at-least + +_spt() { + typeset -A opt_args + typeset -a _arguments_options + local ret=1 + + if is-at-least 5.2; then + _arguments_options=(-s -S -C) + else + _arguments_options=(-s -C) + fi + + local context curcontext="$curcontext" state line + _arguments "${_arguments_options[@]}" \ +'-t+[Set the tick rate (milliseconds): the lower the number the higher the FPS.]' \ +'--tick-rate=[Set the tick rate (milliseconds): the lower the number the higher the FPS.]' \ +'-c+[Specify configuration file path.]' \ +'--config=[Specify configuration file path.]' \ +'--completions=[Generates completions for your preferred shell]: :(bash zsh fish power-shell elvish)' \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +":: :_spt_commands" \ +"*::: :->spotify-tui" \ +&& ret=0 + case $state in + (spotify-tui) + words=($line[1] "${words[@]}") + (( CURRENT += 1 )) + curcontext="${curcontext%:*:*}:spt-command-$line[1]:" + case $line[1] in + (pb) +_arguments "${_arguments_options[@]}" \ +'-d+[Specifies the spotify device to use]' \ +'--device=[Specifies the spotify device to use]' \ +'-f+[Specifies the output format]' \ +'--format=[Specifies the output format]' \ +'--transfer=[Transfers the playback to new DEVICE]' \ +'-v+[Sets the volume of a device to VOLUME (1 - 100)]' \ +'--volume=[Sets the volume of a device to VOLUME (1 - 100)]' \ +'-t[Pauses/resumes the playback of a device]' \ +'--toggle[Pauses/resumes the playback of a device]' \ +'-s[Prints out the current status of a device (default)]' \ +'--status[Prints out the current status of a device (default)]' \ +'--share-track[Returns the url to the current track]' \ +'--share-album[Returns the url to the album of the current track]' \ +'--like[Likes the current song]' \ +'--shuffle[Toggles shuffle mode]' \ +'--repeat[Switches between repeat modes]' \ +'*-n[Jumps to the next song]' \ +'*--next[Jumps to the next song]' \ +'*-p[Jumps to the previous song]' \ +'*--previous[Jumps to the previous song]' \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +&& ret=0 +;; +(playback) +_arguments "${_arguments_options[@]}" \ +'-d+[Specifies the spotify device to use]' \ +'--device=[Specifies the spotify device to use]' \ +'-f+[Specifies the output format]' \ +'--format=[Specifies the output format]' \ +'--transfer=[Transfers the playback to new DEVICE]' \ +'-v+[Sets the volume of a device to VOLUME (1 - 100)]' \ +'--volume=[Sets the volume of a device to VOLUME (1 - 100)]' \ +'-t[Pauses/resumes the playback of a device]' \ +'--toggle[Pauses/resumes the playback of a device]' \ +'-s[Prints out the current status of a device (default)]' \ +'--status[Prints out the current status of a device (default)]' \ +'--share-track[Returns the url to the current track]' \ +'--share-album[Returns the url to the album of the current track]' \ +'--like[Likes the current song]' \ +'--shuffle[Toggles shuffle mode]' \ +'--repeat[Switches between repeat modes]' \ +'*-n[Jumps to the next song]' \ +'*--next[Jumps to the next song]' \ +'*-p[Jumps to the previous song]' \ +'*--previous[Jumps to the previous song]' \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +&& ret=0 +;; +(p) +_arguments "${_arguments_options[@]}" \ +'-d+[Specifies the spotify device to use]' \ +'--device=[Specifies the spotify device to use]' \ +'-f+[Specifies the output format]' \ +'--format=[Specifies the output format]' \ +'-u+[Plays the URI]' \ +'--uri=[Plays the URI]' \ +'-n+[Plays the first match with NAME from the specified category]' \ +'--name=[Plays the first match with NAME from the specified category]' \ +'(-b --album -a --artist -p --playlist -w --show)-q[Adds track to queue instead of playing it directly]' \ +'(-b --album -a --artist -p --playlist -w --show)--queue[Adds track to queue instead of playing it directly]' \ +'(-t --track -b --album -a --artist -w --show)-r[Plays a random track (only works with playlists)]' \ +'(-t --track -b --album -a --artist -w --show)--random[Plays a random track (only works with playlists)]' \ +'-b[Looks for an album]' \ +'--album[Looks for an album]' \ +'-a[Looks for an artist]' \ +'--artist[Looks for an artist]' \ +'-t[Looks for a track]' \ +'--track[Looks for a track]' \ +'-w[Looks for a show]' \ +'--show[Looks for a show]' \ +'-p[Looks for a playlist]' \ +'--playlist[Looks for a playlist]' \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +&& ret=0 +;; +(play) +_arguments "${_arguments_options[@]}" \ +'-d+[Specifies the spotify device to use]' \ +'--device=[Specifies the spotify device to use]' \ +'-f+[Specifies the output format]' \ +'--format=[Specifies the output format]' \ +'-u+[Plays the URI]' \ +'--uri=[Plays the URI]' \ +'-n+[Plays the first match with NAME from the specified category]' \ +'--name=[Plays the first match with NAME from the specified category]' \ +'(-b --album -a --artist -p --playlist -w --show)-q[Adds track to queue instead of playing it directly]' \ +'(-b --album -a --artist -p --playlist -w --show)--queue[Adds track to queue instead of playing it directly]' \ +'(-t --track -b --album -a --artist -w --show)-r[Plays a random track (only works with playlists)]' \ +'(-t --track -b --album -a --artist -w --show)--random[Plays a random track (only works with playlists)]' \ +'-b[Looks for an album]' \ +'--album[Looks for an album]' \ +'-a[Looks for an artist]' \ +'--artist[Looks for an artist]' \ +'-t[Looks for a track]' \ +'--track[Looks for a track]' \ +'-w[Looks for a show]' \ +'--show[Looks for a show]' \ +'-p[Looks for a playlist]' \ +'--playlist[Looks for a playlist]' \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +&& ret=0 +;; +(l) +_arguments "${_arguments_options[@]}" \ +'-f+[Specifies the output format]' \ +'--format=[Specifies the output format]' \ +'--limit=[Specifies the maximum number of results (1 - 50)]' \ +'-d[Lists devices]' \ +'--devices[Lists devices]' \ +'-p[Lists playlists]' \ +'--playlists[Lists playlists]' \ +'--liked[Lists liked songs]' \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +&& ret=0 +;; +(list) +_arguments "${_arguments_options[@]}" \ +'-f+[Specifies the output format]' \ +'--format=[Specifies the output format]' \ +'--limit=[Specifies the maximum number of results (1 - 50)]' \ +'-d[Lists devices]' \ +'--devices[Lists devices]' \ +'-p[Lists playlists]' \ +'--playlists[Lists playlists]' \ +'--liked[Lists liked songs]' \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +&& ret=0 +;; +(s) +_arguments "${_arguments_options[@]}" \ +'-f+[Specifies the output format]' \ +'--format=[Specifies the output format]' \ +'--limit=[Specifies the maximum number of results (1 - 50)]' \ +'-b[Looks for albums]' \ +'--albums[Looks for albums]' \ +'-a[Looks for artists]' \ +'--artists[Looks for artists]' \ +'-p[Looks for playlists]' \ +'--playlists[Looks for playlists]' \ +'-t[Looks for tracks]' \ +'--tracks[Looks for tracks]' \ +'-w[Looks for shows]' \ +'--shows[Looks for shows]' \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +':search -- Specifies the search query:_files' \ +&& ret=0 +;; +(search) +_arguments "${_arguments_options[@]}" \ +'-f+[Specifies the output format]' \ +'--format=[Specifies the output format]' \ +'--limit=[Specifies the maximum number of results (1 - 50)]' \ +'-b[Looks for albums]' \ +'--albums[Looks for albums]' \ +'-a[Looks for artists]' \ +'--artists[Looks for artists]' \ +'-p[Looks for playlists]' \ +'--playlists[Looks for playlists]' \ +'-t[Looks for tracks]' \ +'--tracks[Looks for tracks]' \ +'-w[Looks for shows]' \ +'--shows[Looks for shows]' \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +':search -- Specifies the search query:_files' \ +&& ret=0 +;; +(help) +_arguments "${_arguments_options[@]}" \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +&& ret=0 +;; + esac + ;; +esac +} + +(( $+functions[_spt_commands] )) || +_spt_commands() { + local commands; commands=( + "playback:Interacts with the playback of a device" \ +"pb:Interacts with the playback of a device" \ +"play:Plays a uri or another spotify item by name" \ +"p:Plays a uri or another spotify item by name" \ +"list:Lists devices, liked songs and playlists" \ +"l:Lists devices, liked songs and playlists" \ +"search:Searches for tracks, albums and more" \ +"s:Searches for tracks, albums and more" \ +"help:Prints this message or the help of the given subcommand(s)" \ + ) + _describe -t commands 'spt commands' commands "$@" +} +(( $+functions[_spt__help_commands] )) || +_spt__help_commands() { + local commands; commands=( + + ) + _describe -t commands 'spt help commands' commands "$@" +} +(( $+functions[_l_commands] )) || +_l_commands() { + local commands; commands=( + + ) + _describe -t commands 'l commands' commands "$@" +} +(( $+functions[_spt__l_commands] )) || +_spt__l_commands() { + local commands; commands=( + + ) + _describe -t commands 'spt l commands' commands "$@" +} +(( $+functions[_spt__list_commands] )) || +_spt__list_commands() { + local commands; commands=( + + ) + _describe -t commands 'spt list commands' commands "$@" +} +(( $+functions[_p_commands] )) || +_p_commands() { + local commands; commands=( + + ) + _describe -t commands 'p commands' commands "$@" +} +(( $+functions[_spt__p_commands] )) || +_spt__p_commands() { + local commands; commands=( + + ) + _describe -t commands 'spt p commands' commands "$@" +} +(( $+functions[_pb_commands] )) || +_pb_commands() { + local commands; commands=( + + ) + _describe -t commands 'pb commands' commands "$@" +} +(( $+functions[_spt__pb_commands] )) || +_spt__pb_commands() { + local commands; commands=( + + ) + _describe -t commands 'spt pb commands' commands "$@" +} +(( $+functions[_spt__play_commands] )) || +_spt__play_commands() { + local commands; commands=( + + ) + _describe -t commands 'spt play commands' commands "$@" +} +(( $+functions[_spt__playback_commands] )) || +_spt__playback_commands() { + local commands; commands=( + + ) + _describe -t commands 'spt playback commands' commands "$@" +} +(( $+functions[_s_commands] )) || +_s_commands() { + local commands; commands=( + + ) + _describe -t commands 's commands' commands "$@" +} +(( $+functions[_spt__s_commands] )) || +_spt__s_commands() { + local commands; commands=( + + ) + _describe -t commands 'spt s commands' commands "$@" +} +(( $+functions[_spt__search_commands] )) || +_spt__search_commands() { + local commands; commands=( + + ) + _describe -t commands 'spt search commands' commands "$@" +} + +_spt "$@" \ No newline at end of file diff --git a/zsh/completions/_tmuxinator b/zsh/completions/_tmuxinator new file mode 100644 index 00000000..987db0b9 --- /dev/null +++ b/zsh/completions/_tmuxinator @@ -0,0 +1,30 @@ +#compdef _tmuxinator tmuxinator + +_tmuxinator() { + local commands projects + commands=(${(f)"$(tmuxinator commands zsh)"}) + projects=(${(f)"$(tmuxinator completions start)"}) + + if (( CURRENT == 2 )); then + _alternative \ + 'commands:: _describe -t commands "tmuxinator subcommands" commands' \ + 'projects:: _describe -t projects "tmuxinator projects" projects' + elif (( CURRENT == 3)); then + case $words[2] in + copy|cp|c|debug|delete|rm|open|o|start|s|edit|e) + _arguments '*:projects:($projects)' + ;; + esac + fi + + return +} + + +# Local Variables: +# mode: Shell-Script +# sh-indentation: 2 +# indent-tabs-mode: nil +# sh-basic-offset: 2 +# End: +# vim: ft=zsh sw=2 ts=2 et diff --git a/zsh/completions/completions b/zsh/completions/completions new file mode 120000 index 00000000..d4335079 --- /dev/null +++ b/zsh/completions/completions @@ -0,0 +1 @@ +/home/yigit/.dotfiles/zsh/completions \ No newline at end of file diff --git a/zsh/completions/git-completion.bash b/zsh/completions/git-completion.bash new file mode 100644 index 00000000..7dc6cd8e --- /dev/null +++ b/zsh/completions/git-completion.bash @@ -0,0 +1,3548 @@ +# bash/zsh completion support for core Git. +# +# Copyright (C) 2006,2007 Shawn O. Pearce +# Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/). +# Distributed under the GNU General Public License, version 2.0. +# +# The contained completion routines provide support for completing: +# +# *) local and remote branch names +# *) local and remote tag names +# *) .git/remotes file names +# *) git 'subcommands' +# *) git email aliases for git-send-email +# *) tree paths within 'ref:path/to/file' expressions +# *) file paths within current working directory and index +# *) common --long-options +# +# To use these routines: +# +# 1) Copy this file to somewhere (e.g. ~/.git-completion.bash). +# 2) Add the following line to your .bashrc/.zshrc: +# source ~/.git-completion.bash +# 3) Consider changing your PS1 to also show the current branch, +# see git-prompt.sh for details. +# +# If you use complex aliases of form '!f() { ... }; f', you can use the null +# command ':' as the first command in the function body to declare the desired +# completion style. For example '!f() { : git commit ; ... }; f' will +# tell the completion to use commit completion. This also works with aliases +# of form "!sh -c '...'". For example, "!sh -c ': git commit ; ... '". +# +# If you have a command that is not part of git, but you would still +# like completion, you can use __git_complete: +# +# __git_complete gl git_log +# +# Or if it's a main command (i.e. git or gitk): +# +# __git_complete gk gitk +# +# Compatible with bash 3.2.57. +# +# You can set the following environment variables to influence the behavior of +# the completion routines: +# +# GIT_COMPLETION_CHECKOUT_NO_GUESS +# +# When set to "1", do not include "DWIM" suggestions in git-checkout +# and git-switch completion (e.g., completing "foo" when "origin/foo" +# exists). +# +# GIT_COMPLETION_SHOW_ALL +# +# When set to "1" suggest all options, including options which are +# typically hidden (e.g. '--allow-empty' for 'git commit'). + +case "$COMP_WORDBREAKS" in +*:*) : great ;; +*) COMP_WORDBREAKS="$COMP_WORDBREAKS:" +esac + +# Discovers the path to the git repository taking any '--git-dir=' and +# '-C ' options into account and stores it in the $__git_repo_path +# variable. +__git_find_repo_path () +{ + if [ -n "${__git_repo_path-}" ]; then + # we already know where it is + return + fi + + if [ -n "${__git_C_args-}" ]; then + __git_repo_path="$(git "${__git_C_args[@]}" \ + ${__git_dir:+--git-dir="$__git_dir"} \ + rev-parse --absolute-git-dir 2>/dev/null)" + elif [ -n "${__git_dir-}" ]; then + test -d "$__git_dir" && + __git_repo_path="$__git_dir" + elif [ -n "${GIT_DIR-}" ]; then + test -d "${GIT_DIR-}" && + __git_repo_path="$GIT_DIR" + elif [ -d .git ]; then + __git_repo_path=.git + else + __git_repo_path="$(git rev-parse --git-dir 2>/dev/null)" + fi +} + +# Deprecated: use __git_find_repo_path() and $__git_repo_path instead +# __gitdir accepts 0 or 1 arguments (i.e., location) +# returns location of .git repo +__gitdir () +{ + if [ -z "${1-}" ]; then + __git_find_repo_path || return 1 + echo "$__git_repo_path" + elif [ -d "$1/.git" ]; then + echo "$1/.git" + else + echo "$1" + fi +} + +# Runs git with all the options given as argument, respecting any +# '--git-dir=' and '-C ' options present on the command line +__git () +{ + git ${__git_C_args:+"${__git_C_args[@]}"} \ + ${__git_dir:+--git-dir="$__git_dir"} "$@" 2>/dev/null +} + +# Removes backslash escaping, single quotes and double quotes from a word, +# stores the result in the variable $dequoted_word. +# 1: The word to dequote. +__git_dequote () +{ + local rest="$1" len ch + + dequoted_word="" + + while test -n "$rest"; do + len=${#dequoted_word} + dequoted_word="$dequoted_word${rest%%[\\\'\"]*}" + rest="${rest:$((${#dequoted_word}-$len))}" + + case "${rest:0:1}" in + \\) + ch="${rest:1:1}" + case "$ch" in + $'\n') + ;; + *) + dequoted_word="$dequoted_word$ch" + ;; + esac + rest="${rest:2}" + ;; + \') + rest="${rest:1}" + len=${#dequoted_word} + dequoted_word="$dequoted_word${rest%%\'*}" + rest="${rest:$((${#dequoted_word}-$len+1))}" + ;; + \") + rest="${rest:1}" + while test -n "$rest" ; do + len=${#dequoted_word} + dequoted_word="$dequoted_word${rest%%[\\\"]*}" + rest="${rest:$((${#dequoted_word}-$len))}" + case "${rest:0:1}" in + \\) + ch="${rest:1:1}" + case "$ch" in + \"|\\|\$|\`) + dequoted_word="$dequoted_word$ch" + ;; + $'\n') + ;; + *) + dequoted_word="$dequoted_word\\$ch" + ;; + esac + rest="${rest:2}" + ;; + \") + rest="${rest:1}" + break + ;; + esac + done + ;; + esac + done +} + +# The following function is based on code from: +# +# bash_completion - programmable completion functions for bash 3.2+ +# +# Copyright © 2006-2008, Ian Macdonald +# © 2009-2010, Bash Completion Maintainers +# +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# The latest version of this software can be obtained here: +# +# http://bash-completion.alioth.debian.org/ +# +# RELEASE: 2.x + +# This function can be used to access a tokenized list of words +# on the command line: +# +# __git_reassemble_comp_words_by_ref '=:' +# if test "${words_[cword_-1]}" = -w +# then +# ... +# fi +# +# The argument should be a collection of characters from the list of +# word completion separators (COMP_WORDBREAKS) to treat as ordinary +# characters. +# +# This is roughly equivalent to going back in time and setting +# COMP_WORDBREAKS to exclude those characters. The intent is to +# make option types like --date= and : easy to +# recognize by treating each shell word as a single token. +# +# It is best not to set COMP_WORDBREAKS directly because the value is +# shared with other completion scripts. By the time the completion +# function gets called, COMP_WORDS has already been populated so local +# changes to COMP_WORDBREAKS have no effect. +# +# Output: words_, cword_, cur_. + +__git_reassemble_comp_words_by_ref() +{ + local exclude i j first + # Which word separators to exclude? + exclude="${1//[^$COMP_WORDBREAKS]}" + cword_=$COMP_CWORD + if [ -z "$exclude" ]; then + words_=("${COMP_WORDS[@]}") + return + fi + # List of word completion separators has shrunk; + # re-assemble words to complete. + for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do + # Append each nonempty word consisting of just + # word separator characters to the current word. + first=t + while + [ $i -gt 0 ] && + [ -n "${COMP_WORDS[$i]}" ] && + # word consists of excluded word separators + [ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ] + do + # Attach to the previous token, + # unless the previous token is the command name. + if [ $j -ge 2 ] && [ -n "$first" ]; then + ((j--)) + fi + first= + words_[$j]=${words_[j]}${COMP_WORDS[i]} + if [ $i = $COMP_CWORD ]; then + cword_=$j + fi + if (($i < ${#COMP_WORDS[@]} - 1)); then + ((i++)) + else + # Done. + return + fi + done + words_[$j]=${words_[j]}${COMP_WORDS[i]} + if [ $i = $COMP_CWORD ]; then + cword_=$j + fi + done +} + +if ! type _get_comp_words_by_ref >/dev/null 2>&1; then +_get_comp_words_by_ref () +{ + local exclude cur_ words_ cword_ + if [ "$1" = "-n" ]; then + exclude=$2 + shift 2 + fi + __git_reassemble_comp_words_by_ref "$exclude" + cur_=${words_[cword_]} + while [ $# -gt 0 ]; do + case "$1" in + cur) + cur=$cur_ + ;; + prev) + prev=${words_[$cword_-1]} + ;; + words) + words=("${words_[@]}") + ;; + cword) + cword=$cword_ + ;; + esac + shift + done +} +fi + +# Fills the COMPREPLY array with prefiltered words without any additional +# processing. +# Callers must take care of providing only words that match the current word +# to be completed and adding any prefix and/or suffix (trailing space!), if +# necessary. +# 1: List of newline-separated matching completion words, complete with +# prefix and suffix. +__gitcomp_direct () +{ + local IFS=$'\n' + + COMPREPLY=($1) +} + +# Similar to __gitcomp_direct, but appends to COMPREPLY instead. +# Callers must take care of providing only words that match the current word +# to be completed and adding any prefix and/or suffix (trailing space!), if +# necessary. +# 1: List of newline-separated matching completion words, complete with +# prefix and suffix. +__gitcomp_direct_append () +{ + local IFS=$'\n' + + COMPREPLY+=($1) +} + +__gitcompappend () +{ + local x i=${#COMPREPLY[@]} + for x in $1; do + if [[ "$x" == "$3"* ]]; then + COMPREPLY[i++]="$2$x$4" + fi + done +} + +__gitcompadd () +{ + COMPREPLY=() + __gitcompappend "$@" +} + +# Generates completion reply, appending a space to possible completion words, +# if necessary. +# It accepts 1 to 4 arguments: +# 1: List of possible completion words. +# 2: A prefix to be added to each possible completion word (optional). +# 3: Generate possible completion matches for this word (optional). +# 4: A suffix to be appended to each possible completion word (optional). +__gitcomp () +{ + local cur_="${3-$cur}" + + case "$cur_" in + --*=) + ;; + --no-*) + local c i=0 IFS=$' \t\n' + for c in $1; do + if [[ $c == "--" ]]; then + continue + fi + c="$c${4-}" + if [[ $c == "$cur_"* ]]; then + case $c in + --*=|*.) ;; + *) c="$c " ;; + esac + COMPREPLY[i++]="${2-}$c" + fi + done + ;; + *) + local c i=0 IFS=$' \t\n' + for c in $1; do + if [[ $c == "--" ]]; then + c="--no-...${4-}" + if [[ $c == "$cur_"* ]]; then + COMPREPLY[i++]="${2-}$c " + fi + break + fi + c="$c${4-}" + if [[ $c == "$cur_"* ]]; then + case $c in + *=|*.) ;; + *) c="$c " ;; + esac + COMPREPLY[i++]="${2-}$c" + fi + done + ;; + esac +} + +# Clear the variables caching builtins' options when (re-)sourcing +# the completion script. +if [[ -n ${ZSH_VERSION-} ]]; then + unset ${(M)${(k)parameters[@]}:#__gitcomp_builtin_*} 2>/dev/null +else + unset $(compgen -v __gitcomp_builtin_) +fi + +# This function is equivalent to +# +# __gitcomp "$(git xxx --git-completion-helper) ..." +# +# except that the output is cached. Accept 1-3 arguments: +# 1: the git command to execute, this is also the cache key +# 2: extra options to be added on top (e.g. negative forms) +# 3: options to be excluded +__gitcomp_builtin () +{ + # spaces must be replaced with underscore for multi-word + # commands, e.g. "git remote add" becomes remote_add. + local cmd="$1" + local incl="${2-}" + local excl="${3-}" + + local var=__gitcomp_builtin_"${cmd/-/_}" + local options + eval "options=\${$var-}" + + if [ -z "$options" ]; then + local completion_helper + if [ "$GIT_COMPLETION_SHOW_ALL" = "1" ]; then + completion_helper="--git-completion-helper-all" + else + completion_helper="--git-completion-helper" + fi + # leading and trailing spaces are significant to make + # option removal work correctly. + options=" $incl $(__git ${cmd/_/ } $completion_helper) " || return + + for i in $excl; do + options="${options/ $i / }" + done + eval "$var=\"$options\"" + fi + + __gitcomp "$options" +} + +# Variation of __gitcomp_nl () that appends to the existing list of +# completion candidates, COMPREPLY. +__gitcomp_nl_append () +{ + local IFS=$'\n' + __gitcompappend "$1" "${2-}" "${3-$cur}" "${4- }" +} + +# Generates completion reply from newline-separated possible completion words +# by appending a space to all of them. +# It accepts 1 to 4 arguments: +# 1: List of possible completion words, separated by a single newline. +# 2: A prefix to be added to each possible completion word (optional). +# 3: Generate possible completion matches for this word (optional). +# 4: A suffix to be appended to each possible completion word instead of +# the default space (optional). If specified but empty, nothing is +# appended. +__gitcomp_nl () +{ + COMPREPLY=() + __gitcomp_nl_append "$@" +} + +# Fills the COMPREPLY array with prefiltered paths without any additional +# processing. +# Callers must take care of providing only paths that match the current path +# to be completed and adding any prefix path components, if necessary. +# 1: List of newline-separated matching paths, complete with all prefix +# path components. +__gitcomp_file_direct () +{ + local IFS=$'\n' + + COMPREPLY=($1) + + # use a hack to enable file mode in bash < 4 + compopt -o filenames +o nospace 2>/dev/null || + compgen -f /non-existing-dir/ >/dev/null || + true +} + +# Generates completion reply with compgen from newline-separated possible +# completion filenames. +# It accepts 1 to 3 arguments: +# 1: List of possible completion filenames, separated by a single newline. +# 2: A directory prefix to be added to each possible completion filename +# (optional). +# 3: Generate possible completion matches for this word (optional). +__gitcomp_file () +{ + local IFS=$'\n' + + # XXX does not work when the directory prefix contains a tilde, + # since tilde expansion is not applied. + # This means that COMPREPLY will be empty and Bash default + # completion will be used. + __gitcompadd "$1" "${2-}" "${3-$cur}" "" + + # use a hack to enable file mode in bash < 4 + compopt -o filenames +o nospace 2>/dev/null || + compgen -f /non-existing-dir/ >/dev/null || + true +} + +# Execute 'git ls-files', unless the --committable option is specified, in +# which case it runs 'git diff-index' to find out the files that can be +# committed. It return paths relative to the directory specified in the first +# argument, and using the options specified in the second argument. +__git_ls_files_helper () +{ + if [ "$2" == "--committable" ]; then + __git -C "$1" -c core.quotePath=false diff-index \ + --name-only --relative HEAD -- "${3//\\/\\\\}*" + else + # NOTE: $2 is not quoted in order to support multiple options + __git -C "$1" -c core.quotePath=false ls-files \ + --exclude-standard $2 -- "${3//\\/\\\\}*" + fi +} + + +# __git_index_files accepts 1 or 2 arguments: +# 1: Options to pass to ls-files (required). +# 2: A directory path (optional). +# If provided, only files within the specified directory are listed. +# Sub directories are never recursed. Path must have a trailing +# slash. +# 3: List only paths matching this path component (optional). +__git_index_files () +{ + local root="$2" match="$3" + + __git_ls_files_helper "$root" "$1" "${match:-?}" | + awk -F / -v pfx="${2//\\/\\\\}" '{ + paths[$1] = 1 + } + END { + for (p in paths) { + if (substr(p, 1, 1) != "\"") { + # No special characters, easy! + print pfx p + continue + } + + # The path is quoted. + p = dequote(p) + if (p == "") + continue + + # Even when a directory name itself does not contain + # any special characters, it will still be quoted if + # any of its (stripped) trailing path components do. + # Because of this we may have seen the same directory + # both quoted and unquoted. + if (p in paths) + # We have seen the same directory unquoted, + # skip it. + continue + else + print pfx p + } + } + function dequote(p, bs_idx, out, esc, esc_idx, dec) { + # Skip opening double quote. + p = substr(p, 2) + + # Interpret backslash escape sequences. + while ((bs_idx = index(p, "\\")) != 0) { + out = out substr(p, 1, bs_idx - 1) + esc = substr(p, bs_idx + 1, 1) + p = substr(p, bs_idx + 2) + + if ((esc_idx = index("abtvfr\"\\", esc)) != 0) { + # C-style one-character escape sequence. + out = out substr("\a\b\t\v\f\r\"\\", + esc_idx, 1) + } else if (esc == "n") { + # Uh-oh, a newline character. + # We cannot reliably put a pathname + # containing a newline into COMPREPLY, + # and the newline would create a mess. + # Skip this path. + return "" + } else { + # Must be a \nnn octal value, then. + dec = esc * 64 + \ + substr(p, 1, 1) * 8 + \ + substr(p, 2, 1) + out = out sprintf("%c", dec) + p = substr(p, 3) + } + } + # Drop closing double quote, if there is one. + # (There is not any if this is a directory, as it was + # already stripped with the trailing path components.) + if (substr(p, length(p), 1) == "\"") + out = out substr(p, 1, length(p) - 1) + else + out = out p + + return out + }' +} + +# __git_complete_index_file requires 1 argument: +# 1: the options to pass to ls-file +# +# The exception is --committable, which finds the files appropriate commit. +__git_complete_index_file () +{ + local dequoted_word pfx="" cur_ + + __git_dequote "$cur" + + case "$dequoted_word" in + ?*/*) + pfx="${dequoted_word%/*}/" + cur_="${dequoted_word##*/}" + ;; + *) + cur_="$dequoted_word" + esac + + __gitcomp_file_direct "$(__git_index_files "$1" "$pfx" "$cur_")" +} + +# Lists branches from the local repository. +# 1: A prefix to be added to each listed branch (optional). +# 2: List only branches matching this word (optional; list all branches if +# unset or empty). +# 3: A suffix to be appended to each listed branch (optional). +__git_heads () +{ + local pfx="${1-}" cur_="${2-}" sfx="${3-}" + + __git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \ + "refs/heads/$cur_*" "refs/heads/$cur_*/**" +} + +# Lists branches from remote repositories. +# 1: A prefix to be added to each listed branch (optional). +# 2: List only branches matching this word (optional; list all branches if +# unset or empty). +# 3: A suffix to be appended to each listed branch (optional). +__git_remote_heads () +{ + local pfx="${1-}" cur_="${2-}" sfx="${3-}" + + __git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \ + "refs/remotes/$cur_*" "refs/remotes/$cur_*/**" +} + +# Lists tags from the local repository. +# Accepts the same positional parameters as __git_heads() above. +__git_tags () +{ + local pfx="${1-}" cur_="${2-}" sfx="${3-}" + + __git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \ + "refs/tags/$cur_*" "refs/tags/$cur_*/**" +} + +# List unique branches from refs/remotes used for 'git checkout' and 'git +# switch' tracking DWIMery. +# 1: A prefix to be added to each listed branch (optional) +# 2: List only branches matching this word (optional; list all branches if +# unset or empty). +# 3: A suffix to be appended to each listed branch (optional). +__git_dwim_remote_heads () +{ + local pfx="${1-}" cur_="${2-}" sfx="${3-}" + local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers + + # employ the heuristic used by git checkout and git switch + # Try to find a remote branch that cur_es the completion word + # but only output if the branch name is unique + __git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \ + --sort="refname:strip=3" \ + "refs/remotes/*/$cur_*" "refs/remotes/*/$cur_*/**" | \ + uniq -u +} + +# Lists refs from the local (by default) or from a remote repository. +# It accepts 0, 1 or 2 arguments: +# 1: The remote to list refs from (optional; ignored, if set but empty). +# Can be the name of a configured remote, a path, or a URL. +# 2: In addition to local refs, list unique branches from refs/remotes/ for +# 'git checkout's tracking DWIMery (optional; ignored, if set but empty). +# 3: A prefix to be added to each listed ref (optional). +# 4: List only refs matching this word (optional; list all refs if unset or +# empty). +# 5: A suffix to be appended to each listed ref (optional; ignored, if set +# but empty). +# +# Use __git_complete_refs() instead. +__git_refs () +{ + local i hash dir track="${2-}" + local list_refs_from=path remote="${1-}" + local format refs + local pfx="${3-}" cur_="${4-$cur}" sfx="${5-}" + local match="${4-}" + local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers + + __git_find_repo_path + dir="$__git_repo_path" + + if [ -z "$remote" ]; then + if [ -z "$dir" ]; then + return + fi + else + if __git_is_configured_remote "$remote"; then + # configured remote takes precedence over a + # local directory with the same name + list_refs_from=remote + elif [ -d "$remote/.git" ]; then + dir="$remote/.git" + elif [ -d "$remote" ]; then + dir="$remote" + else + list_refs_from=url + fi + fi + + if [ "$list_refs_from" = path ]; then + if [[ "$cur_" == ^* ]]; then + pfx="$pfx^" + fer_pfx="$fer_pfx^" + cur_=${cur_#^} + match=${match#^} + fi + case "$cur_" in + refs|refs/*) + format="refname" + refs=("$match*" "$match*/**") + track="" + ;; + *) + for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD REBASE_HEAD; do + case "$i" in + $match*) + if [ -e "$dir/$i" ]; then + echo "$pfx$i$sfx" + fi + ;; + esac + done + format="refname:strip=2" + refs=("refs/tags/$match*" "refs/tags/$match*/**" + "refs/heads/$match*" "refs/heads/$match*/**" + "refs/remotes/$match*" "refs/remotes/$match*/**") + ;; + esac + __git_dir="$dir" __git for-each-ref --format="$fer_pfx%($format)$sfx" \ + "${refs[@]}" + if [ -n "$track" ]; then + __git_dwim_remote_heads "$pfx" "$match" "$sfx" + fi + return + fi + case "$cur_" in + refs|refs/*) + __git ls-remote "$remote" "$match*" | \ + while read -r hash i; do + case "$i" in + *^{}) ;; + *) echo "$pfx$i$sfx" ;; + esac + done + ;; + *) + if [ "$list_refs_from" = remote ]; then + case "HEAD" in + $match*) echo "${pfx}HEAD$sfx" ;; + esac + __git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \ + "refs/remotes/$remote/$match*" \ + "refs/remotes/$remote/$match*/**" + else + local query_symref + case "HEAD" in + $match*) query_symref="HEAD" ;; + esac + __git ls-remote "$remote" $query_symref \ + "refs/tags/$match*" "refs/heads/$match*" \ + "refs/remotes/$match*" | + while read -r hash i; do + case "$i" in + *^{}) ;; + refs/*) echo "$pfx${i#refs/*/}$sfx" ;; + *) echo "$pfx$i$sfx" ;; # symbolic refs + esac + done + fi + ;; + esac +} + +# Completes refs, short and long, local and remote, symbolic and pseudo. +# +# Usage: __git_complete_refs [