aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/completion.rs62
-rw-r--r--src/main.rs62
2 files changed, 71 insertions, 53 deletions
diff --git a/src/completion.rs b/src/completion.rs
index 3e2565b..c7a183f 100644
--- a/src/completion.rs
+++ b/src/completion.rs
@@ -1,3 +1,4 @@
+use crate::parse::{self, CompletionContext};
use crate::{BString, Session};
use std::collections::HashMap;
use std::ffi::OsStr;
@@ -139,3 +140,64 @@ pub fn command_completion(session: Arc<Mutex<Session>>, prefix: BString) -> Vec<
out
}
+
+pub struct CompletionResult {
+ pub kind: parse::CompletionKind,
+ pub suggestions: Vec<Suggestion>,
+ pub shared_prefix: BString,
+}
+
+impl CompletionResult {
+ pub fn empty() -> Self {
+ CompletionResult {
+ kind: parse::CompletionKind::None,
+ suggestions: Vec::new(),
+ shared_prefix: BString::new(),
+ }
+ }
+}
+
+pub fn completion(session: Arc<Mutex<Session>>, cmd: &[u8]) -> CompletionResult {
+ let comp = parse::completion_context(
+ &cmd,
+ &mut crate::run::Executor::new_for_completion(session.clone()),
+ );
+
+ let mut suggestions = match comp.kind {
+ parse::CompletionKind::Command => command_completion(session.clone(), comp.partial),
+ parse::CompletionKind::Argument => path_completion(comp.partial),
+ parse::CompletionKind::Variable => variable_completion(session.clone(), comp.partial),
+ parse::CompletionKind::None => return CompletionResult::empty(),
+ };
+
+ suggestions.sort_by(|x, y| x.delta.cmp(&y.delta));
+ suggestions.dedup_by(|x, y| x.delta == y.delta);
+
+ if suggestions.is_empty() {
+ return CompletionResult {
+ kind: comp.kind,
+ ..CompletionResult::empty()
+ };
+ }
+
+ // find longest shared prefix
+ let mut shared_prefix = &suggestions[0].delta[..];
+ for s in suggestions.iter() {
+ let mut new = &shared_prefix[..0];
+ for i in 0..shared_prefix.len().min(s.delta.len()) {
+ if shared_prefix[i] != s.delta[i] {
+ break;
+ } else {
+ new = &s.delta[..=i];
+ }
+ }
+ shared_prefix = new;
+ }
+ let shared_prefix = shared_prefix.to_vec();
+
+ CompletionResult {
+ kind: comp.kind,
+ suggestions,
+ shared_prefix,
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index b7c3dc5..a9a0ff0 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -34,7 +34,7 @@ pub mod wait;
use linebuf::LineBuf;
use raw::*;
-use crate::completion::PathCache;
+use crate::completion::{PathCache, completion};
use crate::ctrlc::CtrlC;
use crate::cursor::{Direction, move_cursor};
use crate::history::HistoryEntry;
@@ -368,65 +368,21 @@ fn event_loop() {
b'\t' => {
let cmd = se.line.pre().to_vec();
drop(se);
- let comp = parse::completion_context(
- &cmd,
- &mut Executor::new_for_completion(session.clone()),
- );
-
- let mut suggestions = match comp.kind {
- parse::CompletionKind::Command => {
- completion::command_completion(session.clone(), comp.partial)
- }
- parse::CompletionKind::Argument => completion::path_completion(comp.partial),
- parse::CompletionKind::Variable => {
- completion::variable_completion(session.clone(), comp.partial)
- }
- parse::CompletionKind::None => continue,
- };
- suggestions.sort_by(|x, y| x.delta.cmp(&y.delta));
- suggestions.dedup_by(|x, y| x.delta == y.delta);
-
- if suggestions.is_empty() {
- continue;
- }
+ let comp = completion(session.clone(), &cmd);
let mut se = session.lock().unwrap();
- if suggestions.len() == 1 {
- // apply suggestion
- se.type_bytes(&suggestions[0].delta);
- continue;
- }
-
- // find longest shared prefix and type it
- {
- let mut longest = &suggestions[0].delta[..];
- for s in suggestions.iter() {
- let mut new = &longest[..0];
- for i in 0..longest.len().min(s.delta.len()) {
- if longest[i] != s.delta[i] {
- break;
- } else {
- new = &s.delta[..=i];
- }
- }
- longest = new;
- }
+ se.type_bytes(&comp.shared_prefix);
- if !longest.is_empty() {
- se.type_bytes(longest);
+ if comp.suggestions.len() > 1 {
+ print!("\r\n");
+ for s in comp.suggestions {
+ io::stdout().lock().write_all(&s.display).unwrap();
+ println!();
}
+ se.reprint_prompt();
}
-
- // one line below
- print!("\r\n");
- for s in suggestions {
- io::stdout().lock().write_all(&s.display).unwrap();
- println!();
- }
-
- se.reprint_prompt();
}
// Escape sequence