refactor: split branch component (#81)

This commit is contained in:
shadmansaleh 2021-10-11 17:42:47 +06:00
parent 0b599b0ace
commit cc64ec3f7c
2 changed files with 96 additions and 82 deletions

View File

@ -1,50 +1,64 @@
-- Copyright (c) 2020-2021 shadmansaleh local M = {}
-- MIT license, see LICENSE for more details.
local M = require('lualine.component'):extend() local require = require('lualine_require').require
local modules = require('lualine_require').lazy_require { local utils = require 'lualine.utils.utils'
utils = 'lualine.utils.utils',
}
-- vars -- vars
M.git_branch = '' local current_git_branch = ''
M.git_dir = '' local current_git_dir = ''
local branch_cache = {} -- stores last known branch for a buffer
local active_bufnr = '0'
-- os specific path separator -- os specific path separator
M.sep = package.config:sub(1, 1) local sep = package.config:sub(1, 1)
-- event watcher to watch head file -- event watcher to watch head file
-- Use file wstch for non windows and poll for windows. -- Use file wstch for non windows and poll for windows.
-- windows doesn't like file watch for some reason. -- windows doesn't like file watch for some reason.
M.file_changed = M.sep ~= '\\' and vim.loop.new_fs_event() or vim.loop.new_fs_poll() local file_changed = sep ~= '\\' and vim.loop.new_fs_event() or vim.loop.new_fs_poll()
M.active_bufnr = '0'
local branch_cache = {} -- stores last known branch for a buffer
-- Initilizer
M.init = function(self, options)
M.super.init(self, options)
if not self.options.icon then
self.options.icon = '' -- e0a0
end
-- run watch head on load so branch is present when component is loaded
M.find_git_dir()
-- update branch state of BufEnter as different Buffer may be on different repos
modules.utils.define_autocmd('BufEnter', "lua require'lualine.components.branch'.find_git_dir()")
end
M.update_status = function(_, is_focused)
if M.active_bufnr ~= vim.g.actual_curbuf then
-- Workaround for https://github.com/hoob3rt/lualine.nvim/issues/286
-- See upstream issue https://github.com/neovim/neovim/issues/15300
-- Diff is out of sync re sync it.
M.find_git_dir()
end
if not is_focused then
return branch_cache[vim.fn.bufnr()] or ''
end
return M.git_branch
end
local git_dir_cache = {} -- Stores git paths that we already know of local git_dir_cache = {} -- Stores git paths that we already know of
-- returns full path to git directory for current directory
function M.find_git_dir() -- sets git_branch veriable to branch name or commit hash if not on branch
local function get_git_head(head_file)
local f_head = io.open(head_file)
if f_head then
local HEAD = f_head:read()
f_head:close()
local branch = HEAD:match 'ref: refs/heads/(.+)$'
if branch then
current_git_branch = branch
else
current_git_branch = HEAD:sub(1, 6)
end
end
return nil
end
-- Update branch
local function update_branch()
active_bufnr = tostring(vim.fn.bufnr())
file_changed:stop()
local git_dir = current_git_dir
if git_dir and #git_dir > 0 then
local head_file = git_dir .. sep .. 'HEAD'
get_git_head(head_file)
file_changed:start(
head_file,
sep ~= '\\' and {} or 1000,
vim.schedule_wrap(function()
-- reset file-watch
update_branch()
end)
)
else
-- set to '' when git dir was not found
current_git_branch = ''
end
branch_cache[vim.fn.bufnr()] = current_git_branch
end
-- returns full path to git directory for dir_path or current directory
function M.find_git_dir(dir_path)
-- get file dir so we can search from that dir -- get file dir so we can search from that dir
local file_dir = vim.fn.expand '%:p:h' local file_dir = dir_path or vim.fn.expand '%:p:h'
local root_dir = file_dir local root_dir = file_dir
local git_dir local git_dir
-- Search upward for .git file or folder -- Search upward for .git file or folder
@ -53,7 +67,7 @@ function M.find_git_dir()
git_dir = git_dir_cache[root_dir] git_dir = git_dir_cache[root_dir]
break break
end end
local git_path = root_dir .. M.sep .. '.git' local git_path = root_dir .. sep .. '.git'
local git_file_stat = vim.loop.fs_stat(git_path) local git_file_stat = vim.loop.fs_stat(git_path)
if git_file_stat then if git_file_stat then
if git_file_stat.type == 'directory' then if git_file_stat.type == 'directory' then
@ -65,12 +79,12 @@ function M.find_git_dir()
git_dir = git_dir:match 'gitdir: (.+)$' git_dir = git_dir:match 'gitdir: (.+)$'
file:close() file:close()
-- submodule / relative file path -- submodule / relative file path
if git_dir and git_dir:sub(1, 1) ~= M.sep and not git_dir:match '^%a:.*$' then if git_dir and git_dir:sub(1, 1) ~= sep and not git_dir:match '^%a:.*$' then
git_dir = git_path:match '(.*).git' .. git_dir git_dir = git_path:match '(.*).git' .. git_dir
end end
end end
if git_dir then if git_dir then
local head_file_stat = vim.loop.fs_stat(git_dir .. M.sep .. 'HEAD') local head_file_stat = vim.loop.fs_stat(git_dir .. sep .. 'HEAD')
if head_file_stat and head_file_stat.type == 'file' then if head_file_stat and head_file_stat.type == 'file' then
break break
else else
@ -78,54 +92,34 @@ function M.find_git_dir()
end end
end end
end end
root_dir = root_dir:match('(.*)' .. M.sep .. '.-') root_dir = root_dir:match('(.*)' .. sep .. '.-')
end end
git_dir_cache[file_dir] = git_dir git_dir_cache[file_dir] = git_dir
if M.git_dir ~= git_dir then if dir_path == nil and current_git_dir ~= git_dir then
M.git_dir = git_dir current_git_dir = git_dir
M.update_branch() update_branch()
end end
return git_dir return git_dir
end end
-- sets git_branch veriable to branch name or commit hash if not on branch function M.init()
function M.get_git_head(head_file) -- run watch head on load so branch is present when component is loaded
local f_head = io.open(head_file) M.find_git_dir()
if f_head then -- update branch state of BufEnter as different Buffer may be on different repos
local HEAD = f_head:read() utils.define_autocmd('BufEnter', "lua require'lualine.components.branch.git_branch'.find_git_dir()")
f_head:close()
local branch = HEAD:match 'ref: refs/heads/(.+)$'
if branch then
M.git_branch = branch
else
M.git_branch = HEAD:sub(1, 6)
end
end
return nil
end end
function M.get_branch(bufnr)
-- Update branch if vim.g.actual_curbuf ~= nil and active_bufnr ~= vim.g.actual_curbuf then
function M.update_branch() -- Workaround for https://github.com/hoob3rt/lualine.nvim/issues/286
M.active_bufnr = tostring(vim.fn.bufnr()) -- See upstream issue https://github.com/neovim/neovim/issues/15300
M.file_changed:stop() -- Diff is out of sync re sync it.
local git_dir = M.git_dir M.find_git_dir()
if git_dir and #git_dir > 0 then
local head_file = git_dir .. M.sep .. 'HEAD'
M.get_git_head(head_file)
M.file_changed:start(
head_file,
M.sep ~= '\\' and {} or 1000,
vim.schedule_wrap(function()
-- reset file-watch
M.update_branch()
end)
)
else
-- set to '' when git dir was not found
M.git_branch = ''
end end
branch_cache[vim.fn.bufnr()] = M.git_branch if bufnr then
return branch_cache[bufnr] or ''
end
return current_git_branch
end end
return M return M

View File

@ -0,0 +1,20 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local M = require('lualine.component'):extend()
local require = require('lualine_require').require
local git_branch = require 'lualine.components.branch.git_branch'
-- Initilizer
M.init = function(self, options)
M.super.init(self, options)
if not self.options.icon then
self.options.icon = '' -- e0a0
end
git_branch.init()
end
M.update_status = function(_, is_focused)
return git_branch.get_branch((not is_focused and vim.fn.bufnr()))
end
return M