working find palette now properly well
This commit is contained in:
@@ -82,6 +82,8 @@ impl TableDependencyGraph {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ... (NavigationState struct and its new(), activate_*, deactivate(), add_char(), remove_char(), move_*, autocomplete_selected(), get_display_input() methods are unchanged) ...
|
||||
pub struct NavigationState {
|
||||
pub active: bool,
|
||||
pub input: String,
|
||||
@@ -114,7 +116,7 @@ impl NavigationState {
|
||||
self.input.clear();
|
||||
self.current_path.clear();
|
||||
self.graph = None;
|
||||
self.update_filtered_options(); // Initial filter with empty input
|
||||
self.update_filtered_options();
|
||||
}
|
||||
|
||||
pub fn activate_table_tree(&mut self, graph: TableDependencyGraph) {
|
||||
@@ -123,7 +125,7 @@ impl NavigationState {
|
||||
self.graph = Some(graph);
|
||||
self.input.clear();
|
||||
self.current_path.clear();
|
||||
self.update_options_for_path(); // Initial options are root tables
|
||||
self.update_options_for_path();
|
||||
}
|
||||
|
||||
pub fn deactivate(&mut self) {
|
||||
@@ -145,7 +147,6 @@ impl NavigationState {
|
||||
NavigationType::TableTree => {
|
||||
if c == '/' {
|
||||
if !self.input.is_empty() {
|
||||
// Append current input to path
|
||||
if self.current_path.is_empty() {
|
||||
self.current_path = self.input.clone();
|
||||
} else {
|
||||
@@ -155,10 +156,9 @@ impl NavigationState {
|
||||
self.input.clear();
|
||||
self.update_options_for_path();
|
||||
}
|
||||
// If input is empty and char is '/', do nothing or define behavior
|
||||
} else {
|
||||
self.input.push(c);
|
||||
self.update_filtered_options(); // Filter current level options based on input
|
||||
self.update_filtered_options();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,24 +172,15 @@ impl NavigationState {
|
||||
}
|
||||
NavigationType::TableTree => {
|
||||
if self.input.is_empty() {
|
||||
// If input is empty, try to go up in path
|
||||
if !self.current_path.is_empty() {
|
||||
if let Some(last_slash_idx) =
|
||||
self.current_path.rfind('/')
|
||||
{
|
||||
// Set input to the segment being removed from path
|
||||
self.input = self.current_path
|
||||
[last_slash_idx + 1..]
|
||||
.to_string();
|
||||
self.current_path =
|
||||
self.current_path[..last_slash_idx].to_string();
|
||||
if let Some(last_slash_idx) = self.current_path.rfind('/') {
|
||||
self.input = self.current_path[last_slash_idx + 1..].to_string();
|
||||
self.current_path = self.current_path[..last_slash_idx].to_string();
|
||||
} else {
|
||||
// Path was a single segment
|
||||
self.input = self.current_path.clone();
|
||||
self.current_path.clear();
|
||||
}
|
||||
self.update_options_for_path();
|
||||
// After path change, current input might match some options, so filter
|
||||
self.update_filtered_options();
|
||||
}
|
||||
} else {
|
||||
@@ -218,9 +209,7 @@ impl NavigationState {
|
||||
return;
|
||||
}
|
||||
self.selected_index = match self.selected_index {
|
||||
Some(current) if current >= self.filtered_options.len() - 1 => {
|
||||
Some(0)
|
||||
}
|
||||
Some(current) if current >= self.filtered_options.len() - 1 => Some(0),
|
||||
Some(current) => Some(current + 1),
|
||||
None => Some(0),
|
||||
};
|
||||
@@ -234,18 +223,11 @@ impl NavigationState {
|
||||
|
||||
pub fn autocomplete_selected(&mut self) {
|
||||
if let Some(selected_option_str) = self.get_selected_option_str() {
|
||||
// The current `self.input` is the text being typed for the current segment/filter.
|
||||
// We replace it with the full string of the selected option.
|
||||
self.input = selected_option_str.to_string();
|
||||
|
||||
// After updating the input, we need to re-filter the options.
|
||||
// This will typically result in the filtered_options containing only the
|
||||
// autocompleted item (or items that start with it, if any).
|
||||
self.update_filtered_options();
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the string to display in the input line of the palette
|
||||
pub fn get_display_input(&self) -> String {
|
||||
match self.navigation_type {
|
||||
NavigationType::FindFile => self.input.clone(),
|
||||
@@ -259,11 +241,12 @@ impl NavigationState {
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the full path of the currently selected item for TableTree, or input for FindFile
|
||||
// --- START FIX ---
|
||||
pub fn get_selected_value(&self) -> Option<String> {
|
||||
match self.navigation_type {
|
||||
NavigationType::FindFile => {
|
||||
if self.input.is_empty() { None } else { Some(self.input.clone()) }
|
||||
// Return the highlighted option, not the raw input buffer.
|
||||
self.get_selected_option_str().map(|s| s.to_string())
|
||||
}
|
||||
NavigationType::TableTree => {
|
||||
self.get_selected_option_str().map(|selected_name| {
|
||||
@@ -276,26 +259,23 @@ impl NavigationState {
|
||||
}
|
||||
}
|
||||
}
|
||||
// --- END FIX ---
|
||||
|
||||
// Update self.all_options based on current_path (for TableTree)
|
||||
fn update_options_for_path(&mut self) {
|
||||
if let NavigationType::TableTree = self.navigation_type {
|
||||
if let Some(graph) = &self.graph {
|
||||
self.all_options =
|
||||
graph.get_dependent_children(&self.current_path);
|
||||
self.all_options = graph.get_dependent_children(&self.current_path);
|
||||
} else {
|
||||
self.all_options.clear();
|
||||
}
|
||||
}
|
||||
// For FindFile, all_options is set once at activation.
|
||||
self.update_filtered_options();
|
||||
}
|
||||
|
||||
// Update self.filtered_options based on self.all_options and self.input
|
||||
fn update_filtered_options(&mut self) {
|
||||
let filter_text = match self.navigation_type {
|
||||
NavigationType::FindFile => &self.input,
|
||||
NavigationType::TableTree => &self.input, // For TableTree, input is the current segment being typed
|
||||
NavigationType::TableTree => &self.input,
|
||||
}
|
||||
.to_lowercase();
|
||||
|
||||
@@ -319,11 +299,12 @@ impl NavigationState {
|
||||
if self.filtered_options.is_empty() {
|
||||
self.selected_index = None;
|
||||
} else {
|
||||
self.selected_index = Some(0); // Default to selecting the first item
|
||||
self.selected_index = Some(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn handle_command_navigation_event(
|
||||
navigation_state: &mut NavigationState,
|
||||
key: KeyEvent,
|
||||
@@ -338,55 +319,15 @@ pub async fn handle_command_navigation_event(
|
||||
navigation_state.deactivate();
|
||||
Ok(EventOutcome::Ok("Navigation cancelled".to_string()))
|
||||
}
|
||||
KeyCode::Enter => {
|
||||
if let Some(selected_value) = navigation_state.get_selected_value() {
|
||||
let outcome = match navigation_state.navigation_type {
|
||||
NavigationType::FindFile => {
|
||||
EventOutcome::Ok(format!("Selected file: {}", selected_value))
|
||||
}
|
||||
NavigationType::TableTree => {
|
||||
EventOutcome::TableSelected { path: selected_value }
|
||||
}
|
||||
};
|
||||
navigation_state.deactivate();
|
||||
Ok(outcome)
|
||||
} else {
|
||||
// Enhanced Enter behavior for TableTree: if input is a valid partial path, try to navigate
|
||||
if navigation_state.navigation_type == NavigationType::TableTree && !navigation_state.input.is_empty() {
|
||||
// Check if current input is a prefix of any option or a full option name
|
||||
if let Some(selected_opt_str) = navigation_state.get_selected_option_str() {
|
||||
if navigation_state.input == selected_opt_str {
|
||||
// Input exactly matches the selected option, try to navigate
|
||||
let input_before_slash = navigation_state.input.clone();
|
||||
navigation_state.add_char('/');
|
||||
|
||||
if navigation_state.input.is_empty() {
|
||||
return Ok(EventOutcome::Ok(format!("Navigated to: {}/", input_before_slash)));
|
||||
} else {
|
||||
return Ok(EventOutcome::Ok(format!("Selected leaf: {}", input_before_slash)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(EventOutcome::Ok("No valid selection to confirm or navigate".to_string()))
|
||||
}
|
||||
}
|
||||
KeyCode::Tab => {
|
||||
if let Some(selected_opt_str) = navigation_state.get_selected_option_str() {
|
||||
// Scenario 1: Input already exactly matches the selected option
|
||||
if navigation_state.input == selected_opt_str {
|
||||
// Only attempt to navigate deeper for TableTree mode
|
||||
if navigation_state.navigation_type == NavigationType::TableTree {
|
||||
let path_before_nav = navigation_state.current_path.clone();
|
||||
let input_before_nav = navigation_state.input.clone();
|
||||
|
||||
navigation_state.add_char('/');
|
||||
|
||||
if navigation_state.input.is_empty() &&
|
||||
(navigation_state.current_path != path_before_nav || !navigation_state.all_options.is_empty()) {
|
||||
// Navigation successful
|
||||
} else {
|
||||
// Revert if navigation didn't happen
|
||||
if !(navigation_state.input.is_empty() &&
|
||||
(navigation_state.current_path != path_before_nav || !navigation_state.all_options.is_empty())) {
|
||||
if !navigation_state.input.is_empty() && navigation_state.input != input_before_nav {
|
||||
navigation_state.input = input_before_nav;
|
||||
if navigation_state.current_path != path_before_nav {
|
||||
@@ -397,20 +338,11 @@ pub async fn handle_command_navigation_event(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Scenario 2: Input is a partial match - autocomplete
|
||||
navigation_state.autocomplete_selected();
|
||||
}
|
||||
}
|
||||
Ok(EventOutcome::Ok(String::new()))
|
||||
}
|
||||
KeyCode::Up => {
|
||||
navigation_state.move_up();
|
||||
Ok(EventOutcome::Ok(String::new()))
|
||||
}
|
||||
KeyCode::Down => {
|
||||
navigation_state.move_down();
|
||||
Ok(EventOutcome::Ok(String::new()))
|
||||
}
|
||||
KeyCode::Backspace => {
|
||||
navigation_state.remove_char();
|
||||
Ok(EventOutcome::Ok(String::new()))
|
||||
@@ -432,12 +364,24 @@ pub async fn handle_command_navigation_event(
|
||||
}
|
||||
"select" => {
|
||||
if let Some(selected_value) = navigation_state.get_selected_value() {
|
||||
let message = match navigation_state.navigation_type {
|
||||
NavigationType::FindFile => format!("Selected file: {}", selected_value),
|
||||
NavigationType::TableTree => format!("Selected table: {}", selected_value),
|
||||
let outcome = match navigation_state.navigation_type {
|
||||
// --- START FIX ---
|
||||
NavigationType::FindFile => {
|
||||
// The purpose of this palette is to select a table.
|
||||
// Emit a TableSelected event instead of a generic Ok message.
|
||||
EventOutcome::TableSelected {
|
||||
path: selected_value,
|
||||
}
|
||||
}
|
||||
// --- END FIX ---
|
||||
NavigationType::TableTree => {
|
||||
EventOutcome::TableSelected {
|
||||
path: selected_value,
|
||||
}
|
||||
}
|
||||
};
|
||||
navigation_state.deactivate();
|
||||
Ok(EventOutcome::Ok(message))
|
||||
Ok(outcome)
|
||||
} else {
|
||||
Ok(EventOutcome::Ok("No selection".to_string()))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user