Skip to content
Snippets Groups Projects
Commit d237ec42 authored by Steven Stanfield's avatar Steven Stanfield
Browse files

Formatted and fixed some tab complete issues for commands.

- If directories in PATH did not end in / then command complete would
not work.
- Also complete commands if previous item ended in '|', '&' or ';'.
This does not handle cases when a space does not follow the special
character.
- Do not include the full path when completing commands.
parent 37afa86f
No related branches found
No related tags found
No related merge requests found
...@@ -96,7 +96,14 @@ impl<'a, 'b> Completer for IonCompleter<'a, 'b> { ...@@ -96,7 +96,14 @@ impl<'a, 'b> Completer for IonCompleter<'a, 'b> {
// in the environment's **$PATH** variable. // in the environment's **$PATH** variable.
let file_completers: Vec<_> = if let Some(paths) = env::var_os("PATH") { let file_completers: Vec<_> = if let Some(paths) = env::var_os("PATH") {
env::split_paths(&paths) env::split_paths(&paths)
.map(|s| IonFileCompleter::new(Some(s), &self.shell, true)) .map(|s| {
let s = if !s.to_string_lossy().ends_with("/") {
PathBuf::from(format!("{}/", s.to_string_lossy()))
} else {
s
};
IonFileCompleter::new(Some(s), &self.shell, true)
})
.collect() .collect()
} else { } else {
vec![IonFileCompleter::new(Some("/bin/".into()), &self.shell, true)] vec![IonFileCompleter::new(Some("/bin/".into()), &self.shell, true)]
...@@ -106,35 +113,36 @@ impl<'a, 'b> Completer for IonCompleter<'a, 'b> { ...@@ -106,35 +113,36 @@ impl<'a, 'b> Completer for IonCompleter<'a, 'b> {
} }
CompletionType::Nothing => (), CompletionType::Nothing => (),
} }
completions completions
} }
fn on_event<W: std::io::Write>(&mut self, event: Event<'_, '_, W>) { fn on_event<W: std::io::Write>(&mut self, event: Event<'_, '_, W>) {
if let EventKind::BeforeComplete = event.kind { if let EventKind::BeforeComplete = event.kind {
let (words, pos) = event.editor.get_words_and_cursor_position(); let (words, pos) = event.editor.get_words_and_cursor_position();
/* self.complete_commands = match pos {
CursorPosition::InWord(_) => false,
CursorPosition::InSpace(Some(_), _) => false,
CursorPosition::InSpace(None, _) => false,
CursorPosition::OnWordLeftEdge(_) => false,
CursorPosition::OnWordRightEdge(index) => if index == 0 {
true
} else {
words
.into_iter()
.nth(index - 1)
.map(|(start, end)| event.editor.current_buffer().range(start, end))
.filter(|filename| filename.ends_with("|"))
.is_some()
},
};
}*/
self.completion = match pos { self.completion = match pos {
_ if words.is_empty() => CompletionType::Nothing, _ if words.is_empty() => CompletionType::Nothing,
CursorPosition::InWord(0) | CursorPosition::OnWordRightEdge(0) => { CursorPosition::InWord(0) => CompletionType::Command,
CompletionType::Command CursorPosition::OnWordRightEdge(index) => {
if index == 0 {
CompletionType::Command
} else {
let is_pipe = words
.into_iter()
.nth(index - 1)
.map(|(start, end)| event.editor.current_buffer().range(start, end))
.filter(|filename| {
filename.ends_with("|")
|| filename.ends_with("&")
|| filename.ends_with(";")
})
.is_some();
if is_pipe {
CompletionType::Command
} else {
CompletionType::VariableAndFiles
}
}
} }
_ => CompletionType::VariableAndFiles, _ => CompletionType::VariableAndFiles,
}; };
...@@ -184,7 +192,6 @@ impl<'a, 'b> Completer for IonFileCompleter<'a, 'b> { ...@@ -184,7 +192,6 @@ impl<'a, 'b> Completer for IonFileCompleter<'a, 'b> {
// Now we obtain completions for the `expanded` form of the `start` value. // Now we obtain completions for the `expanded` form of the `start` value.
let completions = filename_completion(&expanded, &self.path); let completions = filename_completion(&expanded, &self.path);
if expanded == start { if expanded == start {
//return completions.map(|s| s.rsplit('/').nth(0).unwrap_or(&s).to_string()).collect();
return if self.for_command { return if self.for_command {
completions.map(|s| s.rsplit('/').nth(0).unwrap_or(&s).to_string()).collect() completions.map(|s| s.rsplit('/').nth(0).unwrap_or(&s).to_string()).collect()
} else { } else {
...@@ -253,7 +260,7 @@ fn filename_completion<'a>(start: &'a str, path: &'a PathBuf) -> impl Iterator<I ...@@ -253,7 +260,7 @@ fn filename_completion<'a>(start: &'a str, path: &'a PathBuf) -> impl Iterator<I
let globs = glob_with( let globs = glob_with(
&string, &string,
MatchOptions { MatchOptions {
case_sensitive: false, //true, case_sensitive: true,
require_literal_separator: true, require_literal_separator: true,
require_literal_leading_dot: false, require_literal_leading_dot: false,
}, },
......
...@@ -18,8 +18,7 @@ use liner::{Buffer, Context, KeyBindings}; ...@@ -18,8 +18,7 @@ use liner::{Buffer, Context, KeyBindings};
use std::{ use std::{
cell::{Cell, RefCell}, cell::{Cell, RefCell},
fs::{self, OpenOptions}, fs::{self, OpenOptions},
io, io::{self, Write},
io::Write,
path::Path, path::Path,
rc::Rc, rc::Rc,
}; };
...@@ -191,7 +190,10 @@ impl<'a> InteractiveShell<'a> { ...@@ -191,7 +190,10 @@ impl<'a> InteractiveShell<'a> {
context_bis.borrow_mut().history.load_duplicates = false; context_bis.borrow_mut().history.load_duplicates = false;
} }
Some(_) => { Some(_) => {
Status::error("Invalid history option. Choices are [+|-] inc_append and share (implies inc_append)."); Status::error(
"Invalid history option. Choices are [+|-] inc_append, duplicates and \
share (implies inc_append).",
);
} }
None => { None => {
print!("{}", context_bis.borrow().history.buffers.iter().format("\n")); print!("{}", context_bis.borrow().history.buffers.iter().format("\n"));
......
...@@ -18,8 +18,8 @@ ...@@ -18,8 +18,8 @@
//! ## Demo //! ## Demo
//! //!
//! ```rust //! ```rust
//! use ion_shell::{builtins::Status, Value, types, BuiltinFunction, BuiltinMap, Shell}; //! use ion_shell::{builtins::Status, types, BuiltinFunction, BuiltinMap, Shell, Value};
//! use std::{cell::RefCell, rc::Rc, thread, time, fs::File}; //! use std::{cell::RefCell, fs::File, rc::Rc, thread, time};
//! //!
//! enum Layout { //! enum Layout {
//! Simple, //! Simple,
...@@ -57,7 +57,9 @@ ...@@ -57,7 +57,9 @@
//! i += 1; //! i += 1;
//! // call a user-defined callback function named on_update //! // call a user-defined callback function named on_update
//! if let Some(Value::Function(function)) = shell.variables().get("on_update") { //! if let Some(Value::Function(function)) = shell.variables().get("on_update") {
//! if let Err(why) = shell.execute_function(&function.clone(), &["ion", &i.to_string()]) { //! if let Err(why) =
//! shell.execute_function(&function.clone(), &["ion", &i.to_string()])
//! {
//! println!("ERROR: my-application: error in on_update callback: {}", why); //! println!("ERROR: my-application: error in on_update callback: {}", why);
//! } //! }
//! } //! }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment