diff --git a/lua/lualine/components/branch.lua b/lua/lualine/components/branch/git_branch.lua similarity index 55% rename from lua/lualine/components/branch.lua rename to lua/lualine/components/branch/git_branch.lua index 637c311..75831ba 100644 --- a/lua/lualine/components/branch.lua +++ b/lua/lualine/components/branch/git_branch.lua @@ -1,50 +1,64 @@ --- Copyright (c) 2020-2021 shadmansaleh --- MIT license, see LICENSE for more details. -local M = require('lualine.component'):extend() -local modules = require('lualine_require').lazy_require { - utils = 'lualine.utils.utils', -} +local M = {} + +local require = require('lualine_require').require +local utils = require 'lualine.utils.utils' + -- vars -M.git_branch = '' -M.git_dir = '' +local current_git_branch = '' +local current_git_dir = '' +local branch_cache = {} -- stores last known branch for a buffer +local active_bufnr = '0' -- os specific path separator -M.sep = package.config:sub(1, 1) +local sep = package.config:sub(1, 1) -- event watcher to watch head file -- Use file wstch for non windows and poll for windows. -- 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() -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 file_changed = sep ~= '\\' and vim.loop.new_fs_event() or vim.loop.new_fs_poll() 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 - 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 git_dir -- Search upward for .git file or folder @@ -53,7 +67,7 @@ function M.find_git_dir() git_dir = git_dir_cache[root_dir] break 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) if git_file_stat then if git_file_stat.type == 'directory' then @@ -65,12 +79,12 @@ function M.find_git_dir() git_dir = git_dir:match 'gitdir: (.+)$' file:close() -- 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 end end 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 break else @@ -78,54 +92,34 @@ function M.find_git_dir() end end end - root_dir = root_dir:match('(.*)' .. M.sep .. '.-') + root_dir = root_dir:match('(.*)' .. sep .. '.-') end git_dir_cache[file_dir] = git_dir - if M.git_dir ~= git_dir then - M.git_dir = git_dir - M.update_branch() + if dir_path == nil and current_git_dir ~= git_dir then + current_git_dir = git_dir + update_branch() end return git_dir end --- sets git_branch veriable to branch name or commit hash if not on branch -function M.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 - M.git_branch = branch - else - M.git_branch = HEAD:sub(1, 6) - end - end - return nil +function M.init() + -- 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 + utils.define_autocmd('BufEnter', "lua require'lualine.components.branch.git_branch'.find_git_dir()") end - --- Update branch -function M.update_branch() - M.active_bufnr = tostring(vim.fn.bufnr()) - M.file_changed:stop() - local git_dir = M.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 = '' +function M.get_branch(bufnr) + if vim.g.actual_curbuf ~= nil and 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 - branch_cache[vim.fn.bufnr()] = M.git_branch + if bufnr then + return branch_cache[bufnr] or '' + end + return current_git_branch end return M diff --git a/lua/lualine/components/branch/init.lua b/lua/lualine/components/branch/init.lua new file mode 100644 index 0000000..1c5b6b1 --- /dev/null +++ b/lua/lualine/components/branch/init.lua @@ -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