Add options to the Tabs module to align it with the Buffers module (#920)

* Add a path option for tabs

Add get_props to align the module on Buffers.

* Add option to set the tab max size

Shorten dynamically the tab name to minimize its length when needed.

* Show modified status
This commit is contained in:
Anthony Ruhier 2023-10-17 11:37:24 +02:00 committed by GitHub
parent 45e27ca739
commit 5d85dc7858
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 92 additions and 17 deletions

View File

@ -679,6 +679,7 @@ sections = {
lualine_a = { lualine_a = {
{ {
'tabs', 'tabs',
tab_max_length = 40, -- Maximum width of each tab. The content will be shorten dynamically (example: apple/orange -> a/orange)
max_length = vim.o.columns / 3, -- Maximum width of tabs component. max_length = vim.o.columns / 3, -- Maximum width of tabs component.
-- Note: -- Note:
-- It can also be a function that returns -- It can also be a function that returns
@ -687,6 +688,11 @@ sections = {
-- 1: Shows tab_name -- 1: Shows tab_name
-- 2: Shows tab_nr + tab_name -- 2: Shows tab_nr + tab_name
path = 0, -- 0: just shows the filename
-- 1: shows the relative path and shorten $HOME to ~
-- 2: shows the full path
-- 3: shows the full path and shorten $HOME to ~
-- Automatically updates active tab color to match color of other components (will be overidden if buffers_color is set) -- Automatically updates active tab color to match color of other components (will be overidden if buffers_color is set)
use_mode_colors = false, use_mode_colors = false,
@ -696,6 +702,11 @@ sections = {
inactive = 'lualine_{section}_inactive', -- Color for inactive tab. inactive = 'lualine_{section}_inactive', -- Color for inactive tab.
}, },
show_modified_status = true, -- Shows a symbol next to the tab name if the file has been modified.
symbols = {
modified = '[+]', -- Text to show when the file is modified.
},
fmt = function(name, context) fmt = function(name, context)
-- Show + if buffer is modified in tab -- Show + if buffer is modified in tab
local buflist = vim.fn.tabpagebuflist(context.tabnr) local buflist = vim.fn.tabpagebuflist(context.tabnr)

View File

@ -7,12 +7,18 @@ local highlight = require('lualine.highlight')
local default_options = { local default_options = {
max_length = 0, max_length = 0,
tab_max_length = 40,
mode = 0, mode = 0,
use_mode_colors = false, use_mode_colors = false,
path = 0,
tabs_color = { tabs_color = {
active = nil, active = nil,
inactive = nil, inactive = nil,
}, },
show_modified_status = true,
symbols = {
modified = '[+]',
},
} }
-- This function is duplicated in buffers -- This function is duplicated in buffers

View File

@ -13,6 +13,27 @@ function Tab:init(opts)
self.tabId = opts.tabId self.tabId = opts.tabId
self.options = opts.options self.options = opts.options
self.highlights = opts.highlights self.highlights = opts.highlights
self.modified_icon = ''
self:get_props()
end
function Tab:get_props()
local buflist = vim.fn.tabpagebuflist(self.tabnr)
local winnr = vim.fn.tabpagewinnr(self.tabnr)
local bufnr = buflist[winnr]
self.file = modules.utils.stl_escape(vim.api.nvim_buf_get_name(bufnr))
self.filetype = vim.api.nvim_buf_get_option(bufnr, 'filetype')
self.buftype = vim.api.nvim_buf_get_option(bufnr, 'buftype')
if self.options.show_modified_status then
for _, b in ipairs(buflist) do
if vim.api.nvim_buf_get_option(b, 'modified') then
self.modified_icon = self.options.symbols.modified or ''
break
end
end
end
end end
---returns name for tab. Tabs name is the name of buffer in last active window ---returns name for tab. Tabs name is the name of buffer in last active window
@ -26,30 +47,61 @@ function Tab:label()
if custom_tabname and custom_tabname ~= '' then if custom_tabname and custom_tabname ~= '' then
return modules.utils.stl_escape(custom_tabname) return modules.utils.stl_escape(custom_tabname)
end end
local buflist = vim.fn.tabpagebuflist(self.tabnr) if self.filetype == 'fugitive' then
local winnr = vim.fn.tabpagewinnr(self.tabnr) return 'fugitive: ' .. vim.fn.fnamemodify(self.file, ':h:h:t')
local bufnr = buflist[winnr] elseif self.buftype == 'help' then
local file = modules.utils.stl_escape(vim.api.nvim_buf_get_name(bufnr)) return 'help:' .. vim.fn.fnamemodify(self.file, ':t:r')
local buftype = vim.fn.getbufvar(bufnr, '&buftype') elseif self.buftype == 'terminal' then
if vim.api.nvim_buf_get_option(bufnr, 'filetype') == 'fugitive' then local match = string.match(vim.split(self.file, ' ')[1], 'term:.*:(%a+)')
return 'fugitive: ' .. vim.fn.fnamemodify(file, ':h:h:t')
elseif buftype == 'help' then
return 'help:' .. vim.fn.fnamemodify(file, ':t:r')
elseif buftype == 'terminal' then
local match = string.match(vim.split(file, ' ')[1], 'term:.*:(%a+)')
return match ~= nil and match or vim.fn.fnamemodify(vim.env.SHELL, ':t') return match ~= nil and match or vim.fn.fnamemodify(vim.env.SHELL, ':t')
elseif vim.fn.isdirectory(file) == 1 then elseif self.file == '' then
return vim.fn.fnamemodify(file, ':p:.')
elseif file == '' then
return '[No Name]' return '[No Name]'
end end
return vim.fn.fnamemodify(file, ':t') if self.options.path == 1 then
return vim.fn.fnamemodify(self.file, ':~:.')
elseif self.options.path == 2 then
return vim.fn.fnamemodify(self.file, ':p')
elseif self.options.path == 3 then
return vim.fn.fnamemodify(self.file, ':p:~')
else
return vim.fn.fnamemodify(self.file, ':t')
end
end
---shortens path by turning apple/orange -> a/orange
---@param path string
---@param sep string path separator
---@param max_len integer maximum length of the full filename string
---@return string
local function shorten_path(path, sep, max_len)
local len = #path
if len <= max_len then
return path
end
local segments = vim.split(path, sep)
for idx = 1, #segments - 1 do
if len <= max_len then
break
end
local segment = segments[idx]
local shortened = segment:sub(1, vim.startswith(segment, '.') and 2 or 1)
segments[idx] = shortened
len = len - (#segment - #shortened)
end
return table.concat(segments, sep)
end end
---returns rendered tab ---returns rendered tab
---@return string ---@return string
function Tab:render() function Tab:render()
local name = self:label() local name = self:label()
if self.options.tab_max_length ~= 0 then
local path_separator = package.config:sub(1, 1)
name = shorten_path(name, path_separator, self.options.tab_max_length)
end
if self.options.fmt then if self.options.fmt then
name = self.options.fmt(name or '', self) name = self.options.fmt(name or '', self)
end end
@ -59,12 +111,18 @@ function Tab:render()
-- different formats for different modes -- different formats for different modes
if self.options.mode == 0 then if self.options.mode == 0 then
name = tostring(self.tabnr) name = tostring(self.tabnr)
if self.modified_icon ~= '' then
name = string.format('%s%s', name, self.modified_icon)
end
elseif self.options.mode == 1 then elseif self.options.mode == 1 then
name = name if self.modified_icon ~= '' then
name = string.format('%s %s', self.modified_icon, name)
end
else else
name = string.format('%s %s', tostring(self.tabnr), name) name = string.format('%s%s %s', tostring(self.tabnr), self.modified_icon, name)
end end
end end
name = Tab.apply_padding(name, self.options.padding) name = Tab.apply_padding(name, self.options.padding)
self.len = vim.fn.strchars(name) self.len = vim.fn.strchars(name)