feat: add windows component (#595)

Co-authored-by: shadmansaleh <13149513+shadmansaleh@users.noreply.github.com>
This commit is contained in:
Camille Dejoye 2022-03-26 14:31:40 +01:00 committed by GitHub
parent 4480d91e60
commit e9b935ccd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 305 additions and 32 deletions

View File

@ -241,6 +241,7 @@ sections = {lualine_a = {'mode'}}
- `mode` (vim mode) - `mode` (vim mode)
- `progress` (%progress in file) - `progress` (%progress in file)
- `tabs` (shows currently available tabs) - `tabs` (shows currently available tabs)
- `windows` (shows currently available windows)
#### Custom components #### Custom components
@ -597,6 +598,43 @@ sections = {
} }
``` ```
#### windows component options
```lua
sections = {
lualine_a = {
{
'windows',
show_filename_only = true, -- Shows shortened relative path when set to false.
show_modified_status = true, -- Shows indicator when the window is modified.
mode = 0, -- 0: Shows window name
-- 1: Shows window index (bufnr)
-- 2: Shows window name + window index (bufnr)
max_length = vim.o.columns * 2 / 3, -- Maximum width of windows component,
-- it can also be a function that returns
-- the value of `max_length` dynamically.
filetype_names = {
TelescopePrompt = 'Telescope',
dashboard = 'Dashboard',
packer = 'Packer',
fzf = 'FZF',
alpha = 'Alpha'
}, -- Shows specific window name for that filetype ( { `filetype` = `window_name`, ... } )
disabled_buftypes = { 'quickfix', 'prompt' }, -- Hide a window if its buffer's type is disabled
windows_color = {
-- Same values as the general color option can be used here.
active = 'lualine_{section}_normal', -- Color for active window.
inactive = 'lualine_{section}_inactive', -- Color for inactive window.
},
}
}
}
```
--- ---
### Tabline ### Tabline

View File

@ -240,6 +240,7 @@ CHANGING COMPONENTS IN LUALINE SECTIONS ~
- `mode` (vim mode) - `mode` (vim mode)
- `progress` (%progress in file) - `progress` (%progress in file)
- `tabs` (shows currently available tabs) - `tabs` (shows currently available tabs)
- `windows` (shows currently available windows)
*lualine-Custom-components* *lualine-Custom-components*
@ -621,6 +622,44 @@ Component specific options These are options that are available on
< <
*lualine-windows-component-options*
>
sections = {
lualine_a = {
{
'windows',
show_filename_only = true, -- Shows shortened relative path when set to false.
show_modified_status = true, -- Shows indicator when the window is modified.
mode = 0, -- 0: Shows window name
-- 1: Shows window index (bufnr)
-- 2: Shows window name + window index (bufnr)
max_length = vim.o.columns * 2 / 3, -- Maximum width of windows component,
-- it can also be a function that returns
-- the value of `max_length` dynamically.
filetype_names = {
TelescopePrompt = 'Telescope',
dashboard = 'Dashboard',
packer = 'Packer',
fzf = 'FZF',
alpha = 'Alpha'
}, -- Shows specific window name for that filetype ( { `filetype` = `window_name`, ... } )
disabled_buftypes = { 'quickfix', 'prompt' }, -- Hide a window if its buffer's type is disabled
windows_color = {
-- Same values as the general color option can be used here.
active = 'lualine_{section}_normal', -- Color for active window.
inactive = 'lualine_{section}_inactive', -- Color for inactive window.
},
}
}
}
<
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
TABLINE ~ TABLINE ~

View File

@ -277,8 +277,8 @@ local function set_statusline()
end end
-- lualine.statusline function -- lualine.statusline function
--- Draw correct statusline for current winwow --- Draw correct statusline for current window
---@param focused boolean : force the vale of is_focuased . useful for debugginf ---@param focused boolean : force the value of is_focused . useful for debugging
---@return string statusline string ---@return string statusline string
local function status_dispatch(focused) local function status_dispatch(focused)
local retval local retval

View File

