Skip to content

Statusline revamp - #45

Merged
nikero41 merged 22 commits into
mainfrom
statusline-revamp
Apr 9, 2026
Merged

Statusline revamp#45
nikero41 merged 22 commits into
mainfrom
statusline-revamp

Conversation

@nikero41

@nikero41 nikero41 commented Apr 6, 2026

Copy link
Copy Markdown
Owner

This pull request introduces significant improvements to the Neovim statusline and highlights system, focusing on modularity, maintainability, and visual clarity. The main changes include refactoring and enhancing the statusline logic, updating highlight groups for better theme integration, and simplifying the configuration of the lualine plugin.

Statusline and Highlight System Refactoring:

  • Refactored the statusline logic:

    • Removed the old Lualine class in lua/nikero/lualine.lua and introduced a new, more modular StatusLine class in lua/nikero/statusline.lua. The new class provides improved methods for dynamic icon highlighting and a new harpoon_widget for displaying file navigation marks. [1] [2]
    • Updated lualine configuration to use the new StatusLine:harpoon_widget and streamlined how project, branch, filetype, diff, and macro recording are displayed.
  • Enhanced highlight groups and theme integration:

    • Added new highlight groups (OverlayActive, OverlayActiveInverted) for statusline elements and documented highlight table types. [1] [2]
    • Adjusted the color palette for lualine's normal background to use mantle instead of base for better contrast.

Lualine Plugin Configuration Simplification:

  • Simplified separators and improved section arrangement:
    • Removed decorative section and component separators for a cleaner look.
    • Updated winbar and inactive winbar configurations to streamline filetype and filename display, using consistent separators and icon-only settings. [1] [2]

Other Notable UI/UX Improvements:

  • Enhanced color usage for statusline components (project, branch, diagnostics, progress, location) by leveraging the Catppuccin "mocha" palette for better visual integration.
  • Improved logic for displaying linting status and macro recording, ensuring accurate and visually distinct feedback.

These changes collectively modernize the statusline codebase, improve maintainability, and provide a more visually cohesive and informative user experience.

@coderabbitai

coderabbitai Bot commented Apr 6, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Replaces a small lualine helper with a new StatusLine module that builds per-icon highlight groups and renders a Harpoon widget; adds two Overlay statusline highlight groups; rewrites lualine configuration to embed the Harpoon widget and adjust separators/sections/colors; wires Harpoon events to refresh lualine.

Changes

Cohort / File(s) Summary
Highlight Definitions
lua/highlights.lua
Added explicit highlights type annotation and two new statusline highlight groups: OverlayActive (bg = colors.surface1) and OverlayActiveInverted (fg = colors.surface1), merged into final highlights.
Statusline Module Refactor
lua/nikero/lualine.lua, lua/nikero/statusline.lua
Removed lua/nikero/lualine.lua. Added lua/nikero/statusline.lua exporting StatusLine with statusline_icon_hl, harpoon_widget, harpoon_item, and wrap to derive per-(base,icon) highlight groups, query/set Neovim hl, and render a Harpoon statusline widget.
Lualine & Theme Config
lua/plugins/colorschemes.lua, lua/plugins/lualine.lua
Removed custom Catppuccin lualine override; converted lualine opts to a function that reads palette colors, cleared separators, reworked sections (moved many components into lualine_c/lualine_x), integrated nikero.statusline:harpoon_widget, and adjusted project/branch/diff/macro/progress/location components and winbar separators/colors.
Harpoon Integration
lua/plugins/harpoon.lua
Removed inline lualine refresh calls from Harpoon keymaps; added Harpoon extension callbacks (ADD, REMOVE, REORDER, POSITION_UPDATED, LIST_CHANGE) that call require("lualine").refresh().
Keymaps & Diagnostics tweaks
lua/keymaps.lua, lua/options.lua
Diagnostic navigation now uses vim.diagnostic.severity.* constants; vim.diagnostic.open_float now receives bufnr via options table. LSP rename mapping now emits a notification and calls vim.lsp.buf.rename with UI options.
Annotations / Diagnostics
lua/plugins/language/support.lua, lua/plugins/navigation.lua, lua/plugins/snacks/main.lua, lua/plugins/ui.lua
Added/simplified EmmyLua/module annotations and inserted LuaLS diagnostic suppression comments; no runtime behavior changes.

