- Add 37 new tests covering the drag source side of the DND protocol
- Test drag offer registration/unregistration (t=o, t=O)
- Test drag MIME type offering with various operations (copy/move/both)
- Test pre-sent data for valid/invalid indices, chunked data, multiple MIMEs
- Test image thumbnails: valid RGBA/RGB, invalid formats, dimensions, chunking
- Test drag start failures (no window, no offer, image size mismatches)
- Test drag cancellation from client (t=E:y=-1)
- Test offer replacement, cleanup, and error propagation
- Test client_id propagation for drag operations
- Test resource cleanup on window close during drag build
- Fix double-free in drag_free_built_data: set ds.items=NULL after free
- Add drag_free_offer to destroy_fake_window_contents for proper cleanup
Agent-Logs-Url: https://github.com/kovidgoyal/kitty/sessions/f9868553-29a2-48c4-85c2-b6b8f686dccc
Co-authored-by: kovidgoyal <1308621+kovidgoyal@users.noreply.github.com>
Users who define action_alias or kitten_alias in kitty.conf had no way
to discover or trigger these custom commands from the command palette.
Aliased keybindings were miscategorized (landing in "Miscellaneous"
with no help text), and combine bindings had the same problem.
Changes:
- Resolve aliases via opts.alias_map to get correct action names,
categories, and help text for aliased keybindings
- Add dedicated "Action aliases" and "Kitten aliases" sections that
list all user-defined aliases, with bound aliases showing their key
and unbound aliases browsable as unmapped entries
- Add a "Combined actions" section for combine keybindings
- Make alias names searchable in the Go TUI so users can find
bindings by typing the alias name
- Fix action column highlight positions to match the scored text,
preventing visual corruption when searching for alias names
Also refactors collect_keys_data into focused single-responsibility
functions and reduces nesting depth across both Python and Go.
Add --allow-fallback option to the map command that controls shifted
and ascii (alternate_key) fallback for individual key mappings.
For non-Latin keyboard layouts, when the current layout key is
non-ascii (codepoint > 127 and < 0xE000), the alternate_key from
the base layout is used for matching if the mapping opts in via
--allow-fallback=shifted,ascii.
Default kitty bindings use --allow-fallback=shifted,ascii so they
work out of the box with non-Latin layouts. User custom mappings
default to --allow-fallback=shifted (preserving existing shifted_key
behavior without ascii fallback).
--allow-fallback=none disables all fallback for a mapping.
Python side: parse_options_for_map() in options/utils.py handles flag
parsing, ShortcutMapping uses it in __init__. get_shortcut() filters
candidates by per-mapping allow_fallback.
Go side: ParseMap() handles --allow-fallback, KeyAction stores
AllowFallback, ShortcutTracker.Match passes it to matching.
MatchesParsedShortcut defaults to shifted,ascii for hardcoded shortcuts.
Migrated kittens (themes, command_palette, diff, choose_files) to
use ShortcutTracker with configurable map entries.
Tests added for Python (5 test methods) and Go (ParseMap + key matching).
The RC approach sent actions targeting the overlay window itself rather
than the underlying window. Switch to the standard kitten output pattern:
the Go kitten outputs the selected action definition via
KittenOutputSerializer, and handle_result in Python calls boss.combine()
with the correct target window after the overlay closes.
Add a Go-based command_palette kitten that provides a searchable,
interactive overlay for browsing and triggering keyboard shortcuts
and actions.
- New Go kitten at kittens/command_palette/ with FZF fuzzy search,
grouped/flat views, and remote control action triggering
- Python collect_keys_data() does data collection, passed via stdin
- Navigation: arrows, ctrl+j/k (vim), ctrl+n/p (emacs), page up/down
- Enter triggers the selected action via RC command
- Help text displayed in footer for selected binding
- Added Go tests (main_test.go) and Python tests (command_palette.py)
Note this only fixes the test, there is still the actual issue of
the selection not being rendered for the top most line if that line is
partially scrolled offscreen
Implements modern wide gamut color formats with CSS Color Module Level 4
gamut mapping, addressing PR feedback with Go implementation, performance
benchmarks, and reorganized documentation.
Features:
- OKLCH (perceptually uniform color space)
- CIE LAB (device-independent color space)
- CSS Color 4 compliant gamut mapping algorithm
- Inline comment support in color config parsing
Addressing PR Feedback:
1. Go Implementation (tools/utils/style/):
- Complete OKLCH and LAB parsing with gamut mapping
- Matches Python implementation structure
- Comprehensive test suite (all tests passing)
- Performance benchmarks showing acceptable overhead
2. Performance Benchmarks:
- OKLCH: ~4.6 µs/op
- LAB: ~1.5 µs/op
- 10 mixed colors: ~13 µs total
- Typical config (50 colors): <0.5ms startup impact
3. Documentation Reorganization:
- Moved detailed color docs to docs/wide-gamut-colors.rst
- Configuration docs now link to separate documentation
- Reduces size of main configuration documentation
Gamut Mapping:
- Binary search chroma reduction from CSS Color Module Level 4
- Preserves lightness and hue while reducing chroma for out-of-gamut colors
- Uses deltaE OK (JND threshold: 0.02) for perceptual difference
- Ensures graceful degradation on sRGB displays
Python Implementation:
- parse_oklch(): OKLCH color parsing with gamut mapping
- parse_lab(): CIE LAB parsing with gamut mapping via OKLCH conversion
- lab_to_oklch(): LAB to OKLCH conversion for consistent gamut mapping
- oklch_to_srgb_gamut_map(): CSS Color 4 gamut mapping algorithm
- srgb_to_oklab(): Reverse conversion for deltaE calculations
- deltaE_ok(): Perceptual color difference in OKLab space
Go Implementation:
- colorspaces.go: All color space conversions and gamut mapping
- wrapper.go: ParseColor() updated to support OKLCH and LAB
- Comprehensive test coverage with benchmarks
- Matches Python implementation behavior
Robustness:
- NaN and infinity validation in all color parsing functions
- Defense-in-depth with validation at parsing and gamut mapping levels
- Returns None/error for invalid input (consistent error handling)
- Validates before clamping operations to prevent NaN propagation
Files changed:
- Python: kitty/rgb.py, kitty_tests/datatypes.py (+250 lines)
- Go: tools/utils/style/colorspaces.go, wrapper.go (+350 lines, tests)
- Docs: docs/wide-gamut-colors.rst (moved from inline)
- Config: kitty/options/definition.py (simplified, links to docs)
References:
- CSS Color Module Level 4: https://www.w3.org/TR/css-color-4/
- OKLCH Color Space: https://bottosson.github.io/posts/oklab/🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Modified `start_classification` in `utf8_decode_to_esc` in `simd-string-impl.h`, which now:
Rejects `0xC0`, `0xC1` and `0xF5..0xFF` lead bytes in UTF-8 subsequences.
Enforces special ranges for the second subsequence bytes after `0xE0`, `0xED`, `0xF0` and `0xF4` bytes to prevent overlong sequences, surrogates, and code points above U+10FFFF.
Accumulates UTF-8 validation errors in a single vector to avoid many conditional branches.
Worsens unicode benchmark performance by about 4%.