203 lines
6.9 KiB
Text
203 lines
6.9 KiB
Text
# Git branches in buffers.
|
||
#
|
||
# This small script provides convenience mechanisms to operate on Git branches by altering a buffer.
|
||
# It can:
|
||
#
|
||
# - Switch branches.
|
||
# - Create new branches with optional starting point.
|
||
# - Rename branches.
|
||
# - Delete and force-delete branches.
|
||
|
||
declare-option str git_bin "git --no-optional-locks"
|
||
declare-option str git_list_local_branches "%opt{git_bin} branch"
|
||
declare-option str git_branch "xargs %opt{git_bin} branch"
|
||
declare-option str git_branch_rename "xargs %opt{git_bin} branch -m"
|
||
declare-option str git_branch_switch "xargs %opt{git_bin} switch"
|
||
|
||
declare-user-mode git-branches
|
||
|
||
# Create a branch listing buffer.
|
||
define-command git-branches %{
|
||
edit -scratch "*git-branches*"
|
||
set-option buffer filetype git-branches
|
||
git-branches-refresh
|
||
|
||
# highlighters
|
||
add-highlighter buffer/ ref git-branches
|
||
|
||
# mappings
|
||
map buffer normal <ret> ':git-branches-switch<ret>' -docstring 'switch branch'
|
||
map buffer git-branches <ret> ':git-branches-switch<ret>' -docstring 'switch branch'
|
||
map buffer git-branches c ':git-branches-commit-pending<ret>' -docstring 'commit pending changes'
|
||
map buffer git-branches d ':git-branches-delete<ret>' -docstring 'delete branch'
|
||
map buffer git-branches D ':git-branches-force-delete<ret>' -docstring 'force-delete branch'
|
||
map buffer git-branches g ':git-branches-refresh<ret>' -docstring 'refresh'
|
||
map buffer git-branches n ':git-branches-new<ret>' -docstring 'new branch'
|
||
map buffer git-branches r ':git-branches-rename<ret>' -docstring 'rename branch'
|
||
}
|
||
|
||
# Save the content of the current branch (primary sel) in the "b register.
|
||
define-command -hidden git-save-branch-name %{
|
||
try %{
|
||
execute-keys ';,ghll<a-E>"by'
|
||
}
|
||
}
|
||
|
||
# Restore the position of the main selection. Required to have saved something in the "b register.
|
||
define-command -hidden git-restore-branch-name %{
|
||
try %{
|
||
execute-keys '/<c-r>b<ret>;'
|
||
}
|
||
}
|
||
|
||
# Refresh the content of the branch buffer. This will lose all information that have been modified in it.
|
||
# TODO: support + branches (I don’t recall what they are, but I think it means they are checked out in
|
||
# working trees?)
|
||
define-command -hidden git-branches-refresh %{
|
||
evaluate-commands -save-regs b %{
|
||
git-save-branch-name
|
||
execute-keys -draft "%%|%opt{git_list_local_branches}<ret>"
|
||
|
||
# replace the * for current branch by c
|
||
execute-keys -draft '%s^\*<ret>rc'
|
||
|
||
git-restore-branch-name
|
||
execute-keys 'gh'
|
||
}
|
||
}
|
||
|
||
# Delete a branch.
|
||
#
|
||
# Various situations are possible, and are acted upon by dispatching to git-branches-delete-- based on the
|
||
# first charact of every selection’s line.
|
||
define-command -hidden git-branches-delete %{
|
||
execute-keys -itersel '<a-s>ghy:git-branches-delete--<c-r>" d<ret>'
|
||
}
|
||
|
||
# Force delete a branch.
|
||
#
|
||
# Same as the non-force version.
|
||
define-command -hidden git-branches-force-delete %{
|
||
execute-keys -itersel '<a-s>ghy:git-branches-delete--<c-r>" D<ret>'
|
||
}
|
||
|
||
# Switch the branch as pending deletion.
|
||
#
|
||
# The argument is used for regular deletion (d) or force-deletion (D).
|
||
define-command -hidden git-branches-delete-- -params 1 %{
|
||
execute-keys "ghr%arg{1}gh"
|
||
}
|
||
|
||
# Deletion of a rename line simply removes the rename annotation, and delete.
|
||
define-command -hidden git-branches-delete--r -params 1 %{
|
||
git-branches-unrename
|
||
git-branches-delete-- %arg{1}
|
||
}
|
||
|
||
# Undelete.
|
||
define-command -hidden git-branches-delete--d -params 1 %{
|
||
execute-keys 'ghr gh'
|
||
}
|
||
|
||
# Force delete.
|
||
define-command -hidden git-branches-delete--D -params 1 %{
|
||
execute-keys 'ghr gh'
|
||
}
|
||
|
||
# Deletion on current branches is simply not allowed for obvious reasons (Git will refuse it anyway).
|
||
define-command -hidden git-branches-delete--c -params 1 %{
|
||
fail 'cannot delete current branches'
|
||
}
|
||
|
||
# Switch to a given branch (primary selection only).
|
||
define-command -hidden git-branches-switch %{
|
||
execute-keys -draft ",ghllGl<a-|>%opt{git_branch_switch}<ret>"
|
||
git-branches-refresh
|
||
}
|
||
|
||
# Rename branches.
|
||
#
|
||
# Dispatching is done via git-branches-rename--.
|
||
define-command -hidden git-branches-rename %{
|
||
execute-keys -itersel '<a-s>ghy:git-branches-rename--<c-r>"<ret>'
|
||
}
|
||
|
||
# Rename branch implementation.
|
||
define-command -hidden git-branches-rename-- %{
|
||
execute-keys -save-regs b 'ghrrll<a-E>"bya <c-r>b<esc>;<a-i><a-w>'
|
||
}
|
||
|
||
# Renaming a deletion branch.
|
||
define-command -hidden git-branches-rename--d %{
|
||
git-branches-rename--
|
||
}
|
||
|
||
# Remove renaming annotation.
|
||
define-command -hidden git-branches-rename--r %{
|
||
git-branches-unrename
|
||
}
|
||
|
||
# We forbid renaming current branches.
|
||
define-command -hidden git-branches-rename--c %{
|
||
fail 'cannot rename current branches'
|
||
}
|
||
|
||
# Unrename (remove rename annotations).
|
||
define-command -hidden git-branches-unrename %{
|
||
execute-keys 'ghr <a-E><a-E>dgh'
|
||
}
|
||
|
||
# Create new branches.
|
||
#
|
||
# This is a handy version that uses the optional second argument by yanking the branches selections are on.
|
||
define-command -hidden git-branches-new %{
|
||
execute-keys '<a-s>ghll<a-E>ygjo<esc><a-P>a<ret><esc>in new-<c-r>" <esc>hh<a-i><a-w>'
|
||
}
|
||
|
||
# Execute pending deletions. Called on commit.
|
||
define-command -hidden git-branches-execute-delete %{
|
||
try %{
|
||
execute-keys -draft -itersel "%%s^(d|D)y<ret>llGl<a-|>%opt{git_branch} -<c-r>""<ret>"
|
||
}
|
||
}
|
||
|
||
# Execute pending renames. Called on commit.
|
||
define-command -hidden git-branches-execute-rename %{
|
||
try %{
|
||
execute-keys -draft "%%s^r<ret>ddx_<a-|>%opt{git_branch_rename}<ret>"
|
||
}
|
||
}
|
||
|
||
# Execute pending creations. Called on commit.
|
||
define-command -hidden git-branches-execute-new %{
|
||
try %{
|
||
execute-keys -draft "%%s^n<ret>ddx_<a-|>%opt{git_branch}<ret>"
|
||
}
|
||
}
|
||
|
||
# Commit pending modifications in the buffer and refresh.
|
||
define-command -hidden git-branches-commit-pending %{
|
||
git-branches-execute-delete
|
||
git-branches-execute-rename
|
||
git-branches-execute-new
|
||
git-branches-refresh
|
||
}
|
||
|
||
# Highlighting.
|
||
set-face global GitOpsBranchCurrent green
|
||
set-face global GitOpsBranchOther default
|
||
set-face global GitOpsBranchDeleted red+s
|
||
set-face global GitOpsBranchForceDeleted red+bs
|
||
set-face global GitOpsBranchRenameSource blue
|
||
set-face global GitOpsBranchRenameDest cyan+b
|
||
set-face global GitOpsBranchNewName blue
|
||
set-face global GitOpsBranchNewStart yellow+i
|
||
|
||
# Highlighters.
|
||
add-highlighter shared/git-branches group
|
||
add-highlighter shared/git-branches/current-branch regex '^(c)\s+([^\n]+)$' "1:black" "2:GitOpsBranchCurrent"
|
||
add-highlighter shared/git-branches/other-branch regex '^\s+([^\n]+)$' "1:GitOpsBranchOther"
|
||
add-highlighter shared/git-branches/deleted-branch regex '^(d)\s+([^\n]+)$' "1:black" "2:GitOpsBranchDeleted"
|
||
add-highlighter shared/git-branches/force-deleted-branch regex '^(D)\s+([^\n]+)$' "1:black" "2:GitOpsBranchForceDeleted"
|
||
add-highlighter shared/git-branches/renamed-branch regex '^(r)\s+([^\n ]+) ([^\n ]*)$' "1:black" "2:GitOpsBranchRenameSource" "3:GitOpsBranchRenameDest"
|
||
add-highlighter shared/git-branches/new-branch regex '^(n)\s+([^\n ]+) ?([^\n ]*)?$' "1:black" "2:GitOpsBranchNewName" "3:GitOpsBranchNewStart"
|