Skip to content

Commit

Permalink
custom-completions: git: Expand completions
Browse files Browse the repository at this point in the history
The different commands such as `git checkout`, `git switch`, `git
cherry-pick` and `git rebase` all accept slightly differing refspecs.
This commit separates the extraction of refspecs and combines them in
individual completion commands for the different external commands.

All git commands complete with a table of `value | description` now.

Addresses nushell#406
  • Loading branch information
sgasse committed Mar 27, 2023
1 parent d984ff6 commit 6b289e2
Showing 1 changed file with 102 additions and 61 deletions.
163 changes: 102 additions & 61 deletions custom-completions/git/git-completions.nu
Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@
def "nu-complete git branches" [] {
^git branch | lines | each { |line| $line | str replace '\* ' "" | str trim }
}

def "nu-complete git switchable branches" [] {
let remotes_regex = (["(", ((nu-complete git remotes | each {|r| ['remotes/', $r, '/'] | str join}) | str join "|"), ")"] | str join)
^git branch -a
| lines
| parse -r (['^[\* ]+', $remotes_regex, '?(?P<branch>\S+)'] | flatten | str join)
| get branch
| uniq
| where {|branch| $branch != "HEAD"}
}

def "nu-complete git available upstream" [] {
^git branch -a | lines | each { |line| $line | str replace '\* ' "" | str trim }
Expand All @@ -24,15 +11,69 @@ def "nu-complete git log" [] {
^git log --pretty=%h | lines | each { |line| $line | str trim }
}

def "nu-complete git commits" [] {
# Yield all existing commits in descending chronological order.
def "nu-complete git commits all" [] {
^git rev-list --all --remotes --pretty=oneline | lines | parse "{value} {description}"
}

def "nu-complete git branches and commits" [] {
nu-complete git switchable branches
# Yield commits of current branch only. This is useful for e.g. cut points in
# `git rebase`.
def "nu-complete git commits current branch" [] {
^git log --pretty="%h %s" | lines | parse "{value} {description}"
}

# Yield local branches like `main`, `feature/typo_fix`
def "nu-complete git local branches" [] {
^git branch | lines | each { |line| $line | str replace '\* ' "" | str trim }
}

# Yield remote branches like `origin/main`, `upstream/feature-a`
def "nu-complete git remote branches with prefix" [] {
^git branch -r | lines | parse -r '^\*?(\s*|\s*\S* -> )(?P<branch>\S*$)' | get branch | uniq
}

# Yield remote branches *without* prefix which do not have a local counterpart.
# E.g. `upstream/feature-a` as `feature-a` to checkout and track in one command
# with `git checkout` or `git switch`.
def "nu-complete git remote branches nonlocal without prefix" [] {
# Get regex to strip remotes prefixes. It will look like `(origin|upstream)`
# for the two remotes `origin` and `upstream`.
let remotes_regex = (["(", ((nu-complete git remotes | each {|r| [$r, '/'] | str join}) | str join "|"), ")"] | str join)
let local_branches = (nu-complete git local branches)
^git branch -r | lines | parse -r (['^[\* ]+', $remotes_regex, '?(?P<branch>\S+)'] | flatten | str join) | get branch | uniq | where {|branch| $branch != "HEAD"} | where {|branch| $branch not-in $local_branches }
}

def "nu-complete git switch" [] {
(nu-complete git local branches)
| parse "{value}"
| insert description Branch
| append (nu-complete git commits)
| insert description "local branch"
| append (nu-complete git remote branches nonlocal without prefix
| parse "{value}"
| insert description "remote branch")
}

def "nu-complete git checkout" [] {
(nu-complete git local branches)
| parse "{value}"
| insert description "local branch"
| append (nu-complete git remote branches nonlocal without prefix
| parse "{value}"
| insert description "remote branch")
| append (nu-complete git remote branches with prefix
| parse "{value}"
| insert description "remote branch")
| append (nu-complete git commits all)
}

# Arguments to `git rebase --onto <arg1> <arg2>`
def "nu-complete git rebase" [] {
(nu-complete git local branches)
| parse "{value}"
| insert description "local branch"
| append (nu-complete git remote branches with prefix
| parse "{value}"
| insert description "remote branch")
| append (nu-complete git commits all)
}

def "nu-complete git stash-list" [] {
Expand Down Expand Up @@ -61,7 +102,7 @@ def "nu-complete git subcommands" [] {

# Check out git branches and files
export extern "git checkout" [
...targets: string@"nu-complete git switchable branches" # name of the branch or files to checkout
...targets: string@"nu-complete git checkout" # name of the branch or files to checkout
--conflict: string # conflict style (merge or diff3)
--detach(-d) # detach HEAD at named commit
--force(-f) # force checkout (throw away local modifications)
Expand Down Expand Up @@ -135,45 +176,45 @@ export extern "git fetch" [

# Push changes
export extern "git push" [
remote?: string@"nu-complete git remotes", # the name of the remote
...refs: string@"nu-complete git branches" # the branch / refspec
--all # push all refs
--atomic # request atomic transaction on remote side
--delete(-d) # delete refs
--dry-run(-n) # dry run
--exec: string # receive pack program
--follow-tags # push missing but relevant tags
--force-with-lease # require old value of ref to be at this value
--force(-f) # force updates
--ipv4(-4) # use IPv4 addresses only
--ipv6(-6) # use IPv6 addresses only
--mirror # mirror all refs
--no-verify # bypass pre-push hook
--porcelain # machine-readable output
--progress # force progress reporting
--prune # prune locally removed refs
--push-option(-o): string # option to transmit
--quiet(-q) # be more quiet
--receive-pack: string # receive pack program
--recurse-submodules: string # control recursive pushing of submodules
--repo: string # repository
--set-upstream(-u) # set upstream for git pull/status
--signed: string # GPG sign the push
--tags # push tags (can't be used with --all or --mirror)
--thin # use thin pack
--verbose(-v) # be more verbose
remote?: string@"nu-complete git remotes", # the name of the remote
...refs: string@"nu-complete git local branches" # the branch / refspec
--all # push all refs
--atomic # request atomic transaction on remote side
--delete(-d) # delete refs
--dry-run(-n) # dry run
--exec: string # receive pack program
--follow-tags # push missing but relevant tags
--force-with-lease # require old value of ref to be at this value
--force(-f) # force updates
--ipv4(-4) # use IPv4 addresses only
--ipv6(-6) # use IPv6 addresses only
--mirror # mirror all refs
--no-verify # bypass pre-push hook
--porcelain # machine-readable output
--progress # force progress reporting
--prune # prune locally removed refs
--push-option(-o): string # option to transmit
--quiet(-q) # be more quiet
--receive-pack: string # receive pack program
--recurse-submodules: string # control recursive pushing of submodules
--repo: string # repository
--set-upstream(-u) # set upstream for git pull/status
--signed: string # GPG sign the push
--tags # push tags (can't be used with --all or --mirror)
--thin # use thin pack
--verbose(-v) # be more verbose
]

# Pull changes
export extern "git pull" [
remote?: string@"nu-complete git remotes", # the name of the remote
...refs: string@"nu-complete git branches" # the branch / refspec
--rebase # rebase current branch on top of upstream after fetching
remote?: string@"nu-complete git remotes", # the name of the remote
...refs: string@"nu-complete git local branches" # the branch / refspec
--rebase # rebase current branch on top of upstream after fetching
]

# Switch between branches and commits
export extern "git switch" [
switch?: string@"nu-complete git switchable branches" # name of branch to switch to
switch?: string@"nu-complete git switch" # name of branch to switch to
--create(-c): string # create a new branch
--detach(-d): string@"nu-complete git log" # switch to a commit in a detatched state
--force-create(-C): string # forces creation of new branch, if it exists then the existing branch will be reset to starting point
Expand All @@ -194,7 +235,7 @@ export extern "git switch" [

# Apply the change introduced by an existing commit
export extern "git cherry-pick" [
commit?: string@"nu-complete git commits" # The commit ID to be cherry-picked
commit?: string@"nu-complete git commits all" # The commit ID to be cherry-picked
--edit(-e) # Edit the commit message prior to committing
--no-commit(-n) # Apply changes without making any commit
--signoff(-s) # Add Signed-off-by line to the commit message
Expand All @@ -206,19 +247,19 @@ export extern "git cherry-pick" [

# Rebase the current branch
export extern "git rebase" [
branch?: string@"nu-complete git branches and commits" # name of the branch to rebase onto
upstream?: string@"nu-complete git branches and commits" # upstream branch to compare against
--continue # restart rebasing process after editing/resolving a conflict
--abort # abort rebase and reset HEAD to original branch
--quit # abort rebase but do not reset HEAD
--interactive(-i) # rebase interactively with list of commits in editor
--onto: string@"nu-complete git branches and commits" # starting point at which to create the new commits
--root # start rebase from root commit
branch?: string@"nu-complete git rebase" # name of the branch to rebase onto
upstream?: string@"nu-complete git rebase" # upstream branch to compare against
--continue # restart rebasing process after editing/resolving a conflict
--abort # abort rebase and reset HEAD to original branch
--quit # abort rebase but do not reset HEAD
--interactive(-i) # rebase interactively with list of commits in editor
--onto?: string@"nu-complete git rebase" # starting point at which to create the new commits
--root # start rebase from root commit
]

# List or change branches
export extern "git branch" [
branch?: string@"nu-complete git branches" # name of branch to operate on
branch?: string@"nu-complete git local branches" # name of branch to operate on
--abbrev # use short commit hash prefixes
--edit-description # open editor to edit branch description
--merged # list reachable branches
Expand All @@ -236,7 +277,7 @@ export extern "git branch" [
--quiet # suppress messages except errors
--delete(-d) # delete branch
--list # list branches
--contains: string@"nu-complete git commits" # show only branches that contain the specified commit
--contains: string@"nu-complete git commits all" # show only branches that contain the specified commit
--no-contains # show only branches that don't contain specified commit
--track(-t) # when creating a branch, set upstream
]
Expand Down

0 comments on commit 6b289e2

Please sign in to comment.