Skip to content

Conversation

@assagman
Copy link
Owner

Summary

This PR refactors several modules in ghost.nvim to improve code organization and maintainability by extracting large functions into smaller, focused helper functions and replacing nested conditionals with dispatch tables.

Changes

  • context.lua: Extract buffer info collection into separate functions (safe_get_bufnr, get_buffer_info, get_cursor_info, get_selection_info)
  • health.lua: Break down health check logic into focused functions (check_nvim_version, check_config, check_backend_deps, etc.)
  • receiver.lua: Extract session update handlers into separate functions and use a dispatch table (update_handlers)
  • response.lua: Extract text processing logic into functions and use dispatch table for update handlers
  • status.lua: Extract status content building into smaller section builders
  • test.lua: Replace nested conditionals with dispatch table for update handling

Breaking Changes

None - this is a pure internal refactoring with no API changes.

Testing

  • Existing functionality preserved - no behavior changes
  • All refactored functions maintain same input/output contracts
  • Manual testing of ghost.nvim features: prompts, streaming responses, status display

Checklist

  • Code follows project style guidelines
  • No breaking changes introduced
  • Functionality preserved during refactoring
  • Tests added/updated and passing
  • Documentation updated
  • No new warnings generated

Reduce cyclomatic complexity across ghost modules by:
- Extracting small, focused helper functions from large monolithic functions
- Using dispatch tables for update type handling in receiver/response/test
- Breaking down context capture, health checks, and status building
- Removing luacheck ignore annotations no longer needed

Signed-off-by: assagman <ahmetsercansagman@gmail.com>
Copilot AI review requested due to automatic review settings January 20, 2026 09:21
@gemini-code-assist
Copy link

Summary of Changes

Hello @assagman, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors several core modules within ghost.nvim to enhance code organization and maintainability. The primary goal was to break down complex functions into smaller, more manageable helper functions and to replace cumbersome nested conditional statements with more elegant and extensible dispatch tables. These changes aim to make the codebase easier to understand, test, and extend in the future, without introducing any breaking changes to the plugin's existing functionality or API.

Highlights

  • Code Organization: Extracted large, monolithic functions into smaller, more focused helper functions across multiple modules to improve readability and maintainability.
  • Dispatch Tables: Replaced nested conditional logic (if/else if) with dispatch tables in receiver.lua, response.lua, and test.lua for handling various update types, leading to cleaner and more extensible code.
  • Modularity: The context.lua module now uses dedicated functions for safely retrieving buffer numbers, buffer information, cursor position, and visual selection details. The health.lua module's checks are now separated into distinct functions for Neovim version, configuration, backend dependencies, optional dependencies, and ACP connection status. The status.lua module's content building logic is broken down into individual section builders.
  • No Breaking Changes: This refactoring is purely internal, preserving existing functionality and maintaining the same input/output contracts, ensuring no impact on external API users.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This is an excellent refactoring that significantly improves the structure and maintainability of the codebase. Breaking down large functions into smaller, focused helpers in modules like context, health, response, and status makes the logic much easier to follow. The use of dispatch tables to replace long if/elseif chains in receiver, response, and test is a great pattern that enhances clarity and extensibility. The changes are well-executed and align perfectly with the goals stated in the PR description. I've left one minor suggestion in lua/ghost/test.lua to further reduce some code duplication, in line with the spirit of this refactoring.

Comment on lines 51 to 101
local function handle_test_update(update, output_lines)
local inner = update.update or update
local update_type = inner.sessionUpdate

local handlers = {
message_delta = function()
local content = inner.content
if content and type(content) == "table" then
for _, item in ipairs(content) do
if item.type == "text" and item.text then
io.write(item.text)
io.flush()
table.insert(output_lines, item.text)
end
end
end
end,
message = function()
local content = inner.content
if content and type(content) == "table" then
for _, item in ipairs(content) do
if item.type == "text" and item.text then
io.write(item.text)
io.flush()
table.insert(output_lines, item.text)
end
end
end
end,
tool_call = function()
print("\n[Tool: " .. (inner.title or "unknown") .. " (" .. (inner.kind or "?") .. ")]")
end,
tool_call_update = function()
local status = inner.status or "unknown"
print("[Tool update: " .. (inner.toolCallId or "?") .. " - " .. status .. "]")
end,
plan_update = function()
print("[Plan updated]")
end,
plan = function()
print("[Plan updated]")
end,
}

local handler = handlers[update_type]
if handler then
handler()
else
print("[Update: " .. vim.inspect(update):sub(1, 200) .. "]")
end
end

Choose a reason for hiding this comment

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

medium

