Repository: nvim-lualine/lualine.nvim
Pull request #971 (2023-02-16 12:24:16)

Fix dynamic coloring of tabline/winbar components
I noticed that the color of the buffers component wasn't changing with the other components in my lualine setup as I changed modes:<br>
![lua-tabs-before](https://user-images.githubusercontent.com/38540736/219361911-b8b72e35-eaa1-4504-b571-b165b16a5766.PNG)

I attempted to use a function to change the color based on mode, but encountered this visual issue where only part of the background of the active buffer changed:<br>
![lualine-before-with-fn](https://user-images.githubusercontent.com/38540736/219362010-246749b1-8fb8-4910-8ee3-3f2951d956df.PNG)

I fixed that issue in highlight.lua, and added a `get_mode_suffix` function to simplify retrieving the mode suffix from outside of the highlight module.

I also added a `use_mode_colors` option to the buffers, tabs, and windows components (false by default), which automatically sets the colors of those components. 

How it looks now:<br>
![lualine-after](https://user-images.githubusercontent.com/38540736/219363468-37d326ff-42c5-49c2-a5ee-bb0e427c961e.PNG)



Patch:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7d9d37e..53857ff 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -29,7 +29,7 @@ Good luck!
 *Let's introduce you to the tools we use.*
 
 - Your PR needs to pass tests & linter. We lint our codebase with [luacheck](https://github.com/mpeterv/luacheck)
-  and run tests with [plenary-test][plenary.nvim] these will be ran on CI. If you want you can run tests & linter
+  and run tests with [plenary-test][plenary.nvim] these will be run on CI. If you want you can run tests & linter
   locally with `make test` & `make lint` respectively. Or `make check` to run both linter & tests. For running
   tests you'll have to make sure lualine.nvim, [plenary.nvim][plenary.nvim] and
   [nvim-web-devicons](https://github.com/kyazdani42/nvim-web-devicons) are in same directory.
diff --git a/README.md b/README.md
index c96c301..280fc9e 100644
--- a/README.md
+++ b/README.md
@@ -73,7 +73,7 @@ Last Updated On: 18-04-2022
 ```vim
 Plug 'nvim-lualine/lualine.nvim'
 " If you want to have icons in your statusline choose one of these
-Plug 'kyazdani42/nvim-web-devicons'
+Plug 'nvim-tree/nvim-web-devicons'
 ```
 
 ### [packer.nvim](https://github.com/wbthomason/packer.nvim)
@@ -81,7 +81,7 @@ Plug 'kyazdani42/nvim-web-devicons'
 ```lua
 use {
   'nvim-lualine/lualine.nvim',
-  requires = { 'kyazdani42/nvim-web-devicons', opt = true }
+  requires = { 'nvim-tree/nvim-web-devicons', opt = true }
 }
 ```
 
@@ -419,6 +419,9 @@ sections = {
 
       cond = nil,           -- Condition function, the component is loaded when the function returns `true`.
 
+      draw_empty = false,   -- Whether to draw component even if it's empty.
+                            -- Might be useful if you want just the separator.
+
       -- Defines a custom color for the component:
       --
       -- 'highlight_group_name' | { fg = '#rrggbb'|cterm_value(0-255)|'color_name(red)', bg= '#rrggbb', gui='style' } | function
@@ -470,7 +473,7 @@ sections = {
 #### Component specific options
 
 These are options that are available on specific components.
-For example you have option on `diagnostics` component to
+For example, you have option on `diagnostics` component to
 specify what your diagnostic sources will be.
 
 #### buffers component options
@@ -501,6 +504,9 @@ sections = {
         alpha = 'Alpha'
       }, -- Shows specific buffer name for that filetype ( { `filetype` = `buffer_name`, ... } )
 
+      -- Automatically updates active buffer color to match color of other components (will be overidden if buffers_color is set)
+      use_mode_colors = false,
+
       buffers_color = {
         -- Same values as the general color option can be used here.
         active = 'lualine_{section}_normal',     -- Color for active buffer.
@@ -635,6 +641,20 @@ sections = {
 }
 ```
 
+#### datetime component options
+
+```lua
+sections = {
+  lualine_a = {
+    {
+      'datetime',
+      -- options: default, us, uk, iso, or your own format string ("%H:%M", etc..)
+      style = 'default'
+    }
+  }
+}
+```
+
 #### tabs component options
 
 ```lua
@@ -650,6 +670,9 @@ sections = {
                 -- 1: Shows tab_name
                 -- 2: Shows tab_nr + tab_name
 
+      -- Automatically updates active tab color to match color of other components (will be overidden if buffers_color is set)
+      use_mode_colors = false,
+
       tabs_color = {
         -- Same values as the general color option can be used here.
         active = 'lualine_{section}_normal',     -- Color for active tab.
@@ -697,6 +720,9 @@ sections = {
 
       disabled_buftypes = { 'quickfix', 'prompt' }, -- Hide a window if its buffer's type is disabled
 
+      -- Automatically updates active window color to match color of other components (will be overidden if buffers_color is set)
+      use_mode_colors = false,
+
       windows_color = {
         -- Same values as the general color option can be used here.
         active = 'lualine_{section}_normal',     -- Color for active window.
@@ -849,6 +875,7 @@ extensions = {'quickfix'}
 - nerdtree
 - nvim-dap-ui
 - nvim-tree
+- overseer
 - quickfix
 - symbols-outline
 - toggleterm
@@ -867,7 +894,7 @@ require('lualine').setup { extensions = { my_extension } }
 ### Refreshing lualine
 By default lualine refreshes itself based on timer and some events. You can set
 the interval of the timer with refresh option. However you can also force
-lualine to refresh at any time by calling lualine.refresh function.
+lualine to refresh at any time by calling `lualine.refresh` function.
 ```lua
 require('lualine').refresh({
   scope = 'tabpage',  -- scope of refresh all/tabpage/window
@@ -882,7 +909,7 @@ So you can simply do
 require('lualine').refresh()
 ```
 
-Avoid calling lualine.refresh inside components. Since components are evaluated
+Avoid calling `lualine.refresh` inside components. Since components are evaluated
 during refresh, calling refresh while refreshing can have undesirable effects.
 
 ### Disabling lualine
diff --git a/THEMES.md b/THEMES.md
index 6aba355..184bfc7 100644
--- a/THEMES.md
+++ b/THEMES.md
@@ -54,7 +54,7 @@ But if `g:ayuprefermirage` exists, it will load ayu_mirage instead when
 
 ### base16
 
-This theme will automatically uses colors defined by your colorscheme using [RRethy/nvim-base16](https://github.com/RRethy/nvim-base16)] plugin.
+This theme will automatically use colors defined by your colorscheme using [RRethy/nvim-base16](https://github.com/RRethy/nvim-base16)] plugin.
 The following example is using the `tomorrow-night` colorscheme:
 
 <p>
diff --git a/doc/lualine.txt b/doc/lualine.txt
index d36d808..1f6e82f 100644
--- a/doc/lualine.txt
+++ b/doc/lualine.txt
@@ -53,7 +53,7 @@ VIM-PLUG <HTTPS://GITHUB.COM/JUNEGUNN/VIM-PLUG> ~
 >
     Plug 'nvim-lualine/lualine.nvim'
     " If you want to have icons in your statusline choose one of these
-    Plug 'kyazdani42/nvim-web-devicons'
+    Plug 'nvim-tree/nvim-web-devicons'
 <
 
 
@@ -62,7 +62,7 @@ PACKER.NVIM <HTTPS://GITHUB.COM/WBTHOMASON/PACKER.NVIM> ~
 >
     use {
       'nvim-lualine/lualine.nvim',
-      requires = { 'kyazdani42/nvim-web-devicons', opt = true }
+      requires = { 'nvim-tree/nvim-web-devicons', opt = true }
     }
 <
 
@@ -432,6 +432,9 @@ General component options              These are options that control behavior
     
           cond = nil,           -- Condition function, the component is loaded when the function returns `true`.
     
+          draw_empty = false,   -- Whether to draw component even if it's empty.
+                                -- Might be useful if you want just the separator.
+    
           -- Defines a custom color for the component:
           --
           -- 'highlight_group_name' | { fg = '#rrggbb'|cterm_value(0-255)|'color_name(red)', bg= '#rrggbb', gui='style' } | function
@@ -484,7 +487,7 @@ General component options              These are options that control behavior
                                           *lualine-Component-specific-options*
 
 Component specific options             These are options that are available on
-                                       specific components. For example you
+                                       specific components. For example, you
                                        have option on `diagnostics` component
                                        to specify what your diagnostic sources
                                        will be.
@@ -658,6 +661,21 @@ Component specific options             These are options that are available on
 <
 
 
+                                          *lualine-datetime-component-options*
+
+>
+    sections = {
+      lualine_a = {
+        {
+          'datetime',
+          -- options: default, us, uk, iso, or your own format string ("%H:%M", etc..)
+          style = 'default'
+        }
+      }
+    }
+<
+
+
                                               *lualine-tabs-component-options*
 
 >
@@ -900,6 +918,7 @@ extensions with:
 - nerdtree
 - nvim-dap-ui
 - nvim-tree
+- overseer
 - quickfix
 - symbols-outline
 - toggleterm
@@ -924,7 +943,7 @@ REFRESHING LUALINE ~
 
 By default lualine refreshes itself based on timer and some events. You can set
 the interval of the timer with refresh option. However you can also force
-lualine to refresh at any time by calling lualine.refresh function.
+lualine to refresh at any time by calling `lualine.refresh` function.
 
 >
     require('lualine').refresh({
@@ -944,8 +963,9 @@ So you can simply do
 <
 
 
-Avoid calling lualine.refresh inside components. Since components are evaluated
-during refresh, calling refresh while refreshing can have undesirable effects.
+Avoid calling `lualine.refresh` inside components. Since components are
+evaluated during refresh, calling refresh while refreshing can have undesirable
+effects.
 
 DISABLING LUALINE ~
 
diff --git a/examples/evil_lualine.lua b/examples/evil_lualine.lua
index a5be3da..2515520 100644
--- a/examples/evil_lualine.lua
+++ b/examples/evil_lualine.lua
@@ -73,7 +73,7 @@ local function ins_left(component)
   table.insert(config.sections.lualine_c, component)
 end
 
--- Inserts a component in lualine_x ot right section
+-- Inserts a component in lualine_x at right section
 local function ins_right(component)
   table.insert(config.sections.lualine_x, component)
 end
diff --git a/lua/lualine.lua b/lua/lualine.lua
index 435547f..2a87dd7 100644
--- a/lua/lualine.lua
+++ b/lua/lualine.lua
@@ -358,7 +358,7 @@ local function refresh(opts)
   local wins = {}
   local old_actual_curwin = vim.g.actual_curwin
 
-  -- ignore focus on filetypes listes in options.ignore_focus
+  -- ignore focus on filetypes listed in options.ignore_focus
   local curwin = vim.api.nvim_get_current_win()
   local curtab = vim.api.nvim_get_current_tabpage()
   if last_focus[curtab] == nil or not vim.api.nvim_win_is_valid(last_focus[curtab]) then
diff --git a/lua/lualine/component.lua b/lua/lualine/component.lua
index a4d9d9b..17610da 100644
--- a/lua/lualine/component.lua
+++ b/lua/lualine/component.lua
@@ -201,7 +201,7 @@ function M:apply_section_separators()
   end
 end
 
----Add on click funtion description to already drawn item
+---Add on click function description to already drawn item
 function M:apply_on_click()
   if self.on_click_id then
     self.status = self:format_fn(self.on_click_id, self.status)
@@ -274,7 +274,7 @@ function M:draw(default_highlight, is_focused)
   if self.options.fmt then
     status = self.options.fmt(status or '', self)
   end
-  if type(status) == 'string' and #status > 0 then
+  if type(status) == 'string' and (#status > 0 or self.options.draw_empty) then
     self.status = status
     self:apply_icon()
     self:apply_padding()
diff --git a/lua/lualine/components/buffers/init.lua b/lua/lualine/components/buffers/init.lua
index 4a5eb03..880f2a8 100644
--- a/lua/lualine/components/buffers/init.lua
+++ b/lua/lualine/components/buffers/init.lua
@@ -18,6 +18,7 @@ local default_options = {
     fzf = 'FZF',
     alpha = 'Alpha',
   },
+  use_mode_colors = false,
   buffers_color = {
     active = nil,
     inactive = nil,
@@ -35,7 +36,7 @@ local default_options = {
 ---@param is_active boolean
 ---@return string hl name
 local function get_hl(section, is_active)
-  local suffix = is_active and '_normal' or '_inactive'
+  local suffix = is_active and highlight.get_mode_suffix() or '_inactive'
   local section_redirects = {
     lualine_x = 'lualine_c',
     lualine_y = 'lualine_b',
@@ -49,8 +50,12 @@ end
 
 function M:init(options)
   M.super.init(self, options)
+  -- if use_mode_colors is set, use a function so that the colors update
+  local default_active = options.use_mode_colors and
+      function() return get_hl('lualine_' .. options.self.section, true) end
+      or get_hl('lualine_' .. options.self.section, true)
   default_options.buffers_color = {
-    active = get_hl('lualine_' .. options.self.section, true),
+    active = default_active,
     inactive = get_hl('lualine_' .. options.self.section, false),
   }
   self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options)
diff --git a/lua/lualine/components/datetime.lua b/lua/lualine/components/datetime.lua
new file mode 100644
index 0000000..d1c702e
--- /dev/null
+++ b/lua/lualine/components/datetime.lua
@@ -0,0 +1,31 @@
+-- Copyright (c) 2023 Willothy
+-- MIT license, see LICENSE for more details.
+local lualine_require = require('lualine_require')
+local M = lualine_require.require('lualine.component'):extend()
+
+local default_options = {
+  -- default, us, uk, iso, or format (ex. "%d/%m/%Y ...")
+  style = 'default',
+}
+
+function M:init(options)
+  M.super.init(self, options)
+  self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options)
+end
+
+function M:update_status()
+  local fmt = self.options.style
+  if self.options.style == 'default' then
+    fmt = '%A, %B %d | %H:%M'
+  elseif self.options.style == 'us' then
+    fmt = '%m/%d/%Y'
+  elseif self.options.style == 'uk' then
+    fmt = '%d/%m/%Y'
+  elseif self.options.style == 'iso' then
+    fmt = '%Y-%m-%d'
+  end
+
+  return os.date(fmt)
+end
+
+return M
diff --git a/lua/lualine/components/diff/git_diff.lua b/lua/lualine/components/diff/git_diff.lua
index 6879001..a460f8f 100644
--- a/lua/lualine/components/diff/git_diff.lua
+++ b/lua/lualine/components/diff/git_diff.lua
@@ -84,7 +84,7 @@ end
 
 ---updates the job args
 function M.update_diff_args()
-  -- Donn't show git diff when current buffer doesn't have a filename
+  -- Don't show git diff when current buffer doesn't have a filename
   active_bufnr = tostring(vim.api.nvim_get_current_buf())
   if #vim.fn.expand('%') == 0 then
     M.diff_args = nil
@@ -121,7 +121,7 @@ function M.update_diff_args()
   M.update_git_diff()
 end
 
----update git_diff veriable
+---update git_diff variable
 function M.update_git_diff()
   if M.diff_args then
     diff_output_cache = {}
diff --git a/lua/lualine/components/progress.lua b/lua/lualine/components/progress.lua
index 5611fbe..c4891fe 100644
--- a/lua/lualine/components/progress.lua
+++ b/lua/lualine/components/progress.lua
@@ -8,7 +8,7 @@ local function progress()
   elseif cur == total then
     return 'Bot'
   else
-    return math.floor(cur / total * 100) .. '%%'
+    return string.format('%2d%%%%', math.floor(cur / total * 100))
   end
 end
 
diff --git a/lua/lualine/components/tabs/init.lua b/lua/lualine/components/tabs/init.lua
index c99b7d3..e25c179 100644
--- a/lua/lualine/components/tabs/init.lua
+++ b/lua/lualine/components/tabs/init.lua
@@ -8,6 +8,7 @@ local highlight = require('lualine.highlight')
 local default_options = {
   max_length = 0,
   mode = 0,
+  use_mode_colors = false,
   tabs_color = {
     active = nil,
     inactive = nil,
@@ -20,7 +21,7 @@ local default_options = {
 ---@param is_active boolean
 ---@return string hl name
 local function get_hl(section, is_active)
-  local suffix = is_active and '_normal' or '_inactive'
+  local suffix = is_active and highlight.get_mode_suffix() or '_inactive'
   local section_redirects = {
     lualine_x = 'lualine_c',
     lualine_y = 'lualine_b',
@@ -34,15 +35,19 @@ end
 
 function M:init(options)
   M.super.init(self, options)
+  -- if use_mode_colors is set, use a function so that the colors update
+  local default_active = options.use_mode_colors and
+      function() return get_hl('lualine_' .. options.self.section, true) end
+      or get_hl('lualine_' .. options.self.section, true)
   default_options.tabs_color = {
-    active = get_hl('lualine_' .. options.self.section, true),
+    active = default_active,
     inactive = get_hl('lualine_' .. options.self.section, false),
   }
   self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options)
   -- stylua: ignore
   self.highlights = {
-    active = self:create_hl( self.options.tabs_color.active, 'active'),
-    inactive = self:create_hl( self.options.tabs_color.inactive, 'inactive'),
+    active = self:create_hl(self.options.tabs_color.active, 'active'),
+    inactive = self:create_hl(self.options.tabs_color.inactive, 'inactive'),
   }
 end
 
diff --git a/lua/lualine/highlight.lua b/lua/lualine/highlight.lua
index f297d8b..22cea7e 100644
--- a/lua/lualine/highlight.lua
+++ b/lua/lualine/highlight.lua
@@ -34,6 +34,13 @@ local mode_to_highlight = {
   ['TERMINAL'] = '_terminal',
 }
 
+--- Get highlight suffix for current mode, or inactive if not focused
+---@return string mode_suffix
+function M.get_mode_suffix()
+  local mode = require('lualine.utils.mode').get_mode()
+  return mode_to_highlight[mode] or '_normal'
+end
+
 --- determine if an highlight exist and isn't cleared
 ---@param highlight_name string
 ---@return boolean whether hl_group was defined with highlight_name
@@ -183,7 +190,7 @@ function M.highlight(name, foreground, background, gui, link)
   }
 end
 
----Attach a hl to another, so the attachee auto updates on change to hl that it's attached too.
+---Attach a hl to another, so the attached auto updates on change to hl that it's attached too.
 ---@param provider string the hl receiver is getting attached to
 ---@param receiver string the hl that will be auto updated upon change to provider
 ---@param provider_el_type string (fg/bg) what element receiver relates to of provider
@@ -222,8 +229,7 @@ local function append_mode(highlight_group, is_focused)
   if is_focused == false then
     return highlight_group .. '_inactive'
   end
-  local mode = require('lualine.utils.mode').get_mode()
-  return highlight_group .. (mode_to_highlight[mode] or '_normal')
+  return highlight_group .. M.get_mode_suffix()
 end
 
 -- Helper function for create component highlight
@@ -328,7 +334,7 @@ function M.create_component_highlight_group(color, highlight_tag, options, apply
   end
 
   if type(color) ~= 'function' and (apply_no_default or (color.bg and color.fg)) then
-    -- When bg and fg are both present we donn't need to set highlighs for
+    -- When bg and fg are both present we don't need to set highlights for
     -- each mode as they will surely look the same. So we can work without options
     local highlight_group_name = table.concat({ 'lualine', section, highlight_tag }, '_')
     M.highlight(highlight_group_name, color.fg, color.bg, color.gui, nil)
@@ -392,13 +398,13 @@ function M.component_format_highlight(highlight, is_focused)
     local color = highlight.fn { section = highlight.section } or {}
     local hl_name = highlight.name
     if type(color) == 'string' then
-      M.highlight(hl_name, nil, nil, nil, color)
-      return '%#' .. hl_name .. '#'
+      M.highlight(hl_name .. M.get_mode_suffix(), nil, nil, nil, color)
+      return '%#' .. hl_name .. M.get_mode_suffix() .. '#'
     elseif type(color) == 'table' then
       if not highlight.no_default and not (color.fg and color.bg) then
         hl_name = append_mode(highlight.name, is_focused)
         color =
-          get_default_component_color(hl_name, append_mode(''):sub(2), highlight.section, color, highlight.options)
+          get_default_component_color(hl_name, M.get_mode_suffix():sub(2), highlight.section, color, highlight.options)
       end
       M.highlight(hl_name, color.fg, color.bg, color.gui, color.link)
       return '%#' .. hl_name .. '#', color
diff --git a/lua/lualine/themes/auto.lua b/lua/lualine/themes/auto.lua
index 9f2339d..fe106bd 100644
--- a/lua/lualine/themes/auto.lua
+++ b/lua/lualine/themes/auto.lua
@@ -70,11 +70,11 @@ local function clamp(val, left, right)
 end
 
 -- Changes brightness of rgb_color by percentage
-local function brightness_modifier(rgb_color, parcentage)
+local function brightness_modifier(rgb_color, percentage)
   local color = rgb_str2num(rgb_color)
-  color.red = clamp(color.red + (color.red * parcentage / 100), 0, 255)
-  color.green = clamp(color.green + (color.green * parcentage / 100), 0, 255)
-  color.blue = clamp(color.blue + (color.blue * parcentage / 100), 0, 255)
+  color.red = clamp(color.red + (color.red * percentage / 100), 0, 255)
+  color.green = clamp(color.green + (color.green * percentage / 100), 0, 255)
+  color.blue = clamp(color.blue + (color.blue * percentage / 100), 0, 255)
   return rgb_num2str(color)
 end
 
@@ -90,19 +90,17 @@ end
 -- Changes brightness of foreground color to achieve contrast
 -- without changing the color
 local function apply_contrast(highlight)
-  local hightlight_bg_avg = get_color_avg(highlight.bg)
+  local highlight_bg_avg = get_color_avg(highlight.bg)
   local contrast_threshold_config = clamp(contrast_threshold, 0, 0.5)
-  local contranst_change_step = 5
-  if hightlight_bg_avg > 0.5 then
-    contranst_change_step = -contranst_change_step
+  local contrast_change_step = 5
+  if highlight_bg_avg > 0.5 then
+    contrast_change_step = -contrast_change_step
   end
 
   -- Don't waste too much time here max 25 iteration should be more than enough
   local iteration_count = 1
-  while
-    math.abs(get_color_avg(highlight.fg) - hightlight_bg_avg) < contrast_threshold_config and iteration_count < 25
-  do
-    highlight.fg = contrast_modifier(highlight.fg, contranst_change_step)
+  while math.abs(get_color_avg(highlight.fg) - highlight_bg_avg) < contrast_threshold_config and iteration_count < 25 do
+    highlight.fg = contrast_modifier(highlight.fg, contrast_change_step)
     iteration_count = iteration_count + 1
   end
 end
diff --git a/lua/lualine/themes/powerline.lua b/lua/lualine/themes/powerline.lua
index 145a321..5bb354a 100644
--- a/lua/lualine/themes/powerline.lua
+++ b/lua/lualine/themes/powerline.lua
@@ -19,7 +19,7 @@ local Colors = {
   gray10         = '#f0f0f0',
 }
 
-return {
+local M = {
   normal = {
     a = { fg = Colors.darkestgreen, bg = Colors.brightgreen, gui = 'bold' },
     b = { fg = Colors.gray10, bg = Colors.gray5 },
@@ -38,3 +38,7 @@ return {
     c = { bg = Colors.gray1, fg = Colors.gray5 },
   },
 }
+
+M.terminal = M.insert
+
+return M
diff --git a/lua/lualine/themes/powerline_dark.lua b/lua/lualine/themes/powerline_dark.lua
index 1a8225a..e992212 100644
--- a/lua/lualine/themes/powerline_dark.lua
+++ b/lua/lualine/themes/powerline_dark.lua
@@ -22,7 +22,7 @@ local colors = {
   cyan         = '#00DFFF',
 }
 
-return {
+local M = {
   normal = {
     a = { bg = colors.neon, fg = colors.black, gui = 'bold' },
     b = { bg = colors.gray, fg = colors.white },
@@ -54,3 +54,7 @@ return {
     c = { bg = colors.darkgray, fg = colors.gray },
   },
 }
+
+M.terminal = M.insert
+
+return M
diff --git a/lua/lualine/utils/fn_store.lua b/lua/lualine/utils/fn_store.lua
index 8bceeef..a3b59ae 100644
--- a/lua/lualine/utils/fn_store.lua
+++ b/lua/lualine/utils/fn_store.lua
@@ -15,7 +15,7 @@ function M.register_fn(id, fn)
 end
 
 ---Get the function with id
----@param id number id of the fn to retrive
+---@param id number id of the fn to retrieve
 ---@return function
 function M.get_fn(id)
   vim.validate { id = { id, 'n' } }
diff --git a/lua/lualine/utils/loader.lua b/lua/lualine/utils/loader.lua
index 3eba13b..37baa01 100644
--- a/lua/lualine/utils/loader.lua
+++ b/lua/lualine/utils/loader.lua
@@ -243,7 +243,7 @@ local function load_theme(theme_name)
     end
     if not file_found then
       -- This shouldn't happen but somehow we have multiple files but they
-      -- apear to be in lualines repo . Just run the first one
+      -- appear to be in lualines repo . Just run the first one
       retval = dofile(files[1])
     end
   end
diff --git a/lua/lualine/utils/section.lua b/lua/lualine/utils/section.lua
index a288f10..1521a02 100644
--- a/lua/lualine/utils/section.lua
+++ b/lua/lualine/utils/section.lua
@@ -12,7 +12,7 @@ local highlight = require('lualine.highlight')
 ---@param section table list of components
 ---@param section_name string used for getting proper hl
 ---@param is_focused boolean
----@return string formated string for a section
+---@return string formatted string for a section
 --TODO Clean this up this does lots of messy stuff.
 function M.draw_section(section, section_name, is_focused)
   local highlight_name = highlight.format_highlight(section_name, is_focused)
@@ -21,7 +21,7 @@ function M.draw_section(section, section_name, is_focused)
   for _, component in pairs(section) do
     -- load components into status table
     if type(component) ~= 'table' or (type(component) == 'table' and not component.component_no) then
-      return '' -- unknown element in section. section posibly not yet loaded
+      return '' -- unknown element in section. section possibly not yet loaded
     end
     table.insert(status, component:draw(highlight_name, is_focused))
   end
@@ -81,14 +81,14 @@ function M.draw_section(section, section_name, is_focused)
     end
   end
 
-  local left_sparator_string = ''
+  local left_separator_string = ''
   if
     section_name > 'x'
     and section[first_component_no]
     and type(section[first_component_no].options.separator) ~= 'table'
     and (section[1].options.section_separators.right ~= nil and section[1].options.section_separators.right ~= '')
   then
-    left_sparator_string = string.format(
+    left_separator_string = string.format(
       '%%s{%s}',
       section[first_component_no].options.ls_separator or section[1].options.section_separators.right
     )
@@ -107,17 +107,17 @@ function M.draw_section(section, section_name, is_focused)
   local find_start_trans_sep_start, find_start_trans_sep_end = status_str:find('^%%s{.-}')
   if find_start_trans_sep_start then
     -- the section doesn't need to be prepended with default hl when sections
-    -- first component has trasitionals sep
+    -- first component has transitional sep
     needs_hl = status_str:find('^%%#', find_start_trans_sep_end + 1)
   else
     needs_hl = status_str:find('^%%#')
   end
 
   if needs_hl then
-    -- Don't prepend with old highlight when the component changes it imidiately
-    return left_sparator_string .. status_str
+    -- Don't prepend with old highlight when the component changes it immediately
+    return left_separator_string .. status_str
   else
-    return left_sparator_string .. highlight_name .. status_str
+    return left_separator_string .. highlight_name .. status_str
   end
 end
 
diff --git a/lua/lualine/utils/utils.lua b/lua/lualine/utils/utils.lua
index 2f74c3e..143d041 100644
--- a/lua/lualine/utils/utils.lua
+++ b/lua/lualine/utils/utils.lua
@@ -191,13 +191,13 @@ function M.stl_escape(str)
   return str:gsub('%%', '%%%%')
 end
 
----A safe call inside a timmer
+---A safe call inside a timer
 ---@param timer userdata
 ---@param augroup string|nil autocmd group to reset too on error.
 ---@param fn function
 ---@param max_err integer
 ---@param err_msg string
----@return function a wraped fn that can be called inside a timer and that
+---@return function a wrapped fn that can be called inside a timer and that
 ---stops the timer after max_err errors in calling fn
 function M.timer_call(timer, augroup, fn, max_err, err_msg)
   local err_cnt, ret = 0, nil
diff --git a/lua/lualine_require.lua b/lua/lualine_require.lua
index f315728..968e9af 100644
--- a/lua/lualine_require.lua
+++ b/lua/lualine_require.lua
@@ -16,7 +16,7 @@ if source:sub(1, 1) == '@' then
   end
 end
 
---- checks if name is valied
+--- checks if name is valid
 ---@param name string
 ---@return boolean
 function M.is_valid_filename(name)


Test patch:
diff --git a/tests/helpers.lua b/tests/helpers.lua
index f76a3e4..204cc2f 100644
--- a/tests/helpers.lua
+++ b/tests/helpers.lua
@@ -35,7 +35,7 @@ M.assert_component = function(component, opts, result, is_active)
   eq(result, comp:draw(opts.hl, is_active or true))
 end
 
-function M.assert_component_instence(comp, result)
+function M.assert_component_instance(comp, result)
   eq(result, comp:draw(comp.options.hl))
 end
 -- sets defaults for component options
diff --git a/tests/spec/component_spec.lua b/tests/spec/component_spec.lua
index b5dad63..c193109 100644
--- a/tests/spec/component_spec.lua
+++ b/tests/spec/component_spec.lua
@@ -211,6 +211,19 @@ describe('Component:', function()
       assert.stub(hl.component_format_highlight).was_called_with(comp2.options.color_highlight)
       hl.component_format_highlight:revert()
     end)
+
+    it('draw_empty', function()
+      local opts = build_component_opts {
+        component_separators = { left = '', right = '' },
+        padding = 0,
+        separator = '>',
+        fmt = function()
+          return ''
+        end,
+        draw_empty = true,
+      }
+      assert_component(nil, opts, '>')
+    end)
   end)
 end)
 
@@ -757,7 +770,7 @@ describe('Branch component', function()
       "git -c user.name='asdf' -c user.email='asdf@jlk.org' -C " .. tmpdir .. ' ' .. string.format(...)
     )
   end
-  local assert_comp_ins = helpers.assert_component_instence
+  local assert_comp_ins = helpers.assert_component_instance
 
   before_each(function()
     tmpdir = os.tmpname()
diff --git a/tests/spec/config_spec.lua b/tests/spec/config_spec.lua
index 71d29a0..ba7532a 100644
--- a/tests/spec/config_spec.lua
+++ b/tests/spec/config_spec.lua
@@ -73,7 +73,7 @@ describe('config parsing', function()
           eq(config.options.section_separators, { left = 'b', right = 'a' })
         end)
       end)
-      it('no seprarators', function()
+      it('no separators', function()
         local config = {
           options = { component_separators = {}, section_separators = {} },
         }
diff --git a/tests/spec/lualine_spec.lua b/tests/spec/lualine_spec.lua
index 6ba5d5f..47854ea 100644
--- a/tests/spec/lualine_spec.lua
+++ b/tests/spec/lualine_spec.lua
@@ -26,7 +26,7 @@ describe('Lualine', function()
           statusline = 1000,
           tabline = 1000,
           winbar = 1000,
-        }
+        },
       },
       sections = {
         lualine_a = { 'mode' },
@@ -102,7 +102,7 @@ describe('Lualine', function()
     ]===])
   end)
 
-  it('get_config can retrive config', function()
+  it('get_config can retrieve config', function()
     eq(config, require('lualine').get_config())
   end)
 
@@ -207,7 +207,7 @@ describe('Lualine', function()
     ]===])
   end)
 
-  it('mid divider can be disbled on special case', function()
+  it('mid divider can be disabled on special case', function()
     config.options.always_divide_middle = false
     config.sections.lualine_x = {}
     config.sections.lualine_y = {}
diff --git a/tests/spec/utils_spec.lua b/tests/spec/utils_spec.lua
index cc44d07..30654b7 100644
--- a/tests/spec/utils_spec.lua
+++ b/tests/spec/utils_spec.lua
@@ -10,7 +10,7 @@ local stub = require('luassert.stub')
 describe('Utils', function()
   local utils = require('lualine.utils.utils')
 
-  it('can retrive highlight groups', function()
+  it('can retrieve highlight groups', function()
     local hl2 = { fg = '#aabbcc', bg = '#889977', sp = '#997788', reverse = true, undercurl = true }
     -- handles non existing hl groups
     eq(utils.extract_highlight_colors('hl2'), nil)
@@ -79,7 +79,7 @@ describe('Utils', function()
   end)
 end)
 
-describe('Cterm genarator', function()
+describe('Cterm generator', function()
   local cterm = require('lualine.utils.color_utils')
 
   it('can convert rgb to cterm', function()
@@ -90,7 +90,7 @@ describe('Cterm genarator', function()
   end)
 end)
 
-describe('Section genarator', function()
+describe('Section generator', function()
   local hl = require('lualine.highlight')
   stub(hl, 'format_highlight')
   hl.format_highlight.returns('%#lualine_c_normal#')
diff --git a/tests/statusline.lua b/tests/statusline.lua
index 0dac80d..96d1ee4 100644
--- a/tests/statusline.lua
+++ b/tests/statusline.lua
@@ -42,7 +42,7 @@
 ---]===])
 --- ```
 ---
---- For more flexibility you can match a patten in expect block.
+--- For more flexibility you can match a pattern in expect block.
 --- ``lua
 --- statusline:expect([===[
 ---    highlights = {