# 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 ':git-branches-switch' -docstring 'switch branch' map buffer git-branches ':git-branches-switch' -docstring 'switch branch' map buffer git-branches c ':git-branches-commit-pending' -docstring 'commit pending changes' map buffer git-branches d ':git-branches-delete' -docstring 'delete branch' map buffer git-branches D ':git-branches-force-delete' -docstring 'force-delete branch' map buffer git-branches g ':git-branches-refresh' -docstring 'refresh' map buffer git-branches n ':git-branches-new' -docstring 'new branch' map buffer git-branches r ':git-branches-rename' -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"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 '/b;' } } # 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}" # replace the * for current branch by c execute-keys -draft '%s^\*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 'ghy:git-branches-delete--" d' } # Force delete a branch. # # Same as the non-force version. define-command -hidden git-branches-force-delete %{ execute-keys -itersel 'ghy:git-branches-delete--" D' } # 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%opt{git_branch_switch}" git-branches-refresh } # Rename branches. # # Dispatching is done via git-branches-rename--. define-command -hidden git-branches-rename %{ execute-keys -itersel 'ghy:git-branches-rename--"' } # Rename branch implementation. define-command -hidden git-branches-rename-- %{ execute-keys -save-regs b 'ghrrll"bya b;' } # 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 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 'ghllygjoain new-" hh' } # Execute pending deletions. Called on commit. define-command -hidden git-branches-execute-delete %{ try %{ execute-keys -draft -itersel "%%s^(d|D)yllGl%opt{git_branch} -""" } } # Execute pending renames. Called on commit. define-command -hidden git-branches-execute-rename %{ try %{ execute-keys -draft "%%s^rddx_%opt{git_branch_rename}" } } # Execute pending creations. Called on commit. define-command -hidden git-branches-execute-new %{ try %{ execute-keys -draft "%%s^nddx_%opt{git_branch}" } } # 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"