Sequence Diagram(s)

sequenceDiagram
    participant Lualine as Lualine Config
    participant StatusLine as StatusLine Module
    participant Harpoon as Harpoon API
    participant Icons as mini.icons
    participant Neovim as Neovim API
    participant Renderer as Renderer

    Lualine->>StatusLine: harpoon_widget(default_hl)
    StatusLine->>Neovim: get current buffer path
    StatusLine->>Harpoon: list()
    Harpoon-->>StatusLine: items[]

    loop per displayed item
        StatusLine->>Icons: get(file_path) → icon, icon_hl
        Icons-->>StatusLine: icon + icon_hl
        StatusLine->>Neovim: nvim_get_hl(name) / check existence
        alt derived hl exists
            Neovim-->>StatusLine: hl exists
        else create derived hl
            StatusLine->>Neovim: nvim_set_hl(name, {fg=icon_fg, bg=base_bg})
        end
        StatusLine->>StatusLine: wrap hl around icon/text
        StatusLine->>Renderer: append segment
    end

    StatusLine->>Renderer: return concatenated widget
    Renderer-->>Lualine: display widget
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Kickstart rewrite #40 — modifies statusline highlight generation and per-icon highlight logic; touches similar files (lua/highlights.lua, statusline helpers) and is strongly related.

Poem

🐇 I hop along the statusline bright,
New overlays glow in gentle light,
Harpoon icons gather, tidy and near,
Active ones shimmer so the way is clear,
A rabbit cheers — the UI feels right!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Statusline revamp' directly and clearly describes the main change—a comprehensive refactoring and enhancement of the statusline and highlights system.
Description check ✅ Passed The description is well-detailed and directly related to the changeset, covering the refactoring of statusline logic, highlight groups, lualine configuration, and UI/UX improvements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch statusline-revamp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nikero41

nikero41 commented Apr 6, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Apr 6, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Full review triggered.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
lua/plugins/lualine.lua (2)

66-67: TODO comment indicates incomplete work.

The -- TODO: comment suggests the color configuration may need refinement.

