# How Window Capture Functions Work in ThePrimeagen/99 for Prompt Input

> Explore how ThePrimeagen/99 uses window capture functions with Neovim autocmds for responsive prompt input. Learn about BufWriteCmd, WinClosed, and callback delivery via CR or q.

- Repository: [ThePrimeagen/99](https://github.com/theprimeagen/99)
- Tags: how-to-guide
- Published: 2026-02-16

---

**ThePrimeagen/99 implements prompt input through centered floating windows that use Neovim autocmds for `BufWriteCmd` and `WinClosed` to capture or cancel user text, delivering results via callbacks when users press `<CR>` or `q`.**

ThePrimeagen/99 is a Neovim plugin designed for AI-assisted development workflows that require dynamic user interaction. When the plugin needs to collect free-form text input—such as search queries, tutorial names, or visual mode ranges—it relies on specialized **window capture functions** that create temporary, focused interfaces. These functions manage the complete lifecycle from window geometry to input validation, all implemented in the [`lua/99/window/init.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/window/init.lua) module.

## Overview of the Window Capture Architecture

The window capture system follows a six-stage pipeline that transforms a simple callback into an interactive floating interface. Each stage handles specific responsibilities, from calculating screen geometry to processing lifecycle events.

The flow begins with `create_centered_window` calculating editor dimensions to position the window in the exact center of the screen. Next, `create_floating_window` instantiates a non-file buffer with `acwrite` type and displays it with a formatted title "99 *<name>*". The system then configures buffer options through `set_defaul_win_options`, disabling swapfiles and setting the filetype to `99`.

During the active phase, `highlight_rules_found` establishes autocmds on `InsertLeave` and `TextChanged` events to scan for rule keywords and highlight them with the `Search` group. Finally, lifecycle autocmds for `BufWriteCmd` and `WinClosed` handle acceptance and cancellation, while a `q` keymap provides immediate exit functionality.

## Core Window Creation and Configuration

### Centered Window Geometry

The `create_centered_window` function in [`lua/99/window/init.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/window/init.lua) (line 105) calculates the editor's current dimensions using `vim.api.nvim_list_uis()` and constructs a configuration table that positions the floating window at the visual center. This ensures the prompt appears exactly where the user expects it, regardless of screen size or split layout.

### Floating Buffer Setup

The `create_floating_window` function (line 140) creates a scratch buffer using `vim.api.nvim_create_buf(false, true)` with `acwrite` type, meaning it acts like a file buffer that triggers `BufWriteCmd` events but never writes to disk. The window opens with a formatted border title displaying "99 *<name>*" to indicate the prompt's purpose.

### Buffer Options and Filetype

The `set_defaul_win_options` function (line 70) configures the prompt buffer with security and usability settings. It sets the filetype to `99`, disables the swapfile to prevent disk I/O for temporary input, and establishes other window-local options that isolate the prompt from the user's regular editing environment.

## Input Handling and Lifecycle Management

### Accepting Input with BufWriteCmd

When the user completes their input and presses `<CR>` or executes `:w`, the `BufWriteCmd` autocmd (lines 82-92 in [`lua/99/window/init.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/window/init.lua)) triggers the acceptance callback. This handler collects all buffer lines using `vim.api.nvim_buf_get_lines`, concatenates them with newline characters, clears active popups via `M.clear_active_popups`, and invokes the supplied callback with `ok = true` and the resulting text.

### Cancelling with WinClosed and Keymaps

The system provides multiple escape routes for users who decide not to proceed. The `WinClosed` autocmd (lines 106-115) monitors the specific window ID and triggers when the floating window closes for any reason, calling `opts.cb(false, "")` to signal cancellation. Additionally, a buffer-local normal mode mapping binds `q` to immediately clear popups and abort with `ok = false`, providing intuitive vim-style exit behavior.

### Real-Time Rule Highlighting

The `highlight_rules_found` function establishes intelligent text analysis during user input. It creates autocmds for `InsertLeave` and `TextChanged` events that scan buffer content using `Agents.by_name` to identify rule keywords. When matches are found, the function applies the `Search` highlight group to those terms, giving users immediate visual feedback when they reference available rules or commands within their input text.

## Integration with the 99 Plugin

### The capture_prompt Wrapper

While [`lua/99/window/init.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/window/init.lua) contains the low-level window logic, most operations interact with the higher-level `capture_prompt` function defined in [`lua/99/init.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/init.lua) (lines 286-302). This wrapper simplifies the API by accepting a callback, prompt name, context object, and options, then forwarding these to `Window.capture_input` with appropriate defaults. The wrapper also handles the `on_load` hook that triggers `Extensions.setup_buffer` to configure LSP or Treesitter support for the prompt buffer.

### Operation Integration

The window capture system serves as the input foundation for various 99 operations. For example, [`lua/99/ops/search.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/ops/search.lua) invokes `capture_prompt` when building search queries, while tutorial selection and visual mode range specification use the same underlying mechanism. This unified approach ensures consistent UX across all interactive features, with each operation supplying its own callback to process the captured text according to specific business logic.

## Practical Usage Examples

### Direct Window Capture Usage

For plugin developers extending 99, the `Window.capture_input` API provides direct access to the prompt system:

```lua
local win = require("99.window")

win.capture_input("Custom Query", {
  cb = function(ok, text)
    if ok then
      vim.notify("Received: " .. text)
    else
      vim.notify("Cancelled", vim.log.levels.WARN)
    end
  end,
  rules = require("99.agents").default_rules,
})

```

This creates a centered floating window titled "99 Custom Query" with rule highlighting enabled.

### High-Level Operation Example

When implementing new 99 operations, use the `capture_prompt` wrapper for consistency:

```lua
local _99 = require("99")

local function my_operation(context)
  _99.capture_prompt(function(ok, input)
    if ok then
      -- Process the input
      print("Processing:", input)
    end
  end, "My Operation", context, {
    additional_prompt = nil,
  })
end

```

The wrapper automatically handles window cleanup and context preservation.

### Rule Highlighting Configuration

To enable real-time keyword highlighting in custom prompts:

```lua
local win = require("99.window")

win.capture_input("Task Entry", {
  cb = function(ok, text) end,
  rules = {
    custom = {
      { name = "URGENT" },
      { name = "REVIEW" },
      { name = "NOTE" },
    }
  },
})

```

Occurrences of "URGENT", "REVIEW", or "NOTE" will highlight automatically as the user types using the `Search` highlight group.

## Summary

- **ThePrimeagen/99** implements prompt input through a specialized window capture system located in [`lua/99/window/init.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/window/init.lua) that creates centered floating buffers with `acwrite` type.
- The **`capture_input`** function orchestrates window geometry, buffer configuration, and lifecycle management through Neovim's `BufWriteCmd` and `WinClosed` autocmds.
- User input is accepted via `<CR>` or `:w` commands, which trigger callbacks with `ok = true` and concatenated buffer text, while pressing `q` or closing the window signals cancellation with `ok = false`.
- Real-time **rule highlighting** scans buffer content during `InsertLeave` and `TextChanged` events, applying the `Search` highlight group to matched keywords via `Agents.by_name`.
- The **`capture_prompt`** wrapper in [`lua/99/init.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/init.lua) provides a high-level API that integrates the window system with 99's operation framework, supporting optional `on_load` hooks for LSP and Treesitter configuration.

## Frequently Asked Questions

### How does ThePrimeagen/99 handle user cancellation in window capture functions?

When a user decides to abort a prompt, the system provides multiple exit paths that all invoke the callback with `ok = false`. The `WinClosed` autocmd monitors the floating window ID and triggers if the window closes for any reason, while a buffer-local normal mode mapping binds `q` to immediately call `M.clear_active_popups()` and abort. Both mechanisms ensure the calling operation receives an empty string and a false status, allowing graceful handling of cancelled inputs.

### What is the difference between `capture_input` and `capture_prompt` in the 99 plugin?

`capture_input` is the low-level API defined in [`lua/99/window/init.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/window/init.lua) that directly manages window creation, buffer configuration with `acwrite` type, and autocmd registration. It accepts a name string and an options table containing the callback, rules, and optional `on_load` hook. In contrast, `capture_prompt` is a higher-level wrapper in [`lua/99/init.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/init.lua) (lines 286-302) that simplifies the interface for 99 operations by accepting context objects and automatically wiring the callback to the plugin's request pipeline. Most operations use `capture_prompt`, while extensions and custom integrations may call `capture_input` directly.

### How does real-time rule highlighting work in the prompt window?

The `highlight_rules_found` function establishes intelligent text analysis during user input by creating autocmds for `InsertLeave` and `TextChanged` events. When these events fire, the system scans buffer content using `Agents.by_name` to identify rule keywords. When matches are found, the function applies the `Search` highlight group to those terms, giving users immediate visual feedback when they reference available rules or commands within their input text. This highlighting occurs entirely within the floating buffer and does not modify the underlying text.

### Can I customize the window appearance or behavior when using `capture_input`?

While the core geometry and lifecycle management are handled internally to ensure consistency, you can customize several aspects through the options table passed to `capture_input`. The `rules` parameter allows you to enable and configure real-time keyword highlighting by passing a table of rule definitions that `Agents.by_name` will recognize. Additionally, the `on_load` callback lets you execute custom setup code after the window appears, such as configuring LSP support or Treesitter highlighting for the prompt buffer via `Extensions.setup_buffer`. However, fundamental window properties like the centered positioning and `acwrite` buffer type are fixed to ensure reliable behavior across the plugin.