Skip to content

Commit

Permalink
dd filename input with autocompletion support
Browse files Browse the repository at this point in the history
Implement a new function to handle filename input with autocompletion, enhancing user experience and functionality. This change replaces the old user input method used for file saving, which lacked autocompletion features. The new implementation leverages Rustyline's `FilenameCompleter`, providing users with a more intuitive and efficient way to specify file paths while saving content.
  • Loading branch information
Christian Stolz committed Oct 4, 2024
1 parent ebfc303 commit 464c298
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/chat/commands/save_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::chat::{
interface::{ChatBackend, ChatStorage, MessageRole},
service::ChatService,
};
use crate::cli::editor::get_user_input;
use crate::cli::editor::{get_filename_input, get_user_input};
use crate::openai_api::openai_interface::OpenAIInterface;
use regex::Regex;
use std::error::Error;
Expand Down Expand Up @@ -88,8 +88,8 @@ fn save_content(content: &str) -> Result<(), Box<dyn Error>> {
}

let default_file_name = "extracted_content.txt";
let user_file_path = get_user_input(&format!(
"Enter file path to save the content (default: {}): ",
let user_file_path = get_filename_input(&format!(
"Enter file path to save the content (default: {}). Use <Tab> file for autocompletion: ",
default_file_name
))?;
let file_path = if user_file_path.trim().is_empty() {
Expand Down
78 changes: 78 additions & 0 deletions src/cli/editor/filename_input_editor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use std::borrow::Cow::{self, Borrowed, Owned};

use crate::cli::style::configure_mad_skin;
use rustyline::completion::FilenameCompleter;
use rustyline::error::ReadlineError;
use rustyline::highlight::{Highlighter, MatchingBracketHighlighter};
use rustyline::hint::HistoryHinter;
use rustyline::validate::MatchingBracketValidator;
use rustyline::{Cmd, CompletionType, Config, EditMode, Editor, KeyEvent};
use rustyline::{Completer, Helper, Hinter, Validator};

#[derive(Helper, Completer, Hinter, Validator)]
struct MyHelper {
#[rustyline(Completer)]
completer: FilenameCompleter,
highlighter: MatchingBracketHighlighter,
#[rustyline(Validator)]
validator: MatchingBracketValidator,
#[rustyline(Hinter)]
hinter: HistoryHinter,
colored_prompt: String,
}

impl Highlighter for MyHelper {
fn highlight<'l>(&self, line: &'l str, pos: usize) -> Cow<'l, str> {
self.highlighter.highlight(line, pos)
}

fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
&'s self,
prompt: &'p str,
default: bool,
) -> Cow<'b, str> {
if default {
Borrowed(&self.colored_prompt)
} else {
Borrowed(prompt)
}
}

fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
Owned("\x1b[1m".to_owned() + hint + "\x1b[m")
}

fn highlight_char(&self, line: &str, pos: usize, forced: bool) -> bool {
self.highlighter.highlight_char(line, pos, forced)
}
}

pub fn get_filename_input(prompt: &str) -> Result<String, Box<dyn std::error::Error>> {
let config = Config::builder()
.history_ignore_space(true)
.completion_type(CompletionType::List)
.edit_mode(EditMode::Emacs)
.build();
let h = MyHelper {
completer: FilenameCompleter::new(),
highlighter: MatchingBracketHighlighter::new(),
hinter: HistoryHinter::new(),
colored_prompt: "".to_owned(),
validator: MatchingBracketValidator::new(),
};
let mut rl = Editor::with_config(config)?;
rl.set_helper(Some(h));
rl.bind_sequence(KeyEvent::alt('n'), Cmd::HistorySearchForward);
rl.bind_sequence(KeyEvent::alt('p'), Cmd::HistorySearchBackward);

// Print a styled prompt
let skin = configure_mad_skin();
skin.print_text("---\n");
skin.print_text(&format!("**{}**", prompt)); // Make the prompt bold and colored
match rl.readline("") {
Ok(input) => Ok(input.trim().to_string()),
Err(ReadlineError::Interrupted) => Ok(String::new()), // Return empty string as cancelation
Err(ReadlineError::Eof) => Ok(String::new()),
Err(err) => Err(Box::new(err)),
}
}
3 changes: 3 additions & 0 deletions src/cli/editor/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
mod filename_input_editor;
mod multiline_editor;
mod user_input_editor;

pub use multiline_editor::get_multiline_input;

pub use user_input_editor::get_user_input;

pub use filename_input_editor::get_filename_input;

0 comments on commit 464c298

Please sign in to comment.