mirror of
https://github.com/nushell/nushell.git
synced 2025-08-16 08:08:45 +02:00
Small restructuring
This commit is contained in:
240
src/cli.rs
Normal file
240
src/cli.rs
Normal file
@ -0,0 +1,240 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::commands::classified::{ClassifiedCommand, ExternalCommand, InternalCommand};
|
||||
use crate::commands::command::ReturnValue;
|
||||
use crate::context::Context;
|
||||
crate use crate::env::Host;
|
||||
crate use crate::errors::ShellError;
|
||||
crate use crate::format::{EntriesListView, GenericView};
|
||||
use crate::object::Value;
|
||||
|
||||
use rustyline::error::ReadlineError;
|
||||
use rustyline::{self, ColorMode, Config, Editor};
|
||||
use std::collections::VecDeque;
|
||||
use std::error::Error;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MaybeOwned<'a, T> {
|
||||
Owned(T),
|
||||
Borrowed(&'a T),
|
||||
}
|
||||
|
||||
impl<T> MaybeOwned<'a, T> {
|
||||
crate fn borrow(&self) -> &T {
|
||||
match self {
|
||||
MaybeOwned::Owned(v) => v,
|
||||
MaybeOwned::Borrowed(v) => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cli() -> Result<(), Box<Error>> {
|
||||
let config = Config::builder().color_mode(ColorMode::Forced).build();
|
||||
let h = crate::shell::Helper::new();
|
||||
let mut rl: Editor<crate::shell::Helper> = Editor::with_config(config);
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let _ = ansi_term::enable_ansi_support();
|
||||
}
|
||||
|
||||
rl.set_helper(Some(h));
|
||||
if rl.load_history("history.txt").is_err() {
|
||||
println!("No previous history.");
|
||||
}
|
||||
|
||||
let mut context = Context::basic()?;
|
||||
|
||||
{
|
||||
use crate::commands::*;
|
||||
|
||||
context.add_commands(vec![
|
||||
("format", Arc::new(format)),
|
||||
("format-list", Arc::new(format_list)),
|
||||
("ps", Arc::new(ps::ps)),
|
||||
("ls", Arc::new(ls::ls)),
|
||||
("cd", Arc::new(cd::cd)),
|
||||
("view", Arc::new(view::view)),
|
||||
("skip", Arc::new(skip::skip)),
|
||||
("take", Arc::new(take::take)),
|
||||
("select", Arc::new(select::select)),
|
||||
("reject", Arc::new(reject::reject)),
|
||||
("to-array", Arc::new(to_array::to_array)),
|
||||
("where", Arc::new(where_::r#where)),
|
||||
("sort-by", Arc::new(sort_by::sort_by)),
|
||||
]);
|
||||
}
|
||||
|
||||
loop {
|
||||
let readline = rl.readline(&format!("{}> ", context.env.cwd().display().to_string()));
|
||||
|
||||
match process_line(readline, &mut context) {
|
||||
LineResult::Success(line) => {
|
||||
rl.add_history_entry(line.clone());
|
||||
}
|
||||
|
||||
LineResult::Error(err) => {
|
||||
context.host.stdout(&err);
|
||||
}
|
||||
|
||||
LineResult::Break => {
|
||||
break;
|
||||
}
|
||||
|
||||
LineResult::FatalError(err) => {
|
||||
context
|
||||
.host
|
||||
.stdout(&format!("A surprising fatal error occurred.\n{:?}", err));
|
||||
}
|
||||
}
|
||||
}
|
||||
rl.save_history("history.txt").unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
enum LineResult {
|
||||
Success(String),
|
||||
Error(String),
|
||||
Break,
|
||||
|
||||
#[allow(unused)]
|
||||
FatalError(ShellError),
|
||||
}
|
||||
|
||||
fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context) -> LineResult {
|
||||
match &readline {
|
||||
Ok(line) if line.trim() == "exit" => LineResult::Break,
|
||||
|
||||
Ok(line) if line.trim() == "" => LineResult::Success(line.clone()),
|
||||
|
||||
Ok(line) => {
|
||||
let result = match crate::parser::shell_parser(&line) {
|
||||
Err(err) => {
|
||||
return LineResult::Error(format!("{:?}", err));
|
||||
}
|
||||
|
||||
Ok(val) => val,
|
||||
};
|
||||
|
||||
let parsed = result.1;
|
||||
|
||||
let mut input = VecDeque::new();
|
||||
|
||||
for item in parsed {
|
||||
input = match process_command(item.clone(), input, ctx) {
|
||||
Ok(val) => val,
|
||||
Err(err) => return LineResult::Error(format!("{}", err.description())),
|
||||
};
|
||||
}
|
||||
|
||||
if input.len() > 0 {
|
||||
if equal_shapes(&input) {
|
||||
let array = crate::commands::stream_to_array(input);
|
||||
let args = CommandArgs::from_context(ctx, vec![], array);
|
||||
match format(args) {
|
||||
Ok(_) => {}
|
||||
Err(err) => return LineResult::Error(err.to_string()),
|
||||
}
|
||||
} else {
|
||||
let args = CommandArgs::from_context(ctx, vec![], input);
|
||||
match format(args) {
|
||||
Ok(_) => {}
|
||||
Err(err) => return LineResult::Error(err.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LineResult::Success(line.to_string())
|
||||
}
|
||||
Err(ReadlineError::Interrupted) => {
|
||||
println!("CTRL-C");
|
||||
LineResult::Break
|
||||
}
|
||||
Err(ReadlineError::Eof) => {
|
||||
println!("CTRL-D");
|
||||
LineResult::Break
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
LineResult::Break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn process_command(
|
||||
parsed: Vec<crate::parser::Item>,
|
||||
input: VecDeque<Value>,
|
||||
context: &mut Context,
|
||||
) -> Result<VecDeque<Value>, ShellError> {
|
||||
let command = classify_command(&parsed, context)?;
|
||||
|
||||
command.run(input, context)
|
||||
}
|
||||
|
||||
fn classify_command(
|
||||
command: &[crate::parser::Item],
|
||||
context: &Context,
|
||||
) -> Result<ClassifiedCommand, ShellError> {
|
||||
let command_name = &command[0].name()?;
|
||||
|
||||
let arg_list: Vec<Value> = command[1..].iter().map(|i| i.as_value()).collect();
|
||||
let arg_list_strings: Vec<String> = command[1..].iter().map(|i| i.print()).collect();
|
||||
|
||||
match *command_name {
|
||||
other => match context.has_command(*command_name) {
|
||||
true => {
|
||||
let command = context.get_command(command_name);
|
||||
Ok(ClassifiedCommand::Internal(InternalCommand {
|
||||
command,
|
||||
args: arg_list,
|
||||
}))
|
||||
}
|
||||
false => Ok(ClassifiedCommand::External(ExternalCommand {
|
||||
name: other.to_string(),
|
||||
args: arg_list_strings,
|
||||
})),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn format(args: CommandArgs<'caller>) -> Result<VecDeque<ReturnValue>, ShellError> {
|
||||
let last = args.input.len() - 1;
|
||||
for (i, item) in args.input.iter().enumerate() {
|
||||
let view = GenericView::new(item);
|
||||
crate::format::print_view(&view, args.host);
|
||||
|
||||
if last != i {
|
||||
println!("");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(VecDeque::new())
|
||||
}
|
||||
|
||||
fn format_list(args: CommandArgs<'caller>) -> Result<VecDeque<ReturnValue>, ShellError> {
|
||||
let view = EntriesListView::from_stream(args.input);
|
||||
crate::format::print_view(&view, args.host);
|
||||
|
||||
Ok(VecDeque::new())
|
||||
}
|
||||
|
||||
fn equal_shapes(input: &VecDeque<Value>) -> bool {
|
||||
let mut items = input.iter();
|
||||
|
||||
let item = match items.next() {
|
||||
Some(item) => item,
|
||||
None => return false,
|
||||
};
|
||||
|
||||
let desc = item.data_descriptors();
|
||||
|
||||
for item in items {
|
||||
if desc != item.data_descriptors() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
@ -11,7 +11,7 @@ impl ClassifiedCommand {
|
||||
crate fn run(
|
||||
self,
|
||||
input: VecDeque<Value>,
|
||||
context: &mut crate::Context,
|
||||
context: &mut Context,
|
||||
) -> Result<VecDeque<Value>, ShellError> {
|
||||
match self {
|
||||
ClassifiedCommand::Internal(internal) => {
|
||||
@ -22,7 +22,7 @@ impl ClassifiedCommand {
|
||||
for v in result {
|
||||
match v {
|
||||
ReturnValue::Action(action) => match action {
|
||||
crate::CommandAction::ChangeCwd(cwd) => context.env.cwd = cwd,
|
||||
CommandAction::ChangeCwd(cwd) => context.env.cwd = cwd,
|
||||
},
|
||||
|
||||
ReturnValue::Value(v) => next.push_back(v),
|
||||
|
@ -1,12 +1,11 @@
|
||||
use crate::errors::ShellError;
|
||||
use crate::object::Value;
|
||||
use crate::prelude::*;
|
||||
use crate::Context;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct CommandArgs<'caller> {
|
||||
pub host: &'caller mut dyn Host,
|
||||
pub env: &'caller crate::Environment,
|
||||
pub env: &'caller Environment,
|
||||
pub args: Vec<Value>,
|
||||
pub input: VecDeque<Value>,
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ use std::error::Error;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct Context {
|
||||
commands: indexmap::IndexMap<String, Arc<dyn crate::Command>>,
|
||||
crate host: Box<dyn crate::Host>,
|
||||
commands: indexmap::IndexMap<String, Arc<dyn Command>>,
|
||||
crate host: Box<dyn Host>,
|
||||
crate env: Environment,
|
||||
}
|
||||
|
||||
@ -14,11 +14,11 @@ impl Context {
|
||||
Ok(Context {
|
||||
commands: indexmap::IndexMap::new(),
|
||||
host: Box::new(crate::env::host::BasicHost),
|
||||
env: crate::Environment::basic()?,
|
||||
env: Environment::basic()?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn add_commands(&mut self, commands: Vec<(&str, Arc<dyn crate::Command>)>) {
|
||||
pub fn add_commands(&mut self, commands: Vec<(&str, Arc<dyn Command>)>) {
|
||||
for (name, command) in commands {
|
||||
self.commands.insert(name.to_string(), command);
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
#[allow(unused)]
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::Value;
|
||||
use derive_new::new;
|
||||
|
||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, new)]
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::format::RenderView;
|
||||
use crate::prelude::*;
|
||||
use crate::Host;
|
||||
|
||||
use derive_new::new;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::format::{EntriesView, RenderView, TableView};
|
||||
use crate::object::Value;
|
||||
use crate::Host;
|
||||
use crate::prelude::*;
|
||||
use derive_new::new;
|
||||
|
||||
// A list is printed one line at a time with an optional separator between groups
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::format::RenderView;
|
||||
use crate::Host;
|
||||
use crate::prelude::*;
|
||||
use derive_new::new;
|
||||
|
||||
// A list is printed one line at a time with an optional separator between groups
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::format::RenderView;
|
||||
use crate::object::Value;
|
||||
use crate::Host;
|
||||
use crate::prelude::*;
|
||||
use derive_new::new;
|
||||
use prettytable::{Cell, Row, Table};
|
||||
|
||||
|
241
src/main.rs
241
src/main.rs
@ -1,9 +1,7 @@
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(in_band_lifetimes)]
|
||||
|
||||
#[allow(unused)]
|
||||
use crate::prelude::*;
|
||||
|
||||
mod cli;
|
||||
mod commands;
|
||||
mod context;
|
||||
mod env;
|
||||
@ -13,243 +11,10 @@ mod object;
|
||||
mod parser;
|
||||
mod prelude;
|
||||
mod shell;
|
||||
mod stream;
|
||||
|
||||
use crate::commands::classified::{ClassifiedCommand, ExternalCommand, InternalCommand};
|
||||
use crate::commands::command::ReturnValue;
|
||||
crate use crate::commands::command::{Command, CommandAction};
|
||||
use crate::context::Context;
|
||||
crate use crate::env::{Environment, Host};
|
||||
crate use crate::errors::ShellError;
|
||||
crate use crate::format::{EntriesListView, GenericView};
|
||||
use crate::object::Value;
|
||||
|
||||
use rustyline::error::ReadlineError;
|
||||
use rustyline::{self, ColorMode, Config, Editor};
|
||||
use std::collections::VecDeque;
|
||||
use std::error::Error;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MaybeOwned<'a, T> {
|
||||
Owned(T),
|
||||
Borrowed(&'a T),
|
||||
}
|
||||
|
||||
impl<T> MaybeOwned<'a, T> {
|
||||
crate fn borrow(&self) -> &T {
|
||||
match self {
|
||||
MaybeOwned::Owned(v) => v,
|
||||
MaybeOwned::Borrowed(v) => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<Error>> {
|
||||
let config = Config::builder().color_mode(ColorMode::Forced).build();
|
||||
let h = crate::shell::Helper::new();
|
||||
let mut rl: Editor<crate::shell::Helper> = Editor::with_config(config);
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let _ = ansi_term::enable_ansi_support();
|
||||
}
|
||||
|
||||
rl.set_helper(Some(h));
|
||||
if rl.load_history("history.txt").is_err() {
|
||||
println!("No previous history.");
|
||||
}
|
||||
|
||||
let mut context = Context::basic()?;
|
||||
|
||||
{
|
||||
use crate::commands::*;
|
||||
|
||||
context.add_commands(vec![
|
||||
("format", Arc::new(format)),
|
||||
("format-list", Arc::new(format_list)),
|
||||
("ps", Arc::new(ps::ps)),
|
||||
("ls", Arc::new(ls::ls)),
|
||||
("cd", Arc::new(cd::cd)),
|
||||
("view", Arc::new(view::view)),
|
||||
("skip", Arc::new(skip::skip)),
|
||||
("take", Arc::new(take::take)),
|
||||
("select", Arc::new(select::select)),
|
||||
("reject", Arc::new(reject::reject)),
|
||||
("to-array", Arc::new(to_array::to_array)),
|
||||
("where", Arc::new(where_::r#where)),
|
||||
("sort-by", Arc::new(sort_by::sort_by)),
|
||||
]);
|
||||
}
|
||||
|
||||
loop {
|
||||
let readline = rl.readline(&format!("{}> ", context.env.cwd().display().to_string()));
|
||||
|
||||
match process_line(readline, &mut context) {
|
||||
LineResult::Success(line) => {
|
||||
rl.add_history_entry(line.clone());
|
||||
}
|
||||
|
||||
LineResult::Error(err) => {
|
||||
context.host.stdout(&err);
|
||||
}
|
||||
|
||||
LineResult::Break => {
|
||||
break;
|
||||
}
|
||||
|
||||
LineResult::FatalError(err) => {
|
||||
context
|
||||
.host
|
||||
.stdout(&format!("A surprising fatal error occurred.\n{:?}", err));
|
||||
}
|
||||
}
|
||||
}
|
||||
rl.save_history("history.txt").unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
enum LineResult {
|
||||
Success(String),
|
||||
Error(String),
|
||||
Break,
|
||||
|
||||
#[allow(unused)]
|
||||
FatalError(ShellError),
|
||||
}
|
||||
|
||||
fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context) -> LineResult {
|
||||
match &readline {
|
||||
Ok(line) if line.trim() == "exit" => LineResult::Break,
|
||||
|
||||
Ok(line) if line.trim() == "" => LineResult::Success(line.clone()),
|
||||
|
||||
Ok(line) => {
|
||||
let result = match crate::parser::shell_parser(&line) {
|
||||
Err(err) => {
|
||||
return LineResult::Error(format!("{:?}", err));
|
||||
}
|
||||
|
||||
Ok(val) => val,
|
||||
};
|
||||
|
||||
let parsed = result.1;
|
||||
|
||||
let mut input = VecDeque::new();
|
||||
|
||||
for item in parsed {
|
||||
input = match process_command(item.clone(), input, ctx) {
|
||||
Ok(val) => val,
|
||||
Err(err) => return LineResult::Error(format!("{}", err.description())),
|
||||
};
|
||||
}
|
||||
|
||||
if input.len() > 0 {
|
||||
if equal_shapes(&input) {
|
||||
let array = crate::commands::stream_to_array(input);
|
||||
let args = CommandArgs::from_context(ctx, vec![], array);
|
||||
match format(args) {
|
||||
Ok(_) => {}
|
||||
Err(err) => return LineResult::Error(err.to_string()),
|
||||
}
|
||||
} else {
|
||||
let args = CommandArgs::from_context(ctx, vec![], input);
|
||||
match format(args) {
|
||||
Ok(_) => {}
|
||||
Err(err) => return LineResult::Error(err.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LineResult::Success(line.to_string())
|
||||
}
|
||||
Err(ReadlineError::Interrupted) => {
|
||||
println!("CTRL-C");
|
||||
LineResult::Break
|
||||
}
|
||||
Err(ReadlineError::Eof) => {
|
||||
println!("CTRL-D");
|
||||
LineResult::Break
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
LineResult::Break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn process_command(
|
||||
parsed: Vec<crate::parser::Item>,
|
||||
input: VecDeque<Value>,
|
||||
context: &mut Context,
|
||||
) -> Result<VecDeque<Value>, ShellError> {
|
||||
let command = classify_command(&parsed, context)?;
|
||||
|
||||
command.run(input, context)
|
||||
}
|
||||
|
||||
fn classify_command(
|
||||
command: &[crate::parser::Item],
|
||||
context: &Context,
|
||||
) -> Result<ClassifiedCommand, ShellError> {
|
||||
let command_name = &command[0].name()?;
|
||||
|
||||
let arg_list: Vec<Value> = command[1..].iter().map(|i| i.as_value()).collect();
|
||||
let arg_list_strings: Vec<String> = command[1..].iter().map(|i| i.print()).collect();
|
||||
|
||||
match *command_name {
|
||||
other => match context.has_command(*command_name) {
|
||||
true => {
|
||||
let command = context.get_command(command_name);
|
||||
Ok(ClassifiedCommand::Internal(InternalCommand {
|
||||
command,
|
||||
args: arg_list,
|
||||
}))
|
||||
}
|
||||
false => Ok(ClassifiedCommand::External(ExternalCommand {
|
||||
name: other.to_string(),
|
||||
args: arg_list_strings,
|
||||
})),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn format(args: CommandArgs<'caller>) -> Result<VecDeque<ReturnValue>, ShellError> {
|
||||
let last = args.input.len() - 1;
|
||||
for (i, item) in args.input.iter().enumerate() {
|
||||
let view = GenericView::new(item);
|
||||
crate::format::print_view(&view, args.host);
|
||||
|
||||
if last != i {
|
||||
println!("");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(VecDeque::new())
|
||||
}
|
||||
|
||||
fn format_list(args: CommandArgs<'caller>) -> Result<VecDeque<ReturnValue>, ShellError> {
|
||||
let view = EntriesListView::from_stream(args.input);
|
||||
crate::format::print_view(&view, args.host);
|
||||
|
||||
Ok(VecDeque::new())
|
||||
}
|
||||
|
||||
fn equal_shapes(input: &VecDeque<Value>) -> bool {
|
||||
let mut items = input.iter();
|
||||
|
||||
let item = match items.next() {
|
||||
Some(item) => item,
|
||||
None => return false,
|
||||
};
|
||||
|
||||
let desc = item.data_descriptors();
|
||||
|
||||
for item in items {
|
||||
if desc != item.data_descriptors() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
crate::cli::cli()
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::errors::ShellError;
|
||||
use crate::object::desc::DataDescriptor;
|
||||
use crate::parser::parse::Operator;
|
||||
use crate::prelude::*;
|
||||
use ansi_term::Color;
|
||||
use chrono::{DateTime, Utc};
|
||||
use chrono_humanize::Humanize;
|
||||
@ -75,21 +76,21 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn get_data_by_key(&'a self, name: &str) -> crate::MaybeOwned<'a, Value> {
|
||||
crate fn get_data_by_key(&'a self, name: &str) -> MaybeOwned<'a, Value> {
|
||||
match self {
|
||||
Value::Primitive(_) => crate::MaybeOwned::Owned(Value::nothing()),
|
||||
Value::Primitive(_) => MaybeOwned::Owned(Value::nothing()),
|
||||
Value::Object(o) => o.get_data_by_key(name),
|
||||
Value::List(_) => crate::MaybeOwned::Owned(Value::nothing()),
|
||||
Value::Error(_) => crate::MaybeOwned::Owned(Value::nothing()),
|
||||
Value::List(_) => MaybeOwned::Owned(Value::nothing()),
|
||||
Value::Error(_) => MaybeOwned::Owned(Value::nothing()),
|
||||
}
|
||||
}
|
||||
|
||||
crate fn get_data(&'a self, desc: &DataDescriptor) -> crate::MaybeOwned<'a, Value> {
|
||||
crate fn get_data(&'a self, desc: &DataDescriptor) -> MaybeOwned<'a, Value> {
|
||||
match self {
|
||||
Value::Primitive(_) => crate::MaybeOwned::Owned(Value::nothing()),
|
||||
Value::Primitive(_) => MaybeOwned::Owned(Value::nothing()),
|
||||
Value::Object(o) => o.get_data(desc),
|
||||
Value::List(_) => crate::MaybeOwned::Owned(Value::nothing()),
|
||||
Value::Error(_) => crate::MaybeOwned::Owned(Value::nothing()),
|
||||
Value::List(_) => MaybeOwned::Owned(Value::nothing()),
|
||||
Value::Error(_) => MaybeOwned::Owned(Value::nothing()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
#[allow(unused)]
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::object::desc::DataDescriptor;
|
||||
use crate::object::{Primitive, Value};
|
||||
use crate::MaybeOwned;
|
||||
use indexmap::IndexMap;
|
||||
use std::cmp::{Ordering, PartialOrd};
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
use crate::prelude::*;
|
||||
use rustyline::{completion, Context};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[allow(unused)]
|
||||
crate struct Completer {
|
||||
commands: BTreeMap<String, Box<dyn crate::Command>>,
|
||||
commands: BTreeMap<String, Box<dyn Command>>,
|
||||
}
|
||||
|
||||
impl completion::Completer for Completer {
|
||||
|
@ -1,4 +1,6 @@
|
||||
crate use crate::commands::command::{Command, CommandArgs, ReturnValue};
|
||||
crate use crate::cli::MaybeOwned;
|
||||
crate use crate::commands::command::{Command, CommandAction, CommandArgs, ReturnValue};
|
||||
crate use crate::context::Context;
|
||||
crate use crate::env::{Environment, Host};
|
||||
crate use crate::errors::ShellError;
|
||||
crate use crate::object::{Primitive, Value};
|
||||
|
0
src/stream.rs
Normal file
0
src/stream.rs
Normal file
Reference in New Issue
Block a user