Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@aweis89
Copy link
Contributor

@aweis89 aweis89 commented Dec 27, 2025

Summary

  • Add ability to toggle (hide/show) the input window independently of the output window
  • Add new ui.input.dynamic config option that automatically hides the input window when focus moves to the output window or when a prompt is submitted

Motivation

When working with AI responses, the output window benefits from maximum screen real estate. The input window (especially when configured larger) takes up space that isn't needed while waiting for or reading responses. This feature allows the input window to stay out of the way until you're ready to type the next prompt.

Features

Toggle Input Window

  • New toggle_input API function and command (:Opencode toggle_input)
  • Default keymap: <M-i> (Alt+i) in both input and output windows
  • When hidden, the input window is completely closed (not just minimized) to give full space to the output
  • Input buffer content is preserved when hidden

Dynamic Input Mode (ui.input.dynamic = true by default)

  • When enabled, the input window automatically hides when:
    • Submitting a prompt (<cr>)
    • Focus moves to the output window (via any method - keymaps, mouse, <C-w> commands, etc.)
  • The input window automatically shows when focusing it via focus_input, open_input, or toggle_pane
  • When toggling the UI with dynamic mode enabled, no longer defaults to last focused window (always focuses input)

Bug Fixes

Auto-scroll preservation during dynamic input resize

When the input window hides/shows with dynamic = true, the output window resizes. This could incorrectly update viewport_at_bottom via the WinScrolled autocmd, breaking auto-scroll. Fixed by:

  • Capturing was_at_bottom state before hide/show
  • Scheduling scroll_to_bottom() after resize if previously at bottom

Tab keymap conflicts with completion plugins

  • Fix: Restricted the default <Tab> toggle focus mapping to only trigger in normal mode, preventing conflicts with auto-complete mappings that use <Tab> in insert mode

Test Fixes

Date formatting tests fail on year boundaries (CI)

Tests for util.format_time failed when run on year boundaries (e.g., Jan 1, 2026):

  • "formats yesterday" expected 31 Dec 09:46 PM but got 31 Dec 2025 09:46 PM (year included because Dec 31 is a different year than Jan 1)
  • "formats last week" had the same issue
  • "handles large millisecond timestamps" also failed due to year comparison

Fix: Made tests year-boundary-aware by checking if test dates fall in the same year as today before asserting the expected format pattern.

Files Changed

  • lua/opencode/api.lua - Add toggle_input, update submit_input_prompt, toggle
  • lua/opencode/config.lua - Add ui.input.dynamic option and keymaps
  • lua/opencode/ui/autocmds.lua - Prevent closing all windows during toggle
  • lua/opencode/ui/input_window.lua - Add toggle, _hide, _show, is_hidden functions; preserve scroll position
  • lua/opencode/ui/output_window.lua - Auto-hide input on focus when dynamic enabled
  • lua/opencode/ui/ui.lua - Handle hidden state in focus_input, simplify toggle_pane
  • tests/unit/util_spec.lua - Fix year-boundary-aware date formatting tests

- allow 'current' as a valid position option for UI placement
- update position handling in dimensions and window closing logic
- ensure compatibility with existing configurations
- introduce a new configurable system prompt to customize assistant behavior
- include guidance for file referencing to assist users with integration
- modifies message sending logic to incorporate the system prompt if set
- changes to reference detection streamline navigation for file-related responses
- Remove dead code referencing non-existent ref.context field
- Only show line number in display when present (avoid 'path:?')
…icons

- Parse file references when session becomes idle (AI done responding)
- Cache parsed references per-message for faster picker opening
- Handle session load from previous sessions
- Display reference icon before recognized file paths in output
- Subscribe to 'messages' state changes to parse loaded sessions
- Update test expected data files with new icon rendering
Remove legacy path:line and path-only pattern detection in favor of
exclusively parsing file:// URIs. This simplifies the code significantly
and avoids false positives from ambiguous path patterns.

