@@ -439,8 +439,12 @@ impl ChatComposer {
439
439
let ( text, cursor) = Self :: prompt_command_text ( & prompt. name , & args) ;
440
440
self . textarea . set_text ( & text) ;
441
441
let target = cursor. or_else ( || {
442
- ( !self . textarea . text ( ) . is_empty ( ) )
443
- . then_some ( self . textarea . text ( ) . len ( ) )
442
+ let text = self . textarea . text ( ) ;
443
+ if text. is_empty ( ) {
444
+ None
445
+ } else {
446
+ Some ( text. len ( ) )
447
+ }
444
448
} ) ;
445
449
if let Some ( pos) = target {
446
450
self . textarea . set_cursor ( pos) ;
@@ -1193,7 +1197,7 @@ impl ChatComposer {
1193
1197
let cursor = self . textarea . cursor ( ) ;
1194
1198
let caret_on_first_line = cursor <= first_line_end;
1195
1199
1196
- let in_slash_name_context = if first_line. starts_with ( '/' ) && caret_on_first_line {
1200
+ let is_editing_slash_command_name = if first_line. starts_with ( '/' ) && caret_on_first_line {
1197
1201
let token_end = first_line
1198
1202
. char_indices ( )
1199
1203
. find ( |( _, c) | c. is_whitespace ( ) )
@@ -1206,14 +1210,14 @@ impl ChatComposer {
1206
1210
1207
1211
match & mut self . active_popup {
1208
1212
ActivePopup :: Command ( popup) => {
1209
- if in_slash_name_context {
1213
+ if is_editing_slash_command_name {
1210
1214
popup. on_composer_text_change ( first_line. to_string ( ) ) ;
1211
1215
} else {
1212
1216
self . active_popup = ActivePopup :: None ;
1213
1217
}
1214
1218
}
1215
1219
_ => {
1216
- if in_slash_name_context {
1220
+ if is_editing_slash_command_name {
1217
1221
let mut command_popup = CommandPopup :: new ( self . custom_prompts . clone ( ) ) ;
1218
1222
command_popup. on_composer_text_change ( first_line. to_string ( ) ) ;
1219
1223
self . active_popup = ActivePopup :: Command ( command_popup) ;
@@ -1644,10 +1648,6 @@ mod tests {
1644
1648
1645
1649
#[ test]
1646
1650
fn handle_paste_small_inserts_text ( ) {
1647
- use crossterm:: event:: KeyCode ;
1648
- use crossterm:: event:: KeyEvent ;
1649
- use crossterm:: event:: KeyModifiers ;
1650
-
1651
1651
let ( tx, _rx) = unbounded_channel :: < AppEvent > ( ) ;
1652
1652
let sender = AppEventSender :: new ( tx) ;
1653
1653
let mut composer = ChatComposer :: new (
@@ -1673,10 +1673,6 @@ mod tests {
1673
1673
1674
1674
#[ test]
1675
1675
fn empty_enter_returns_none ( ) {
1676
- use crossterm:: event:: KeyCode ;
1677
- use crossterm:: event:: KeyEvent ;
1678
- use crossterm:: event:: KeyModifiers ;
1679
-
1680
1676
let ( tx, _rx) = unbounded_channel :: < AppEvent > ( ) ;
1681
1677
let sender = AppEventSender :: new ( tx) ;
1682
1678
let mut composer = ChatComposer :: new (
@@ -1700,10 +1696,6 @@ mod tests {
1700
1696
1701
1697
#[ test]
1702
1698
fn handle_paste_large_uses_placeholder_and_replaces_on_submit ( ) {
1703
- use crossterm:: event:: KeyCode ;
1704
- use crossterm:: event:: KeyEvent ;
1705
- use crossterm:: event:: KeyModifiers ;
1706
-
1707
1699
let ( tx, _rx) = unbounded_channel :: < AppEvent > ( ) ;
1708
1700
let sender = AppEventSender :: new ( tx) ;
1709
1701
let mut composer = ChatComposer :: new (
@@ -1734,10 +1726,6 @@ mod tests {
1734
1726
1735
1727
#[ test]
1736
1728
fn edit_clears_pending_paste ( ) {
1737
- use crossterm:: event:: KeyCode ;
1738
- use crossterm:: event:: KeyEvent ;
1739
- use crossterm:: event:: KeyModifiers ;
1740
-
1741
1729
let large = "y" . repeat ( LARGE_PASTE_CHAR_THRESHOLD + 1 ) ;
1742
1730
let ( tx, _rx) = unbounded_channel :: < AppEvent > ( ) ;
1743
1731
let sender = AppEventSender :: new ( tx) ;
@@ -1759,9 +1747,6 @@ mod tests {
1759
1747
1760
1748
#[ test]
1761
1749
fn ui_snapshots ( ) {
1762
- use crossterm:: event:: KeyCode ;
1763
- use crossterm:: event:: KeyEvent ;
1764
- use crossterm:: event:: KeyModifiers ;
1765
1750
use ratatui:: Terminal ;
1766
1751
use ratatui:: backend:: TestBackend ;
1767
1752
@@ -1878,9 +1863,6 @@ mod tests {
1878
1863
1879
1864
// Test helper: simulate human typing with a brief delay and flush the paste-burst buffer
1880
1865
fn type_chars_humanlike ( composer : & mut ChatComposer , chars : & [ char ] ) {
1881
- use crossterm:: event:: KeyCode ;
1882
- use crossterm:: event:: KeyEvent ;
1883
- use crossterm:: event:: KeyModifiers ;
1884
1866
for & ch in chars {
1885
1867
let _ = composer. handle_key_event ( KeyEvent :: new ( KeyCode :: Char ( ch) , KeyModifiers :: NONE ) ) ;
1886
1868
std:: thread:: sleep ( ChatComposer :: recommended_paste_flush_delay ( ) ) ;
@@ -1890,10 +1872,6 @@ mod tests {
1890
1872
1891
1873
#[ test]
1892
1874
fn slash_init_dispatches_command_and_does_not_submit_literal_text ( ) {
1893
- use crossterm:: event:: KeyCode ;
1894
- use crossterm:: event:: KeyEvent ;
1895
- use crossterm:: event:: KeyModifiers ;
1896
-
1897
1875
let ( tx, _rx) = unbounded_channel :: < AppEvent > ( ) ;
1898
1876
let sender = AppEventSender :: new ( tx) ;
1899
1877
let mut composer = ChatComposer :: new (
@@ -1927,10 +1905,6 @@ mod tests {
1927
1905
1928
1906
#[ test]
1929
1907
fn slash_tab_completion_moves_cursor_to_end ( ) {
1930
- use crossterm:: event:: KeyCode ;
1931
- use crossterm:: event:: KeyEvent ;
1932
- use crossterm:: event:: KeyModifiers ;
1933
-
1934
1908
let ( tx, _rx) = unbounded_channel :: < AppEvent > ( ) ;
1935
1909
let sender = AppEventSender :: new ( tx) ;
1936
1910
let mut composer = ChatComposer :: new (
@@ -1952,10 +1926,6 @@ mod tests {
1952
1926
1953
1927
#[ test]
1954
1928
fn slash_mention_dispatches_command_and_inserts_at ( ) {
1955
- use crossterm:: event:: KeyCode ;
1956
- use crossterm:: event:: KeyEvent ;
1957
- use crossterm:: event:: KeyModifiers ;
1958
-
1959
1929
let ( tx, _rx) = unbounded_channel :: < AppEvent > ( ) ;
1960
1930
let sender = AppEventSender :: new ( tx) ;
1961
1931
let mut composer = ChatComposer :: new (
@@ -1987,10 +1957,6 @@ mod tests {
1987
1957
1988
1958
#[ test]
1989
1959
fn test_multiple_pastes_submission ( ) {
1990
- use crossterm:: event:: KeyCode ;
1991
- use crossterm:: event:: KeyEvent ;
1992
- use crossterm:: event:: KeyModifiers ;
1993
-
1994
1960
let ( tx, _rx) = unbounded_channel :: < AppEvent > ( ) ;
1995
1961
let sender = AppEventSender :: new ( tx) ;
1996
1962
let mut composer = ChatComposer :: new (
@@ -2066,10 +2032,6 @@ mod tests {
2066
2032
2067
2033
#[ test]
2068
2034
fn test_placeholder_deletion ( ) {
2069
- use crossterm:: event:: KeyCode ;
2070
- use crossterm:: event:: KeyEvent ;
2071
- use crossterm:: event:: KeyModifiers ;
2072
-
2073
2035
let ( tx, _rx) = unbounded_channel :: < AppEvent > ( ) ;
2074
2036
let sender = AppEventSender :: new ( tx) ;
2075
2037
let mut composer = ChatComposer :: new (
@@ -2138,10 +2100,6 @@ mod tests {
2138
2100
2139
2101
#[ test]
2140
2102
fn test_partial_placeholder_deletion ( ) {
2141
- use crossterm:: event:: KeyCode ;
2142
- use crossterm:: event:: KeyEvent ;
2143
- use crossterm:: event:: KeyModifiers ;
2144
-
2145
2103
let ( tx, _rx) = unbounded_channel :: < AppEvent > ( ) ;
2146
2104
let sender = AppEventSender :: new ( tx) ;
2147
2105
let mut composer = ChatComposer :: new (
@@ -2276,10 +2234,6 @@ mod tests {
2276
2234
2277
2235
#[ test]
2278
2236
fn backspace_with_multibyte_text_before_placeholder_does_not_panic ( ) {
2279
- use crossterm:: event:: KeyCode ;
2280
- use crossterm:: event:: KeyEvent ;
2281
- use crossterm:: event:: KeyModifiers ;
2282
-
2283
2237
let ( tx, _rx) = unbounded_channel :: < AppEvent > ( ) ;
2284
2238
let sender = AppEventSender :: new ( tx) ;
2285
2239
let mut composer = ChatComposer :: new (
@@ -2373,6 +2327,8 @@ mod tests {
2373
2327
2374
2328
#[ test]
2375
2329
fn selecting_custom_prompt_without_args_submits_content ( ) {
2330
+ let prompt_text = "Hello from saved prompt" ;
2331
+
2376
2332
let ( tx, _rx) = unbounded_channel :: < AppEvent > ( ) ;
2377
2333
let sender = AppEventSender :: new ( tx) ;
2378
2334
let mut composer = ChatComposer :: new (
@@ -2387,7 +2343,7 @@ mod tests {
2387
2343
composer. set_custom_prompts ( vec ! [ CustomPrompt {
2388
2344
name: "my-prompt" . to_string( ) ,
2389
2345
path: "/tmp/my-prompt.md" . to_string( ) . into( ) ,
2390
- content: "Hello from saved prompt" . to_string( ) ,
2346
+ content: prompt_text . to_string( ) ,
2391
2347
} ] ) ;
2392
2348
2393
2349
type_chars_humanlike (
@@ -2398,19 +2354,12 @@ mod tests {
2398
2354
let ( result, _needs_redraw) =
2399
2355
composer. handle_key_event ( KeyEvent :: new ( KeyCode :: Enter , KeyModifiers :: NONE ) ) ;
2400
2356
2401
- assert_eq ! (
2402
- InputResult :: Submitted ( "Hello from saved prompt" . to_string( ) ) ,
2403
- result
2404
- ) ;
2357
+ assert_eq ! ( InputResult :: Submitted ( prompt_text. to_string( ) ) , result) ;
2405
2358
assert ! ( composer. textarea. is_empty( ) ) ;
2406
2359
}
2407
2360
2408
2361
#[ test]
2409
2362
fn custom_prompt_submission_expands_arguments ( ) {
2410
- use crossterm:: event:: KeyCode ;
2411
- use crossterm:: event:: KeyEvent ;
2412
- use crossterm:: event:: KeyModifiers ;
2413
-
2414
2363
let ( tx, _rx) = unbounded_channel :: < AppEvent > ( ) ;
2415
2364
let sender = AppEventSender :: new ( tx) ;
2416
2365
let mut composer = ChatComposer :: new (
@@ -2441,15 +2390,8 @@ mod tests {
2441
2390
assert ! ( composer. textarea. is_empty( ) ) ;
2442
2391
}
2443
2392
2444
- // Note: manual UI flow test omitted for Enter-with-popup; core logic
2445
- // is covered by other prompt expansion tests.
2446
-
2447
2393
#[ test]
2448
2394
fn custom_prompt_submission_accepts_quoted_values ( ) {
2449
- use crossterm:: event:: KeyCode ;
2450
- use crossterm:: event:: KeyEvent ;
2451
- use crossterm:: event:: KeyModifiers ;
2452
-
2453
2395
let ( tx, _rx) = unbounded_channel :: < AppEvent > ( ) ;
2454
2396
let sender = AppEventSender :: new ( tx) ;
2455
2397
let mut composer = ChatComposer :: new (
@@ -2482,10 +2424,6 @@ mod tests {
2482
2424
2483
2425
#[ test]
2484
2426
fn custom_prompt_invalid_args_reports_error ( ) {
2485
- use crossterm:: event:: KeyCode ;
2486
- use crossterm:: event:: KeyEvent ;
2487
- use crossterm:: event:: KeyModifiers ;
2488
-
2489
2427
let ( tx, mut rx) = unbounded_channel :: < AppEvent > ( ) ;
2490
2428
let sender = AppEventSender :: new ( tx) ;
2491
2429
let mut composer = ChatComposer :: new (
@@ -2529,10 +2467,6 @@ mod tests {
2529
2467
2530
2468
#[ test]
2531
2469
fn custom_prompt_missing_required_args_reports_error ( ) {
2532
- use crossterm:: event:: KeyCode ;
2533
- use crossterm:: event:: KeyEvent ;
2534
- use crossterm:: event:: KeyModifiers ;
2535
-
2536
2470
let ( tx, mut rx) = unbounded_channel :: < AppEvent > ( ) ;
2537
2471
let sender = AppEventSender :: new ( tx) ;
2538
2472
let mut composer = ChatComposer :: new (
@@ -2581,10 +2515,6 @@ mod tests {
2581
2515
2582
2516
#[ test]
2583
2517
fn burst_paste_fast_small_buffers_and_flushes_on_stop ( ) {
2584
- use crossterm:: event:: KeyCode ;
2585
- use crossterm:: event:: KeyEvent ;
2586
- use crossterm:: event:: KeyModifiers ;
2587
-
2588
2518
let ( tx, _rx) = unbounded_channel :: < AppEvent > ( ) ;
2589
2519
let sender = AppEventSender :: new ( tx) ;
2590
2520
let mut composer = ChatComposer :: new (
@@ -2625,10 +2555,6 @@ mod tests {
2625
2555
2626
2556
#[ test]
2627
2557
fn burst_paste_fast_large_inserts_placeholder_on_flush ( ) {
2628
- use crossterm:: event:: KeyCode ;
2629
- use crossterm:: event:: KeyEvent ;
2630
- use crossterm:: event:: KeyModifiers ;
2631
-
2632
2558
let ( tx, _rx) = unbounded_channel :: < AppEvent > ( ) ;
2633
2559
let sender = AppEventSender :: new ( tx) ;
2634
2560
let mut composer = ChatComposer :: new (
0 commit comments