diff --git a/.github/README.md b/.github/README.md index 7ed5c7c..c49cc01 100644 --- a/.github/README.md +++ b/.github/README.md @@ -88,11 +88,11 @@ Adds indentline:

-

Nvim-bufferline.lua

+

Tabufline (our own pertab bufferline)

-A snazzy bufferline for Neovim - -
+
+
+

Nvim-web-devicons

diff --git a/lua/core/default_config.lua b/lua/core/default_config.lua index cf92e3b..e5e0dd9 100644 --- a/lua/core/default_config.lua +++ b/lua/core/default_config.lua @@ -4,7 +4,6 @@ local M = {} M.options = { - -- load your options here or load module with options user = function() end, @@ -25,9 +24,11 @@ M.ui = { statusline = { separator_style = "default", -- default/round/block/arrow - config = "%!v:lua.require'ui.statusline'.run()", + config = "%!v:lua.require('ui.statusline').run()", override = {}, }, + + tabufline_enabled = true, } M.plugins = { diff --git a/lua/core/init.lua b/lua/core/init.lua index e0a889a..709f878 100644 --- a/lua/core/init.lua +++ b/lua/core/init.lua @@ -4,9 +4,9 @@ vim.cmd "silent! command! NvChadSnapshotCreate lua require('nvchad').snap_create vim.cmd "silent! command! NvChadSnapshotDelete lua require('nvchad').snap_delete()" vim.cmd "silent! command! NvChadSnapshotCheckout lua require('nvchad').snap_checkout()" - -- autocmds local autocmd = vim.api.nvim_create_autocmd +local api = vim.api -- wrap the PackerSync command to warn people before using it in NvChadSnapshots autocmd("VimEnter", { @@ -36,12 +36,45 @@ autocmd("BufEnter", { command = "set fo-=c fo-=r fo-=o", }) -autocmd("InsertLeave", { - callback = function() - if require("luasnip").session.current_nodes[vim.api.nvim_get_current_buf()] - and not require("luasnip").session.jump_active - then - require("luasnip").unlink_current() +vim.t.bufs = vim.api.nvim_list_bufs() + +-- thx to https://github.com/ii14 && stores buffer per tab -> table +autocmd({ "BufAdd" }, { + callback = function(args) + if vim.t.bufs == nil then + vim.t.bufs = { args.buf } + else + local bufs = vim.t.bufs + + -- check for duplicates + if not vim.tbl_contains(bufs, args.buf) then + table.insert(bufs, args.buf) + vim.t.bufs = bufs + end end end, }) + +autocmd("BufDelete", { + callback = function(args) + for _, tab in ipairs(api.nvim_list_tabpages()) do + local bufs = vim.t[tab].bufs + if bufs then + for i, bufnr in ipairs(bufs) do + if bufnr == args.buf then + table.remove(bufs, i) + vim.t[tab].bufs = bufs + break + end + end + end + end + end, +}) + +if require("core.utils").load_config().ui.tabufline_enabled then + require("core.lazy_load").tabufline() +else + vim.opt.showtabline = 2 + vim.opt.tabline = "%!v:lua.require('ui.tabline').run()" +end diff --git a/lua/core/lazy_load.lua b/lua/core/lazy_load.lua index edb32be..8712f68 100644 --- a/lua/core/lazy_load.lua +++ b/lua/core/lazy_load.lua @@ -1,8 +1,8 @@ --- thx to https://github.com/max397574/omega-nvim/blob/master/lua/omega/modules/ui/bufferline.lua local M = {} +local autocmd = vim.api.nvim_create_autocmd M.lazy_load = function(tb) - vim.api.nvim_create_autocmd(tb.events, { + autocmd(tb.events, { pattern = "*", group = vim.api.nvim_create_augroup(tb.augroup_name, {}), callback = function() @@ -23,18 +23,6 @@ M.lazy_load = function(tb) }) end -M.bufferline = function() - M.lazy_load { - events = { "BufNewFile", "BufRead", "TabEnter" }, - augroup_name = "BufferLineLazy", - plugins = "bufferline.nvim", - - condition = function() - return #vim.fn.getbufinfo { buflisted = 1 } >= 2 - end, - } -end - M.colorizer = function() M.lazy_load { events = { "BufRead", "BufNewFile" }, @@ -96,7 +84,7 @@ M.treesitter_cmds = { M.gitsigns = function() -- taken from https://github.com/max397574 - vim.api.nvim_create_autocmd({ "BufRead" }, { + autocmd({ "BufRead" }, { callback = function() local function onexit(code, _) if code == 0 then @@ -119,4 +107,20 @@ M.gitsigns = function() }) end +M.tabufline = function() + autocmd({ "BufNewFile", "BufRead", "TabEnter" }, { + pattern = "*", + group = vim.api.nvim_create_augroup("TabuflineLazyLoad", {}), + callback = function() + if #vim.fn.getbufinfo { buflisted = 1 } >= 2 then + vim.opt.showtabline = 2 + vim.opt.tabline = "%!v:lua.require('ui.tabline').run()" + vim.api.nvim_del_augroup_by_name "TabuflineLazyLoad" + else + return "" + end + end, + }) +end + return M diff --git a/lua/core/mappings.lua b/lua/core/mappings.lua index 9b08bc4..5638d38 100644 --- a/lua/core/mappings.lua +++ b/lua/core/mappings.lua @@ -58,15 +58,19 @@ M.general = { }, } -M.bufferline = { +M.tabufline = { n = { -- new buffer [""] = { " enew ", "烙 new buffer" }, -- cycle through buffers - [""] = { " BufferLineCycleNext ", " cycle next buffer" }, - [""] = { " BufferLineCyclePrev ", " cycle prev buffer" }, + [""] = { " Tbufnext ", " goto next buffer" }, + [""] = { " Tbufprev ", " goto prev buffer" }, + + -- cycle through tabs + ["tp"] = { " tabprevious ", " goto next tab" }, + ["tn"] = { " tabnext ", " goto prev tab" }, -- close buffer + hide terminal buffer ["x"] = { diff --git a/lua/core/utils.lua b/lua/core/utils.lua index 33545ee..b1c09c8 100644 --- a/lua/core/utils.lua +++ b/lua/core/utils.lua @@ -1,30 +1,28 @@ local M = {} local api = vim.api -local fn = vim.fn local merge_tb = vim.tbl_deep_extend -M.close_buffer = function(force) +M.close_buffer = function(bufnr) if vim.bo.buftype == "terminal" then - force = force or #api.nvim_list_wins() < 2 and ":bd!" - local swap = force and #api.nvim_list_bufs() > 1 and ":bp | bd!" .. fn.bufnr() - return vim.cmd(swap or force or "hide") - end - - local fileExists = fn.filereadable(fn.expand "%p") - local modified = api.nvim_buf_get_option(fn.bufnr(), "modified") - - -- if file doesnt exist & its modified - if fileExists == 0 and modified then - print "no file name? add it now!" + if vim.bo.buflisted then + vim.bo.buflisted = false + vim.cmd "enew" + else + vim.cmd "hide" + end return end - force = force or not vim.bo.buflisted or vim.bo.buftype == "nofile" + -- if file doesnt exist & its modified + if vim.bo.modified then + print "save the file!" + return + end - -- if not force, change to prev buf and then close current - local close_cmd = force and ":bd!" or ":bp | bd" .. fn.bufnr() - vim.cmd(close_cmd) + bufnr = bufnr or api.nvim_get_current_buf() + require("core.utils").tabuflinePrev() + vim.cmd("bd" .. bufnr) end M.load_config = function() @@ -151,9 +149,7 @@ M.load_override = function(default_table, plugin_name) if type(user_table) == "function" then user_table = user_table() - end - - if type(user_table) == "table" then + elseif type(user_table) == "table" then default_table = merge_tb("force", default_table, user_table) else default_table = default_table @@ -175,13 +171,16 @@ M.packer_sync = function(...) vim.api.nvim_echo({ { "WARNING: You are trying to use ", "WarningMsg" }, { "PackerSync" }, - { " on a NvChadSnapshot. This will cause issues if NvChad dependencies contain " - .. "any breaking changes! Plugin updates will not be included in this " - .. "snapshot, so they will be lost after switching between snapshots! Would " - .. "you still like to continue? [y/N]\n", "WarningMsg" } + { + " on a NvChadSnapshot. This will cause issues if NvChad dependencies contain " + .. "any breaking changes! Plugin updates will not be included in this " + .. "snapshot, so they will be lost after switching between snapshots! Would " + .. "you still like to continue? [y/N]\n", + "WarningMsg", + }, }, false, {}) - local ans = vim.trim(string.lower(vim.fn.input("-> "))) + local ans = vim.trim(string.lower(vim.fn.input "-> ")) if ans ~= "y" then return @@ -192,7 +191,39 @@ M.packer_sync = function(...) if packer_exists then packer.sync(...) else - error("Packer could not be loaded!") + error "Packer could not be loaded!" + end +end + +M.tabuflineNext = function() + local bufs = vim.t.bufs or {} + + for i, v in ipairs(bufs) do + if api.nvim_get_current_buf() == v then + vim.cmd(i == #bufs and "b" .. bufs[1] or "b" .. bufs[i + 1]) + break + end + end +end + +M.tabuflinePrev = function() + local bufs = vim.t.bufs or {} + + for i, v in ipairs(bufs) do + if api.nvim_get_current_buf() == v then + vim.cmd(i == 1 and "b" .. bufs[#bufs] or "b" .. bufs[i - 1]) + break + end + end +end +-- closes tab + all of its buffers +M.tabuflineCloseTab = function() + local bufs = vim.t.bufs or {} + + vim.cmd "tabclose" + + for _, buf in ipairs(bufs) do + vim.cmd("bd" .. buf) end end diff --git a/lua/plugins/configs/bufferline.lua b/lua/plugins/configs/bufferline.lua deleted file mode 100644 index cb55bd5..0000000 --- a/lua/plugins/configs/bufferline.lua +++ /dev/null @@ -1,53 +0,0 @@ -local present, bufferline = pcall(require, "bufferline") - -if not present then - return -end - -require("base46").load_highlight "bufferline" - -vim.cmd [[ - - function! Toggle_theme(a,b,c,d) - lua require('base46').toggle_theme() - endfunction - - function! Quit_vim(a,b,c,d) - qa - endfunction -]] - -local options = { - options = { - offsets = { { filetype = "NvimTree", text = "", padding = 1 } }, - buffer_close_icon = "", - modified_icon = "", - close_icon = "", - show_close_icon = false, - left_trunc_marker = " ", - right_trunc_marker = " ", - max_name_length = 20, - max_prefix_length = 13, - tab_size = 20, - show_tab_indicators = true, - enforce_regular_tabs = false, - show_buffer_close_icons = true, - separator_style = "thin", - themable = true, - - -- top right buttons in bufferline - custom_areas = { - right = function() - return { - { text = "%@Toggle_theme@" .. vim.g.toggle_theme_icon .. "%X" }, - { text = "%@Quit_vim@ %X" }, - } - end, - }, - }, -} - --- check for any override -options = require("core.utils").load_override(options, "akinsho/bufferline.nvim") - -bufferline.setup(options) diff --git a/lua/plugins/configs/others.lua b/lua/plugins/configs/others.lua index 0ca3bf3..161b097 100644 --- a/lua/plugins/configs/others.lua +++ b/lua/plugins/configs/others.lua @@ -113,6 +113,17 @@ M.luasnip = function() options = load_override(options, "L3MON4D3/LuaSnip") luasnip.config.set_config(options) require("luasnip.loaders.from_vscode").lazy_load() + + vim.api.nvim_create_autocmd("InsertLeave", { + callback = function() + if + require("luasnip").session.current_nodes[vim.api.nvim_get_current_buf()] + and not require("luasnip").session.jump_active + then + require("luasnip").unlink_current() + end + end, + }) end M.gitsigns = function() diff --git a/lua/plugins/init.lua b/lua/plugins/init.lua index 68661b6..bc3e1bf 100644 --- a/lua/plugins/init.lua +++ b/lua/plugins/init.lua @@ -4,7 +4,7 @@ local plugins = { ["nvim-lua/plenary.nvim"] = { module = "plenary" }, ["wbthomason/packer.nvim"] = {}, - ["NvChad/extensions"] = {}, + ["NvChad/extensions"] = { module = { "telescope", "nvchad" } }, ["NvChad/base46"] = { config = function() @@ -30,17 +30,6 @@ local plugins = { end, }, - ["akinsho/bufferline.nvim"] = { - tag = "v2.*", - opt = true, - setup = function() - require("core.lazy_load").bufferline() - end, - config = function() - require "plugins.configs.bufferline" - end, - }, - ["lukas-reineke/indent-blankline.nvim"] = { opt = true, setup = function() diff --git a/lua/ui/statusline.lua b/lua/ui/statusline.lua index c7b9a0c..df52cb9 100644 --- a/lua/ui/statusline.lua +++ b/lua/ui/statusline.lua @@ -50,7 +50,7 @@ M.fileInfo = function() local devicons_present, devicons = pcall(require, "nvim-web-devicons") if devicons_present then - local ft_icon = devicons.get_icon(filename, fn.expand "%:e") + local ft_icon = devicons.get_icon(filename) icon = (ft_icon ~= nil and " " .. ft_icon) or "" end diff --git a/lua/ui/tabline.lua b/lua/ui/tabline.lua new file mode 100644 index 0000000..09112a2 --- /dev/null +++ b/lua/ui/tabline.lua @@ -0,0 +1,126 @@ +require("base46").load_highlight "tbline" +local api = vim.api + +-- btn click functions +vim.cmd "function! TbGoToBuf(bufnr,b,c,d) \n execute 'b'..a:bufnr \n endfunction" + +vim.cmd [[ + function! TbKillBuf(bufnr,b,c,d) + call luaeval('require("core.utils").close_buffer(_A)', a:bufnr) + endfunction]] + +vim.cmd "function! TbNewTab(a,b,c,d) \n tabnew \n endfunction" +vim.cmd "function! TbGotoTab(tabnr,b,c,d) \n execute a:tabnr ..'tabnext' \n endfunction" +vim.cmd "function! TbTabClose(a,b,c,d) \n lua require('core.utils').tabuflineCloseTab() \n endfunction" +vim.cmd "function! TbToggle_theme(a,b,c,d) \n lua require('base46').toggle_theme() \n endfunction" +vim.cmd "function! TbToggleTabs(a,b,c,d) \n let g:TbTabsToggled = !g:TbTabsToggled | redrawtabline \n endfunction" + +local devicons_present, devicons = pcall(require, "nvim-web-devicons") +local fn = vim.fn +local new_cmd = api.nvim_create_user_command + +new_cmd("Tbufnext", function() + require("core.utils").tabuflineNext() +end, {}) + +new_cmd("Tbufprev", function() + require("core.utils").tabuflinePrev() +end, {}) + +new_cmd("Tbufclose", function() + require("core.utils").close_buffer() +end, {}) + +local function new_hl(group1, group2) + local fg = fn.synIDattr(fn.synIDtrans(fn.hlID(group1)), "fg#") + local bg = fn.synIDattr(fn.synIDtrans(fn.hlID(group2)), "bg#") + api.nvim_set_hl(0, "Tbline" .. group1 .. group2, { fg = fg, bg = bg }) + return "%#" .. "Tbline" .. group1 .. group2 .. "#" +end + +local function Offset() + for _, win in pairs(api.nvim_tabpage_list_wins(0)) do + if vim.bo[api.nvim_win_get_buf(win)].ft == "NvimTree" then + return "%#NvimTreeNormal#" .. string.rep(" ", api.nvim_win_get_width(win) + 1) + end + end +end + +local function add_fileInfo(name, bufnr) + if devicons_present then + local icon, icon_hl = devicons.get_icon(name, string.match(name, "%a+$")) + + if not icon then + icon, icon_hl = devicons.get_icon "default_icon" + end + + local fileInfo = " " .. icon .. " " .. name .. " " -- initial value + local pad = (24 - #fileInfo) / 2 + + icon = ( + api.nvim_get_current_buf() == bufnr and new_hl(icon_hl, "TbLineBufOn") .. " " .. icon + or new_hl(icon_hl, "TbLineBufOff") .. " " .. icon + ) + + name = (#name > 20 and string.sub(name, 1, 15) .. "...") or name + name = (api.nvim_get_current_buf() == bufnr and "%#TbLineBufOn# " .. name .. " ") + or ("%#TbLineBufOff# " .. name .. " ") + + return string.rep(" ", pad) .. icon .. name .. string.rep(" ", pad - 1) + end +end + +local function bufferlist() + local buffers = "" + + for _, nr in ipairs(vim.t.bufs or {}) do -- buf = bufnr + local name = (#api.nvim_buf_get_name(nr) ~= 0) and fn.fnamemodify(api.nvim_buf_get_name(nr), ":t") or " No Name " + local close_btn = "%" .. nr .. "@TbKillBuf@ %X" + name = "%" .. nr .. "@TbGoToBuf@" .. add_fileInfo(name, nr) .. "%X" + + -- color close btn for focused / hidden buffers + if nr == api.nvim_get_current_buf() then + close_btn = (vim.bo[0].modified and "%#TbLineBufOnModified# ") or ("%#TbLineBufOnClose#" .. close_btn) + name = "%#TbLineBufOn#" .. name .. close_btn + else + close_btn = (vim.bo[nr].modified and "%#TbBufLineBufOffModified# ") or ("%#TbLineBufOffClose#" .. close_btn) + name = "%#TbLineBufOff#" .. name .. close_btn + end + + buffers = buffers .. name + end + + return buffers .. "%#TblineFill#" .. "%=" -- buffers + empty space +end + +vim.g.TbTabsToggled = 0 + +local function tablist() + local result, number_of_tabs = "", fn.tabpagenr "$" + + if number_of_tabs > 1 then + for i = 1, number_of_tabs, 1 do + local tab_hl = ((i == fn.tabpagenr()) and "%#TbLineTabOn# ") or "%#TbLineTabOff# " + result = result .. ("%" .. i .. "@TbGotoTab@" .. tab_hl .. i .. " ") + result = (i == fn.tabpagenr() and result .. "%#TbLineTabCloseBtn#" .. "%@TbTabClose@ %X") or result + end + + local new_tabtn = "%#TblineTabNewBtn#" .. "%@TbNewTab@  %X" + local tabstoggleBtn = "%@TbToggleTabs@ %#TBTabTitle# TABS %X" + + result = (vim.g.TbTabsToggled == 1 and tabstoggleBtn:gsub("()", { [36] = " " })) + or new_tabtn .. tabstoggleBtn .. result + + return result + end +end + +local function buttons() + return "%@TbToggle_theme@%#TbLineThemeToggleBtn#" .. vim.g.toggle_theme_icon .. "%X" +end + +return { + run = function() + return (Offset() or "") .. bufferlist() .. (tablist() or "") .. buttons() + end, +}