The system prompt instructs the LLM to use file:// URIs, making the
legacy patterns unnecessary.
- refine explanation for system prompt usage in assistant responses
- emphasize file URI scheme for better navigation and tooling integration
- remove old system prompt setting in configuration
- replace it with a hardcoded prompt including URI format examples
- modifies behavior to improve navigation and tooling integration
- add support for line range format: file://path:start-end
- modify regex pattern to accommodate optional end line numbers
- update reference structure to include optional end_pos for highlighting
- enhance clarity in the instructions for referencing files
- emphasize the use of the file:// URI scheme as critical
- provide examples to illustrate correct and incorrect formats
- ensure compatibility with the existing reference picker for navigation
- improve reference location display by including line and column info
- handle cases where end position is available for better accuracy
- simplify display logic to ensure consistent output for references
- populate entry path, lnum, and col in telescope entries to support previewers
- enable file previewer configuration when options request file preview
- ensures code references can be previewed directly in the telescope picker UI
- update system prompt to explicitly require backticks around file:// URIs
- add examples distinguishing correct backticked format from incorrect ones
- ensures file references are consistently formatted for UI and parsing
- add key binding for timeline picker with `<leader>oT`
- include new key binding for browsing code references with `gr`
- clarify command usage for creating and selecting sessions
- touches(config): update default keyboard shortcuts for new features
Resolves conflicts in:
- lua/opencode/ui/highlight.lua: Added both OpencodeReference and OpencodeReasoningText highlights
- lua/opencode/ui/icons.lua: Added both reference and reasoning icons to nerdfonts preset, added reference to text preset
Icon characters changed in upstream, requiring test snapshot updates
Telescope supports highlighting line ranges in the file previewer using
the lnend field. Map end_pos[1] to lnend so that references with line
ranges (file://path:start-end) get highlighted in Telescope previewer.
The default file_previewer uses the 'cat' previewer which doesn't call
jump_to_line, so lnend field is ignored. Switch to vim_buffer_vimgrep
which properly highlights line ranges using the lnend field.
Add builtin previewer support to fzf-lua picker backend with automatic
line/column positioning for code references.

Changes:
- Enable 'builtin' previewer when preview='file'
- Append file:line:col: format to entries for fzf-lua parsing
- Update fn_fzf_index to strip position info before matching
- Supports navigation to specific lines (range highlighting shows start line only)

Implementation details:
- Uses tab separator between display text and file position
- fzf-lua's entry_to_file() automatically parses path:line:col: format
- Cursorline highlights the target line in preview
- Gracefully degrades when preview is disabled

Comparison with other pickers:
- Telescope: Full range highlighting (start-end lines)
- Snacks: Full range highlighting (start-end lines)
- fzf-lua: Single line highlighting (cursorline at start)
- Mini.pick: No file preview support
fzf-lua uses nbsp (U+2002 EN SPACE) as the standard separator between
display text and file path info, not tab. The builtin previewer parses
entries by splitting on utils.nbsp and extracting the path:line:col:
portion.

From fzf-lua/path.lua entry_to_file():
  local parts = utils.strsplit(entry, utils.nbsp)
  for i = 1, #parts - 1 do
    if s:match(".-:%d+:") then break end
    idx0 = idx0 + #s + #utils.nbsp
  end
  return entry:sub(idx0), idx0

Changes:
- Use nbsp (\xe2\x80\x82) instead of \t as separator
- Update fn_fzf_index to split by nbsp
- Use file_path (relative) before file (absolute) for correct resolution

This fixes 'Unable to stat file' errors in preview.
- implement toggle_input function to show/hide input window
- update key mappings for input window toggle: <leader>oa and <M-i>
- modify autocmd to prevent closing all windows during input toggle
- enhance input_window module to manage visibility and state tracking
- show input window if hidden in open_input and focus_input functions
- add submit_and_hide_input to handle submission and hide input window
- ensures smoother user experience by managing input window visibility
- implement dynamic input behavior, focusing on input when enabled
- auto-hide input window when navigating away if dynamic input is active
- revision of input displaying logic for cleaner state management
- update config to include dynamic input setting

Closes sudo-tee#123
- remove unnecessary promise handling in toggle_pane method
- directly call ui.toggle_pane for improved clarity and performance
- auto-hide input window when prompt is submitted or focus switches
- enhances user experience by reducing screen clutter
- change input toggle from `<leader>oa` to `<M-i>`
- improves ease of access by using a different key combination
@aweis89 aweis89 marked this pull request as draft December 27, 2025 06:53
- make input_window.handle_submit return true if a message was sent
- conditionally hide input window only if a message was sent and dynamic input is enabled
- prevent hiding the input window when viewing slash command outputs like /help
- adjusts behavior of input window in various contextual situations
- restrict toggle pane key mapping for output and input windows to 'n'
- improves input handling by focusing on normal mode usage only
@aweis89 aweis89 marked this pull request as ready for review December 27, 2025 17:45
- add checks to track if the output window was at the bottom
- if previously at bottom, scroll to bottom after showing the input window
- change test messages for better clarity
- modify date format checks to include year where necessary
- enhance tests to handle different date outputs based on the year context
@aweis89
Copy link
Contributor Author

aweis89 commented Jan 1, 2026

@sudo-tee curious to hear if you had any thoughts on this if you had a chance to try it out.

  • Perhaps dynamic = true should not be the default?
  • It is more inline with the way the TUI works, where the input window is hiddent during model output I believe
  • The main advantage for me is having a larger input window without having to compromise on output window size
  • Hitting i from the output window, to get the input window (in insert mode) has been perferable to a static input window in my experience but curious if you have reservations

@sudo-tee
Copy link
Owner

sudo-tee commented Jan 1, 2026

I didn't had time to look at it yet. Been busy with the holidays and family. But I will look at it pretty soon

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