@ -15,6 +15,10 @@ function Buffer:init(opts)
self:get_props() self:get_props()
end end
function Buffer:is_current()
return vim.api.nvim_get_current_buf() == self.bufnr
end
---setup icons, modified status for buffer ---setup icons, modified status for buffer
function Buffer:get_props() function Buffer:get_props()
self.file = modules.utils.stl_escape(vim.api.nvim_buf_get_name(self.bufnr)) self.file = modules.utils.stl_escape(vim.api.nvim_buf_get_name(self.bufnr))
@ -48,6 +52,13 @@ function Buffer:get_props()
end end
end end
---returns line configured for handling mouse click
---@param name string
---@return string
function Buffer:configure_mouse_click(name)
return string.format('%%%s@LualineSwitchBuffer@%s%%T', self.bufnr, name)
end
---returns rendered buffer ---returns rendered buffer
---@return string ---@return string
function Buffer:render() function Buffer:render()
@ -59,19 +70,13 @@ function Buffer:render()
if self.ellipse then -- show elipsis if self.ellipse then -- show elipsis
name = '...' name = '...'
else else
if self.options.mode == 0 then name = self:apply_mode(name)
name = string.format('%s%s%s', self.icon, name, self.modified_icon)
elseif self.options.mode == 1 then
name = string.format('%s %s%s', self.bufnr, self.icon, self.modified_icon)
else
name = string.format('%s %s%s%s', self.bufnr, self.icon, name, self.modified_icon)
end
end end
name = Buffer.apply_padding(name, self.options.padding) name = Buffer.apply_padding(name, self.options.padding)
self.len = vim.fn.strchars(name) self.len = vim.fn.strchars(name)
-- setup for mouse clicks -- setup for mouse clicks
local line = string.format('%%%s@LualineSwitchBuffer@%s%%T', self.bufnr, name) local line = self:configure_mouse_click(name)
-- apply highlight -- apply highlight
line = modules.highlight.component_format_highlight(self.highlights[(self.current and 'active' or 'inactive')]) line = modules.highlight.component_format_highlight(self.highlights[(self.current and 'active' or 'inactive')])
.. line .. line
@ -119,6 +124,9 @@ function Buffer:name()
elseif self.buftype == 'terminal' then elseif self.buftype == 'terminal' then
local match = string.match(vim.split(self.file, ' ')[1], 'term:.*:(%a+)') local match = string.match(vim.split(self.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 self.buftype == 'quickfix' then
local is_loclist = 0 ~= vim.fn.getloclist(0, { filewinid = 1 }).filewinid
return is_loclist and 'Location list' or 'Quickfix List'
elseif vim.fn.isdirectory(self.file) == 1 then elseif vim.fn.isdirectory(self.file) == 1 then
return vim.fn.fnamemodify(self.file, ':p:.') return vim.fn.fnamemodify(self.file, ':p:.')
elseif self.file == '' then elseif self.file == '' then
@ -139,4 +147,16 @@ function Buffer.apply_padding(str, padding)
return string.rep(' ', l_padding) .. str .. string.rep(' ', r_padding) return string.rep(' ', l_padding) .. str .. string.rep(' ', r_padding)
end end
function Buffer:apply_mode(name)
if self.options.mode == 0 then
return string.format('%s%s%s', self.icon, name, self.modified_icon)
end
if self.options.mode == 1 then
return string.format('%s %s%s', self.bufnr, self.icon, self.modified_icon)
end
return string.format('%s %s%s%s', self.bufnr, self.icon, name, self.modified_icon)
end
return Buffer return Buffer

View File

@ -48,6 +48,7 @@ function M:init(options)
inactive = get_hl('lualine_' .. options.self.section, false), inactive = get_hl('lualine_' .. options.self.section, false),
} }
self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options) self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options)
if self.options.component_name == 'buffers' then
self.highlights = { self.highlights = {
active = highlight.create_component_highlight_group( active = highlight.create_component_highlight_group(
self.options.buffers_color.active, self.options.buffers_color.active,
@ -63,16 +64,32 @@ function M:init(options)
), ),
} }
end end
end
function M:update_status() function M:new_buffer(bufnr)
local data = {} bufnr = bufnr or vim.api.nvim_get_current_buf()
return Buffer:new {
bufnr = bufnr,
options = self.options,
highlights = self.highlights,
}
end
function M:buffers()
local buffers = {} local buffers = {}
for b = 1, vim.fn.bufnr('$') do for b = 1, vim.fn.bufnr('$') do
if vim.fn.buflisted(b) ~= 0 and vim.api.nvim_buf_get_option(b, 'buftype') ~= 'quickfix' then if vim.fn.buflisted(b) ~= 0 and vim.api.nvim_buf_get_option(b, 'buftype') ~= 'quickfix' then
buffers[#buffers + 1] = Buffer { bufnr = b, options = self.options, highlights = self.highlights } buffers[#buffers + 1] = self:new_buffer(b)
end end
end end
local current_bufnr = vim.api.nvim_get_current_buf()
return buffers
end
function M:update_status()
local data = {}
local buffers = self:buffers()
local current = -2 local current = -2
-- mark the first, last, current, before current, after current buffers -- mark the first, last, current, before current, after current buffers
-- for rendering -- for rendering
@ -83,7 +100,7 @@ function M:update_status()
buffers[#buffers].last = true buffers[#buffers].last = true
end end
for i, buffer in ipairs(buffers) do for i, buffer in ipairs(buffers) do
if buffer.bufnr == current_bufnr then if buffer:is_current() then
buffer.current = true buffer.current = true
current = i current = i
end end
@ -112,7 +129,7 @@ function M:update_status()
-- start drawing from current buffer and draw left and right of it until -- start drawing from current buffer and draw left and right of it until
-- all buffers are drawn or max_length has been reached. -- all buffers are drawn or max_length has been reached.
if current == -2 then if current == -2 then
local b = Buffer { bufnr = vim.api.nvim_get_current_buf(), options = self.options, highlights = self.highlights } local b = self:new_buffer()
b.current = true b.current = true
if self.options.self.section < 'x' then if self.options.self.section < 'x' then
b.last = true b.last = true

View File

@ -0,0 +1,75 @@
local Window = require('lualine.components.windows.window')
local M = require('lualine.components.buffers'):extend()
local highlight = require('lualine.highlight')
local default_options = {
disabled_filetypes = {},
disabled_buftypes = { 'quickfix', 'prompt' },
}
function M:init(options)
options.buffers_color = nil -- bufers_color isn't windpws option.
M.super.init(self, options)
self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options)
self.options.windows_color = vim.tbl_deep_extend('keep', self.options.windows_color or {}, self.options.buffers_color)
self.options.buffers_color = nil -- this is the default value of colors generated by parent bufferes component.
self.highlights = {
active = highlight.create_component_highlight_group(
self.options.windows_color.active,
'windows_active',
self.options,
false
),
inactive = highlight.create_component_highlight_group(
self.options.windows_color.inactive,
'windows_inactive',
self.options,
false
),
}
end
function M:new_buffer(winnr)
winnr = winnr or vim.api.nvim_get_current_win()
return Window:new {
winnr = winnr,
options = self.options,
highlights = self.highlights,
}
end
--- Override to only return buffers shown in the windows of the current tab
function M:buffers()
local tabnr = vim.api.nvim_get_current_tabpage()
local buffers = {}
for _, winnr in ipairs(vim.api.nvim_tabpage_list_wins(tabnr)) do
if not self:should_hide(winnr) then
buffers[#buffers + 1] = self:new_buffer(winnr)
end
end
return buffers
end
function M:should_hide(winnr)
local bufnr = vim.api.nvim_win_get_buf(winnr)
local filetype = vim.api.nvim_buf_get_option(bufnr, 'filetype')
local buftype = vim.api.nvim_buf_get_option(bufnr, 'buftype')
local is_filetype_disabled = vim.tbl_contains(self.options.disabled_filetypes, filetype)
local is_buftype_disabled = vim.tbl_contains(self.options.disabled_buftypes, buftype)
local is_floating = '' ~= vim.api.nvim_win_get_config(winnr).relative
return is_floating or is_buftype_disabled or is_filetype_disabled
end
vim.cmd([[
function! LualineSwitchWindow(win_number, mouseclicks, mousebutton, modifiers)
execute a:win_number . 'wincmd w'
endfunction
]])
return M

View File

@ -0,0 +1,35 @@
local Window = require('lualine.components.buffers.buffer'):extend()
---intialize a new buffer from opts
---@param opts table
function Window:init(opts)
assert(opts.winnr, 'Cannot create Window without winnr')
opts.bufnr = vim.api.nvim_win_get_buf(opts.winnr)
Window.super.init(self, opts)
self.winnr = opts.winnr
self.win_number = vim.api.nvim_win_get_number(self.winnr)
end
function Window:is_current()
return vim.api.nvim_get_current_win() == self.winnr
end
function Window:apply_mode(name)
if self.options.mode == 0 then
return string.format('%s%s%s', self.icon, name, self.modified_icon)
end
if self.options.mode == 1 then
return string.format('%s %s%s', self.win_number, self.icon, self.modified_icon)
end
return string.format('%s %s%s%s', self.win_number, self.icon, name, self.modified_icon)
end
function Window:configure_mouse_click(name)
return string.format('%%%s@LualineSwitchWindow@%s%%T', self.win_number, name)
end
return Window

View File

@ -752,6 +752,55 @@ describe('Lualine', function()
]===]) ]===])
end) end)
end) end)
describe('windows component', function()
it('works', function()
local conf = vim.deepcopy(tab_conf)
conf.tabline.lualine_a = { { 'windows', max_length = 1e3, mode = 2, icons_enabled = false } }
vim.cmd('e ' .. 'a.txt')
vim.cmd('tabe ' .. 'b.txt')
vim.cmd('vsplit ' .. 'c.txt')
vim.cmd('tabe ' .. 'd.txt')
require('lualine').setup(conf)
require('lualine').statusline()
tabline:expect([===[
highlights = {
1: lualine_a_windows_active = { bg = "#a89984", bold = true, fg = "#282828" }
2: lualine_transitional_lualine_a_windows_active_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" }
3: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" }
}
|{1: 1 d.txt }
{2:}
{3: }|
]===])
vim.cmd('tabprev')
tabline:expect([===[
highlights = {
1: lualine_a_windows_active = { bg = "#a89984", bold = true, fg = "#282828" }
2: lualine_transitional_lualine_a_windows_active_to_lualine_a_windows_inactive = { bg = "#3c3836", fg = "#a89984" }
3: lualine_a_windows_inactive = { bg = "#3c3836", bold = true, fg = "#a89984" }
4: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" }
}
|{1: 1 c.txt }
{2:}
{3: 2 b.txt }
{4: }|
]===])
vim.cmd('tabprev')
tabline:expect([===[
highlights = {
1: lualine_a_windows_active = { bg = "#a89984", bold = true, fg = "#282828" }
2: lualine_transitional_lualine_a_windows_active_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" }
3: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" }
}
|{1: 1 a.txt }
{2:}
{3: }|
]===])
end)
end)
end) end)
describe('diagnostics', function() describe('diagnostics', function()