suggestions on tab, still not working yet
This commit is contained in:
@@ -52,10 +52,12 @@ delete_char_forward = ["delete"]
|
||||
delete_char_backward = ["backspace"]
|
||||
next_field = ["enter"]
|
||||
prev_field = ["backtab"]
|
||||
suggestion_down = ["shift+tab"]
|
||||
suggestion_up = ["tab"]
|
||||
move_left = ["left"]
|
||||
move_right = ["right"]
|
||||
suggestion_down = ["shift+tab"]
|
||||
suggestion_up = ["tab"]
|
||||
select_suggestion = ["enter"]
|
||||
exit_suggestion_mode = ["esc"]
|
||||
|
||||
[keybindings.command]
|
||||
exit_command_mode = ["ctrl+g", "esc"]
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
use crate::config::colors::themes::Theme;
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
layout::Rect,
|
||||
style::{Modifier, Style},
|
||||
widgets::{Block, Borders, List, ListItem, ListState},
|
||||
style::{Color, Modifier, Style},
|
||||
widgets::{List, ListItem, ListState, StatefulWidget, Widget},
|
||||
Frame,
|
||||
};
|
||||
|
||||
@@ -19,25 +20,27 @@ pub fn render_autocomplete_dropdown(
|
||||
if suggestions.is_empty() {
|
||||
return; // Don't render if no suggestions
|
||||
}
|
||||
// --- Render Background ---
|
||||
struct GrayBackground;
|
||||
impl Widget for GrayBackground {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
buf.set_style(area, Style::default().bg(Color::DarkGray)); // Set background
|
||||
}
|
||||
}
|
||||
f.render_widget(GrayBackground, area);
|
||||
|
||||
// --- Render Suggestions List (without block/border) ---
|
||||
let items: Vec<ListItem> = suggestions
|
||||
.iter()
|
||||
.map(|s| ListItem::new(s.as_str()))
|
||||
.map(|s| ListItem::new(s.as_str()).style(Style::default().fg(theme.fg))) // Set default text color
|
||||
.collect();
|
||||
|
||||
let list = List::new(items)
|
||||
.block(
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_type(ratatui::widgets::BorderType::Plain)
|
||||
.border_style(Style::default().fg(theme.accent)) // Highlight border
|
||||
.style(Style::default().bg(theme.bg).fg(theme.fg)),
|
||||
)
|
||||
.highlight_style(
|
||||
Style::default()
|
||||
.add_modifier(Modifier::BOLD)
|
||||
.bg(theme.highlight) // Highlight background for selected item
|
||||
.fg(theme.bg), // Text color for selected item
|
||||
.bg(theme.highlight)
|
||||
.fg(theme.bg),
|
||||
)
|
||||
.highlight_symbol("> "); // Symbol for selected item
|
||||
|
||||
|
||||
@@ -299,13 +299,13 @@ pub async fn execute_edit_action<S: CanvasState + Any + Send>(
|
||||
}
|
||||
|
||||
// --- Autocomplete Actions ---
|
||||
"suggestion_down" | "suggestion_up" | "select_suggestion" | "hide_suggestions" => {
|
||||
"suggestion_down" | "suggestion_up" | "select_suggestion" | "exit_suggestion_mode" => {
|
||||
// Attempt to downcast to RegisterState
|
||||
if let Some(register_state) = (state as &mut dyn Any).downcast_mut::<RegisterState>() {
|
||||
// Only handle if it's the role field (index 4) and suggestions are shown (except for hide)
|
||||
if register_state.current_field() == 4 {
|
||||
match action {
|
||||
"suggestion_down" if register_state.show_role_suggestions => {
|
||||
"suggestion_down" if register_state.in_suggestion_mode => {
|
||||
let max_index = register_state.role_suggestions.len().saturating_sub(1);
|
||||
let current_index = register_state.selected_suggestion_index.unwrap_or(0);
|
||||
register_state.selected_suggestion_index = Some(if current_index >= max_index { 0 } else { current_index + 1 });
|
||||
@@ -317,7 +317,7 @@ pub async fn execute_edit_action<S: CanvasState + Any + Send>(
|
||||
register_state.selected_suggestion_index = Some(if current_index == 0 { max_index } else { current_index.saturating_sub(1) });
|
||||
Ok("Suggestion changed up".to_string())
|
||||
}
|
||||
"select_suggestion" if register_state.show_role_suggestions => {
|
||||
"select_suggestion" if register_state.in_suggestion_mode => {
|
||||
if let Some(selected_index) = register_state.selected_suggestion_index {
|
||||
if let Some(selected_role) = register_state.role_suggestions.get(selected_index) {
|
||||
register_state.role = selected_role.clone();
|
||||
@@ -335,9 +335,10 @@ pub async fn execute_edit_action<S: CanvasState + Any + Send>(
|
||||
Ok("No suggestion selected".to_string())
|
||||
}
|
||||
}
|
||||
"hide_suggestions" => {
|
||||
"exit_suggestion_mode" => { // Handle Esc
|
||||
register_state.show_role_suggestions = false;
|
||||
register_state.selected_suggestion_index = None;
|
||||
register_state.in_suggestion_mode = false;
|
||||
Ok("Suggestions hidden".to_string())
|
||||
}
|
||||
_ => Ok("".to_string()) // Action doesn't apply in this state (e.g., suggestions not shown)
|
||||
|
||||
@@ -80,6 +80,29 @@ pub async fn handle_edit_event(
|
||||
|
||||
// Edit-specific actions
|
||||
if let Some(action) = config.get_edit_action_for_key(key.code, key.modifiers) {
|
||||
// --- Special Handling for Tab/Shift+Tab in Role Field ---
|
||||
if app_state.ui.show_register && register_state.current_field() == 4 {
|
||||
match action {
|
||||
"suggestion_up" | "suggestion_down" => { // Mapped to Tab/Shift+Tab
|
||||
if !register_state.in_suggestion_mode {
|
||||
// Enter suggestion mode
|
||||
register_state.update_role_suggestions(); // Populate suggestions
|
||||
if !register_state.role_suggestions.is_empty() {
|
||||
register_state.in_suggestion_mode = true;
|
||||
register_state.show_role_suggestions = true;
|
||||
register_state.selected_suggestion_index = Some(0); // Select first
|
||||
return Ok("Suggestions shown".to_string()); // Consume the event
|
||||
} else {
|
||||
return Ok("No suggestions available".to_string()); // Consume, do nothing else
|
||||
}
|
||||
}
|
||||
// If already in suggestion mode, fall through to execute the action via auth_e
|
||||
}
|
||||
_ => {} // Other actions fall through
|
||||
}
|
||||
}
|
||||
// --- End Special Handling ---
|
||||
|
||||
return if app_state.ui.show_login {
|
||||
auth_e::execute_edit_action(
|
||||
action,
|
||||
@@ -115,6 +138,12 @@ pub async fn handle_edit_event(
|
||||
|
||||
// Character insertion
|
||||
if let KeyCode::Char(_) = key.code {
|
||||
// If in suggestion mode, exit it before inserting char
|
||||
if app_state.ui.show_register && register_state.in_suggestion_mode {
|
||||
register_state.in_suggestion_mode = false;
|
||||
register_state.show_role_suggestions = false;
|
||||
register_state.selected_suggestion_index = None;
|
||||
}
|
||||
let is_role_field = app_state.ui.show_register && register_state.current_field() == 4;
|
||||
// --- End Autocomplete Trigger ---
|
||||
|
||||
@@ -149,15 +178,16 @@ pub async fn handle_edit_event(
|
||||
total_count
|
||||
).await
|
||||
};
|
||||
|
||||
// After character insertion/deletion, update suggestions if it was the role field
|
||||
if is_role_field {
|
||||
register_state.update_role_suggestions();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Backspace/Delete for Autocomplete Trigger
|
||||
if matches!(key.code, KeyCode::Backspace | KeyCode::Delete) {
|
||||
// If in suggestion mode, exit it before deleting char
|
||||
if app_state.ui.show_register && register_state.in_suggestion_mode {
|
||||
register_state.in_suggestion_mode = false;
|
||||
register_state.show_role_suggestions = false;
|
||||
register_state.selected_suggestion_index = None;
|
||||
}
|
||||
let is_role_field = app_state.ui.show_register && register_state.current_field() == 4;
|
||||
let action_str = if key.code == KeyCode::Backspace { "backspace" } else { "delete_char" };
|
||||
|
||||
@@ -177,9 +207,6 @@ pub async fn handle_edit_event(
|
||||
Ok("Action not applicable here".to_string()) // Placeholder
|
||||
}?;
|
||||
|
||||
if is_role_field {
|
||||
register_state.update_role_suggestions();
|
||||
}
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,10 @@ use lazy_static::lazy_static;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref AVAILABLE_ROLES: Vec<String> = vec![
|
||||
"accountant".to_string(),
|
||||
"admin".to_string(),
|
||||
"moderator".to_string(),
|
||||
"accountant".to_string(),
|
||||
"viewer".to_string(),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -37,6 +39,7 @@ pub struct RegisterState {
|
||||
pub show_role_suggestions: bool,
|
||||
pub role_suggestions: Vec<String>,
|
||||
pub selected_suggestion_index: Option<usize>,
|
||||
pub in_suggestion_mode: bool,
|
||||
}
|
||||
|
||||
impl AuthState {
|
||||
@@ -71,6 +74,7 @@ impl RegisterState {
|
||||
show_role_suggestions: false,
|
||||
role_suggestions: Vec::new(),
|
||||
selected_suggestion_index: None,
|
||||
in_suggestion_mode: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,9 +82,7 @@ impl RegisterState {
|
||||
pub fn update_role_suggestions(&mut self) {
|
||||
let current_input = self.role.to_lowercase();
|
||||
if current_input.is_empty() {
|
||||
self.role_suggestions = Vec::new(); // Or show all? For now, clear.
|
||||
self.show_role_suggestions = false;
|
||||
self.selected_suggestion_index = None;
|
||||
self.role_suggestions = AVAILABLE_ROLES.to_vec();
|
||||
} else {
|
||||
self.role_suggestions = AVAILABLE_ROLES
|
||||
.iter()
|
||||
@@ -88,7 +90,6 @@ impl RegisterState {
|
||||
.cloned()
|
||||
.collect();
|
||||
self.show_role_suggestions = !self.role_suggestions.is_empty();
|
||||
self.selected_suggestion_index = if self.show_role_suggestions { Some(0) } else { None }; // Default to first suggestion selected
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -269,7 +270,7 @@ impl CanvasState for RegisterState {
|
||||
|
||||
fn get_suggestions(&self) -> Option<&[String]> {
|
||||
// Only show suggestions for the role field (index 4) when requested
|
||||
if self.current_field == 4 && self.show_role_suggestions {
|
||||
if self.current_field == 4 && self.in_suggestion_mode && self.show_role_suggestions {
|
||||
Some(&self.role_suggestions)
|
||||
} else {
|
||||
None
|
||||
@@ -277,8 +278,7 @@ impl CanvasState for RegisterState {
|
||||
}
|
||||
|
||||
fn get_selected_suggestion_index(&self) -> Option<usize> {
|
||||
// Only return index if suggestions are shown for the role field
|
||||
if self.current_field == 4 && self.show_role_suggestions {
|
||||
if self.current_field == 4 && self.in_suggestion_mode && self.show_role_suggestions {
|
||||
self.selected_suggestion_index
|
||||
} else {
|
||||
None
|
||||
|
||||
Reference in New Issue
Block a user