Would you like me to help address this TODO, or should I open an issue to track it?

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lua/plugins/lualine.lua` around lines 66 - 67, The TODO indicates an
unfinished color choice for lualine's component (the table entry setting color =
"SpecialChar"); remove the TODO and decide whether to keep "SpecialChar" or
replace it with a more appropriate highlight group or configurable option:
update the lualine component configuration in lua/plugins/lualine.lua (the table
containing color = "SpecialChar") to either (a) use a documented highlight group
name that matches your theme, (b) read the color from a plugin/theme setting or
a new config option, or (c) add a short clarifying comment explaining why
"SpecialChar" is intentionally used, then remove the TODO marker so the code no
longer signals incomplete work.

26-28: Consider extracting repeated palette lookups.

The require("catppuccin.palettes").get_palette("mocha") call is repeated in multiple color functions. While lualine likely caches these renders, extracting to a module-level variable would improve clarity.

♻️ Optional refactor
 ---@type LazySpec
 return {
 	{
 		"nvim-lualine/lualine.nvim",
 		lazy = false,
+		config = function(_, opts)
+			local mocha = require("catppuccin.palettes").get_palette("mocha")
+			-- Update color functions to use mocha variable
+			local lualine_require = require("lualine_require")
+			lualine_require.require = require
+			require("lualine").setup(opts)
+		end,

Alternatively, keep as-is since the current approach ensures palette is always fresh if colorscheme changes.

Also applies to: 34-36, 78-80, 93-95, 99-101

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lua/plugins/lualine.lua` around lines 26 - 28, Repeated calls to
require("catppuccin.palettes").get_palette("mocha") are used inside multiple
anonymous color = function() blocks; extract the palette once into a
module-level local (e.g., local mocha_palette =
require("catppuccin.palettes").get_palette("mocha")) and replace each repeated
call in the color functions with references like mocha_palette.blue /
mocha_palette.surface0 etc.; update all occurrences noted (the color =
function() blocks around the shown diff and at the commented ranges 34-36,
78-80, 93-95, 99-101) so the code reads the palette variable instead of calling
require/get_palette each time.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lua/nikero/statusline.lua`:
- Around line 5-17: In StatusLine:statusline_icon_hl, the existence check for
the highlight group is inverted: the local `icon = vim.api.nvim_get_hl(0, { name
= group, link = false })` should return early when the group already exists, not
when it's empty. Change the condition that currently tests `if icon ==
vim.empty_dict() then return group end` to return when `icon` is NOT empty
(e.g., `if icon ~= vim.empty_dict() then return group end`) so the function only
creates the group when it doesn't exist, leaving the rest of the logic in
`StatusLine:statusline_icon_hl` to compute and call `vim.api.nvim_set_hl` for
missing groups.

---

Nitpick comments:
In `@lua/plugins/lualine.lua`:
- Around line 66-67: The TODO indicates an unfinished color choice for lualine's
component (the table entry setting color = "SpecialChar"); remove the TODO and
decide whether to keep "SpecialChar" or replace it with a more appropriate
highlight group or configurable option: update the lualine component
configuration in lua/plugins/lualine.lua (the table containing color =
"SpecialChar") to either (a) use a documented highlight group name that matches
your theme, (b) read the color from a plugin/theme setting or a new config
option, or (c) add a short clarifying comment explaining why "SpecialChar" is
intentionally used, then remove the TODO marker so the code no longer signals
incomplete work.
- Around line 26-28: Repeated calls to
require("catppuccin.palettes").get_palette("mocha") are used inside multiple
anonymous color = function() blocks; extract the palette once into a
module-level local (e.g., local mocha_palette =
require("catppuccin.palettes").get_palette("mocha")) and replace each repeated
call in the color functions with references like mocha_palette.blue /
mocha_palette.surface0 etc.; update all occurrences noted (the color =
function() blocks around the shown diff and at the commented ranges 34-36,
78-80, 93-95, 99-101) so the code reads the palette variable instead of calling
require/get_palette each time.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7d75cc69-8f26-4359-a122-f1c04edb1d8c

📥 Commits

Reviewing files that changed from the base of the PR and between 2069457 and 5e32cd0.

📒 Files selected for processing (5)
  • lua/highlights.lua
  • lua/nikero/lualine.lua
  • lua/nikero/statusline.lua
  • lua/plugins/colorschemes.lua
  • lua/plugins/lualine.lua
💤 Files with no reviewable changes (1)
  • lua/nikero/lualine.lua

Comment thread lua/nikero/statusline.lua

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
lua/plugins/lualine.lua (1)

66-67: Incomplete TODO comment.

The -- TODO: comment on line 66 has no description. Either add the intended note or remove it if no longer needed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lua/plugins/lualine.lua` around lines 66 - 67, The TODO comment above the
lualine segment configuration is incomplete; either remove the bare "-- TODO:"
or replace it with a descriptive note explaining the intended change for this
segment (for example why color = "SpecialChar" is used or what needs to be
implemented). Locate the table entry containing color = "SpecialChar" in
lua/plugins/lualine.lua and update or remove the TODO so the comment clearly
documents the next action or is omitted if no action is required.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@lua/plugins/lualine.lua`:
- Around line 66-67: The TODO comment above the lualine segment configuration is
incomplete; either remove the bare "-- TODO:" or replace it with a descriptive
note explaining the intended change for this segment (for example why color =
"SpecialChar" is used or what needs to be implemented). Locate the table entry
containing color = "SpecialChar" in lua/plugins/lualine.lua and update or remove
the TODO so the comment clearly documents the next action or is omitted if no
action is required.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 23876691-10e1-4f72-ab4d-1ec08052e526

📥 Commits

Reviewing files that changed from the base of the PR and between 8409288 and 6804b44.

📒 Files selected for processing (1)
  • lua/plugins/lualine.lua

@nikero41

nikero41 commented Apr 7, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@nikero41

nikero41 commented Apr 7, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
lua/keymaps.lua (1)

209-219: Consider removing debug-style rename notification on Line [210].

vim.notify("🪚 ⭐") fires on every rename and can feel noisy in normal flow. The snacks-based rename config itself looks good.

🧹 Optional cleanup
 	function()
-		vim.notify("🪚 ⭐")
 		vim.lsp.buf.rename(nil, {
 			---@type snacks.input.Config
 			snacks = {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lua/keymaps.lua` around lines 209 - 219, Remove the debug notification that
