forked from extern/nushell
commit
ff6cc2cbdd
1
TODO.md
1
TODO.md
@ -29,6 +29,7 @@
|
|||||||
- [x] Value serialization
|
- [x] Value serialization
|
||||||
- [x] Handling rows with missing columns during a cell path
|
- [x] Handling rows with missing columns during a cell path
|
||||||
- [x] finish operator type-checking
|
- [x] finish operator type-checking
|
||||||
|
- [x] Config file loading
|
||||||
- [ ] Input/output types
|
- [ ] Input/output types
|
||||||
- [ ] Support for `$in`
|
- [ ] Support for `$in`
|
||||||
- [ ] ctrl-c support
|
- [ ] ctrl-c support
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
extern crate unicode_segmentation;
|
extern crate unicode_segmentation;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
// use indexmap::indexmap;
|
|
||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{Command, EvaluationContext};
|
use nu_protocol::engine::{Command, EvaluationContext};
|
||||||
use nu_protocol::{ShellError, Signature, Span, Spanned, Type, Value};
|
use nu_protocol::{Example, ShellError, Signature, Span, Type, Value};
|
||||||
|
|
||||||
pub struct Size;
|
pub struct Size;
|
||||||
|
|
||||||
@ -33,32 +30,72 @@ impl Command for Size {
|
|||||||
size(context, call, input)
|
size(context, call, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
// vec![
|
vec![
|
||||||
// Example {
|
Example {
|
||||||
// description: "Count the number of words in a string",
|
description: "Count the number of words in a string",
|
||||||
// example: r#"echo "There are seven words in this sentence" | size"#,
|
example: r#""There are seven words in this sentence" | size"#,
|
||||||
// result: Some(vec![Value::row(indexmap! {
|
result: Some(Value::Record {
|
||||||
// "lines".to_string() => UntaggedValue::int(0).into(),
|
cols: vec![
|
||||||
// "words".to_string() => UntaggedValue::int(7).into(),
|
"lines".into(),
|
||||||
// "chars".to_string() => UntaggedValue::int(38).into(),
|
"words".into(),
|
||||||
// "bytes".to_string() => UntaggedValue::int(38).into(),
|
"chars".into(),
|
||||||
// })
|
"bytes".into(),
|
||||||
// .into()]),
|
],
|
||||||
// },
|
vals: vec![
|
||||||
// Example {
|
Value::Int {
|
||||||
// description: "Counts Unicode characters correctly in a string",
|
val: 0,
|
||||||
// example: r#"echo "Amélie Amelie" | size"#,
|
span: Span::unknown(),
|
||||||
// result: Some(vec![UntaggedValue::row(indexmap! {
|
},
|
||||||
// "lines".to_string() => UntaggedValue::int(0).into(),
|
Value::Int {
|
||||||
// "words".to_string() => UntaggedValue::int(2).into(),
|
val: 7,
|
||||||
// "chars".to_string() => UntaggedValue::int(13).into(),
|
span: Span::unknown(),
|
||||||
// "bytes".to_string() => UntaggedValue::int(15).into(),
|
},
|
||||||
// })
|
Value::Int {
|
||||||
// .into()]),
|
val: 38,
|
||||||
// },
|
span: Span::unknown(),
|
||||||
// ]
|
},
|
||||||
// }
|
Value::Int {
|
||||||
|
val: 38,
|
||||||
|
span: Span::unknown(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: Span::unknown(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Counts Unicode characters correctly in a string",
|
||||||
|
example: r#""Amélie Amelie" | size"#,
|
||||||
|
result: Some(Value::Record {
|
||||||
|
cols: vec![
|
||||||
|
"lines".into(),
|
||||||
|
"words".into(),
|
||||||
|
"chars".into(),
|
||||||
|
"bytes".into(),
|
||||||
|
],
|
||||||
|
vals: vec![
|
||||||
|
Value::Int {
|
||||||
|
val: 0,
|
||||||
|
span: Span::unknown(),
|
||||||
|
},
|
||||||
|
Value::Int {
|
||||||
|
val: 2,
|
||||||
|
span: Span::unknown(),
|
||||||
|
},
|
||||||
|
Value::Int {
|
||||||
|
val: 13,
|
||||||
|
span: Span::unknown(),
|
||||||
|
},
|
||||||
|
Value::Int {
|
||||||
|
val: 15,
|
||||||
|
span: Span::unknown(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: Span::unknown(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size(_context: &EvaluationContext, call: &Call, input: Value) -> Result<Value, ShellError> {
|
fn size(_context: &EvaluationContext, call: &Call, input: Value) -> Result<Value, ShellError> {
|
||||||
@ -100,24 +137,32 @@ fn count(contents: &str, span: Span) -> Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut item: HashMap<String, Value> = HashMap::new();
|
let mut cols = vec![];
|
||||||
item.insert("lines".to_string(), Value::Int { val: lines, span });
|
let mut vals = vec![];
|
||||||
item.insert("words".to_string(), Value::Int { val: words, span });
|
|
||||||
item.insert("chars".to_string(), Value::Int { val: chars, span });
|
|
||||||
item.insert("bytes".to_string(), Value::Int { val: bytes, span });
|
|
||||||
|
|
||||||
Value::from(Spanned { item, span })
|
cols.push("lines".into());
|
||||||
|
vals.push(Value::Int { val: lines, span });
|
||||||
|
|
||||||
|
cols.push("words".into());
|
||||||
|
vals.push(Value::Int { val: words, span });
|
||||||
|
|
||||||
|
cols.push("chars".into());
|
||||||
|
vals.push(Value::Int { val: chars, span });
|
||||||
|
|
||||||
|
cols.push("bytes".into());
|
||||||
|
vals.push(Value::Int { val: bytes, span });
|
||||||
|
|
||||||
|
Value::Record { cols, vals, span }
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[cfg(test)]
|
#[cfg(test)]
|
||||||
// mod tests {
|
mod test {
|
||||||
// use super::ShellError;
|
use super::*;
|
||||||
// use super::Size;
|
|
||||||
|
|
||||||
// #[test]
|
#[test]
|
||||||
// fn examples_work_as_expected() -> Result<(), ShellError> {
|
fn test_examples() {
|
||||||
// use crate::examples::test as test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
// test_examples(Size {})
|
test_examples(Size {})
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
9
crates/nu-path/src/helpers.rs
Normal file
9
crates/nu-path/src/helpers.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
pub fn home_dir() -> Option<PathBuf> {
|
||||||
|
dirs_next::home_dir()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config_dir() -> Option<PathBuf> {
|
||||||
|
dirs_next::config_dir()
|
||||||
|
}
|
@ -1,8 +1,10 @@
|
|||||||
mod dots;
|
mod dots;
|
||||||
mod expansions;
|
mod expansions;
|
||||||
|
mod helpers;
|
||||||
mod tilde;
|
mod tilde;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
pub use expansions::{canonicalize, canonicalize_with, expand_path, expand_path_with};
|
pub use expansions::{canonicalize, canonicalize_with, expand_path, expand_path_with};
|
||||||
|
pub use helpers::{config_dir, home_dir};
|
||||||
pub use tilde::expand_tilde;
|
pub use tilde::expand_tilde;
|
||||||
pub use util::trim_trailing_slash;
|
pub use util::trim_trailing_slash;
|
||||||
|
113
src/main.rs
113
src/main.rs
@ -91,6 +91,23 @@ fn main() -> Result<()> {
|
|||||||
let mut nu_prompt = NushellPrompt::new();
|
let mut nu_prompt = NushellPrompt::new();
|
||||||
let stack = nu_protocol::engine::Stack::new();
|
let stack = nu_protocol::engine::Stack::new();
|
||||||
|
|
||||||
|
// Load config startup file
|
||||||
|
if let Some(mut config_path) = nu_path::config_dir() {
|
||||||
|
config_path.push("nushell");
|
||||||
|
config_path.push("config.nu");
|
||||||
|
|
||||||
|
// FIXME: remove this message when we're ready
|
||||||
|
println!("Loading config from: {:?}", config_path);
|
||||||
|
|
||||||
|
if config_path.exists() {
|
||||||
|
let config_filename = config_path.to_string_lossy().to_owned();
|
||||||
|
|
||||||
|
if let Ok(contents) = std::fs::read_to_string(&config_path) {
|
||||||
|
eval_source(engine_state.clone(), &stack, &contents, &config_filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let prompt = update_prompt(
|
let prompt = update_prompt(
|
||||||
PROMPT_COMMAND,
|
PROMPT_COMMAND,
|
||||||
@ -124,45 +141,12 @@ fn main() -> Result<()> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (block, delta) = {
|
eval_source(
|
||||||
let engine_state = engine_state.borrow();
|
engine_state.clone(),
|
||||||
let mut working_set = StateWorkingSet::new(&*engine_state);
|
&stack,
|
||||||
let (output, err) = parse(
|
&s,
|
||||||
&mut working_set,
|
&format!("entry #{}", entry_num),
|
||||||
Some(&format!("entry #{}", entry_num)),
|
);
|
||||||
s.as_bytes(),
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
if let Some(err) = err {
|
|
||||||
report_error(&working_set, &err);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
(output, working_set.render())
|
|
||||||
};
|
|
||||||
|
|
||||||
EngineState::merge_delta(&mut *engine_state.borrow_mut(), delta);
|
|
||||||
|
|
||||||
let state = nu_protocol::engine::EvaluationContext {
|
|
||||||
engine_state: engine_state.clone(),
|
|
||||||
stack: stack.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
match eval_block(&state, &block, Value::nothing()) {
|
|
||||||
Ok(value) => {
|
|
||||||
if let Err(err) = print_value(value, &state) {
|
|
||||||
let engine_state = engine_state.borrow();
|
|
||||||
let working_set = StateWorkingSet::new(&*engine_state);
|
|
||||||
|
|
||||||
report_error(&working_set, &err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
let engine_state = engine_state.borrow();
|
|
||||||
let working_set = StateWorkingSet::new(&*engine_state);
|
|
||||||
|
|
||||||
report_error(&working_set, &err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(Signal::CtrlC) => {
|
Ok(Signal::CtrlC) => {
|
||||||
println!("Ctrl-c");
|
println!("Ctrl-c");
|
||||||
@ -267,3 +251,54 @@ fn update_prompt<'prompt>(
|
|||||||
|
|
||||||
nu_prompt as &dyn Prompt
|
nu_prompt as &dyn Prompt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn eval_source(
|
||||||
|
engine_state: Rc<RefCell<EngineState>>,
|
||||||
|
stack: &Stack,
|
||||||
|
source: &str,
|
||||||
|
fname: &str,
|
||||||
|
) -> bool {
|
||||||
|
let (block, delta) = {
|
||||||
|
let engine_state = engine_state.borrow();
|
||||||
|
let mut working_set = StateWorkingSet::new(&*engine_state);
|
||||||
|
let (output, err) = parse(
|
||||||
|
&mut working_set,
|
||||||
|
Some(fname), // format!("entry #{}", entry_num)
|
||||||
|
source.as_bytes(),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
if let Some(err) = err {
|
||||||
|
report_error(&working_set, &err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
(output, working_set.render())
|
||||||
|
};
|
||||||
|
|
||||||
|
EngineState::merge_delta(&mut *engine_state.borrow_mut(), delta);
|
||||||
|
|
||||||
|
let state = nu_protocol::engine::EvaluationContext {
|
||||||
|
engine_state: engine_state.clone(),
|
||||||
|
stack: stack.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
match eval_block(&state, &block, Value::nothing()) {
|
||||||
|
Ok(value) => {
|
||||||
|
if let Err(err) = print_value(value, &state) {
|
||||||
|
let engine_state = engine_state.borrow();
|
||||||
|
let working_set = StateWorkingSet::new(&*engine_state);
|
||||||
|
|
||||||
|
report_error(&working_set, &err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
let engine_state = engine_state.borrow();
|
||||||
|
let working_set = StateWorkingSet::new(&*engine_state);
|
||||||
|
|
||||||
|
report_error(&working_set, &err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user