Skip to content

Commit dc63bee

Browse files
committed
Add file/folder name auto-completion in q chat
1 parent 151873d commit dc63bee

File tree

1 file changed

+48
-9
lines changed

1 file changed

+48
-9
lines changed

crates/q_cli/src/cli/chat/prompt.rs

+48-9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use eyre::Result;
55
use rustyline::completion::{
66
Completer,
77
extract_word,
8+
FilenameCompleter,
89
};
910
use rustyline::error::ReadlineError;
1011
use rustyline::highlight::{
@@ -61,11 +62,29 @@ pub fn generate_prompt(current_profile: Option<&str>) -> String {
6162
"> ".to_string()
6263
}
6364

64-
pub struct ChatCompleter {}
65+
pub struct ChatCompleter {
66+
filename_completer: FilenameCompleter,
67+
}
6568

6669
impl ChatCompleter {
6770
fn new() -> Self {
68-
Self {}
71+
Self {
72+
filename_completer: FilenameCompleter::new(),
73+
}
74+
}
75+
76+
// Check if the input might be referring to a file path
77+
fn is_path_context(&self, line: &str) -> bool {
78+
// Check for common file path indicators in the input
79+
line.contains("file:") ||
80+
line.contains("path:") ||
81+
line.contains("directory:") ||
82+
line.contains("folder:") ||
83+
line.contains("open ") ||
84+
line.contains("read ") ||
85+
line.contains("cat ") ||
86+
line.contains("ls ") ||
87+
line.contains("cd ")
6988
}
7089
}
7190

@@ -79,18 +98,38 @@ impl Completer for ChatCompleter {
7998
_ctx: &Context<'_>,
8099
) -> Result<(usize, Vec<Self::Candidate>), ReadlineError> {
81100
let (start, word) = extract_word(line, pos, None, |c| c.is_space());
82-
Ok((
83-
start,
84-
if word.starts_with('/') {
101+
102+
// Handle command completion
103+
if word.starts_with('/') {
104+
return Ok((
105+
start,
85106
COMMANDS
86107
.iter()
87108
.filter(|p| p.starts_with(word))
88109
.map(|s| (*s).to_owned())
89110
.collect()
90-
} else {
91-
Vec::new()
92-
},
93-
))
111+
));
112+
}
113+
114+
// Handle file path completion if the word contains path separators or context suggests file paths
115+
if word.contains('/') || word.starts_with('~') || self.is_path_context(line) {
116+
// Use the filename completer to get path completions
117+
if let Ok((pos, completions)) = self.filename_completer.complete(line, pos, _ctx) {
118+
// Convert the filename completer's pairs to strings
119+
let file_completions: Vec<String> = completions
120+
.iter()
121+
.map(|pair| pair.replacement.clone())
122+
.collect();
123+
124+
// If we have completions, return them
125+
if !file_completions.is_empty() {
126+
return Ok((pos, file_completions));
127+
}
128+
}
129+
}
130+
131+
// Default: no completions
132+
Ok((start, Vec::new()))
94133
}
95134
}
96135

0 commit comments

Comments
 (0)