Merge pull request #187 from jonathandturner/release_cleanup_012

Release cleanup for the 0.1.2 release
This commit is contained in:
Jonathan Turner 2019-07-17 07:52:40 +12:00 committed by GitHub
commit 5bb20aa372
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 142 additions and 587 deletions

32
Cargo.lock generated
View file

@ -1285,13 +1285,13 @@ dependencies = [
[[package]]
name = "language-reporting"
version = "0.3.0"
source = "git+https://github.com/jonathandturner/language-reporting#0a6c284a19a00b5b6b680480c0ad5f241fc5edac"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"derive-new 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"render-tree 0.1.1 (git+https://github.com/jonathandturner/language-reporting)",
"render-tree 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1620,9 +1620,9 @@ dependencies = [
]
[[package]]
name = "nom_locate"
version = "0.3.1"
source = "git+https://github.com/wycats/nom_locate.git?branch=nom5#5baeede19605e2049994eca8f7b366ddc85bb9cd"
name = "nom5_locate"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1659,7 +1659,7 @@ dependencies = [
"image 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)",
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"language-reporting 0.3.0 (git+https://github.com/jonathandturner/language-reporting)",
"language-reporting 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"logos 0.10.0-rc2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1667,7 +1667,7 @@ dependencies = [
"mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"neso 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"nom_locate 0.3.1 (git+https://github.com/wycats/nom_locate.git?branch=nom5)",
"nom5_locate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"pretty-hex 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1675,7 +1675,7 @@ dependencies = [
"prettyprint 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"prettytable-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ptree 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rawkey 0.1.0 (git+https://github.com/jonathandturner/rawkey.git)",
"rawkey 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"reqwest 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)",
"roxmltree 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2266,8 +2266,8 @@ dependencies = [
[[package]]
name = "rawkey"
version = "0.1.0"
source = "git+https://github.com/jonathandturner/rawkey.git#f06456a6f662eff142ed019fb5583043e11b771c"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"readkey 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2365,7 +2365,7 @@ dependencies = [
[[package]]
name = "render-tree"
version = "0.1.1"
source = "git+https://github.com/jonathandturner/language-reporting#0a6c284a19a00b5b6b680480c0ad5f241fc5edac"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3517,7 +3517,7 @@ dependencies = [
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
"checksum jpeg-decoder 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c8b7d43206b34b3f94ea9445174bda196e772049b9bddbc620c9d29b2d20110d"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum language-reporting 0.3.0 (git+https://github.com/jonathandturner/language-reporting)" = "<none>"
"checksum language-reporting 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "628912b84af4304e1e7e78ebb6a1f503f3a973cba79d072d12e6eb40e7f815db"
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
@ -3553,7 +3553,7 @@ dependencies = [
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
"checksum nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9761d859320e381010a4f7f8ed425f2c924de33ad121ace447367c713ad561b"
"checksum nom_locate 0.3.1 (git+https://github.com/wycats/nom_locate.git?branch=nom5)" = "<none>"
"checksum nom5_locate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d4312467f8b28d909344b934207e502212fa5a3adf1bff7428b0b86a666223d"
"checksum num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2"
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e"
@ -3615,7 +3615,7 @@ dependencies = [
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
"checksum rawkey 0.1.0 (git+https://github.com/jonathandturner/rawkey.git)" = "<none>"
"checksum rawkey 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cd49689ad95f53f9ba07322fa4fa75f08c338f5f7556eb2952705071eaf681b"
"checksum rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4b0186e22767d5b9738a05eab7c6ac90b15db17e5b5f9bd87976dd7d89a10a4"
"checksum rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe0df8435ac0c397d467b6cad6d25543d06e8a019ef3f6af3c384597515bd2"
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
@ -3626,7 +3626,7 @@ dependencies = [
"checksum regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d9d8297cc20bbb6184f8b45ff61c8ee6a9ac56c156cec8e38c3e5084773c44ad"
"checksum regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d76410686f9e3a17f06128962e0ecc5755870bb890c34820c7af7f1db2e1d48"
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
"checksum render-tree 0.1.1 (git+https://github.com/jonathandturner/language-reporting)" = "<none>"
"checksum render-tree 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "68ed587df09cfb7ce1bc6fe8f77e24db219f222c049326ccbfb948ec67e31664"
"checksum reqwest 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)" = "00eb63f212df0e358b427f0f40aa13aaea010b470be642ad422bcbca2feff2e4"
"checksum result 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "194d8e591e405d1eecf28819740abed6d719d1a2db87fc0bcdedee9a26d55560"
"checksum roxmltree 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "330d8f80a274bc3cb608908ee345970e7e24b96907f1ad69615a498bec57871c"

View file

@ -5,7 +5,10 @@ authors = ["Yehuda Katz <wycats@gmail.com>", "Jonathan Turner <jonathan.d.turner
description = "A shell for the GitHub era"
license = "MIT"
edition = "2018"
readme = "README.md"
default-run = "nu"
repository = "https://github.com/nushell/nushell"
homepage = "https://github.com/nushell/nushell"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -41,7 +44,7 @@ serde_bytes = "0.11.1"
getset = "0.0.7"
logos = "0.10.0-rc2"
logos-derive = "0.10.0-rc2"
language-reporting = {git = "https://github.com/jonathandturner/language-reporting"}
language-reporting = "0.3.1"
app_dirs = "1.2.1"
toml = "0.5.1"
toml-query = "0.9.2"
@ -56,7 +59,7 @@ ptree = "0.2"
clipboard = "0.5"
reqwest = "0.9"
roxmltree = "0.6.1"
nom_locate = { git = "https://github.com/wycats/nom_locate.git", branch = "nom5" }
nom5_locate = "0.1.1"
derive_more = "0.15.0"
enum-utils = "0.1.1"
unicode-xid = "0.1.0"
@ -67,7 +70,7 @@ mime = "0.3.13"
regex = "1.1.9"
pretty-hex = "0.1.0"
neso = "0.5.0"
rawkey = { git = "https://github.com/jonathandturner/rawkey.git" }
rawkey = "0.1.1"
crossterm = "0.9.6"
tempfile = "3.1.0"
image = "0.21.2"

View file

@ -19,7 +19,7 @@ Nu draws inspiration from projects like PowerShell, functional programming langu
In Unix, it's common to pipe between commands to split up a sophisticated command over multiple steps. Nu takes this a step further and builds heavily on the idea of _pipelines_. Just as the Unix philosophy, Nu allows commands to output from stdout and read from stdin. Additionally, commands can output structured data (you can think of this as a third kind of stream). Commands that work in the pipeline fit into one of three categories
* Commands that produce a stream (eg, `ls`)
* Commands that filter a stream (eg, `where "file type" == "Directory"`)
* Commands that filter a stream (eg, `where type == "Directory"`)
* Commands that consumes the output of the pipeline (eg, `autoview`)
Commands are separated by the pipe symbol (`|`) to denote a pipeline flowing left to right.
@ -93,52 +93,13 @@ Finally, we can use commands outside of Nu once we have the data we want:
Here we use the variable `$it` to refer to the value being piped to the external command.
## Navigation
## Plugins
By default, Nu opens up into your filesystem and the current working directory. One way to think of this is a pair: the current object and the current path in the object. The filesystem is our first object, and the path is the cwd.
Nu supports plugins that offer additional functionality to the shell and follow the same object model that built-in commands use. This allows you to extend nu for your needs.
| object | path |
| ------ | ---- |
| Filesystem | /home/jonathan/Source/nushell |
There are a few examples in the `plugins` directory.
Using the `cd` command allows you to change the path from the current path to a new path, just as you might expect. Using `ls` allows you to view the contents of the filesystem at the current path (or at the path of your choosing).
In addition to `cd` and `ls`, we can `enter` an object. Entering an object makes it the current object to navigate (similar to the concept of mounting a filesystem in Unix systems).
```
/home/jonathan/Source/nushell(master)> enter Cargo.toml
object/>
```
As we enter, we create a stack of objects we're navigating:
| object | path |
| ------ | ---- |
| Filesystem | /home/jonathan/Source/nushell |
| object (from Cargo.toml) | / |
Commands `cd` and `ls` now work on the object being navigated.
```
object/> ls
-----------------+------------------+-----------------
dependencies | dev-dependencies | package
-----------------+------------------+-----------------
[object Object] | [object Object] | [object Object]
-----------------+------------------+-----------------
```
```
object/> cd package/version
object/package/version> ls
-------
value
-------
0.1.2
-------
```
The `exit` command will pop the stack and get us back to a previous object we were navigating.
Plugins are binaries that are available in your path and follow a "nu_plugin_*" naming convention. These binaries interact with nu via a simple JSON-RPC protocol where the command identifies itself and passes along its configuration, which then makes it available for use. If the plugin is a filter, data streams to it one element at a time, and it can stream data back in return via stdin/stdout. If the plugin is a sink, it is given the full vector of final data and is given free reign over stdin/stdout to use as it pleases.
# Goals
@ -152,7 +113,7 @@ Nu adheres closely to a set of goals that make up its design philosophy. As feat
* Nu views data as both structured and unstructured. It is an object shell like PowerShell.
These goals are all critical, project-defining priorities. Priority #1 is "direct compatibility" because any new shell absolutely needs a way to use existing executables in a direct and natural way.
* Finally, Nu views data functionally. Rather than using mutation, pipelines act as a mean to load, change, and save data without mutable state.
# Commands
## Initial commands
@ -163,8 +124,7 @@ These goals are all critical, project-defining priorities. Priority #1 is "direc
| ps | View current processes |
| sysinfo | View information about the current system |
| open {filename or url} | Load a file into a cell, convert to table if possible (avoid by appending '--raw') |
| enter {filename or url} | Enter (mount) the given contents as the current object |
| exit | Leave/pop from the current object (exits if in filesystem object) |
| exit | Exit the shell |
## Filters on tables (structured data)
| command | description |
@ -179,7 +139,7 @@ These goals are all critical, project-defining priorities. Priority #1 is "direc
| to-array | Collapse rows into a single list |
| to-json | Convert table into .json text |
| to-toml | Convert table into .toml text |
| to-ini | Convert table into .ini text |
| to-yaml | Convert table into .yaml text |
## Filters on text (unstructured data)
| command | description |
@ -189,6 +149,8 @@ These goals are all critical, project-defining priorities. Priority #1 is "direc
| from-toml | Parse text as .toml and create table |
| from-xml | Parse text as .xml and create a table |
| from-yaml | Parse text as a .yaml/.yml and create a table |
| lines | Split single string into rows, one per line |
| size | Gather word count statistics on the text |
| split-column sep ...fields | Split row contents across multiple columns via the separator |
| split-row sep | Split row contents over multiple rows via the separator |
| trim | Trim leading and following whitespace from text data |
@ -198,6 +160,7 @@ These goals are all critical, project-defining priorities. Priority #1 is "direc
| command | description |
| ------------- | ------------- |
| autoview | View the contents of the pipeline as a table or list |
| binaryview | Autoview of binary data |
| clip | Copy the contents of the pipeline to the copy/paste buffer |
| save filename | Save the contents of the pipeline to a file |
| table | View the contents of the pipeline as a table |

View file

@ -154,8 +154,6 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
command("ls", Box::new(ls::ls)),
command("sysinfo", Box::new(sysinfo::sysinfo)),
command("cd", Box::new(cd::cd)),
command("view", Box::new(view::view)),
// command("skip", skip::Skip),
command("first", Box::new(first::first)),
command("size", Box::new(size::size)),
command("from-ini", Box::new(from_ini::from_ini)),
@ -182,7 +180,6 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
Arc::new(Where),
Arc::new(Config),
Arc::new(SkipWhile),
Arc::new(Enter),
]);
context.add_sinks(vec![
@ -220,22 +217,18 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
continue;
}
let (obj, cwd) = {
let cwd = {
let env = context.env.lock().unwrap();
let last = env.back().unwrap();
(last.obj().clone(), last.path().display().to_string())
};
let readline = match obj.item {
Value::Filesystem => rl.readline(&format!(
"{}{}> ",
cwd,
match current_branch() {
Some(s) => format!("({})", s),
None => "".to_string(),
}
)),
_ => rl.readline(&format!("{}{}> ", obj.type_name(), cwd)),
env.path().display().to_string()
};
let readline = rl.readline(&format!(
"{}{}> ",
cwd,
match current_branch() {
Some(s) => format!("({})", s),
None => "".to_string(),
}
));
match process_line(readline, &mut context).await {
LineResult::Success(line) => {

View file

@ -8,7 +8,6 @@ crate mod classified;
crate mod clip;
crate mod command;
crate mod config;
crate mod enter;
crate mod exit;
crate mod first;
crate mod from_ini;
@ -37,13 +36,11 @@ crate mod to_json;
crate mod to_toml;
crate mod to_yaml;
crate mod trim;
crate mod view;
crate mod vtable;
crate mod where_;
crate use command::command;
crate use config::Config;
crate use enter::Enter;
crate use open::Open;
crate use skip_while::SkipWhile;
crate use where_::Where;

View file

@ -1,85 +1,52 @@
use crate::errors::ShellError;
use crate::prelude::*;
use std::env;
use std::path::PathBuf;
pub fn cd(args: CommandArgs) -> Result<OutputStream, ShellError> {
let env = args.env.lock().unwrap();
let latest = env.back().unwrap();
let obj = &latest.obj;
let cwd = env.path().to_path_buf();
match obj.item() {
Value::Filesystem => {
let cwd = latest.path().to_path_buf();
let path = match args.nth(0) {
None => match dirs::home_dir() {
Some(o) => o,
_ => {
return Err(ShellError::maybe_labeled_error(
"Can not change to home directory",
"can not go to home",
args.name_span,
))
}
},
Some(v) => {
let target = v.as_string()?;
match dunce::canonicalize(cwd.join(target).as_path()) {
Ok(p) => p,
Err(_) => {
return Err(ShellError::labeled_error(
"Can not change to directory",
"directory not found",
v.span.clone(),
));
}
}
}
};
let mut stream = VecDeque::new();
match env::set_current_dir(&path) {
Ok(_) => {}
let path = match args.nth(0) {
None => match dirs::home_dir() {
Some(o) => o,
_ => {
return Err(ShellError::maybe_labeled_error(
"Can not change to home directory",
"can not go to home",
args.name_span,
))
}
},
Some(v) => {
let target = v.as_string()?;
match dunce::canonicalize(cwd.join(target).as_path()) {
Ok(p) => p,
Err(_) => {
if args.len() > 0 {
return Err(ShellError::labeled_error(
"Can not change to directory",
"directory not found",
args.nth(0).unwrap().span.clone(),
));
} else {
return Err(ShellError::string("Can not change to directory"));
}
return Err(ShellError::labeled_error(
"Can not change to directory",
"directory not found",
v.span.clone(),
));
}
}
stream.push_back(ReturnSuccess::change_cwd(path));
Ok(stream.into())
}
_ => {
let mut stream = VecDeque::new();
match args.nth(0) {
None => {
stream.push_back(ReturnSuccess::change_cwd(PathBuf::from("/")));
}
Some(v) => {
let mut cwd = latest.path().to_path_buf();
let target = v.as_string()?.clone();
match target {
x if x == ".." => {
cwd.pop();
}
_ => match target.chars().nth(0) {
Some(x) if x == '/' => cwd = PathBuf::from(target),
_ => {
cwd.push(target);
}
},
}
stream.push_back(ReturnSuccess::change_cwd(cwd));
}
};
Ok(stream.into())
};
let mut stream = VecDeque::new();
match env::set_current_dir(&path) {
Ok(_) => {}
Err(_) => {
if args.len() > 0 {
return Err(ShellError::labeled_error(
"Can not change to directory",
"directory not found",
args.nth(0).unwrap().span.clone(),
));
} else {
return Err(ShellError::string("Can not change to directory"));
}
}
}
stream.push_back(ReturnSuccess::change_cwd(path));
Ok(stream.into())
}

View file

@ -6,7 +6,6 @@ use futures::stream::StreamExt;
use futures_codec::{Decoder, Encoder, Framed};
use log::{log_enabled, trace};
use std::io::{Error, ErrorKind};
use std::path::PathBuf;
use std::sync::Arc;
use subprocess::Exec;
@ -145,30 +144,9 @@ impl InternalCommand {
match item? {
ReturnSuccess::Action(action) => match action {
CommandAction::ChangePath(path) => {
context.env.lock().unwrap().back_mut().map(|x| {
x.path = path;
x
});
context.env.lock().unwrap().path = path;
}
CommandAction::Enter(obj) => {
let new_env = Environment {
obj: obj,
path: PathBuf::from("/"),
};
context.env.lock().unwrap().push_back(new_env);
}
CommandAction::Exit => match context.env.lock().unwrap().pop_back() {
Some(Environment {
obj:
Spanned {
item: Value::Filesystem,
..
},
..
}) => std::process::exit(0),
None => std::process::exit(-1),
_ => {}
},
CommandAction::Exit => std::process::exit(0),
},
ReturnSuccess::Value(v) => {
@ -306,7 +284,7 @@ impl ExternalCommand {
process = Exec::shell(new_arg_string);
}
process = process.cwd(context.env.lock().unwrap().front().unwrap().path());
process = process.cwd(context.env.lock().unwrap().path());
let mut process = match stream_next {
StreamNext::Last => process,

View file

@ -13,7 +13,7 @@ use std::path::PathBuf;
#[get = "crate"]
pub struct CommandArgs {
pub host: Arc<Mutex<dyn Host + Send>>,
pub env: Arc<Mutex<VecDeque<Environment>>>,
pub env: Arc<Mutex<Environment>>,
pub name_span: Option<Span>,
pub args: Args,
pub input: InputStream,
@ -40,6 +40,7 @@ impl CommandArgs {
self.args.get(name)
}
#[allow(unused)]
pub fn has(&self, name: &str) -> bool {
self.args.has(name)
}
@ -55,7 +56,6 @@ pub struct SinkCommandArgs {
#[derive(Debug, Serialize, Deserialize)]
pub enum CommandAction {
ChangePath(PathBuf),
Enter(Spanned<Value>),
Exit,
}

View file

@ -1,105 +0,0 @@
use crate::commands::command::CommandAction;
use crate::commands::open::{fetch, parse_as_value};
use crate::errors::ShellError;
use crate::object::{Primitive, Value};
use crate::parser::registry::{CommandConfig, PositionalType};
use crate::prelude::*;
use std::path::PathBuf;
pub struct Enter;
impl Command for Enter {
fn config(&self) -> CommandConfig {
CommandConfig {
name: self.name().to_string(),
positional: vec![PositionalType::mandatory_block("path")],
rest_positional: false,
is_filter: false,
is_sink: false,
named: indexmap::IndexMap::new(),
}
}
fn name(&self) -> &str {
"enter"
}
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
enter(args)
}
}
pub fn enter(args: CommandArgs) -> Result<OutputStream, ShellError> {
if args.len() == 0 {
return Err(ShellError::maybe_labeled_error(
"open requires a path or url",
"missing path",
args.name_span,
));
}
let span = args.name_span;
let cwd = args
.env()
.lock()
.unwrap()
.front()
.unwrap()
.path()
.to_path_buf();
let full_path = PathBuf::from(cwd);
let (file_extension, contents, contents_span) = match &args.expect_nth(0)?.item {
Value::Primitive(Primitive::String(s)) => fetch(&full_path, s, args.expect_nth(0)?.span)?,
_ => {
return Err(ShellError::labeled_error(
"Expected string value for filename",
"expected filename",
args.expect_nth(0)?.span,
));
}
};
let mut stream = VecDeque::new();
let file_extension = if args.has("raw") {
None
} else if args.has("json") {
Some("json".to_string())
} else if args.has("xml") {
Some("xml".to_string())
} else if args.has("ini") {
Some("ini".to_string())
} else if args.has("yaml") {
Some("yaml".to_string())
} else if args.has("toml") {
Some("toml".to_string())
} else {
if let Some(ref named_args) = args.args.named {
for named in named_args.iter() {
return Err(ShellError::labeled_error(
"Unknown flag for enter",
"unknown flag",
named.1.span.clone(),
));
}
file_extension
} else {
file_extension
}
};
match contents {
Value::Primitive(Primitive::String(string)) => {
stream.push_back(Ok(ReturnSuccess::Action(CommandAction::Enter(
parse_as_value(file_extension, string, contents_span, span)?,
))));
}
other => stream.push_back(ReturnSuccess::value(other.spanned(contents_span))),
};
Ok(stream.into())
}

View file

@ -2,13 +2,11 @@ use crate::errors::ShellError;
use crate::object::{dir_entry_dict, Primitive, Value};
use crate::parser::Spanned;
use crate::prelude::*;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};
pub fn ls(args: CommandArgs) -> Result<OutputStream, ShellError> {
let env = args.env.lock().unwrap();
let path = env.back().unwrap().path.to_path_buf();
let obj = &env.back().unwrap().obj;
let path = env.path.to_path_buf();
let mut full_path = PathBuf::from(path);
match &args.nth(0) {
Some(Spanned {
@ -18,126 +16,32 @@ pub fn ls(args: CommandArgs) -> Result<OutputStream, ShellError> {
_ => {}
}
match obj.item {
Value::Filesystem => {
let entries = std::fs::read_dir(&full_path);
let entries = std::fs::read_dir(&full_path);
let entries = match entries {
Err(e) => {
if let Some(s) = args.nth(0) {
return Err(ShellError::labeled_error(
e.to_string(),
e.to_string(),
s.span,
));
} else {
return Err(ShellError::maybe_labeled_error(
e.to_string(),
e.to_string(),
args.name_span,
));
}
}
Ok(o) => o,
};
let mut shell_entries = VecDeque::new();
for entry in entries {
let value = dir_entry_dict(&entry?, args.name_span)?;
shell_entries.push_back(ReturnSuccess::value(value))
let entries = match entries {
Err(e) => {
if let Some(s) = args.nth(0) {
return Err(ShellError::labeled_error(
e.to_string(),
e.to_string(),
s.span,
));
} else {
return Err(ShellError::maybe_labeled_error(
e.to_string(),
e.to_string(),
args.name_span,
));
}
Ok(shell_entries.to_output_stream())
}
_ => {
let mut entries = VecDeque::new();
let mut viewed = obj;
let sep_string = std::path::MAIN_SEPARATOR.to_string();
let sep = OsStr::new(&sep_string);
for p in full_path.iter() {
//let p = p.to_string_lossy();
match p {
x if x == sep => {}
step => {
let tmp = step.to_string_lossy();
let split_tmp = tmp.split('[');
let mut first = true;
Ok(o) => o,
};
for s in split_tmp {
if !first {
match s.find(']') {
Some(finish) => {
let idx = s[0..finish].parse::<usize>();
match idx {
Ok(idx) => match viewed.get_data_by_index(idx) {
Some(v) => {
viewed = v;
}
_ => {
return Err(ShellError::maybe_labeled_error(
"Given incorrect index",
format!("path given bad index: {}", idx),
args.name_span,
))
}
},
_ => {
return Err(ShellError::maybe_labeled_error(
"Given incorrect index",
format!(
"path index not a number: {}",
&s[0..finish]
),
args.name_span,
))
}
}
}
_ => {
return Err(ShellError::maybe_labeled_error(
"Index not closed",
format!("path missing closing ']'"),
if args.len() > 0 {
Some(args.nth(0).unwrap().span)
} else {
args.name_span
},
))
}
}
} else {
match viewed.get_data_by_key(s) {
Some(v) => {
viewed = v;
}
_ => {
return Err(ShellError::maybe_labeled_error(
"Could not find key",
format!("could not find: {}", s),
args.name_span,
))
}
}
first = false;
}
}
}
}
}
match viewed {
Spanned {
item: Value::List(l),
..
} => {
for item in l {
entries.push_back(ReturnSuccess::value(item.clone()));
}
}
x => {
entries.push_back(ReturnSuccess::value(x.clone()));
}
}
Ok(entries.to_output_stream())
}
let mut shell_entries = VecDeque::new();
for entry in entries {
let value = dir_entry_dict(&entry?, args.name_span)?;
shell_entries.push_back(ReturnSuccess::value(value))
}
Ok(shell_entries.to_output_stream())
}

View file

@ -14,8 +14,6 @@ command! {
.env
.lock()
.unwrap()
.front()
.unwrap()
.path()
.to_path_buf();
@ -39,29 +37,8 @@ command! {
let file_extension = if raw.is_present() {
None
} else if args.has("json") {
Some("json".to_string())
} else if args.has("xml") {
Some("xml".to_string())
} else if args.has("ini") {
Some("ini".to_string())
} else if args.has("yaml") {
Some("yaml".to_string())
} else if args.has("toml") {
Some("toml".to_string())
} else {
if let Some(ref named_args) = args.args.named {
for named in named_args.iter() {
return Err(ShellError::labeled_error(
"Unknown flag for open",
"unknown flag",
named.1.span.clone(),
));
}
file_extension
} else {
file_extension
}
file_extension
};
match contents {

View file

@ -21,15 +21,7 @@ pub fn save(args: SinkCommandArgs) -> Result<(), ShellError> {
Some(p) => p,
};
let cwd = args
.ctx
.env
.lock()
.unwrap()
.front()
.unwrap()
.path()
.to_path_buf();
let cwd = args.ctx.env.lock().unwrap().path().to_path_buf();
let mut full_path = PathBuf::from(cwd);
match &(positional[0].item) {
Value::Primitive(Primitive::String(s)) => full_path.push(Path::new(s)),

View file

@ -1,42 +1,23 @@
use crate::errors::ShellError;
use crate::object::{SpannedDictBuilder, Value};
use crate::prelude::*;
use std::fs::File;
use std::io::prelude::*;
pub fn size(args: CommandArgs) -> Result<OutputStream, ShellError> {
if args.len() == 0 {
return Err(ShellError::maybe_labeled_error(
"Size requires a filepath",
"needs path",
args.name_span,
));
}
let cwd = args
.env
.lock()
.unwrap()
.front()
.unwrap()
.path()
.to_path_buf();
let mut contents = String::new();
let mut list: VecDeque<ReturnValue> = VecDeque::new();
for spanned_name in args.positional_iter() {
let name = spanned_name.as_string()?;
let path = cwd.join(&name);
let mut file = File::open(path)?;
file.read_to_string(&mut contents)?;
list.push_back(count(&name, &contents, spanned_name).into());
contents.clear();
}
Ok(list.to_output_stream())
let input = args.input;
Ok(input
.values
.map(move |v| match v.item {
Value::Primitive(Primitive::String(s)) => ReturnSuccess::value(count(&s, v.span)),
_ => Err(ShellError::maybe_labeled_error(
"Expected string values from pipeline",
"expects strings from pipeline",
Some(v.span),
)),
})
.to_output_stream())
}
fn count(name: &str, contents: &str, span: impl Into<Span>) -> Spanned<Value> {
fn count(contents: &str, span: impl Into<Span>) -> Spanned<Value> {
let mut lines: i64 = 0;
let mut words: i64 = 0;
let mut chars: i64 = 0;
@ -62,7 +43,8 @@ fn count(name: &str, contents: &str, span: impl Into<Span>) -> Spanned<Value> {
}
let mut dict = SpannedDictBuilder::new(span);
dict.insert("name", Value::string(name));
//TODO: add back in name when we have it in the span
//dict.insert("name", Value::string(name));
dict.insert("lines", Value::int(lines));
dict.insert("words", Value::int(words));
dict.insert("chars", Value::int(chars));

View file

@ -3,8 +3,6 @@ use crate::object::{Primitive, SpannedDictBuilder, Value};
use crate::prelude::*;
use log::trace;
// TODO: "Amount remaining" wrapper
pub fn split_column(args: CommandArgs) -> Result<OutputStream, ShellError> {
let positional: Vec<_> = args.positional_iter().cloned().collect();
let span = args.name_span;

View file

@ -4,8 +4,6 @@ use crate::parser::Spanned;
use crate::prelude::*;
use log::trace;
// TODO: "Amount remaining" wrapper
pub fn split_row(args: CommandArgs) -> Result<OutputStream, ShellError> {
let positional: Vec<Spanned<Value>> = args.positional_iter().cloned().collect();
let span = args.name_span;

View file

@ -19,7 +19,6 @@ pub fn value_to_json_value(v: &Value) -> serde_json::Value {
Value::Primitive(Primitive::String(s)) => serde_json::Value::String(s.clone()),
Value::Primitive(Primitive::Path(s)) => serde_json::Value::String(s.display().to_string()),
Value::Filesystem => serde_json::Value::Null,
Value::List(l) => {
serde_json::Value::Array(l.iter().map(|x| value_to_json_value(x)).collect())
}

View file

@ -15,7 +15,6 @@ pub fn value_to_toml_value(v: &Value) -> toml::Value {
Value::Primitive(Primitive::String(s)) => toml::Value::String(s.clone()),
Value::Primitive(Primitive::Path(s)) => toml::Value::String(s.display().to_string()),
Value::Filesystem => toml::Value::String("<Filesystem>".to_string()),
Value::List(l) => toml::Value::Array(l.iter().map(|x| value_to_toml_value(x)).collect()),
Value::Block(_) => toml::Value::String("<Block>".to_string()),
Value::Binary(b) => {

View file

@ -19,7 +19,6 @@ pub fn value_to_yaml_value(v: &Value) -> serde_yaml::Value {
Value::Primitive(Primitive::String(s)) => serde_yaml::Value::String(s.clone()),
Value::Primitive(Primitive::Path(s)) => serde_yaml::Value::String(s.display().to_string()),
Value::Filesystem => serde_yaml::Value::Null,
Value::List(l) => {
serde_yaml::Value::Sequence(l.iter().map(|x| value_to_yaml_value(x)).collect())
}

View file

@ -1,50 +0,0 @@
use crate::errors::ShellError;
use crate::prelude::*;
use prettyprint::PrettyPrinter;
pub fn view(args: CommandArgs) -> Result<OutputStream, ShellError> {
if args.len() == 0 {
return Err(ShellError::maybe_labeled_error(
"View requires a filename",
"needs parameter",
args.name_span,
));
}
let target = match args.expect_nth(0)?.as_string() {
Ok(s) => s.clone(),
Err(e) => {
if let Some(span) = args.name_span {
return Err(ShellError::labeled_error(
"Expected a string",
"not a filename",
span,
));
} else {
return Err(e);
}
}
};
let cwd = args
.env
.lock()
.unwrap()
.front()
.unwrap()
.path()
.to_path_buf();
let printer = PrettyPrinter::default()
.line_numbers(false)
.header(false)
.grid(false)
.build()
.map_err(|e| ShellError::string(e))?;
let file = cwd.join(&target);
let _ = printer.file(file.display().to_string());
Ok(OutputStream::empty())
}

View file

@ -14,18 +14,16 @@ pub struct Context {
commands: IndexMap<String, Arc<dyn Command>>,
sinks: IndexMap<String, Arc<dyn Sink>>,
crate host: Arc<Mutex<dyn Host + Send>>,
crate env: Arc<Mutex<VecDeque<Environment>>>,
crate env: Arc<Mutex<Environment>>,
}
impl Context {
crate fn basic() -> Result<Context, Box<dyn Error>> {
let mut env = VecDeque::new();
env.push_back(Environment::basic()?);
Ok(Context {
commands: indexmap::IndexMap::new(),
sinks: indexmap::IndexMap::new(),
host: Arc::new(Mutex::new(crate::env::host::BasicHost)),
env: Arc::new(Mutex::new(env)),
env: Arc::new(Mutex::new(Environment::basic()?)),
})
}

View file

@ -1,10 +1,7 @@
use crate::object::base::Value;
use crate::prelude::*;
use std::path::{Path, PathBuf};
#[derive(Debug, Clone)]
pub struct Environment {
crate obj: Spanned<Value>,
crate path: PathBuf,
}
@ -12,17 +9,10 @@ impl Environment {
pub fn basic() -> Result<Environment, std::io::Error> {
let path = std::env::current_dir()?;
Ok(Environment {
obj: Value::Filesystem.spanned_unknown(),
path,
})
Ok(Environment { path })
}
pub fn path(&self) -> &Path {
self.path.as_path()
}
pub fn obj(&self) -> &Spanned<Value> {
&self.obj
}
}

View file

@ -98,7 +98,7 @@ impl ShellError {
}
crate fn parse_error(
error: nom::Err<(nom_locate::LocatedSpan<&str>, nom::error::ErrorKind)>,
error: nom::Err<(nom5_locate::LocatedSpan<&str>, nom::error::ErrorKind)>,
) -> ShellError {
use language_reporting::*;

View file

@ -40,11 +40,6 @@ impl RenderView for GenericView<'value> {
host.stdout("<Binary>");
Ok(())
}
Value::Filesystem => {
host.stdout("<filesystem>");
Ok(())
}
}
}
}

View file

@ -185,7 +185,6 @@ pub enum Value {
List(Vec<Spanned<Value>>),
#[allow(unused)]
Block(Block),
Filesystem,
}
pub fn debug_list(values: &'a Vec<Spanned<Value>>) -> ValuesDebug<'a> {
@ -215,7 +214,6 @@ impl fmt::Debug for ValueDebug<'a> {
Value::Object(o) => o.debug(f),
Value::List(l) => debug_list(l).fmt(f),
Value::Block(_) => write!(f, "[[block]]"),
Value::Filesystem => write!(f, "[[filesystem]]"),
Value::Binary(_) => write!(f, "[[binary]]"),
}
}
@ -300,7 +298,6 @@ impl Value {
Value::Object(_) => format!("object"),
Value::List(_) => format!("list"),
Value::Block(_) => format!("block"),
Value::Filesystem => format!("filesystem"),
Value::Binary(_) => format!("binary"),
}
}
@ -316,7 +313,6 @@ impl Value {
.collect(),
Value::Block(_) => vec![],
Value::List(_) => vec![],
Value::Filesystem => vec![],
Value::Binary(_) => vec![],
}
}
@ -343,6 +339,7 @@ impl Value {
}
}
#[allow(unused)]
crate fn get_data_by_index(&'a self, idx: usize) -> Option<&Spanned<Value>> {
match self {
Value::List(l) => l.iter().nth(idx),
@ -353,7 +350,6 @@ impl Value {
pub fn get_data(&'a self, desc: &String) -> MaybeOwned<'a, Value> {
match self {
p @ Value::Primitive(_) => MaybeOwned::Borrowed(p),
p @ Value::Filesystem => MaybeOwned::Borrowed(p),
Value::Object(o) => o.get_data(desc),
Value::Block(_) => MaybeOwned::Owned(Value::nothing()),
Value::List(_) => MaybeOwned::Owned(Value::nothing()),
@ -372,7 +368,6 @@ impl Value {
),
Value::Object(_) => format!("[object Object]"),
Value::List(_) => format!("[list List]"),
Value::Filesystem => format!("<filesystem>"),
Value::Binary(_) => format!("<binary>"),
}
}

View file

@ -16,7 +16,7 @@ use log::trace;
use nom::dbg;
use nom::*;
use nom::{AsBytes, FindSubstring, IResult, InputLength, InputTake, Slice};
use nom_locate::{position, LocatedSpan};
use nom5_locate::{position, LocatedSpan};
use std::fmt::Debug;
use std::str::FromStr;

View file

@ -99,8 +99,8 @@ impl From<&Span> for Span {
}
}
impl From<nom_locate::LocatedSpan<&str>> for Span {
fn from(input: nom_locate::LocatedSpan<&str>) -> Span {
impl From<nom5_locate::LocatedSpan<&str>> for Span {
fn from(input: nom5_locate::LocatedSpan<&str>) -> Span {
Span {
start: input.offset,
end: input.offset + input.fragment.len(),
@ -108,8 +108,8 @@ impl From<nom_locate::LocatedSpan<&str>> for Span {
}
}
impl<T> From<(nom_locate::LocatedSpan<T>, nom_locate::LocatedSpan<T>)> for Span {
fn from(input: (nom_locate::LocatedSpan<T>, nom_locate::LocatedSpan<T>)) -> Span {
impl<T> From<(nom5_locate::LocatedSpan<T>, nom5_locate::LocatedSpan<T>)> for Span {
fn from(input: (nom5_locate::LocatedSpan<T>, nom5_locate::LocatedSpan<T>)) -> Span {
Span {
start: input.0.offset,
end: input.1.offset,

View file

@ -32,6 +32,10 @@ impl PositionalType {
PositionalType::Mandatory(name.to_string(), SyntaxType::Any)
}
pub fn mandatory_block(name: &str) -> PositionalType {
PositionalType::Mandatory(name.to_string(), SyntaxType::Block)
}
pub fn optional(name: &str, ty: SyntaxType) -> PositionalType {
PositionalType::Optional(name.to_string(), ty)
}
@ -40,10 +44,6 @@ impl PositionalType {
PositionalType::Optional(name.to_string(), SyntaxType::Any)
}
pub fn mandatory_block(name: &str) -> PositionalType {
PositionalType::Mandatory(name.to_string(), SyntaxType::Block)
}
#[allow(unused)]
crate fn to_coerce_hint(&self) -> Option<SyntaxType> {
match self {

View file

@ -31,7 +31,6 @@ impl TreeView {
}
}
Value::Block(_) => {}
Value::Filesystem => {}
Value::Binary(_) => {}
}
}

View file

@ -46,6 +46,7 @@ pub struct OutputStream {
}
impl OutputStream {
#[allow(unused)]
pub fn empty() -> OutputStream {
let v: VecDeque<ReturnValue> = VecDeque::new();
v.into()

View file

@ -1 +0,0 @@
markup

View file

@ -1,10 +0,0 @@
cd tests
enter test.json
cd glossary
cd GlossDiv
cd GlossList
cd GlossEntry
cd GlossSee
ls | echo $it
exit
exit

View file

@ -92,17 +92,11 @@ mod tests {
test_helper("split");
}
#[test]
fn enter() {
test_helper("enter");
}
#[test]
fn lines() {
test_helper("lines");
}
#[test]
fn external_num() {
test_helper("external_num");