fires on every rename: delete the vim.notify("🪚 ⭐") call inside the anonymous
function that wraps vim.lsp.buf.rename (the function containing the snacks
config), so the snacks-based rename behavior remains but no debug notification
is emitted.
lua/plugins/harpoon.lua (1)

73-77: Deduplicate repeated refresh callbacks.

Lines 73–77 repeat the same closure 5 times; extracting one local callback improves readability and reduces maintenance churn.

♻️ Proposed refactor
+		local refresh_lualine = function() require("lualine").refresh() end
+
 		harpoon:extend({
 			UI_CREATE = function(cx)
@@
-			ADD = function() require("lualine").refresh() end,
-			REMOVE = function() require("lualine").refresh() end,
-			REORDER = function() require("lualine").refresh() end,
-			POSITION_UPDATED = function() require("lualine").refresh() end,
-			LIST_CHANGE = function() require("lualine").refresh() end,
+			ADD = refresh_lualine,
+			REMOVE = refresh_lualine,
+			REORDER = refresh_lualine,
+			POSITION_UPDATED = refresh_lualine,
+			LIST_CHANGE = refresh_lualine,
 		})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lua/plugins/harpoon.lua` around lines 73 - 77, The repeated inline callbacks
for ADD, REMOVE, REORDER, POSITION_UPDATED, and LIST_CHANGE all call
require("lualine").refresh(); extract a single local callback (e.g., local
refresh = function() require("lualine").refresh() end) and replace each repeated
closure with that local symbol so the event table uses refresh for those keys;
update the table entries for ADD, REMOVE, REORDER, POSITION_UPDATED, and
LIST_CHANGE to reference refresh and remove the duplicated function literals.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lua/nikero/statusline.lua`:
- Around line 67-70: The overflow chevron logic may add a trailing ">" even when
there are no hidden items; update the trailing-marker condition to check actual
overflow instead of comparing start_index to `#items` - MAX_DISPLAYED_WIDGETS + 1.
Compute the visible end index as start_index + MAX_DISPLAYED_WIDGETS - 1 (or
equivalently check start_index + MAX_DISPLAYED_WIDGETS - 1 < `#items`) and only
call string.gsub on widgets to append ">" when that condition is true; keep the
leading-chev check (start_index ~= 1) as-is and reference start_index,
MAX_DISPLAYED_WIDGETS, items, widgets and string.gsub when making the change.
- Around line 51-57: active_index (result of vim.iter(ipairs(items)):find(...))
can be nil when current_file isn't present; guard it before numeric comparison
by treating nil as 0 or skipping the comparison. Update the logic around
start_index calculation (the block that checks `#items` > MAX_DISPLAYED_WIDGETS
and active_index >= MAX_DISPLAYED_WIDGETS - 1) to first coerce active_index to a
numeric value (e.g., local active_index_num = active_index or 0) or add an
explicit check (if active_index and active_index >= ...) so comparisons against
MAX_DISPLAYED_WIDGETS won't error when active_index is nil.

In `@lua/plugins/lualine.lua`:
- Around line 40-42: The lualine component is using the wrong gating key:
replace the unrecognized `condition` option with `cond` so the guard works; in
the component definition that returns
require("nikero.statusline"):harpoon_widget(...) and currently uses condition =
function() return `#require`("harpoon"):list().items ~= 0 end, change that key to
`cond` (retain the function body and the separator) so the component gating in
the lualine configuration (the harpoon_widget component) functions correctly.

---

