diff --git a/README.md b/README.md index b1ae756..2392a41 100644 --- a/README.md +++ b/README.md @@ -314,16 +314,26 @@ export FORGIT_LOG_FZF_OPTS=' - [`emoji-cli`](https://github.com/wfxr/emoji-cli): Emoji support for `git log`. +### Completions + +#### Bash + +- Put [`completions/git-forgit.bash`](https://github.com/wfxr/forgit/blob/master/completions/git-forgit.bash) in + `~/.local/share/bash-completion/completions` to have bash tab completion for `git forgit` and configured git aliases. +- Source [`completions/git-forgit.bash`](https://github.com/wfxr/forgit/blob/master/completions/git-forgit.bash) explicitly to have + bash tab completion for forgit shell functions and aliases (e.g. `gcb ` completes branches). + +#### Zsh + +- Put [`completions/_git-forgit`](completions/_git-forgit) in a directory in your `$fpath` (e.g. `/usr/share/zsh/site-functions`) to have zsh tab completion for `git forgit` and configured git aliases. +- Source [`completions/git-forgit.zsh`](completions/git-forgit.zsh) to have zsh tab completion for forgit shell functions and aliases (e.g. `gcb ` completes branches). + ### 💡 Tips - Most of the commands accept optional arguments (eg, `glo develop`, `glo f738479..188a849b -- main.go`, `gco master`). - `gd` supports specifying revision(eg, `gd HEAD~`, `gd v1.0 README.md`). - Call `gi` with arguments to get the wanted `.gitignore` contents directly(eg, `gi cmake c++`). - You can use the commands as sub-commands of `git`, see [#147](https://github.com/wfxr/forgit/issues/147) for details. -- Put [`completions/git-forgit.bash`](https://github.com/wfxr/forgit/blob/master/completions/git-forgit.bash) in - `~/.local/share/bash-completion/completions` to have bash tab completion for `git forgit` and configured git aliases. -- Source [`completions/git-forgit.bash`](https://github.com/wfxr/forgit/blob/master/completions/git-forgit.bash) explicitly to have - bash tab completion for forgit shell functions and aliases (e.g. `gcb ` completes branches). ### 📃 License diff --git a/completions/_git-forgit b/completions/_git-forgit new file mode 100644 index 0000000..35919e7 --- /dev/null +++ b/completions/_git-forgit @@ -0,0 +1,101 @@ +#compdef git-forgit +#description Utility tool for using git interactively +# +# forgit completions for zsh +# +# Place this file in your $fpath (e.g. /usr/share/zsh/site-functions) to enable +# tab completions for forgit as a git subcommmand. When using forgit as a shell +# plugin, additionally source completions/git-forgit.zsh after +# forgit.plugin.zsh to enable tab completion for shell functions and aliases. + +_git-branches() { + _alternative "branches:branchname:($(git branch -a --format '%(refname:short)'))" +} + +_git-checkout-file() { + _alternative "files:filename:($(git ls-files --modified))" +} + +_git-stash-show() { + _alternative "files:filename:($(git stash list | sed -n -e 's/:.*//p'))" +} + +# The completions for git already define a _git-diff completion function, but +# it provides the wrong results when called from _git-forgit because it heavily +# depends on the context it's been called from (usage of $curcontext and +# $CURRENT), so we use a simplified version here which always provides the same +# results independent of the context. +_git-forgit-diff() { + _alternative \ + 'commit-ranges::__git_commit_ranges' \ + 'blobs-and-trees-in-treeish::__git_blobs_and_trees_in_treeish' \ + 'files::__git_changed-in-working-tree_files' \ + 'blobs::__git_blobs ' +} + +_git-staged() { + _alternative "files:filename:($(git diff --name-only --staged))" +} + +_git-forgit() { + local subcommand cword cmd + subcommand="${words[1]}" + if [[ "$subcommand" != "forgit" ]]; then + # Forgit is obviously called via a git alias. Get the original + # aliased subcommand and proceed as if it was the previous word. + cmd=$(git config --get "alias.$subcommand" | cut -d ' ' -f 2) + cword=$((CURRENT + 1)) + else + cword=$CURRENT + cmd=${words[2]} + fi + + case ${cword} in + 1) ;; + 2) + local -a subcommands + subcommands=( + 'add:git add selector' + 'blame:git blame viewer' + 'branch_delete:git branch deletion selector' + 'checkout_branch:git checkout branch selector' + 'checkout_commit:git checkout commit selector' + 'checkout_file:git checkout-file selector' + 'checkout_tag:git checkout tag selector' + 'cherry_pick:git cherry-picking' + 'cherry_pick_from_branch:git cherry-picking with interactive branch selection' + 'clean:git clean selector' + 'diff:git diff viewer' + 'fixup:git fixup' + 'ignore:git ignore generator' + 'log:git commit viewer' + 'rebase:git rebase' + 'reset_head:git reset HEAD (unstage) selector' + 'revert_commit:git revert commit selector' + 'stash_show:git stash viewer' + 'stash_push:git stash push selector' + ) + _describe -t commands 'git forgit' subcommands + ;; + *) + case ${cmd} in + add) _git-add ;; + branch_delete) _git-branches ;; + checkout_branch) _git-branches ;; + checkout_commit) __git_recent_commits ;; + checkout_file) _git-checkout-file ;; + checkout_tag) __git_tags ;; + cherry_pick) _git-cherry-pick ;; + cherry_pick_from_branch) _git-branches ;; + clean) _git-clean ;; + diff) _git-forgit-diff ;; + fixup) __git_branch_names ;; + log) _git-log ;; + rebase) _git-rebase ;; + reset_head) _git-staged ;; + revert_commit) __git_recent_commits ;; + stash_show) _git-stash-show ;; + esac + ;; + esac +} diff --git a/completions/git-forgit.zsh b/completions/git-forgit.zsh new file mode 100644 index 0000000..60f3f73 --- /dev/null +++ b/completions/git-forgit.zsh @@ -0,0 +1,34 @@ +#!/bin/zsh +# +# forgit completions for zsh plugin +# +# When using forgit via the shell plugin, place completions/_git-forgit in your +# $fpath (e.g. /usr/share/zsh/site-functions) and source this file after +# forgit.plugin.zsh to enable tab completion for shell functions and aliases. + +# Check if forgit plugin is loaded +if (( $+functions[forgit::add] )); then + # We're reusing existing completion functions, so load those first + # if not already loaded and check if completion function exists afterwards. + (( $+functions[_git-add] )) || _git + (( $+functions[_git-add] )) || return 1 + (( $+functions[_git-branches] )) || _git-forgit + (( $+functions[_git-branches] )) || return 1 + # Completions for forgit plugin shell functions (also works for aliases) + compdef _git-add forgit::add + compdef _git-branches forgit::branch::delete + compdef _git-branches forgit::checkout::branch + compdef __git_recent_commits forgit::checkout::commit + compdef _git-checkout-file forgit::checkout::file + compdef __git_tags forgit::checkout::tag + compdef _git-cherry-pick forgit::cherry::pick + compdef _git-branches forgit::cherry::pick::from::branch + compdef _git-clean forgit::clean + compdef _git-forgit-diff forgit::diff + compdef __git_branch_names forgit::fixup + compdef _git-log forgit::log + compdef _git-rebase forgit::rebase + compdef _git-staged forgit::reset::head + compdef __git_recent_commits forgit::revert::commit + compdef _git-stash-show forgit::stash::show +fi diff --git a/conf.d/forgit.plugin.fish b/conf.d/forgit.plugin.fish index b8ca8b0..48e3182 100644 --- a/conf.d/forgit.plugin.fish +++ b/conf.d/forgit.plugin.fish @@ -87,15 +87,15 @@ function forgit::checkout::commit -d "git checkout commit selector" --argument-n "$FORGIT" checkout_commit $argv end -function forgit::branch::delete -d "git checkout branch deleter" --wraps "git branch --delete" +function forgit::branch::delete -d "git branch deletion selector" --wraps "git branch --delete" "$FORGIT" branch_delete $argv end -function forgit::revert::commit --argument-names 'commit_hash' --wraps "git revert --" +function forgit::revert::commit -d "git revert commit selector" --argument-names 'commit_hash' --wraps "git revert --" "$FORGIT" revert_commit $argv end -function forgit::blame +function forgit::blame -d "git blame viewer" "$FORGIT" blame $argv end