This is a great refactoring to use a dispatch table. To further improve it and reduce code duplication, you can extract the shared logic for message_delta/message and plan_update/plan into separate helper functions. This makes the handlers table even cleaner and more declarative.

local function handle_test_update(update, output_lines)
  local inner = update.update or update
  local update_type = inner.sessionUpdate

  local function handle_text_message()
    local content = inner.content
    if content and type(content) == "table" then
      for _, item in ipairs(content) do
        if item.type == "text" and item.text then
          io.write(item.text)
          io.flush()
          table.insert(output_lines, item.text)
        end
      end
    end
  end

  local function handle_plan_update()
    print("[Plan updated]")
  end

  local handlers = {
    message_delta = handle_text_message,
    message = handle_text_message,
    tool_call = function()
      print("\n[Tool: " .. (inner.title or "unknown") .. " (" .. (inner.kind or "?") .. ")]")
    end,
    tool_call_update = function()
      local status = inner.status or "unknown"
      print("[Tool update: " .. (inner.toolCallId or "?") .. " - " .. status .. "]")
    end,
    plan_update = handle_plan_update,
    plan = handle_plan_update,
  }

  local handler = handlers[update_type]
  if handler then
    handler()
  else
    print("[Update: " .. vim.inspect(update):sub(1, 200) .. "]")
  end
end

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors multiple modules in ghost.nvim to improve code organization and maintainability by extracting large functions into smaller, focused helper functions and replacing nested conditionals with dispatch tables for better readability and extensibility.

Changes:

  • Extract complex conditional logic into dispatch tables for cleaner update handling
  • Break down large functions into smaller, single-purpose helper functions
  • Improve code organization while preserving all existing functionality

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
lua/ghost/test.lua Extracted handle_test_update function with dispatch table for update types
lua/ghost/status.lua Split build_status_content into focused section builder functions
lua/ghost/response.lua Extracted text processing logic and update handlers with dispatch table
lua/ghost/receiver.lua Refactored session update processing into separate handlers with dispatch table
lua/ghost/health.lua Broke down health check into focused functions for each check type
lua/ghost/context.lua Extracted buffer info, cursor, and selection gathering into helper functions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 55 to 78
local handlers = {
message_delta = function()
local content = inner.content
if content and type(content) == "table" then
for _, item in ipairs(content) do
if item.type == "text" and item.text then
io.write(item.text)
io.flush()
table.insert(output_lines, item.text)
end
end
end
end,
message = function()
local content = inner.content
if content and type(content) == "table" then
for _, item in ipairs(content) do
if item.type == "text" and item.text then
io.write(item.text)
io.flush()
table.insert(output_lines, item.text)
end
end
end
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

The handlers for message_delta and message contain identical logic. Consider extracting this into a single shared handler function to eliminate the duplication.

Suggested change
local handlers = {
message_delta = function()
local content = inner.content
if content and type(content) == "table" then
for _, item in ipairs(content) do
if item.type == "text" and item.text then
io.write(item.text)
io.flush()
table.insert(output_lines, item.text)
end
end
end
end,
message = function()
local content = inner.content
if content and type(content) == "table" then
for _, item in ipairs(content) do
if item.type == "text" and item.text then
io.write(item.text)
io.flush()
table.insert(output_lines, item.text)
end
end
end
local function handle_message_content()
local content = inner.content
if content and type(content) == "table" then
for _, item in ipairs(content) do
if item.type == "text" and item.text then
io.write(item.text)
io.flush()
table.insert(output_lines, item.text)
end
end
end
end
local handlers = {
message_delta = function()
handle_message_content()
end,
message = function()
handle_message_content()

Copilot uses AI. Check for mistakes.
Extract shared helper functions for message and plan handlers to eliminate duplication. This improves code maintainability and readability while keeping the dispatch table declarative.

Closes review threads #1 and #2 in PR #8

Signed-off-by: assagman <ahmetsercansagman@gmail.com>
@assagman
Copy link
Owner Author

Thanks for the review suggestions! I've addressed all the identified issues:

Changes Made

Deduplicated Handlers

  • Extracted handle_message_content() function (shared logic for message_delta and message)
  • Extracted handle_plan_update() function (shared logic for plan_update and plan)
  • Replaced duplicated inline functions with function calls

Impact: Reduced code from 29 to 20 lines (-9 lines)

Review Status

✅ All review threads resolved

Ready for re-review! 🎉

@gemini-code-assist
Copy link

Thanks for the update, @assagman! I appreciate you addressing the feedback and providing a clear summary of the changes. I will proceed with a re-review of the pull request.

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.

2 participants