mui 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +18 -10
- data/CHANGELOG.md +162 -0
- data/README.md +309 -6
- data/docs/_config.yml +56 -0
- data/docs/configuration.md +314 -0
- data/docs/getting-started.md +140 -0
- data/docs/index.md +55 -0
- data/docs/jobs.md +297 -0
- data/docs/keybindings.md +229 -0
- data/docs/plugins.md +285 -0
- data/docs/syntax-highlighting.md +155 -0
- data/lib/mui/color_manager.rb +140 -6
- data/lib/mui/color_scheme.rb +1 -0
- data/lib/mui/command_completer.rb +11 -2
- data/lib/mui/command_history.rb +89 -0
- data/lib/mui/command_line.rb +32 -2
- data/lib/mui/command_registry.rb +21 -2
- data/lib/mui/config.rb +3 -1
- data/lib/mui/editor.rb +90 -2
- data/lib/mui/floating_window.rb +53 -1
- data/lib/mui/handler_result.rb +13 -7
- data/lib/mui/highlighters/search_highlighter.rb +2 -1
- data/lib/mui/highlighters/syntax_highlighter.rb +4 -1
- data/lib/mui/insert_completion_state.rb +15 -2
- data/lib/mui/key_handler/base.rb +87 -0
- data/lib/mui/key_handler/command_mode.rb +68 -0
- data/lib/mui/key_handler/insert_mode.rb +10 -41
- data/lib/mui/key_handler/normal_mode.rb +24 -51
- data/lib/mui/key_handler/operators/paste_operator.rb +9 -3
- data/lib/mui/key_handler/search_mode.rb +10 -7
- data/lib/mui/key_handler/visual_mode.rb +15 -10
- data/lib/mui/key_notation_parser.rb +159 -0
- data/lib/mui/key_sequence.rb +67 -0
- data/lib/mui/key_sequence_buffer.rb +85 -0
- data/lib/mui/key_sequence_handler.rb +163 -0
- data/lib/mui/key_sequence_matcher.rb +79 -0
- data/lib/mui/line_renderer.rb +52 -1
- data/lib/mui/mode_manager.rb +3 -2
- data/lib/mui/screen.rb +30 -6
- data/lib/mui/search_state.rb +74 -27
- data/lib/mui/syntax/language_detector.rb +33 -1
- data/lib/mui/syntax/lexers/c_lexer.rb +2 -0
- data/lib/mui/syntax/lexers/css_lexer.rb +121 -0
- data/lib/mui/syntax/lexers/go_lexer.rb +207 -0
- data/lib/mui/syntax/lexers/html_lexer.rb +118 -0
- data/lib/mui/syntax/lexers/javascript_lexer.rb +219 -0
- data/lib/mui/syntax/lexers/markdown_lexer.rb +210 -0
- data/lib/mui/syntax/lexers/ruby_lexer.rb +3 -0
- data/lib/mui/syntax/lexers/rust_lexer.rb +150 -0
- data/lib/mui/syntax/lexers/typescript_lexer.rb +225 -0
- data/lib/mui/terminal_adapter/base.rb +21 -0
- data/lib/mui/terminal_adapter/curses.rb +37 -11
- data/lib/mui/themes/default.rb +263 -132
- data/lib/mui/version.rb +1 -1
- data/lib/mui/window.rb +105 -39
- data/lib/mui/window_manager.rb +7 -0
- data/lib/mui/wrap_cache.rb +40 -0
- data/lib/mui/wrap_helper.rb +84 -0
- data/lib/mui.rb +15 -0
- metadata +26 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fc6a6725223b44bd937314729fc4008b726123dd1624adfdf3adc868b9d4d71d
|
|
4
|
+
data.tar.gz: 1c58af876fa5c06fb9033a9968dd1de012265f3d3b85bb50a46b17a9e24eeca5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a7a0d46bdf37d31dd6a475b4c42665462e15ed2eee1cad432eed7dcec13776974cd95ed1853e2856fffae2005d367ae6a78294d30e2343ee25240995e943c5dc
|
|
7
|
+
data.tar.gz: 1f7b17692e0f2349eadbdd38b3687ca661f6d8f6196ba162579e28cc8b7f837d00d36d1ba1533a57d52e3e20f0f1510f51dc5333c2b494bc053c6533e62fd324
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2025-12-
|
|
3
|
+
# on 2025-12-18 10:56:40 UTC using RuboCop version 1.81.7.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
@@ -12,10 +12,11 @@ Gemspec/RequiredRubyVersion:
|
|
|
12
12
|
Exclude:
|
|
13
13
|
- 'test/fixtures/mui-test-plugin/mui-test-plugin.gemspec'
|
|
14
14
|
|
|
15
|
-
# Offense count:
|
|
15
|
+
# Offense count: 4
|
|
16
16
|
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
|
|
17
17
|
Lint/DuplicateBranch:
|
|
18
18
|
Exclude:
|
|
19
|
+
- 'lib/mui/editor.rb'
|
|
19
20
|
- 'lib/mui/key_handler/command_mode.rb'
|
|
20
21
|
- 'lib/mui/plugin_manager.rb'
|
|
21
22
|
- 'lib/mui/register.rb'
|
|
@@ -33,35 +34,36 @@ Lint/MissingSuper:
|
|
|
33
34
|
Exclude:
|
|
34
35
|
- 'test/test_helper.rb'
|
|
35
36
|
|
|
36
|
-
# Offense count:
|
|
37
|
+
# Offense count: 3
|
|
37
38
|
# This cop supports safe autocorrection (--autocorrect).
|
|
38
39
|
# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
|
|
39
40
|
# NotImplementedExceptions: NotImplementedError
|
|
40
41
|
Lint/UnusedMethodArgument:
|
|
41
42
|
Exclude:
|
|
42
43
|
- 'lib/mui/terminal_adapter/base.rb'
|
|
44
|
+
- 'test/mui/highlighters/test_search_highlighter.rb'
|
|
43
45
|
|
|
44
46
|
# Offense count: 1
|
|
45
47
|
Lint/UselessConstantScoping:
|
|
46
48
|
Exclude:
|
|
47
49
|
- 'lib/mui/buffer_word_cache.rb'
|
|
48
50
|
|
|
49
|
-
# Offense count:
|
|
51
|
+
# Offense count: 35
|
|
50
52
|
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
|
51
53
|
Metrics/CyclomaticComplexity:
|
|
52
54
|
Max: 49
|
|
53
55
|
|
|
54
|
-
# Offense count:
|
|
56
|
+
# Offense count: 2
|
|
55
57
|
# Configuration parameters: CountComments, CountAsOne.
|
|
56
58
|
Metrics/ModuleLength:
|
|
57
|
-
Max:
|
|
59
|
+
Max: 328
|
|
58
60
|
|
|
59
61
|
# Offense count: 10
|
|
60
62
|
# Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
|
|
61
63
|
Metrics/ParameterLists:
|
|
62
64
|
Max: 9
|
|
63
65
|
|
|
64
|
-
# Offense count:
|
|
66
|
+
# Offense count: 15
|
|
65
67
|
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
|
66
68
|
Metrics/PerceivedComplexity:
|
|
67
69
|
Max: 19
|
|
@@ -90,7 +92,7 @@ Naming/MethodName:
|
|
|
90
92
|
- 'test/mui/key_handler/test_visual_mode.rb'
|
|
91
93
|
- 'test/mui/key_handler/test_window_command.rb'
|
|
92
94
|
|
|
93
|
-
# Offense count:
|
|
95
|
+
# Offense count: 45
|
|
94
96
|
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
|
|
95
97
|
# AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to
|
|
96
98
|
Naming/MethodParameterName:
|
|
@@ -108,17 +110,20 @@ Naming/MethodParameterName:
|
|
|
108
110
|
- 'test/e2e/test_helper.rb'
|
|
109
111
|
- 'test/test_helper.rb'
|
|
110
112
|
|
|
111
|
-
# Offense count:
|
|
113
|
+
# Offense count: 11
|
|
112
114
|
# Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
|
|
113
115
|
# AllowedMethods: call
|
|
114
116
|
# WaywardPredicates: nonzero?
|
|
115
117
|
Naming/PredicateMethod:
|
|
116
118
|
Exclude:
|
|
119
|
+
- 'lib/mui/command_line.rb'
|
|
120
|
+
- 'lib/mui/editor.rb'
|
|
117
121
|
- 'lib/mui/key_handler/insert_mode.rb'
|
|
122
|
+
- 'lib/mui/key_sequence_buffer.rb'
|
|
118
123
|
- 'lib/mui/undo_manager.rb'
|
|
119
124
|
- 'lib/mui/window_manager.rb'
|
|
120
125
|
|
|
121
|
-
# Offense count:
|
|
126
|
+
# Offense count: 4
|
|
122
127
|
# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros, UseSorbetSigs.
|
|
123
128
|
# NamePrefix: is_, has_, have_, does_
|
|
124
129
|
# ForbiddenPrefixes: is_, has_, have_, does_
|
|
@@ -128,6 +133,9 @@ Naming/PredicatePrefix:
|
|
|
128
133
|
Exclude:
|
|
129
134
|
- 'spec/**/*'
|
|
130
135
|
- 'lib/mui/search_state.rb'
|
|
136
|
+
- 'lib/mui/terminal_adapter/base.rb'
|
|
137
|
+
- 'lib/mui/terminal_adapter/curses.rb'
|
|
138
|
+
- 'test/test_helper.rb'
|
|
131
139
|
|
|
132
140
|
# Offense count: 2
|
|
133
141
|
# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,167 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.4.0] 2025-12-19
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- `<S-Tab>` (Shift+Tab) notation support in keymap configuration:
|
|
7
|
+
- Added `s-tab` and `btab` to `SPECIAL_KEYS` mapping to `:shift_tab` symbol
|
|
8
|
+
- `normalize_input_key()` now handles `KEY_BTAB` (353) from Curses
|
|
9
|
+
- Enables tab navigation keymaps like:
|
|
10
|
+
```ruby
|
|
11
|
+
Mui.keymap :normal, "<Tab>", ->(ctx) { ctx.editor.tab_manager.next_tab }
|
|
12
|
+
Mui.keymap :normal, "<S-Tab>", ->(ctx) { ctx.editor.tab_manager.prev_tab }
|
|
13
|
+
```
|
|
14
|
+
- Function definition name highlighting for 6 languages:
|
|
15
|
+
- Ruby: `def hello` highlights `hello` (lookbehind pattern `(?<=def )`)
|
|
16
|
+
- Go: `func main()` highlights `main` (lookbehind pattern `(?<=func )`)
|
|
17
|
+
- Rust: `fn calculate()` highlights `calculate` (lookbehind pattern `(?<=fn )`)
|
|
18
|
+
- JavaScript: `function add()` highlights `add` (post-process after `function` keyword)
|
|
19
|
+
- TypeScript: `function fetchData()` highlights `fetchData` (post-process after `function` keyword)
|
|
20
|
+
- C: `int main()` highlights `main` (lookahead pattern for identifier before `(`)
|
|
21
|
+
- New token type `:function_definition` mapped to `syntax_function_definition` color scheme element
|
|
22
|
+
- All 8 themes updated with `syntax_function_definition` style (same color as `syntax_method_call`)
|
|
23
|
+
- Improved mui default theme with 256-color palette:
|
|
24
|
+
- Eye-friendly gray-based color scheme using 256-color palette
|
|
25
|
+
- 19 new `mui_*` colors in `EXTENDED_COLOR_MAP` (mui_bg, mui_fg, mui_comment, etc.)
|
|
26
|
+
- Syntax highlighting follows Vim standard highlight groups (Comment, Constant, Identifier, Statement, PreProc, Type, Special)
|
|
27
|
+
- 8-color fallbacks for all mui colors
|
|
28
|
+
- Improved all bundled themes to match their original color schemes:
|
|
29
|
+
- Solarized Dark/Light: Adjusted visual selection, operators, and diff colors
|
|
30
|
+
- Monokai: Fixed comment color to olive gray (#75715e), added `monokai_comment` color
|
|
31
|
+
- Nord: Adjusted status line and constant colors to match Nord palette
|
|
32
|
+
- Gruvbox: Adjusted identifier and keyword colors
|
|
33
|
+
- Dracula: Adjusted visual selection and symbol colors
|
|
34
|
+
- Tokyo Night: Adjusted operator and constant colors
|
|
35
|
+
- Added LSP diagnostics and floating window styles to all themes:
|
|
36
|
+
- `diagnostic_error`, `diagnostic_warning`, `diagnostic_info`, `diagnostic_hint`
|
|
37
|
+
- `floating_window`
|
|
38
|
+
- 256-color support stabilization:
|
|
39
|
+
- Environment capability detection (`Curses.has_colors?`, `Curses.colors`, `Curses.color_pairs`)
|
|
40
|
+
- Automatic 8-color fallback for terminals without 256-color support
|
|
41
|
+
- `FALLBACK_MAP` to map extended colors to nearest basic 8-color equivalents
|
|
42
|
+
- LRU cache for color pairs to prevent pair exhaustion
|
|
43
|
+
- Automatic eviction of oldest pairs when limit is reached
|
|
44
|
+
- Backward compatible: `ColorManager.new` without adapter assumes 256 colors
|
|
45
|
+
- `ColorManager#supports_256_colors` to check color capability
|
|
46
|
+
- `TerminalAdapter::Base#has_colors?`, `#colors`, `#color_pairs` interface methods
|
|
47
|
+
|
|
48
|
+
### Fixed
|
|
49
|
+
- Fixed text corruption after closing floating window or completion popup:
|
|
50
|
+
- Japanese/CJK multibyte characters were not displaying correctly after popup closed
|
|
51
|
+
- Added `touchwin` method to force complete screen redraw using `Curses.stdscr.redraw`
|
|
52
|
+
- `FloatingWindow` now tracks `last_bounds` and `needs_clear` flag
|
|
53
|
+
- `InsertCompletionState` now tracks `needs_clear` flag
|
|
54
|
+
- Editor calls `touchwin` when popup is closed to restore corrupted characters
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
- Improved search performance for large files:
|
|
58
|
+
- Added row-based index (`row_index`) to search match cache for O(1) lookup
|
|
59
|
+
- `matches_for_row()` now uses hash lookup instead of linear search
|
|
60
|
+
- Before: O(M × visible_rows) per frame, After: O(visible_rows) per frame
|
|
61
|
+
- Improved navigation performance for large files (G, gg commands):
|
|
62
|
+
- Added smart scroll jump for cursor movements over 100 rows
|
|
63
|
+
- Directly calculates scroll position instead of iterating line by line
|
|
64
|
+
- Before: O(n) where n = cursor distance, After: O(1)
|
|
65
|
+
|
|
66
|
+
## [0.3.0] - 2025-12-15
|
|
67
|
+
|
|
68
|
+
### Added
|
|
69
|
+
- Additional syntax highlighting for 7 languages:
|
|
70
|
+
- Go: keywords, types, constants, raw strings (backtick), block comments
|
|
71
|
+
- Rust: macros (`println!`), lifetimes (`'a`), attributes (`#[derive]`), doc comments (`///`), raw strings (`r#"..."#`)
|
|
72
|
+
- JavaScript: template literals, regex literals, BigInt (`123n`), ES6+ keywords (`const`, `let`, `async`, `await`)
|
|
73
|
+
- TypeScript: extends JavaScript with type keywords (`interface`, `type`, `enum`, `declare`, `abstract`)
|
|
74
|
+
- Markdown: headings, emphasis (`*italic*`, `**bold**`), code blocks, links, lists, blockquotes
|
|
75
|
+
- HTML: tags, attributes, comments (`<!-- -->`), DOCTYPE, entities (`&`)
|
|
76
|
+
- CSS: selectors (`.class`, `#id`, `:pseudo`), properties, hex colors, @rules, functions (`calc`, `rgb`, `var`)
|
|
77
|
+
- Supported extensions: `.go`, `.rs`, `.js`/`.mjs`/`.cjs`/`.jsx`, `.ts`/`.tsx`/`.mts`/`.cts`, `.md`/`.markdown`, `.html`/`.htm`/`.xhtml`, `.css`/`.scss`/`.sass`
|
|
78
|
+
- Multi-key sequence and leader key support (Vim-compatible):
|
|
79
|
+
- Leader key: `Mui.set :leader, "\\"` (default: backslash)
|
|
80
|
+
- `<Leader>` notation: `Mui.keymap :normal, "<Leader>gd" do ... end`
|
|
81
|
+
- Multi-key sequences: `<Leader>ff`, `<C-x><C-s>`, etc.
|
|
82
|
+
- Special key notation: `<Space>`, `<Tab>`, `<CR>`, `<Enter>`, `<Esc>`, `<BS>`
|
|
83
|
+
- Control key notation: `<C-x>`, `<Ctrl-x>`, `<C-S-x>` (Ctrl+Shift)
|
|
84
|
+
- Shift key notation: `<S-x>`, `<Shift-x>`
|
|
85
|
+
- Timeout setting: `Mui.set :timeoutlen, 1000` (milliseconds)
|
|
86
|
+
- All modes supported: Normal, Insert, Visual, Command, Search
|
|
87
|
+
- Built-in commands (dd, dw, gg, etc.) take priority over plugin keymaps
|
|
88
|
+
- Partial match waiting: typing `<Leader>g` waits for more keys if `<Leader>gd` is registered
|
|
89
|
+
- Exact match with longer possibilities: waits for timeout before executing
|
|
90
|
+
- Backward compatible with single-key keymaps
|
|
91
|
+
- External shell command execution (`:!cmd`):
|
|
92
|
+
- `:!echo hello` to run shell commands asynchronously
|
|
93
|
+
- Output displayed in `[Shell Output]` scratch buffer (readonly)
|
|
94
|
+
- stdout/stderr/exit status formatted and displayed
|
|
95
|
+
- "Running: cmd" message shown during execution
|
|
96
|
+
- Subsequent `:!cmd` updates existing scratch buffer (doesn't create new windows)
|
|
97
|
+
- Supports pipes, redirects, and all shell features via Open3
|
|
98
|
+
- Empty command (`:!` or `:! `) shows error: "E471: Argument required"
|
|
99
|
+
- Case-insensitive command completion:
|
|
100
|
+
- `:git` now matches `:Git`, `:lsp` matches `:LspHover`, `:LspDefinition`, etc.
|
|
101
|
+
- Original command case is preserved in completion results
|
|
102
|
+
- Only applies to command completion (file path completion remains case-sensitive)
|
|
103
|
+
- Command history with persistence:
|
|
104
|
+
- Up/Down arrow keys navigate through command history in command mode
|
|
105
|
+
- History saved to `~/.mui_history` (persists across sessions)
|
|
106
|
+
- Maximum 100 entries stored
|
|
107
|
+
- Duplicate commands move to most recent position
|
|
108
|
+
- Empty commands are not added to history
|
|
109
|
+
- Current input is preserved when browsing history (restored with Down at end)
|
|
110
|
+
|
|
111
|
+
### Fixed
|
|
112
|
+
- Fixed long lines not displaying correctly by implementing line wrapping
|
|
113
|
+
- Lines exceeding screen width are now automatically wrapped to next screen line
|
|
114
|
+
- Unicode width aware wrapping (Japanese characters count as 2 width)
|
|
115
|
+
- Removed broken horizontal scrolling (`scroll_col`) in favor of wrap mode
|
|
116
|
+
- Cursor position correctly calculated across wrapped lines
|
|
117
|
+
- Selection and search highlights work correctly across wrap boundaries
|
|
118
|
+
- Added `WrapCache` for performance optimization (content-based caching)
|
|
119
|
+
- Added `WrapHelper` module for wrap calculations
|
|
120
|
+
- Fixed search returning "Pattern not found" after switching buffers via `:e`
|
|
121
|
+
- `execute_search` was using `@buffer` (initial buffer) instead of `buffer` method (current buffer)
|
|
122
|
+
- Now correctly searches in the current buffer after buffer switch
|
|
123
|
+
- Search highlight now recalculates correctly when switching buffers via `:e`
|
|
124
|
+
- Previously, search highlight from old buffer remained visible in new buffer
|
|
125
|
+
- Now calls `find_all_matches` on buffer switch to recalculate matches (Vim-compatible behavior)
|
|
126
|
+
- Search pattern is preserved, only match positions are updated for new buffer content
|
|
127
|
+
- Search highlight now recalculates correctly when opening files via `:sp`, `:vs`, `:tabnew`
|
|
128
|
+
- Previously, search highlight was not calculated for new buffers opened with split/tab commands
|
|
129
|
+
- Now calls `find_all_matches` when path is specified, consistent with `:e` behavior
|
|
130
|
+
- Improved Escape key response time in Insert mode
|
|
131
|
+
- Set `ESCDELAY = 10` to reduce escape sequence detection delay from 1000ms to 10ms
|
|
132
|
+
- Use `timeout = 0` instead of `nodelay` for `getch_nonblock`
|
|
133
|
+
- Insert mode completion now closes when pressing Left/Right arrow keys
|
|
134
|
+
- Previously, arrow keys would move cursor but completion popup remained open
|
|
135
|
+
- Now matches Vim behavior: completion closes on cursor movement
|
|
136
|
+
- Undo/Redo now works correctly for buffers opened via `:e`, `:sp`, `:vs`, `:tabnew`
|
|
137
|
+
- Previously, buffers opened with these commands had no UndoManager set
|
|
138
|
+
- Each buffer now gets its own UndoManager (Vim-compatible: independent undo history per buffer)
|
|
139
|
+
- Handlers now use dynamic `undo_manager` reference to support buffer switching
|
|
140
|
+
- Fixed screen remnants after `:e` command when new file has fewer lines
|
|
141
|
+
- Previously, lines from the old buffer would remain visible below the new content
|
|
142
|
+
- Now explicitly clears lines beyond buffer content during render
|
|
143
|
+
- Fixed background color not applied to lines beyond buffer content
|
|
144
|
+
- Previously, when opening a file with fewer lines than the visible height, lines beyond buffer were rendered without background color (transparent)
|
|
145
|
+
- Now uses `put_with_style` with `:normal` color scheme to ensure consistent background color
|
|
146
|
+
- Plugin commands now appear in command completion suggestions
|
|
147
|
+
- Previously, commands registered via `Mui.command` were not shown in Tab completion
|
|
148
|
+
- `CommandCompleter` now includes plugin commands from `Mui.config.commands`
|
|
149
|
+
- Multi-line paste now undos as a single action (Vim-compatible)
|
|
150
|
+
- Previously, pasting multiple lines would undo one line at a time
|
|
151
|
+
- Now uses `begin_group`/`end_group` to group all paste operations into a single undo unit
|
|
152
|
+
- Fixed direct array assignment to use `replace_line` for proper undo recording
|
|
153
|
+
- Search highlight now works correctly per buffer when switching tabs/windows
|
|
154
|
+
- Previously, search matches from old buffer remained when using `gt`/`gT` or `Ctrl+W` commands
|
|
155
|
+
- `SearchState` now caches matches per buffer (keyed by `object_id`) with lazy evaluation
|
|
156
|
+
- Each buffer maintains its own match positions while sharing the global search pattern
|
|
157
|
+
- Cache automatically invalidates when pattern changes or buffer content is modified
|
|
158
|
+
- Vim-compatible behavior: search pattern is global, highlights are buffer-specific
|
|
159
|
+
- Plugin commands now recognized by CommandRegistry for alias configuration
|
|
160
|
+
- Previously, `CommandRegistry#exists?` and `#find` only checked built-in commands
|
|
161
|
+
- Now also checks `Mui.config.commands` for plugin-registered commands
|
|
162
|
+
- Enables setting command aliases for plugin commands without errors
|
|
163
|
+
- Built-in commands take precedence over plugin commands with the same name
|
|
164
|
+
|
|
3
165
|
## [0.2.0] - 2025-12-12
|
|
4
166
|
|
|
5
167
|
### Added
|
data/README.md
CHANGED
|
@@ -17,13 +17,316 @@ gem install mui
|
|
|
17
17
|
mui [file]
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
## Features
|
|
20
|
+
## Features
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
-
|
|
22
|
+
### Modal Editing
|
|
23
|
+
|
|
24
|
+
Vim-like modal editing with five modes:
|
|
25
|
+
|
|
26
|
+
- **Normal mode**: Navigation and text manipulation
|
|
27
|
+
- **Insert mode**: Text input with auto-completion
|
|
28
|
+
- **Command mode**: Ex commands (`:w`, `:q`, `:e`, etc.)
|
|
29
|
+
- **Visual mode** (`v`): Character-wise selection
|
|
30
|
+
- **Visual Line mode** (`V`): Line-wise selection
|
|
31
|
+
|
|
32
|
+
### Tab Pages and Window Splits
|
|
33
|
+
|
|
34
|
+
- **Tab pages**: `:tabnew`, `:tabclose`, `gt`/`gT` to switch
|
|
35
|
+
- **Horizontal split**: `:sp [file]`
|
|
36
|
+
- **Vertical split**: `:vs [file]`
|
|
37
|
+
- **Window navigation**: `Ctrl-w h/j/k/l` or `Ctrl-w w`
|
|
38
|
+
|
|
39
|
+
### Syntax Highlighting
|
|
40
|
+
|
|
41
|
+
Supports 9 languages:
|
|
42
|
+
|
|
43
|
+
- Ruby (`.rb`, `.rake`, `.gemspec`)
|
|
44
|
+
- C (`.c`, `.h`, `.y`)
|
|
45
|
+
- Go (`.go`)
|
|
46
|
+
- Rust (`.rs`)
|
|
47
|
+
- JavaScript (`.js`, `.mjs`, `.cjs`, `.jsx`)
|
|
48
|
+
- TypeScript (`.ts`, `.tsx`, `.mts`, `.cts`)
|
|
49
|
+
- Markdown (`.md`, `.markdown`)
|
|
50
|
+
- HTML (`.html`, `.htm`, `.xhtml`)
|
|
51
|
+
- CSS (`.css`, `.scss`, `.sass`)
|
|
52
|
+
|
|
53
|
+
### Search
|
|
54
|
+
|
|
55
|
+
- Forward search: `/pattern`
|
|
56
|
+
- Backward search: `?pattern`
|
|
57
|
+
- Next/previous match: `n`/`N`
|
|
58
|
+
- Word under cursor: `*` (forward), `#` (backward)
|
|
59
|
+
- Incremental search with real-time highlighting
|
|
60
|
+
|
|
61
|
+
### Undo/Redo
|
|
62
|
+
|
|
63
|
+
- Undo: `u`
|
|
64
|
+
- Redo: `Ctrl-r`
|
|
65
|
+
- Insert mode changes grouped as single undo unit
|
|
66
|
+
|
|
67
|
+
### Named Registers
|
|
68
|
+
|
|
69
|
+
- Named registers: `"a` - `"z`
|
|
70
|
+
- Unnamed register: `""`
|
|
71
|
+
- Yank register: `"0`
|
|
72
|
+
- Delete history: `"1` - `"9`
|
|
73
|
+
- Black hole register: `"_`
|
|
74
|
+
|
|
75
|
+
### Completion
|
|
76
|
+
|
|
77
|
+
- Command-line completion with popup
|
|
78
|
+
- Buffer word completion in Insert mode (`Ctrl-n`/`Ctrl-p`)
|
|
79
|
+
- LSP completion support (via [mui-lsp](https://github.com/S-H-GAMELINKS/mui-lsp) gem)
|
|
80
|
+
|
|
81
|
+
### Multi-key Sequences and Leader Key
|
|
82
|
+
|
|
83
|
+
```ruby
|
|
84
|
+
# Set leader key (default: backslash)
|
|
85
|
+
Mui.set :leader, " " # Space as leader
|
|
86
|
+
|
|
87
|
+
# Define multi-key mappings
|
|
88
|
+
Mui.keymap :normal, "<Leader>ff" do |ctx|
|
|
89
|
+
# Find file
|
|
90
|
+
end
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Supports:
|
|
94
|
+
- `<Leader>` notation
|
|
95
|
+
- Control keys: `<C-x>`, `<C-S-x>`
|
|
96
|
+
- Special keys: `<Space>`, `<Tab>`, `<CR>`, `<Esc>`, `<BS>`
|
|
97
|
+
|
|
98
|
+
### Other Features
|
|
99
|
+
|
|
100
|
+
- Japanese and multibyte character support (UTF-8)
|
|
101
|
+
- Floating windows for hover info
|
|
102
|
+
- Asynchronous job execution
|
|
103
|
+
- External shell command execution (`:!cmd`)
|
|
104
|
+
- Command history with persistence
|
|
105
|
+
|
|
106
|
+
## Key Bindings
|
|
107
|
+
|
|
108
|
+
### Normal Mode
|
|
109
|
+
|
|
110
|
+
| Key | Action |
|
|
111
|
+
|-----|--------|
|
|
112
|
+
| `h`, `j`, `k`, `l` | Cursor movement |
|
|
113
|
+
| `w`, `b`, `e` | Word movement |
|
|
114
|
+
| `0`, `^`, `$` | Line movement |
|
|
115
|
+
| `gg`, `G` | File start/end |
|
|
116
|
+
| `f{char}`, `t{char}` | Find character |
|
|
117
|
+
| `i`, `a`, `o`, `O` | Enter Insert mode |
|
|
118
|
+
| `v`, `V` | Enter Visual mode |
|
|
119
|
+
| `d`, `c`, `y` | Delete/Change/Yank operators |
|
|
120
|
+
| `p`, `P` | Paste after/before |
|
|
121
|
+
| `u`, `Ctrl-r` | Undo/Redo |
|
|
122
|
+
| `/`, `?` | Search forward/backward |
|
|
123
|
+
| `n`, `N` | Next/previous match |
|
|
124
|
+
| `*`, `#` | Search word under cursor |
|
|
125
|
+
| `gt`, `gT` | Next/previous tab |
|
|
126
|
+
| `gv` | Reselect last visual selection |
|
|
127
|
+
| `Ctrl-w` + `h/j/k/l` | Window navigation |
|
|
128
|
+
|
|
129
|
+
### Visual Mode
|
|
130
|
+
|
|
131
|
+
| Key | Action |
|
|
132
|
+
|-----|--------|
|
|
133
|
+
| `d` | Delete selection |
|
|
134
|
+
| `c` | Change selection |
|
|
135
|
+
| `y` | Yank selection |
|
|
136
|
+
| `>`, `<` | Indent/unindent |
|
|
137
|
+
| `Esc` | Exit to Normal mode |
|
|
138
|
+
|
|
139
|
+
### Command Mode
|
|
140
|
+
|
|
141
|
+
| Command | Action |
|
|
142
|
+
|---------|--------|
|
|
143
|
+
| `:w` | Save file |
|
|
144
|
+
| `:q` | Quit |
|
|
145
|
+
| `:wq` | Save and quit |
|
|
146
|
+
| `:e <file>` | Open file |
|
|
147
|
+
| `:sp [file]` | Horizontal split |
|
|
148
|
+
| `:vs [file]` | Vertical split |
|
|
149
|
+
| `:tabnew [file]` | New tab |
|
|
150
|
+
| `:!cmd` | Run shell command |
|
|
151
|
+
|
|
152
|
+
## Configuration
|
|
153
|
+
|
|
154
|
+
Mui can be configured via `~/.muirc` (global) or `.lmuirc` (project-local).
|
|
155
|
+
|
|
156
|
+
```ruby
|
|
157
|
+
# ~/.muirc
|
|
158
|
+
|
|
159
|
+
# Color scheme
|
|
160
|
+
Mui.set :colorscheme, "tokyo_night"
|
|
161
|
+
|
|
162
|
+
# Editor settings
|
|
163
|
+
Mui.set :tabstop, 4
|
|
164
|
+
Mui.set :shiftwidth, 4
|
|
165
|
+
Mui.set :expandtab, true
|
|
166
|
+
Mui.set :syntax, true
|
|
167
|
+
|
|
168
|
+
# Leader key
|
|
169
|
+
Mui.set :leader, " "
|
|
170
|
+
|
|
171
|
+
# Custom keymaps
|
|
172
|
+
Mui.keymap :normal, "<Leader>w" do |ctx|
|
|
173
|
+
ctx.editor.execute_command("w")
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Custom commands
|
|
177
|
+
Mui.command :hello do |ctx|
|
|
178
|
+
ctx.set_message("Hello, World!")
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Autocmd
|
|
182
|
+
Mui.autocmd :BufWritePre, pattern: "*.rb" do |ctx|
|
|
183
|
+
# Before saving Ruby files
|
|
184
|
+
end
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Available Themes
|
|
188
|
+
|
|
189
|
+
- `mui` (default)
|
|
190
|
+
- `solarized_dark`
|
|
191
|
+
- `solarized_light`
|
|
192
|
+
- `monokai`
|
|
193
|
+
- `nord`
|
|
194
|
+
- `gruvbox_dark`
|
|
195
|
+
- `dracula`
|
|
196
|
+
- `tokyo_night`
|
|
197
|
+
|
|
198
|
+
## Plugin System
|
|
199
|
+
|
|
200
|
+
Mui supports plugins via Ruby gems.
|
|
201
|
+
|
|
202
|
+
### Official Plugins
|
|
203
|
+
|
|
204
|
+
- [mui-lsp](https://github.com/S-H-GAMELINKS/mui-lsp) - LSP (Language Server Protocol) support
|
|
205
|
+
- [mui-git](https://github.com/S-H-GAMELINKS/mui-git) - Git integration
|
|
206
|
+
- [mui-fzf](https://github.com/S-H-GAMELINKS/mui-fzf) - Fuzzy finder integration with fzf
|
|
207
|
+
|
|
208
|
+
### Using Plugins
|
|
209
|
+
|
|
210
|
+
```ruby
|
|
211
|
+
# ~/.muirc
|
|
212
|
+
Mui.use "mui-lsp"
|
|
213
|
+
Mui.use "mui-git"
|
|
214
|
+
Mui.use "mui-fzf"
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Creating Plugins
|
|
218
|
+
|
|
219
|
+
```ruby
|
|
220
|
+
# Class-based plugin
|
|
221
|
+
class MyPlugin < Mui::Plugin
|
|
222
|
+
name :my_plugin
|
|
223
|
+
|
|
224
|
+
def setup
|
|
225
|
+
command :greet do |ctx|
|
|
226
|
+
ctx.set_message("Hello from MyPlugin!")
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
keymap :normal, "<Leader>g" do |ctx|
|
|
230
|
+
ctx.editor.execute_command("greet")
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
autocmd :BufEnter, pattern: "*.txt" do |ctx|
|
|
234
|
+
ctx.set_message("Opened a text file")
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Asynchronous Job Execution
|
|
241
|
+
|
|
242
|
+
Plugins can run background tasks without blocking the editor:
|
|
243
|
+
|
|
244
|
+
```ruby
|
|
245
|
+
class MyAsyncPlugin < Mui::Plugin
|
|
246
|
+
name :my_async_plugin
|
|
247
|
+
|
|
248
|
+
def setup
|
|
249
|
+
# Run a shell command asynchronously
|
|
250
|
+
command :run_tests do |ctx|
|
|
251
|
+
ctx.run_shell_command("bundle exec rake test") do |result|
|
|
252
|
+
if result[:success]
|
|
253
|
+
ctx.open_scratch_buffer("[Test Results]", result[:stdout])
|
|
254
|
+
else
|
|
255
|
+
ctx.set_error("Tests failed: #{result[:stderr]}")
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# Run a Ruby block asynchronously
|
|
261
|
+
command :fetch_data do |ctx|
|
|
262
|
+
ctx.run_async do
|
|
263
|
+
# This runs in a background thread
|
|
264
|
+
sleep 2 # Simulate long operation
|
|
265
|
+
"Data fetched!"
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Check if jobs are running
|
|
270
|
+
command :job_status do |ctx|
|
|
271
|
+
if ctx.jobs_running?
|
|
272
|
+
ctx.set_message("Jobs are running...")
|
|
273
|
+
else
|
|
274
|
+
ctx.set_message("No jobs running")
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Available job methods:
|
|
282
|
+
- `ctx.run_async { ... }` - Run a Ruby block in background
|
|
283
|
+
- `ctx.run_shell_command(cmd) { |result| ... }` - Run shell command asynchronously
|
|
284
|
+
- `ctx.jobs_running?` - Check if any jobs are active
|
|
285
|
+
- `ctx.cancel_job(id)` - Cancel a running job
|
|
286
|
+
- `ctx.open_scratch_buffer(name, content)` - Display results in a scratch buffer
|
|
287
|
+
|
|
288
|
+
Autocmd events for jobs:
|
|
289
|
+
- `JobStarted` - When a job begins
|
|
290
|
+
- `JobCompleted` - When a job finishes successfully
|
|
291
|
+
- `JobFailed` - When a job fails
|
|
292
|
+
- `JobCancelled` - When a job is cancelled
|
|
293
|
+
|
|
294
|
+
### Interactive Command Execution
|
|
295
|
+
|
|
296
|
+
Plugins can run interactive external commands:
|
|
297
|
+
|
|
298
|
+
```ruby
|
|
299
|
+
class FzfPlugin < Mui::Plugin
|
|
300
|
+
name :fzf
|
|
301
|
+
|
|
302
|
+
def setup
|
|
303
|
+
command :Files do |ctx|
|
|
304
|
+
if ctx.command_exists?("fzf")
|
|
305
|
+
result = ctx.run_interactive_command("fzf")
|
|
306
|
+
ctx.editor.execute_command("e #{result}") if result && !result.empty?
|
|
307
|
+
else
|
|
308
|
+
ctx.set_error("fzf is not installed")
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### LSP Configuration
|
|
316
|
+
|
|
317
|
+
```ruby
|
|
318
|
+
# ~/.muirc
|
|
319
|
+
Mui.use "mui-lsp"
|
|
320
|
+
|
|
321
|
+
Mui.lsp do
|
|
322
|
+
use :ruby # Use preset configuration
|
|
323
|
+
|
|
324
|
+
# Or custom server
|
|
325
|
+
server :custom_lsp,
|
|
326
|
+
command: ["my-lsp", "--stdio"],
|
|
327
|
+
filetypes: ["mylang"]
|
|
328
|
+
end
|
|
329
|
+
```
|
|
27
330
|
|
|
28
331
|
## Development
|
|
29
332
|
|
data/docs/_config.yml
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
title: Mui(無為) Documentation
|
|
2
|
+
description: A Vim-like TUI text editor written in Ruby
|
|
3
|
+
baseurl: "/mui"
|
|
4
|
+
url: "https://s-h-gamelinks.github.io"
|
|
5
|
+
|
|
6
|
+
remote_theme: just-the-docs/just-the-docs
|
|
7
|
+
|
|
8
|
+
color_scheme: dark
|
|
9
|
+
|
|
10
|
+
permalink: pretty
|
|
11
|
+
|
|
12
|
+
aux_links:
|
|
13
|
+
GitHub: https://github.com/S-H-GAMELINKS/mui
|
|
14
|
+
RubyGems: https://rubygems.org/gems/mui
|
|
15
|
+
|
|
16
|
+
nav_external_links:
|
|
17
|
+
- title: GitHub
|
|
18
|
+
url: https://github.com/S-H-GAMELINKS/mui
|
|
19
|
+
|
|
20
|
+
search_enabled: true
|
|
21
|
+
search:
|
|
22
|
+
heading_level: 2
|
|
23
|
+
previews: 3
|
|
24
|
+
preview_words_before: 5
|
|
25
|
+
preview_words_after: 10
|
|
26
|
+
tokenizer_separator: /[\s/]+/
|
|
27
|
+
rel_url: true
|
|
28
|
+
button: false
|
|
29
|
+
|
|
30
|
+
heading_anchors: true
|
|
31
|
+
|
|
32
|
+
back_to_top: true
|
|
33
|
+
back_to_top_text: "Back to top"
|
|
34
|
+
|
|
35
|
+
footer_content: "Copyright © 2025 S-H-GAMELINKS. Distributed under the <a href=\"https://opensource.org/licenses/MIT\">MIT License</a>."
|
|
36
|
+
|
|
37
|
+
last_edit_timestamp: true
|
|
38
|
+
last_edit_time_format: "%Y-%m-%d"
|
|
39
|
+
|
|
40
|
+
gh_edit_link: true
|
|
41
|
+
gh_edit_link_text: "Edit this page on GitHub"
|
|
42
|
+
gh_edit_repository: "https://github.com/S-H-GAMELINKS/mui"
|
|
43
|
+
gh_edit_branch: "master"
|
|
44
|
+
gh_edit_source: docs
|
|
45
|
+
gh_edit_view_mode: "edit"
|
|
46
|
+
|
|
47
|
+
callouts:
|
|
48
|
+
warning:
|
|
49
|
+
title: Warning
|
|
50
|
+
color: yellow
|
|
51
|
+
note:
|
|
52
|
+
title: Note
|
|
53
|
+
color: blue
|
|
54
|
+
tip:
|
|
55
|
+
title: Tip
|
|
56
|
+
color: green
|