Nitpick comments:
In `@lua/keymaps.lua`:
- Around line 209-219: Remove the debug notification that fires on every rename:
delete the vim.notify("🪚 ⭐") call inside the anonymous function that wraps
vim.lsp.buf.rename (the function containing the snacks config), so the
snacks-based rename behavior remains but no debug notification is emitted.

In `@lua/plugins/harpoon.lua`:
- Around line 73-77: The repeated inline callbacks for ADD, REMOVE, REORDER,
POSITION_UPDATED, and LIST_CHANGE all call require("lualine").refresh(); extract
a single local callback (e.g., local refresh = function()
require("lualine").refresh() end) and replace each repeated closure with that
local symbol so the event table uses refresh for those keys; update the table
entries for ADD, REMOVE, REORDER, POSITION_UPDATED, and LIST_CHANGE to reference
refresh and remove the duplicated function literals.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4a3df892-9bd2-4a48-a342-72a84c3a71c0

📥 Commits

Reviewing files that changed from the base of the PR and between 6804b44 and e7f56c1.

📒 Files selected for processing (10)
  • lua/keymaps.lua
  • lua/nikero/statusline.lua
  • lua/options.lua
  • lua/plugins/colorschemes.lua
  • lua/plugins/harpoon.lua
  • lua/plugins/language/support.lua
  • lua/plugins/lualine.lua
  • lua/plugins/navigation.lua
  • lua/plugins/snacks/main.lua
  • lua/plugins/ui.lua
💤 Files with no reviewable changes (1)
  • lua/plugins/colorschemes.lua
✅ Files skipped from review due to trivial changes (4)
  • lua/plugins/navigation.lua
  • lua/plugins/ui.lua
  • lua/plugins/language/support.lua
  • lua/plugins/snacks/main.lua

Comment thread lua/nikero/statusline.lua Outdated
Comment thread lua/nikero/statusline.lua
Comment thread lua/plugins/lualine.lua Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
lua/plugins/lualine.lua (1)

71-78: Consider caching get_running() to avoid duplicate calls.

The lint component calls require("lint").get_running() twice per render cycle—once in the function body and once in cond. While this is unlikely to cause noticeable performance issues, you could cache the result if desired.

♻️ Optional: Use a local cache pattern
-- Alternative approach using a wrapper function
local function lint_component()
	local linters = require("lint").get_running()
	if `#linters` == 0 then return nil end
	return require("icons").status.working .. "  " .. table.concat(linters, ", ")
end

-- Then use as component (lualine hides nil returns):
{ lint_component, color = { fg = colors.peach } },

Note: This changes behavior slightly—returning nil hides the component vs using cond. The current approach is also perfectly valid.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lua/plugins/lualine.lua` around lines 71 - 78, The lint component calls
require("lint").get_running() twice (once in the anonymous function and once in
cond); cache the result so you only call get_running() once per render by
replacing the table entry with a single wrapper that captures the linters local
and returns nil when empty (or use a named function like lint_component) so both
visibility and text use the same cached linters value; update the anonymous
function/cond pair (or replace them with lint_component and remove cond) to
reference that cached linters and keep color = { fg = colors.peach } unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@lua/plugins/lualine.lua`:
- Around line 71-78: The lint component calls require("lint").get_running()
twice (once in the anonymous function and once in cond); cache the result so you
only call get_running() once per render by replacing the table entry with a
single wrapper that captures the linters local and returns nil when empty (or
use a named function like lint_component) so both visibility and text use the
same cached linters value; update the anonymous function/cond pair (or replace
them with lint_component and remove cond) to reference that cached linters and
keep color = { fg = colors.peach } unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 87c67e6b-b3d7-415a-9112-189f88d42b45

📥 Commits

Reviewing files that changed from the base of the PR and between e7f56c1 and b9d3cb4.

📒 Files selected for processing (2)
  • lua/nikero/statusline.lua
  • lua/plugins/lualine.lua
🚧 Files skipped from review as they are similar to previous changes (1)
  • lua/nikero/statusline.lua

@nikero41
nikero41 merged commit 2c404ef into main Apr 9, 2026
3 checks passed
@nikero41
nikero41 deleted the statusline-revamp branch April 9, 2026 00:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant