1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
--
-- 50-highlight.lua
--
-- * Creates a function to adjust highlight groups for the solarized colorscheme. It also sets popup
-- menu width and border style.
-- * Creates a function that outputs a 'tabline' compatible strings that sets the tabline
-- format and style.
-- * Creates an autocommand to trigger these functions when the background or color scheme changes.
-- * Sets the default colorscheme (solarized) and background (dark).
--
-- User commands:
-- `ColorsBgToggle`: toggle light/dark background
-- `TabRename`: rename current tab
-- `TabRenameFileName`: rename current tab with current active buffer file name
--
local solarized = { blue = "#268bd2" }
-- Adjust highlights (for the solarized theme) to fit my personal tastes.
local function adjust_solarized_highlights()
-- Window bar style
vim.api.nvim_set_hl(0, "WinBarCwd", { fg = solarized.blue, italic = true })
vim.api.nvim_set_hl(0, "WinBarFilePath", { italic = true })
-- Matching delimiter
vim.api.nvim_set_hl(0, "MatchParen", { link = "CurSearch" })
-- Floating windows and popup menu windows follow the editor background, their borders too so
-- that the popup menu border draws a clean separation.
vim.opt.pumborder = "rounded"
vim.opt.pumwidth = 25 -- Minimum popup menu width
vim.api.nvim_set_hl(0, "NormalFloat", { link = "Normal" })
local normal_bg = vim.api.nvim_get_hl(0, { name = "Normal", link = false }).bg
vim.api.nvim_set_hl(0, "FloatBorder", { bg = normal_bg, update = true })
vim.api.nvim_set_hl(0, "Pmenu", { bg = normal_bg, update = true })
vim.api.nvim_set_hl(0, "PmenuSbar", { bg = normal_bg, update = true })
-- Currently selected tabpage
vim.api.nvim_set_hl(0, "TabLineSel", { bold = true, italic = true, update = true })
-- Todo hl group
vim.api.nvim_set_hl(0, "Todo", { bg = "Yellow", fg = "Black", bold = true })
-- Fold lines being the same color as the cursor line (default) make unfocused windows unreadable
-- Their background is set to blend in, the folds are visible enough with their dotted lines
vim.api.nvim_set_hl(0, "Folded", { bg = normal_bg, underline = true, update = true })
end
local function toggle_theme()
vim.opt.background = vim.o.background == "light" and "dark" or "light"
vim.notify("Color theme set to " .. vim.o.background)
end
-- Creates custom highlight groups for styling the tabpage title bars:
-- * TabLineWinCount: number of open windows in the tabpage
-- * TabLineSelWinCount: number of open windows in the currently active tabpage
local function create_tabpage_title_hl()
local normal = vim.api.nvim_get_hl(0, { name = "Normal", link = false })
local tabline = vim.api.nvim_get_hl(0, { name = "TabLine", link = false })
local tablinesel = vim.api.nvim_get_hl(0, { name = "TabLineSel", link = false })
vim.api.nvim_set_hl(0, "TabLineSel", { fg = normal.fg, update = true })
vim.api.nvim_set_hl(0, "TabLineWinCount", { fg = solarized.blue, bg = tabline.bg })
vim.api.nvim_set_hl(
0,
"TabLineSelWinCount",
{ fg = solarized.blue, bg = tablinesel.bg, bold = true }
)
end
-- Builds the window-count segment of a tabpage label, e.g. ` (2)[+] ` (no styling).
-- `is_modified` appends the `[+]` marker when any window in the tab has pending changes.
local function make_tab_info_label(win_count, is_modified)
local tab_win_count = "(" .. (win_count >= 10 and ">9" or tostring(win_count)) .. ")"
local tab_win_count_suffix = is_modified and "[+] " or " "
return " " .. tab_win_count .. tab_win_count_suffix
end
-- Builds the title segment of a tabpage label, padded or truncated to `width` (no styling).
-- Uses the tab's `tabname` if set, else the active buffer's file name, else `[No Name]`, prefixed
-- with `*` for the current tab and `-` for the last-accessed tab.
local function make_tab_label(id, is_current, width)
local is_last_accessed = vim.api.nvim_tabpage_get_number(id) == vim.fn.tabpagenr("#")
local tab_label_prefix = (is_current and "*" or "") .. (is_last_accessed and "-" or "")
local tab_label = vim.t[id].tabname
if tab_label == nil or tab_label == "" then
local win = vim.api.nvim_tabpage_get_win(id)
local bufname = vim.api.nvim_buf_get_name(vim.api.nvim_win_get_buf(win))
tab_label = vim.fn.fnamemodify(bufname, ":t")
end
if tab_label == "" then
tab_label = "[No Name]"
end
tab_label = tab_label_prefix .. tab_label
local display_width = vim.fn.strdisplaywidth(tab_label)
return (display_width > width)
and (vim.fn.strcharpart(tab_label, 0, width - 1) .. "…")
or (tab_label .. string.rep(" ", width - display_width))
end
-- Returns a string compatible with the 'tabline' option, used to set the tabline content and style.
-- Declared as a global function to be available as `v:lua.GetTabLine` in the Vimscript engine for
-- the 'tabline' option. See `:help 'statusline'`.
function GetTabLine()
local max_tab_label_width = 30
local s = ""
for _, id in pairs(vim.api.nvim_list_tabpages()) do
local is_current = id == vim.api.nvim_get_current_tabpage()
local is_modified = false
local wins = vim.api.nvim_tabpage_list_wins(id)
for _, win in ipairs(wins) do
if vim.bo[vim.api.nvim_win_get_buf(win)].modified then
is_modified = true
break
end
end
-- Define start of tabpage label (marks where clickage region begins)
s = s .. "%" .. vim.api.nvim_tabpage_get_number(id) .. "T"
local tab_info_label = make_tab_info_label(#wins, is_modified)
local tab_label_width = max_tab_label_width - vim.fn.strdisplaywidth(tab_info_label)
local tab_label = make_tab_label(id, is_current, tab_label_width)
s = s .. (is_current and "%#TabLineSelWinCount#" or "%#TabLineWinCount#") .. tab_info_label
s = s .. (is_current and "%#TabLineSel#" or "%#TabLine#") .. tab_label
end
return s .. "%#TabLineFill#"
end
local function rename_tab(opts)
vim.t.tabname = opts.args
vim.cmd.redrawtabline()
end
local function rename_tab_to_cur_filename()
vim.t.tabname = vim.fn.expand("%:t:r")
vim.cmd.redrawtabline()
end
-- Adjust highlights to fit my personal tastes.
local function adjust_highlights()
if vim.g.colors_name == "solarized" then
adjust_solarized_highlights()
end
create_tabpage_title_hl()
end
----------------------------------------------------------------------------------------------------
vim.api.nvim_create_autocmd("ColorScheme", {
desc = "Adjust custom highlights",
group = vim.g.dotfiles.augroup,
callback = adjust_highlights,
})
vim.api.nvim_create_autocmd("OptionSet", {
desc = "Adjust custom highlights on theme change",
pattern = "background",
group = vim.g.dotfiles.augroup,
callback = adjust_highlights,
})
vim.api.nvim_create_user_command(
"ColorsBgToggle",
toggle_theme,
{ desc = "Toggle light/dark theme" }
)
vim.api.nvim_create_user_command("TabRename", rename_tab, { nargs = 1 })
vim.api.nvim_create_user_command("TabRenameFileName", rename_tab_to_cur_filename, { nargs = 0 })
-- See `:help stl-%!`
vim.o.tabline = "%!v:lua.GetTabLine()"
vim.cmd.colorscheme("solarized")
vim.opt.background = "dark"
|