Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions lua/neogit/buffers/branch_select_view/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
local Buffer = require("neogit.lib.buffer")
local ui = require 'neogit.buffers.branch_select_view.ui'

local M = {}

-- @class BranchSelectViewBuffer
-- @field branches the branches list
-- @field action action dispatched by line selection
-- @field buffer Buffer
-- @see Buffer
--
--- Creates a new BranchSelectViewBuffer
-- @param branches
-- @param action
-- @return BranchSelectViewBuffer
function M.new(branches, action)
local instance = {
action = action,
branches = branches,
buffer = nil
}

setmetatable(instance, { __index = M })

return instance
end

function M:close()
self.buffer:close()
self.buffer = nil
end

function M:open()
self.buffer = Buffer.create {
name = "NeogitBranchSelectView",
filetype = "NeogitBranchSelectView",
kind = "split",
mappings = {
n = {
["<enter>"] = function(buffer)
local current_line = buffer:get_current_line()
local branch_name = current_line[1]
if self.action then
self.action(branch_name)
end
self:close()
end,
}
},
render = function()
return ui.View(self.branches)
end
}
end

return M
18 changes: 18 additions & 0 deletions lua/neogit/buffers/branch_select_view/ui.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
local Ui = require 'neogit.lib.ui'
local util = require 'neogit.lib.util'

local row = Ui.row
local text = Ui.text
local map = util.map

local M = {}

function M.View(branches)
return map(branches, function(branch_name)
return row{
text(branch_name)
}
end)
end

return M
24 changes: 20 additions & 4 deletions lua/neogit/lib/git/branch.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,18 @@ local function parse_branches(branches)
return other_branches
end

local function get_local_branches()
function M.get_local_branches()
local branches = cli.branch
.list
.call()
.call_sync()

return parse_branches(branches)
end

function M.get_remote_branches()
local branches = cli.branch
.remotes
.call_sync()

return parse_branches(branches)
end
Expand All @@ -27,7 +35,7 @@ function M.get_all_branches()
local branches = cli.branch
.list
.all
.call()
.call_sync()

return parse_branches(branches)
end
Expand Down Expand Up @@ -64,7 +72,7 @@ function M.prompt_for_branch(options)
end

function M.checkout_local()
local branches = get_local_branches()
local branches = M.get_local_branches()

a.util.scheduler()
local chosen = M.prompt_for_branch(branches)
Expand Down Expand Up @@ -111,4 +119,12 @@ function M.checkout_new()
cli.interactive_git_cmd(tostring(cli.checkout.new_branch(name)))
end

function M.current()
local branch_name = cli.branch.current.call_sync()
if #branch_name > 0 then
return branch_name[1]
end
return nil
end

return M
8 changes: 6 additions & 2 deletions lua/neogit/lib/git/cli.lua
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ local configurations = {
return function (branch)
return tbl.b(branch)
end
end,
new_branch_with_start_point = function (tbl)
return function (branch, start_point)
return tbl.args(branch, start_point).b()
end
end
}
}),
Expand Down Expand Up @@ -195,6 +200,7 @@ local configurations = {
remotes = '-r',
current = '--show-current',
very_verbose = '-vv',
move = '-m',
},
aliases = {
name = function (tbl)
Expand Down Expand Up @@ -725,7 +731,6 @@ local cli = setmetatable({
-- from: https://stackoverflow.com/questions/48948630/lua-ansi-escapes-pattern
local ansi_escape_sequence_pattern = "[\27\155][][()#;?%d]*[A-PRZcf-ntqry=><~]"
local stdout = {}
local raw_stdout = {}
local chan
local skip_count = 0

Expand All @@ -735,7 +740,6 @@ local cli = setmetatable({
pty = true,
width = 100,
on_stdout = function(_, data)
table.insert(raw_stdout, data)
local is_end = #data == 1 and data[1] == ""
if is_end then
return
Expand Down
90 changes: 77 additions & 13 deletions lua/neogit/popups/branch.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,29 @@ local cli = require 'neogit.lib.git.cli'
local popup = require('neogit.lib.popup')
local branch = require('neogit.lib.git.branch')
local operation = require('neogit.operations')
local BranchSelectViewBuffer = require 'neogit.buffers.branch_select_view'
local input = require('neogit.lib.input')

local function format_branches(list)
local branches = {}
for _,name in ipairs(list) do
local name_formatted = name:match("^remotes/(.*)") or name
if not name_formatted:match('^(.*)/HEAD') then
table.insert(branches, name_formatted)
end
end
return branches
end

local function parse_remote_branch_name(remote_name)
local offset = remote_name:find('/')
if not offset then return nil, nil end

local remote = remote_name:sub(1, offset-1)
local branch_name = remote_name:sub(offset+1, remote_name:len())

return remote, branch_name
end

function M.create()
local p = popup.builder()
Expand All @@ -13,27 +36,68 @@ function M.create()
status.refresh(true)
end))
:action("b", "checkout branch/revision", operation('checkout_branch', function ()
branch.checkout()
status.refresh(true)
local branches = format_branches(branch.get_all_branches())
BranchSelectViewBuffer.new(branches, function (selected_branch)
if selected_branch == '' then return end

cli.checkout.branch(selected_branch).call_sync()
status.dispatch_refresh(true)
end):open()
end))
:action("d", "delete local branch", operation('delete_branch', function ()
branch.delete()
status.refresh(true)
local branches = branch.get_local_branches()
BranchSelectViewBuffer.new(branches, function (selected_branch)
cli.branch.delete.name(selected_branch).call_sync()
status.dispatch_refresh(true)
end):open()
end))
:action("D", "delete local branch and remote", operation('delete_branch', function ()
local branch = branch.delete()
if branch and branch ~= '' then
cli.interactive_git_cmd(tostring(cli.push.remote("origin").delete.to(branch)))
end
status.refresh(true)
local branches = format_branches(branch.get_remote_branches())
BranchSelectViewBuffer.new(branches, function (selected_branch)
if selected_branch == '' then return end

local remote, branch_name = parse_remote_branch_name(selected_branch)
if not remote or not branch_name then return end

cli.branch.delete.name(branch_name).call_sync()
cli.push.remote(remote).delete.to(branch_name).call_sync()
status.dispatch_refresh(true)
end):open()
end))
:action("l", "checkout local branch", operation('checkout_local-branch', function ()
branch.checkout_local()
status.refresh(true)
local branches = branch.get_local_branches()
BranchSelectViewBuffer.new(branches, function (selected_branch)
if selected_branch == '' then return end
cli.checkout.branch(selected_branch).call_sync()
status.dispatch_refresh(true)
end):open()
end))
:action("c", "checkout new branch", operation('checkout_create-branch', function ()
branch.checkout_new()
status.refresh(true)
local branches = format_branches(branch.get_all_branches())
BranchSelectViewBuffer.new(branches, function(selected_branch)
if selected_branch == '' then return end

local name = input.get_user_input('branch > ')
if not name or name == '' then return end

cli.checkout.new_branch_with_start_point(name, selected_branch).call_sync()
status.dispatch_refresh(true)
end):open()
end))
:action("m", "rename branch", operation('rename_branch', function ()
local current_branch = branch.current() or ''
local branches = branch.get_local_branches()
table.insert(branches, current_branch)

BranchSelectViewBuffer.new(branches, function (selected_branch)
if selected_branch == '' then return end

local new_name = input.get_user_input('new branch name > ')
if not new_name or new_name == '' then return end

cli.branch.move.args(selected_branch, new_name).call_sync()
status.dispatch_refresh(true)
end):open()
end))
:build()

Expand Down