vtcode_tui/core_tui/session/
palette.rs1use ratatui::crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
9use std::path::PathBuf;
10
11use super::{
12 Session,
13 file_palette::{FilePalette, extract_file_reference},
14};
15use crate::ui::tui::session::slash;
16
17impl Session {
18 pub(super) fn load_file_palette(&mut self, files: Vec<String>, workspace: PathBuf) {
20 let mut palette = FilePalette::new(workspace);
21 palette.load_files(files);
22 self.file_palette = Some(palette);
23 self.file_palette_active = false;
24 self.check_file_reference_trigger();
25 }
26
27 pub fn check_file_reference_trigger(&mut self) {
29 if let Some(palette) = self.file_palette.as_mut() {
30 if let Some((_start, _end, query)) =
31 extract_file_reference(self.input_manager.content(), self.input_manager.cursor())
32 {
33 palette.set_filter(query);
34 if !self.file_palette_active {
35 self.ensure_inline_lists_visible_for_trigger();
36 self.file_palette_active = true;
37 self.needs_full_clear = true;
38 self.mark_dirty();
39 }
40 } else if self.file_palette_active {
41 self.close_file_palette();
42 }
43 }
44 }
45
46 pub(super) fn close_file_palette(&mut self) {
48 self.file_palette_active = false;
49 self.needs_full_clear = true;
50
51 if let Some(palette) = self.file_palette.as_mut() {
53 palette.set_filter(String::new());
54 }
55 }
56
57 pub(super) fn handle_file_palette_key(&mut self, key: &KeyEvent) -> bool {
61 if !self.file_palette_active {
62 return false;
63 }
64
65 let Some(palette) = self.file_palette.as_mut() else {
66 return false;
67 };
68
69 match key.code {
70 KeyCode::Up => {
71 palette.move_selection_up();
72 self.mark_dirty();
73 true
74 }
75 KeyCode::Down => {
76 palette.move_selection_down();
77 self.mark_dirty();
78 true
79 }
80 KeyCode::Tab => {
81 palette.select_best_match();
82 self.mark_dirty();
83 true
84 }
85 KeyCode::Enter => {
86 let selected_path = palette.get_selected().map(|e| e.relative_path.clone());
87 if let Some(path) = selected_path {
88 self.insert_file_reference(&path);
89 self.close_file_palette();
90 self.mark_dirty();
91 true } else {
93 self.close_file_palette();
95 self.mark_dirty();
96 false }
98 }
99 KeyCode::Esc => {
100 self.close_file_palette();
101 self.mark_dirty();
102 true
103 }
104 KeyCode::Char('n') if key.modifiers.contains(KeyModifiers::CONTROL) => {
105 palette.move_selection_down();
106 self.mark_dirty();
107 true
108 }
109 KeyCode::Char('p') if key.modifiers.contains(KeyModifiers::CONTROL) => {
110 palette.move_selection_up();
111 self.mark_dirty();
112 true
113 }
114 _ => false,
115 }
116 }
117
118 pub(super) fn insert_file_reference(&mut self, file_path: &str) {
120 if let Some((start, end, _)) =
121 extract_file_reference(self.input_manager.content(), self.input_manager.cursor())
122 {
123 let before = &self.input_manager.content()[..start];
124 let after = &self.input_manager.content()[end..];
125 let reference_alias = format!("@{}", file_path);
126 let new_content = format!("{}{} {}", before, reference_alias, after);
127 let new_cursor = start + reference_alias.len() + 1;
128
129 self.input_manager.set_content(new_content);
130 self.input_manager.set_cursor(new_cursor);
131 slash::update_slash_suggestions(self);
132 }
133 }
134}