mirror of
https://github.com/nushell/nushell.git
synced 2024-11-29 03:44:19 +01:00
Merge master
This commit is contained in:
commit
fa2c6ec227
125
.circleci/config.yml
Normal file
125
.circleci/config.yml
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
# CircleCI 2.0 configuration file
|
||||||
|
#
|
||||||
|
# Check https://circleci.com/docs/2.0/configuration-reference/ for more details
|
||||||
|
# See https://circleci.com/docs/2.0/config-intro/#section=configuration for spec
|
||||||
|
#
|
||||||
|
version: 2.1
|
||||||
|
|
||||||
|
# Commands
|
||||||
|
|
||||||
|
commands:
|
||||||
|
|
||||||
|
check_token:
|
||||||
|
description: Check that QUAY_TOKEN is provided in environment
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
if [[ -z "${QUAY_TOKEN}" ]]; then
|
||||||
|
echo "QUAY_TOKEN is undefined. Add to CircleCI environment to continue."
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
pull_cache:
|
||||||
|
description: Pulls Quay.io docker images usable for our cache
|
||||||
|
steps:
|
||||||
|
- run: docker pull quay.io/nushell/nu:latest
|
||||||
|
- run: docker pull quay.io/nushell/nu-base:latest
|
||||||
|
|
||||||
|
|
||||||
|
orbs:
|
||||||
|
# https://circleci.com/orbs/registry/orb/circleci/docker
|
||||||
|
docker: circleci/docker@0.5.13
|
||||||
|
|
||||||
|
workflows:
|
||||||
|
version: 2.0
|
||||||
|
|
||||||
|
# This builds on all pull requests to test, and ignores master
|
||||||
|
build_without_deploy:
|
||||||
|
jobs:
|
||||||
|
- docker/publish:
|
||||||
|
deploy: false
|
||||||
|
image: nushell/nu-base
|
||||||
|
tag: latest
|
||||||
|
dockerfile: docker/Dockerfile.nu-base
|
||||||
|
extra_build_args: --cache-from=quay.io/nushell/nu-base:latest,quay.io/nushell/nu:latest
|
||||||
|
filters:
|
||||||
|
branches:
|
||||||
|
ignore:
|
||||||
|
- master
|
||||||
|
before_build:
|
||||||
|
- check_token
|
||||||
|
- pull_cache
|
||||||
|
after_build:
|
||||||
|
- run:
|
||||||
|
name: Build Multistage (smaller) container
|
||||||
|
command: |
|
||||||
|
docker build -f docker/Dockerfile -t quay.io/nushell/nu .
|
||||||
|
- run:
|
||||||
|
name: Preview Docker Tag for Nushell Build
|
||||||
|
command: |
|
||||||
|
DOCKER_TAG=$(docker run quay.io/nushell/nu --version | cut -d' ' -f2)
|
||||||
|
echo "Version that would be used for Docker tag is v${DOCKER_TAG}"
|
||||||
|
|
||||||
|
# workflow publishes to Docker Hub, with each job having different triggers
|
||||||
|
build_with_deploy:
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
# Deploy versioned and latest images on tags (releases) only.
|
||||||
|
- docker/publish:
|
||||||
|
image: nushell/nu-base
|
||||||
|
registry: quay.io
|
||||||
|
tag: latest
|
||||||
|
dockerfile: docker/Dockerfile.nu-base
|
||||||
|
extra_build_args: --cache-from=quay.io/nushell/nu-base:latest,quay.io/nushell/nu:latest
|
||||||
|
filters:
|
||||||
|
branches:
|
||||||
|
ignore: /.*/
|
||||||
|
tags:
|
||||||
|
only: /^v.*/
|
||||||
|
before_build:
|
||||||
|
- check_token
|
||||||
|
- pull_cache
|
||||||
|
after_build:
|
||||||
|
- run:
|
||||||
|
name: Build Multistage (smaller) container
|
||||||
|
command: |
|
||||||
|
docker build -f docker/Dockerfile -t quay.io/nushell/nu .
|
||||||
|
- run:
|
||||||
|
name: Publish Docker Tag with Nushell Version
|
||||||
|
command: |
|
||||||
|
DOCKER_TAG=$(docker run quay.io/nushell/nu --version | cut -d' ' -f2)
|
||||||
|
echo "Version for Docker tag is ${DOCKER_TAG}"
|
||||||
|
docker tag quay.io/nushell/nu-base:latest quay.io/nushell/nu-base:${DOCKER_TAG}
|
||||||
|
docker tag quay.io/nushell/nu:latest quay.io/nushell/nu:${DOCKER_TAG}
|
||||||
|
docker login -u="nushell+circleci" -p="${QUAY_TOKEN}" quay.io
|
||||||
|
docker push quay.io/nushell/nu-base
|
||||||
|
docker push quay.io/nushell/nu
|
||||||
|
|
||||||
|
|
||||||
|
# publish devel to Docker Hub on merge to master
|
||||||
|
build_with_deploy_devel:
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
# Deploy devel tag on merge to master
|
||||||
|
- docker/publish:
|
||||||
|
image: nushell/nu-base
|
||||||
|
registry: quay.io
|
||||||
|
tag: devel
|
||||||
|
dockerfile: docker/Dockerfile.nu-base
|
||||||
|
extra_build_args: --cache-from=quay.io/nushell/nu-base:latest,quay.io/nushell/nu:latest
|
||||||
|
before_build:
|
||||||
|
- check_token
|
||||||
|
- pull_cache
|
||||||
|
filters:
|
||||||
|
branches:
|
||||||
|
only: master
|
||||||
|
after_build:
|
||||||
|
- run:
|
||||||
|
name: Build Multistage (smaller) container
|
||||||
|
command: |
|
||||||
|
docker build --build-arg FROMTAG=devel -f docker/Dockerfile -t quay.io/nushell/nu:devel .
|
||||||
|
- run:
|
||||||
|
name: Publish Development Docker Tags
|
||||||
|
command: |
|
||||||
|
docker login -u="nushell+circleci" -p="${QUAY_TOKEN}" quay.io
|
||||||
|
docker push quay.io/nushell/nu-base:devel
|
||||||
|
docker push quay.io/nushell/nu:devel
|
478
Cargo.lock
generated
478
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
14
Cargo.toml
14
Cargo.toml
@ -15,7 +15,6 @@ documentation = "https://book.nushell.sh"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rustyline = "5.0.2"
|
rustyline = "5.0.2"
|
||||||
sysinfo = "0.9"
|
|
||||||
chrono = { version = "0.4.7", features = ["serde"] }
|
chrono = { version = "0.4.7", features = ["serde"] }
|
||||||
derive-new = "0.5.7"
|
derive-new = "0.5.7"
|
||||||
prettytable-rs = "0.8.0"
|
prettytable-rs = "0.8.0"
|
||||||
@ -27,16 +26,15 @@ indexmap = { version = "1.0.2", features = ["serde-1"] }
|
|||||||
chrono-humanize = "0.0.11"
|
chrono-humanize = "0.0.11"
|
||||||
byte-unit = "3.0.1"
|
byte-unit = "3.0.1"
|
||||||
ordered-float = {version = "1.0.2", features = ["serde"]}
|
ordered-float = {version = "1.0.2", features = ["serde"]}
|
||||||
futures-preview = { version = "=0.3.0-alpha.17", features = ["compat", "io-compat"] }
|
futures-preview = { version = "=0.3.0-alpha.18", features = ["compat", "io-compat"] }
|
||||||
futures-sink-preview = "=0.3.0-alpha.17"
|
futures-async-stream = "=0.1.0-alpha.5"
|
||||||
futures-async-stream = "=0.1.0-alpha.2"
|
|
||||||
futures_codec = "0.2.5"
|
futures_codec = "0.2.5"
|
||||||
term = "0.5.2"
|
term = "0.5.2"
|
||||||
bytes = "0.4.12"
|
bytes = "0.4.12"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
pretty_env_logger = "0.3.1"
|
pretty_env_logger = "0.3.1"
|
||||||
serde = { version = "1.0.98", features = ["derive"] }
|
serde = { version = "1.0.98", features = ["derive"] }
|
||||||
bson = "0.13.0"
|
bson = "=0.13.0"
|
||||||
serde_json = "1.0.40"
|
serde_json = "1.0.40"
|
||||||
serde-hjson = "0.9.1"
|
serde-hjson = "0.9.1"
|
||||||
serde_yaml = "0.8"
|
serde_yaml = "0.8"
|
||||||
@ -52,7 +50,7 @@ dirs = "2.0.2"
|
|||||||
glob = "0.3.0"
|
glob = "0.3.0"
|
||||||
ctrlc = "3.1.3"
|
ctrlc = "3.1.3"
|
||||||
ptree = "0.2"
|
ptree = "0.2"
|
||||||
surf = "1.0"
|
surf = "1.0.2"
|
||||||
url = "2.1.0"
|
url = "2.1.0"
|
||||||
roxmltree = "0.7.0"
|
roxmltree = "0.7.0"
|
||||||
nom5_locate = "0.1.1"
|
nom5_locate = "0.1.1"
|
||||||
@ -71,13 +69,15 @@ semver = "0.9.0"
|
|||||||
uuid = {version = "0.7.4", features = [ "v4", "serde" ]}
|
uuid = {version = "0.7.4", features = [ "v4", "serde" ]}
|
||||||
syntect = "3.2.0"
|
syntect = "3.2.0"
|
||||||
onig_sys = "=69.1.0"
|
onig_sys = "=69.1.0"
|
||||||
heim = "0.0.6"
|
heim = "0.0.7"
|
||||||
which = "2.0.1"
|
which = "2.0.1"
|
||||||
battery = "0.7.4"
|
battery = "0.7.4"
|
||||||
textwrap = {version = "0.11.0", features = ["term_size"]}
|
textwrap = {version = "0.11.0", features = ["term_size"]}
|
||||||
rawkey = {version = "0.1.2", optional = true }
|
rawkey = {version = "0.1.2", optional = true }
|
||||||
clipboard = {version = "0.5", optional = true }
|
clipboard = {version = "0.5", optional = true }
|
||||||
shellexpand = "1.0.0"
|
shellexpand = "1.0.0"
|
||||||
|
futures-timer = "0.3.0"
|
||||||
|
pin-utils = "0.1.0-alpha.4"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
raw-key = ["rawkey", "neso"]
|
raw-key = ["rawkey", "neso"]
|
||||||
|
16
Dockerfile
16
Dockerfile
@ -1,16 +0,0 @@
|
|||||||
FROM rust:1.37-slim
|
|
||||||
|
|
||||||
# docker build -t nu .
|
|
||||||
# docker run -it nu
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND noninteractive
|
|
||||||
RUN apt-get update && apt-get install -y libssl-dev \
|
|
||||||
libxcb-composite0-dev \
|
|
||||||
libx11-dev \
|
|
||||||
pkg-config && \
|
|
||||||
mkdir -p /code
|
|
||||||
|
|
||||||
ADD . /code
|
|
||||||
WORKDIR /code
|
|
||||||
RUN cargo install nu
|
|
||||||
ENTRYPOINT ["nu"]
|
|
31
README.md
31
README.md
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Nu Shell
|
# Nu Shell
|
||||||
|
|
||||||
A modern, GitHub-era shell written in Rust
|
A modern shell for the GitHub era
|
||||||
|
|
||||||
![Example of nushell](images/nushell-autocomplete4.gif "Example of nushell")
|
![Example of nushell](images/nushell-autocomplete4.gif "Example of nushell")
|
||||||
|
|
||||||
@ -51,19 +51,40 @@ The following optional features are currently supported:
|
|||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
|
|
||||||
Optionally, you can build a container with nu installed using the [Dockerfile](Dockerfile):
|
If you want to pull a pre-built container, you can browse tags for the [nushell organization](https://quay.io/organization/nushell)
|
||||||
|
on Quay.io. Pulling a container would come down to:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ docker build -t nu .
|
$ docker pull quay.io/nushell/nu
|
||||||
|
$ docker pull quay.io/nushell/nu-base
|
||||||
|
```
|
||||||
|
|
||||||
|
Both "nu-base" and "nu" provide the nu binary, however nu-base also includes the source code at `/code`
|
||||||
|
in the container and all dependencies.
|
||||||
|
|
||||||
|
Optionally, you can also build the containers locally using the [dockerfiles provided](docker):
|
||||||
|
To build the base image:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ docker build -f docker/Dockerfile.nu-base -t nushell/nu-base .
|
||||||
```
|
```
|
||||||
|
|
||||||
And then run the container:
|
And then to build the smaller container (using a Multistage build):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ docker run -it nu
|
$ docker build -f docker/Dockerfile -t nushell/nu .
|
||||||
|
```
|
||||||
|
|
||||||
|
Either way, you can run either container as follows:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ docker run -it nushell/nu-base
|
||||||
|
$ docker run -it nushell/nu
|
||||||
/> exit
|
/> exit
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The second container is a bit smaller, if size is important to you.
|
||||||
|
|
||||||
# Philosophy
|
# Philosophy
|
||||||
|
|
||||||
Nu draws inspiration from projects like PowerShell, functional programming languages, and modern cli tools. Rather than thinking of files and services as raw streams of text, Nu looks at each input as something with structure. For example, when you list the contents of a directory, what you get back is a list of objects, where each object represents an item in that directory. These values can be piped through a series of steps, in a series of commands called a 'pipeline'.
|
Nu draws inspiration from projects like PowerShell, functional programming languages, and modern cli tools. Rather than thinking of files and services as raw streams of text, Nu looks at each input as something with structure. For example, when you list the contents of a directory, what you get back is a list of objects, where each object represents an item in that directory. These values can be piped through a series of steps, in a series of commands called a 'pipeline'.
|
||||||
|
5
docker/Dockerfile
Normal file
5
docker/Dockerfile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
ARG FROMTAG=latest
|
||||||
|
FROM quay.io/nushell/nu-base:${FROMTAG} as base
|
||||||
|
FROM rust:1.37-slim
|
||||||
|
COPY --from=base /usr/local/bin/nu /usr/local/bin/nu
|
||||||
|
ENTRYPOINT ["nu"]
|
18
docker/Dockerfile.nu-base
Normal file
18
docker/Dockerfile.nu-base
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
FROM rust:1.37-slim
|
||||||
|
|
||||||
|
# docker build -f docker/Dockerfile.nu-base -t nushell/nu-base .
|
||||||
|
# docker run -it nushell/nu-base
|
||||||
|
|
||||||
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
|
RUN apt-get update && apt-get install -y libssl-dev \
|
||||||
|
libxcb-composite0-dev \
|
||||||
|
libx11-dev \
|
||||||
|
pkg-config
|
||||||
|
|
||||||
|
RUN USER=root cargo new --bin /code
|
||||||
|
|
||||||
|
WORKDIR /code
|
||||||
|
ADD . /code
|
||||||
|
RUN cargo build --release && cargo run --release
|
||||||
|
RUN cp target/release/nu /usr/local/bin
|
||||||
|
ENTRYPOINT ["nu"]
|
19
src/cli.rs
19
src/cli.rs
@ -7,7 +7,7 @@ use crate::commands::plugin::JsonRpc;
|
|||||||
use crate::commands::plugin::{PluginCommand, PluginSink};
|
use crate::commands::plugin::{PluginCommand, PluginSink};
|
||||||
use crate::commands::whole_stream_command;
|
use crate::commands::whole_stream_command;
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
crate use crate::errors::ShellError;
|
pub(crate) use crate::errors::ShellError;
|
||||||
use crate::git::current_branch;
|
use crate::git::current_branch;
|
||||||
use crate::object::Value;
|
use crate::object::Value;
|
||||||
use crate::parser::registry::Signature;
|
use crate::parser::registry::Signature;
|
||||||
@ -17,7 +17,7 @@ use crate::prelude::*;
|
|||||||
use log::{debug, trace};
|
use log::{debug, trace};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use rustyline::error::ReadlineError;
|
use rustyline::error::ReadlineError;
|
||||||
use rustyline::{self, ColorMode, Config, Editor};
|
use rustyline::{self, ColorMode, Config, Editor, config::Configurer, config::EditMode};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::io::{BufRead, BufReader, Write};
|
use std::io::{BufRead, BufReader, Write};
|
||||||
@ -30,7 +30,7 @@ pub enum MaybeOwned<'a, T> {
|
|||||||
Borrowed(&'a T),
|
Borrowed(&'a T),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> MaybeOwned<'a, T> {
|
impl<T> MaybeOwned<'_, T> {
|
||||||
pub fn borrow(&self) -> &T {
|
pub fn borrow(&self) -> &T {
|
||||||
match self {
|
match self {
|
||||||
MaybeOwned::Owned(v) => v,
|
MaybeOwned::Owned(v) => v,
|
||||||
@ -180,6 +180,7 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
|||||||
whole_stream_command(ToCSV),
|
whole_stream_command(ToCSV),
|
||||||
whole_stream_command(ToJSON),
|
whole_stream_command(ToJSON),
|
||||||
whole_stream_command(ToTOML),
|
whole_stream_command(ToTOML),
|
||||||
|
whole_stream_command(ToTSV),
|
||||||
whole_stream_command(ToYAML),
|
whole_stream_command(ToYAML),
|
||||||
whole_stream_command(SortBy),
|
whole_stream_command(SortBy),
|
||||||
whole_stream_command(Tags),
|
whole_stream_command(Tags),
|
||||||
@ -188,6 +189,7 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
|||||||
whole_stream_command(FromArray),
|
whole_stream_command(FromArray),
|
||||||
whole_stream_command(FromArray),
|
whole_stream_command(FromArray),
|
||||||
whole_stream_command(FromCSV),
|
whole_stream_command(FromCSV),
|
||||||
|
whole_stream_command(FromTSV),
|
||||||
whole_stream_command(FromINI),
|
whole_stream_command(FromINI),
|
||||||
whole_stream_command(FromBSON),
|
whole_stream_command(FromBSON),
|
||||||
whole_stream_command(FromJSON),
|
whole_stream_command(FromJSON),
|
||||||
@ -255,6 +257,17 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
|||||||
context.shell_manager.clone(),
|
context.shell_manager.clone(),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
let edit_mode = crate::object::config::config(Span::unknown())?
|
||||||
|
.get("edit_mode")
|
||||||
|
.map(|s| match s.as_string().unwrap().as_ref() {
|
||||||
|
"vi" => EditMode::Vi,
|
||||||
|
"emacs" => EditMode::Emacs,
|
||||||
|
_ => EditMode::Emacs,
|
||||||
|
})
|
||||||
|
.unwrap_or(EditMode::Emacs);
|
||||||
|
|
||||||
|
rl.set_edit_mode(edit_mode);
|
||||||
|
|
||||||
let readline = rl.readline(&format!(
|
let readline = rl.readline(&format!(
|
||||||
"{}{}> ",
|
"{}{}> ",
|
||||||
cwd,
|
cwd,
|
||||||
|
228
src/commands.rs
228
src/commands.rs
@ -1,118 +1,122 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
crate mod macros;
|
pub(crate) mod macros;
|
||||||
|
|
||||||
crate mod args;
|
pub(crate) mod args;
|
||||||
crate mod autoview;
|
pub(crate) mod autoview;
|
||||||
crate mod cd;
|
pub(crate) mod cd;
|
||||||
crate mod classified;
|
pub(crate) mod classified;
|
||||||
crate mod clip;
|
pub(crate) mod clip;
|
||||||
crate mod command;
|
pub(crate) mod command;
|
||||||
crate mod config;
|
pub(crate) mod config;
|
||||||
crate mod cp;
|
pub(crate) mod cp;
|
||||||
crate mod date;
|
pub(crate) mod date;
|
||||||
crate mod debug;
|
pub(crate) mod debug;
|
||||||
crate mod enter;
|
pub(crate) mod enter;
|
||||||
crate mod exit;
|
pub(crate) mod exit;
|
||||||
crate mod first;
|
pub(crate) mod first;
|
||||||
crate mod from_array;
|
pub(crate) mod from_array;
|
||||||
crate mod from_bson;
|
pub(crate) mod from_bson;
|
||||||
crate mod from_csv;
|
pub(crate) mod from_csv;
|
||||||
crate mod from_ini;
|
pub(crate) mod from_ini;
|
||||||
crate mod from_json;
|
pub(crate) mod from_json;
|
||||||
crate mod from_toml;
|
pub(crate) mod from_toml;
|
||||||
crate mod from_xml;
|
pub(crate) mod from_tsv;
|
||||||
crate mod from_yaml;
|
pub(crate) mod from_xml;
|
||||||
crate mod get;
|
pub(crate) mod from_yaml;
|
||||||
crate mod last;
|
pub(crate) mod get;
|
||||||
crate mod lines;
|
pub(crate) mod last;
|
||||||
crate mod ls;
|
pub(crate) mod lines;
|
||||||
crate mod mkdir;
|
pub(crate) mod ls;
|
||||||
crate mod mv;
|
pub(crate) mod mkdir;
|
||||||
crate mod next;
|
pub(crate) mod mv;
|
||||||
crate mod nth;
|
pub(crate) mod next;
|
||||||
crate mod open;
|
pub(crate) mod nth;
|
||||||
crate mod pick;
|
pub(crate) mod open;
|
||||||
crate mod plugin;
|
pub(crate) mod pick;
|
||||||
crate mod prev;
|
pub(crate) mod plugin;
|
||||||
crate mod ps;
|
pub(crate) mod prev;
|
||||||
crate mod reject;
|
pub(crate) mod ps;
|
||||||
crate mod reverse;
|
pub(crate) mod reject;
|
||||||
crate mod rm;
|
pub(crate) mod reverse;
|
||||||
crate mod save;
|
pub(crate) mod rm;
|
||||||
crate mod shells;
|
pub(crate) mod save;
|
||||||
crate mod size;
|
pub(crate) mod shells;
|
||||||
crate mod skip_while;
|
pub(crate) mod size;
|
||||||
crate mod sort_by;
|
pub(crate) mod skip_while;
|
||||||
crate mod split_column;
|
pub(crate) mod sort_by;
|
||||||
crate mod split_row;
|
pub(crate) mod split_column;
|
||||||
crate mod table;
|
pub(crate) mod split_row;
|
||||||
crate mod tags;
|
pub(crate) mod table;
|
||||||
crate mod to_array;
|
pub(crate) mod tags;
|
||||||
crate mod to_bson;
|
pub(crate) mod to_array;
|
||||||
crate mod to_csv;
|
pub(crate) mod to_bson;
|
||||||
crate mod to_json;
|
pub(crate) mod to_csv;
|
||||||
crate mod to_toml;
|
pub(crate) mod to_json;
|
||||||
crate mod to_yaml;
|
pub(crate) mod to_toml;
|
||||||
crate mod trim;
|
pub(crate) mod to_tsv;
|
||||||
crate mod version;
|
pub(crate) mod to_yaml;
|
||||||
crate mod vtable;
|
pub(crate) mod trim;
|
||||||
crate mod where_;
|
pub(crate) mod version;
|
||||||
crate mod which_;
|
pub(crate) mod vtable;
|
||||||
|
pub(crate) mod where_;
|
||||||
|
pub(crate) mod which_;
|
||||||
|
|
||||||
crate use autoview::Autoview;
|
pub(crate) use autoview::Autoview;
|
||||||
crate use cd::CD;
|
pub(crate) use cd::CD;
|
||||||
crate use command::{
|
pub(crate) use command::{
|
||||||
per_item_command, whole_stream_command, Command, PerItemCommand, RawCommandArgs,
|
per_item_command, whole_stream_command, Command, PerItemCommand, RawCommandArgs,
|
||||||
UnevaluatedCallInfo, WholeStreamCommand,
|
UnevaluatedCallInfo, WholeStreamCommand,
|
||||||
};
|
};
|
||||||
crate use config::Config;
|
pub(crate) use config::Config;
|
||||||
crate use cp::Cpy;
|
pub(crate) use cp::Cpy;
|
||||||
crate use date::Date;
|
pub(crate) use date::Date;
|
||||||
crate use debug::Debug;
|
pub(crate) use debug::Debug;
|
||||||
crate use enter::Enter;
|
pub(crate) use enter::Enter;
|
||||||
crate use exit::Exit;
|
pub(crate) use exit::Exit;
|
||||||
crate use first::First;
|
pub(crate) use first::First;
|
||||||
crate use from_array::FromArray;
|
pub(crate) use from_array::FromArray;
|
||||||
crate use from_bson::FromBSON;
|
pub(crate) use from_bson::FromBSON;
|
||||||
crate use from_csv::FromCSV;
|
pub(crate) use from_csv::FromCSV;
|
||||||
crate use from_ini::FromINI;
|
pub(crate) use from_ini::FromINI;
|
||||||
crate use from_json::FromJSON;
|
pub(crate) use from_json::FromJSON;
|
||||||
crate use from_toml::FromTOML;
|
pub(crate) use from_toml::FromTOML;
|
||||||
crate use from_xml::FromXML;
|
pub(crate) use from_tsv::FromTSV;
|
||||||
crate use from_yaml::FromYAML;
|
pub(crate) use from_xml::FromXML;
|
||||||
crate use from_yaml::FromYML;
|
pub(crate) use from_yaml::FromYAML;
|
||||||
crate use get::Get;
|
pub(crate) use from_yaml::FromYML;
|
||||||
crate use last::Last;
|
pub(crate) use get::Get;
|
||||||
crate use lines::Lines;
|
pub(crate) use last::Last;
|
||||||
crate use ls::LS;
|
pub(crate) use lines::Lines;
|
||||||
crate use mkdir::Mkdir;
|
pub(crate) use ls::LS;
|
||||||
crate use mv::Move;
|
pub(crate) use mkdir::Mkdir;
|
||||||
crate use next::Next;
|
pub(crate) use mv::Move;
|
||||||
crate use nth::Nth;
|
pub(crate) use next::Next;
|
||||||
crate use open::Open;
|
pub(crate) use nth::Nth;
|
||||||
crate use pick::Pick;
|
pub(crate) use open::Open;
|
||||||
crate use prev::Previous;
|
pub(crate) use pick::Pick;
|
||||||
crate use ps::PS;
|
pub(crate) use prev::Previous;
|
||||||
crate use reject::Reject;
|
pub(crate) use ps::PS;
|
||||||
crate use reverse::Reverse;
|
pub(crate) use reject::Reject;
|
||||||
crate use rm::Remove;
|
pub(crate) use reverse::Reverse;
|
||||||
crate use save::Save;
|
pub(crate) use rm::Remove;
|
||||||
crate use shells::Shells;
|
pub(crate) use save::Save;
|
||||||
crate use size::Size;
|
pub(crate) use shells::Shells;
|
||||||
crate use skip_while::SkipWhile;
|
pub(crate) use size::Size;
|
||||||
crate use sort_by::SortBy;
|
pub(crate) use skip_while::SkipWhile;
|
||||||
crate use split_column::SplitColumn;
|
pub(crate) use sort_by::SortBy;
|
||||||
crate use split_row::SplitRow;
|
pub(crate) use split_column::SplitColumn;
|
||||||
crate use table::Table;
|
pub(crate) use split_row::SplitRow;
|
||||||
crate use tags::Tags;
|
pub(crate) use table::Table;
|
||||||
crate use to_array::ToArray;
|
pub(crate) use tags::Tags;
|
||||||
crate use to_bson::ToBSON;
|
pub(crate) use to_array::ToArray;
|
||||||
crate use to_csv::ToCSV;
|
pub(crate) use to_bson::ToBSON;
|
||||||
crate use to_json::ToJSON;
|
pub(crate) use to_csv::ToCSV;
|
||||||
crate use to_toml::ToTOML;
|
pub(crate) use to_json::ToJSON;
|
||||||
crate use to_yaml::ToYAML;
|
pub(crate) use to_toml::ToTOML;
|
||||||
crate use trim::Trim;
|
pub(crate) use to_tsv::ToTSV;
|
||||||
crate use version::Version;
|
pub(crate) use to_yaml::ToYAML;
|
||||||
crate use vtable::VTable;
|
pub(crate) use trim::Trim;
|
||||||
crate use where_::Where;
|
pub(crate) use version::Version;
|
||||||
crate use which_::Which;
|
pub(crate) use vtable::VTable;
|
||||||
|
pub(crate) use where_::Where;
|
||||||
|
pub(crate) use which_::Which;
|
||||||
|
@ -45,27 +45,27 @@ impl Decoder for LinesCodec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate struct ClassifiedInputStream {
|
pub(crate) struct ClassifiedInputStream {
|
||||||
crate objects: InputStream,
|
pub(crate) objects: InputStream,
|
||||||
crate stdin: Option<std::fs::File>,
|
pub(crate) stdin: Option<std::fs::File>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClassifiedInputStream {
|
impl ClassifiedInputStream {
|
||||||
crate fn new() -> ClassifiedInputStream {
|
pub(crate) fn new() -> ClassifiedInputStream {
|
||||||
ClassifiedInputStream {
|
ClassifiedInputStream {
|
||||||
objects: VecDeque::new().into(),
|
objects: VecDeque::new().into(),
|
||||||
stdin: None,
|
stdin: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn from_input_stream(stream: impl Into<InputStream>) -> ClassifiedInputStream {
|
pub(crate) fn from_input_stream(stream: impl Into<InputStream>) -> ClassifiedInputStream {
|
||||||
ClassifiedInputStream {
|
ClassifiedInputStream {
|
||||||
objects: stream.into(),
|
objects: stream.into(),
|
||||||
stdin: None,
|
stdin: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn from_stdout(stdout: std::fs::File) -> ClassifiedInputStream {
|
pub(crate) fn from_stdout(stdout: std::fs::File) -> ClassifiedInputStream {
|
||||||
ClassifiedInputStream {
|
ClassifiedInputStream {
|
||||||
objects: VecDeque::new().into(),
|
objects: VecDeque::new().into(),
|
||||||
stdin: Some(stdout),
|
stdin: Some(stdout),
|
||||||
@ -73,11 +73,11 @@ impl ClassifiedInputStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate struct ClassifiedPipeline {
|
pub(crate) struct ClassifiedPipeline {
|
||||||
crate commands: Vec<ClassifiedCommand>,
|
pub(crate) commands: Vec<ClassifiedCommand>,
|
||||||
}
|
}
|
||||||
|
|
||||||
crate enum ClassifiedCommand {
|
pub(crate) enum ClassifiedCommand {
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
Expr(TokenNode),
|
Expr(TokenNode),
|
||||||
Internal(InternalCommand),
|
Internal(InternalCommand),
|
||||||
@ -95,14 +95,14 @@ impl ClassifiedCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate struct InternalCommand {
|
pub(crate) struct InternalCommand {
|
||||||
crate command: Arc<Command>,
|
pub(crate) command: Arc<Command>,
|
||||||
crate name_span: Span,
|
pub(crate) name_span: Span,
|
||||||
crate args: hir::Call,
|
pub(crate) args: hir::Call,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InternalCommand {
|
impl InternalCommand {
|
||||||
crate async fn run(
|
pub(crate) async fn run(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
input: ClassifiedInputStream,
|
input: ClassifiedInputStream,
|
||||||
@ -206,21 +206,21 @@ impl InternalCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate struct ExternalCommand {
|
pub(crate) struct ExternalCommand {
|
||||||
crate name: String,
|
pub(crate) name: String,
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
crate name_span: Span,
|
pub(crate) name_span: Span,
|
||||||
crate args: Vec<Tagged<String>>,
|
pub(crate) args: Vec<Tagged<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
crate enum StreamNext {
|
pub(crate) enum StreamNext {
|
||||||
Last,
|
Last,
|
||||||
External,
|
External,
|
||||||
Internal,
|
Internal,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExternalCommand {
|
impl ExternalCommand {
|
||||||
crate async fn run(
|
pub(crate) async fn run(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
input: ClassifiedInputStream,
|
input: ClassifiedInputStream,
|
||||||
|
@ -111,6 +111,7 @@ pub fn config(
|
|||||||
|
|
||||||
if result.contains_key(&key) {
|
if result.contains_key(&key) {
|
||||||
result.remove(&key);
|
result.remove(&key);
|
||||||
|
config::write_config(&result)?;
|
||||||
} else {
|
} else {
|
||||||
return Err(ShellError::string(&format!(
|
return Err(ShellError::string(&format!(
|
||||||
"{} does not exist in config",
|
"{} does not exist in config",
|
||||||
|
@ -3,7 +3,7 @@ use crate::{EntriesListView, GenericView, TreeView};
|
|||||||
use futures::stream::{self, StreamExt};
|
use futures::stream::{self, StreamExt};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
crate fn format(input: Vec<Value>, host: &mut dyn Host) {
|
pub(crate) fn format(input: Vec<Value>, host: &mut dyn Host) {
|
||||||
let last = input.len() - 1;
|
let last = input.len() - 1;
|
||||||
for (i, item) in input.iter().enumerate() {
|
for (i, item) in input.iter().enumerate() {
|
||||||
let view = GenericView::new(item);
|
let view = GenericView::new(item);
|
||||||
|
135
src/commands/from_tsv.rs
Normal file
135
src/commands/from_tsv.rs
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
use crate::commands::WholeStreamCommand;
|
||||||
|
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
||||||
|
use crate::prelude::*;
|
||||||
|
use csv::ReaderBuilder;
|
||||||
|
|
||||||
|
pub struct FromTSV;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct FromTSVArgs {
|
||||||
|
headerless: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WholeStreamCommand for FromTSV {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"from-tsv"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("from-tsv").switch("headerless")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
&self,
|
||||||
|
args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
args.process(registry, from_tsv)?.run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_tsv_string_to_value(
|
||||||
|
s: String,
|
||||||
|
headerless: bool,
|
||||||
|
tag: impl Into<Tag>,
|
||||||
|
) -> Result<Tagged<Value>, csv::Error> {
|
||||||
|
let mut reader = ReaderBuilder::new()
|
||||||
|
.has_headers(false)
|
||||||
|
.delimiter(b'\t')
|
||||||
|
.from_reader(s.as_bytes());
|
||||||
|
let tag = tag.into();
|
||||||
|
|
||||||
|
let mut fields: VecDeque<String> = VecDeque::new();
|
||||||
|
let mut iter = reader.records();
|
||||||
|
let mut rows = vec![];
|
||||||
|
|
||||||
|
if let Some(result) = iter.next() {
|
||||||
|
let line = result?;
|
||||||
|
|
||||||
|
for (idx, item) in line.iter().enumerate() {
|
||||||
|
if headerless {
|
||||||
|
fields.push_back(format!("Column{}", idx + 1));
|
||||||
|
} else {
|
||||||
|
fields.push_back(item.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if let Some(row_values) = iter.next() {
|
||||||
|
let row_values = row_values?;
|
||||||
|
|
||||||
|
let mut row = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
|
for (idx, entry) in row_values.iter().enumerate() {
|
||||||
|
row.insert_tagged(
|
||||||
|
fields.get(idx).unwrap(),
|
||||||
|
Value::Primitive(Primitive::String(String::from(entry))).tagged(tag),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
rows.push(row.into_tagged_value());
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Tagged::from_item(Value::List(rows), tag))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_tsv(
|
||||||
|
FromTSVArgs {
|
||||||
|
headerless: skip_headers,
|
||||||
|
}: FromTSVArgs,
|
||||||
|
RunnableContext { input, name, .. }: RunnableContext,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
let name_span = name;
|
||||||
|
|
||||||
|
let stream = async_stream_block! {
|
||||||
|
let values: Vec<Tagged<Value>> = input.values.collect().await;
|
||||||
|
|
||||||
|
let mut concat_string = String::new();
|
||||||
|
let mut latest_tag: Option<Tag> = None;
|
||||||
|
|
||||||
|
for value in values {
|
||||||
|
let value_tag = value.tag();
|
||||||
|
latest_tag = Some(value_tag);
|
||||||
|
match value.item {
|
||||||
|
Value::Primitive(Primitive::String(s)) => {
|
||||||
|
concat_string.push_str(&s);
|
||||||
|
concat_string.push_str("\n");
|
||||||
|
}
|
||||||
|
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||||
|
"Expected a string from pipeline",
|
||||||
|
"requires string input",
|
||||||
|
name_span,
|
||||||
|
"value originates from here",
|
||||||
|
value_tag.span,
|
||||||
|
)),
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match from_tsv_string_to_value(concat_string, skip_headers, name_span) {
|
||||||
|
Ok(x) => match x {
|
||||||
|
Tagged { item: Value::List(list), .. } => {
|
||||||
|
for l in list {
|
||||||
|
yield ReturnSuccess::value(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x => yield ReturnSuccess::value(x),
|
||||||
|
},
|
||||||
|
Err(_) => if let Some(last_tag) = latest_tag {
|
||||||
|
yield Err(ShellError::labeled_error_with_secondary(
|
||||||
|
"Could not parse as TSV",
|
||||||
|
"input cannot be parsed as TSV",
|
||||||
|
name_span,
|
||||||
|
"value originates from here",
|
||||||
|
last_tag.span,
|
||||||
|
))
|
||||||
|
} ,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
|
}
|
@ -1,8 +1,13 @@
|
|||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::object::process::process_dict;
|
use crate::object::TaggedDictBuilder;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use sysinfo::SystemExt;
|
use std::time::Duration;
|
||||||
|
use std::usize;
|
||||||
|
|
||||||
|
use futures::stream::{StreamExt, TryStreamExt};
|
||||||
|
use heim::process::{self as process, Process, ProcessResult};
|
||||||
|
use heim::units::{ratio, Ratio};
|
||||||
|
|
||||||
pub struct PS;
|
pub struct PS;
|
||||||
|
|
||||||
@ -24,28 +29,44 @@ impl WholeStreamCommand for PS {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ps(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
async fn usage(process: Process) -> ProcessResult<(process::Process, Ratio)> {
|
||||||
let system;
|
let usage_1 = process.cpu_usage().await?;
|
||||||
|
futures_timer::Delay::new(Duration::from_millis(100)).await?;
|
||||||
|
let usage_2 = process.cpu_usage().await?;
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
Ok((process, usage_2 - usage_1))
|
||||||
{
|
}
|
||||||
system = sysinfo::System::new();
|
|
||||||
}
|
fn ps(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
|
let args = args.evaluate_once(registry)?;
|
||||||
#[cfg(not(target_os = "linux"))]
|
let span = args.name_span();
|
||||||
{
|
|
||||||
use sysinfo::RefreshKind;
|
let stream = async_stream_block! {
|
||||||
let mut sy = sysinfo::System::new_with_specifics(RefreshKind::new().with_processes());
|
let processes = process::processes()
|
||||||
sy.refresh_processes();
|
.map_ok(|process| {
|
||||||
|
// Note that there is no `.await` here,
|
||||||
system = sy;
|
// as we want to pass the returned future
|
||||||
}
|
// into the `.try_buffer_unordered`.
|
||||||
let list = system.get_process_list();
|
usage(process)
|
||||||
|
})
|
||||||
let list = list
|
.try_buffer_unordered(usize::MAX);
|
||||||
.into_iter()
|
pin_utils::pin_mut!(processes);
|
||||||
.map(|(_, process)| process_dict(process, Tag::unknown_origin(args.call_info.name_span)))
|
|
||||||
.collect::<VecDeque<_>>();
|
while let Some(res) = processes.next().await {
|
||||||
|
if let Ok((process, usage)) = res {
|
||||||
Ok(list.from_input_stream())
|
let mut dict = TaggedDictBuilder::new(Tag::unknown_origin(span));
|
||||||
|
dict.insert("pid", Value::int(process.pid()));
|
||||||
|
if let Ok(name) = process.name().await {
|
||||||
|
dict.insert("name", Value::string(name));
|
||||||
|
}
|
||||||
|
if let Ok(status) = process.status().await {
|
||||||
|
dict.insert("status", Value::string(format!("{:?}", status)));
|
||||||
|
}
|
||||||
|
dict.insert("cpu", Value::float(usage.get::<ratio::percent>() as f64));
|
||||||
|
yield ReturnSuccess::value(dict.into_tagged_value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::commands::to_csv::{to_string as to_csv_to_string, value_to_csv_value};
|
use crate::commands::to_csv::{to_string as to_csv_to_string, value_to_csv_value};
|
||||||
|
use crate::commands::to_tsv::{to_string as to_tsv_to_string, value_to_tsv_value};
|
||||||
use crate::commands::to_json::value_to_json_value;
|
use crate::commands::to_json::value_to_json_value;
|
||||||
use crate::commands::to_toml::value_to_toml_value;
|
use crate::commands::to_toml::value_to_toml_value;
|
||||||
use crate::commands::to_yaml::value_to_yaml_value;
|
use crate::commands::to_yaml::value_to_yaml_value;
|
||||||
@ -166,6 +167,14 @@ async fn to_string_for(
|
|||||||
}
|
}
|
||||||
to_csv_to_string(&value_to_csv_value(&input[0]))?
|
to_csv_to_string(&value_to_csv_value(&input[0]))?
|
||||||
}
|
}
|
||||||
|
Some(x) if x == "tsv" => {
|
||||||
|
if input.len() != 1 {
|
||||||
|
return Err(ShellError::string(
|
||||||
|
"saving to tsv requires a single object (or use --raw)",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
to_tsv_to_string(&value_to_tsv_value(&input[0]))?
|
||||||
|
}
|
||||||
Some(x) if x == "toml" => {
|
Some(x) if x == "toml" => {
|
||||||
if input.len() != 1 {
|
if input.len() != 1 {
|
||||||
return Err(ShellError::string(
|
return Err(ShellError::string(
|
||||||
|
108
src/commands/to_tsv.rs
Normal file
108
src/commands/to_tsv.rs
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
use crate::commands::WholeStreamCommand;
|
||||||
|
use crate::object::{Primitive, Value};
|
||||||
|
use crate::prelude::*;
|
||||||
|
use csv::WriterBuilder;
|
||||||
|
|
||||||
|
pub struct ToTSV;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct ToTSVArgs {
|
||||||
|
headerless: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WholeStreamCommand for ToTSV {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"to-tsv"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("to-tsv").switch("headerless")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
&self,
|
||||||
|
args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
args.process(registry, to_tsv)?.run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value_to_tsv_value(v: &Value) -> Value {
|
||||||
|
match v {
|
||||||
|
Value::Primitive(Primitive::String(s)) => Value::Primitive(Primitive::String(s.clone())),
|
||||||
|
Value::Primitive(Primitive::Nothing) => Value::Primitive(Primitive::Nothing),
|
||||||
|
Value::Primitive(Primitive::Boolean(b)) => Value::Primitive(Primitive::Boolean(b.clone())),
|
||||||
|
Value::Primitive(Primitive::Bytes(b)) => Value::Primitive(Primitive::Bytes(b.clone())),
|
||||||
|
Value::Primitive(Primitive::Date(d)) => Value::Primitive(Primitive::Date(d.clone())),
|
||||||
|
Value::Object(o) => Value::Object(o.clone()),
|
||||||
|
Value::List(l) => Value::List(l.clone()),
|
||||||
|
Value::Block(_) => Value::Primitive(Primitive::Nothing),
|
||||||
|
_ => Value::Primitive(Primitive::Nothing),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_string_helper(v: &Value) -> Result<String, Box<dyn std::error::Error>> {
|
||||||
|
match v {
|
||||||
|
Value::Primitive(Primitive::Date(d)) => Ok(d.to_string()),
|
||||||
|
Value::Primitive(Primitive::Bytes(b)) => Ok(format!("{}", *b as u64)),
|
||||||
|
Value::Primitive(Primitive::Boolean(_)) => Ok(v.as_string()?),
|
||||||
|
Value::List(_) => return Ok(String::from("[list list]")),
|
||||||
|
Value::Object(_) => return Ok(String::from("[object]")),
|
||||||
|
Value::Primitive(Primitive::String(s)) => return Ok(s.to_string()),
|
||||||
|
_ => return Err("Bad input".into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_string(v: &Value) -> Result<String, Box<dyn std::error::Error>> {
|
||||||
|
match v {
|
||||||
|
Value::Object(o) => {
|
||||||
|
let mut wtr = WriterBuilder::new().delimiter(b'\t').from_writer(vec![]);
|
||||||
|
let mut fields: VecDeque<String> = VecDeque::new();
|
||||||
|
let mut values: VecDeque<String> = VecDeque::new();
|
||||||
|
|
||||||
|
for (k, v) in o.entries.iter() {
|
||||||
|
fields.push_back(k.clone());
|
||||||
|
values.push_back(to_string_helper(&v)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
wtr.write_record(fields).expect("can not write.");
|
||||||
|
wtr.write_record(values).expect("can not write.");
|
||||||
|
|
||||||
|
return Ok(String::from_utf8(wtr.into_inner()?)?);
|
||||||
|
}
|
||||||
|
_ => return to_string_helper(&v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_tsv(
|
||||||
|
ToTSVArgs { headerless }: ToTSVArgs,
|
||||||
|
RunnableContext { input, name, .. }: RunnableContext,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
let name_span = name;
|
||||||
|
let out = input;
|
||||||
|
|
||||||
|
Ok(out
|
||||||
|
.values
|
||||||
|
.map(move |a| match to_string(&value_to_tsv_value(&a.item)) {
|
||||||
|
Ok(x) => {
|
||||||
|
let converted = if headerless {
|
||||||
|
x.lines().skip(1).collect()
|
||||||
|
} else {
|
||||||
|
x
|
||||||
|
};
|
||||||
|
|
||||||
|
ReturnSuccess::value(
|
||||||
|
Value::Primitive(Primitive::String(converted)).simple_spanned(name_span),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => Err(ShellError::labeled_error_with_secondary(
|
||||||
|
"Expected an object with TSV-compatible structure from pipeline",
|
||||||
|
"requires TSV-compatible input",
|
||||||
|
name_span,
|
||||||
|
format!("{} originates from here", a.item.type_name()),
|
||||||
|
a.span(),
|
||||||
|
)),
|
||||||
|
})
|
||||||
|
.to_output_stream())
|
||||||
|
}
|
@ -41,13 +41,13 @@ pub struct CommandRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CommandRegistry {
|
impl CommandRegistry {
|
||||||
crate fn empty() -> CommandRegistry {
|
pub(crate) fn empty() -> CommandRegistry {
|
||||||
CommandRegistry {
|
CommandRegistry {
|
||||||
registry: Arc::new(Mutex::new(IndexMap::default())),
|
registry: Arc::new(Mutex::new(IndexMap::default())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn get_command(&self, name: &str) -> Option<Arc<Command>> {
|
pub(crate) fn get_command(&self, name: &str) -> Option<Arc<Command>> {
|
||||||
let registry = self.registry.lock().unwrap();
|
let registry = self.registry.lock().unwrap();
|
||||||
|
|
||||||
registry.get(name).map(|c| c.clone())
|
registry.get(name).map(|c| c.clone())
|
||||||
@ -64,7 +64,7 @@ impl CommandRegistry {
|
|||||||
registry.insert(name.into(), command);
|
registry.insert(name.into(), command);
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn names(&self) -> Vec<String> {
|
pub(crate) fn names(&self) -> Vec<String> {
|
||||||
let registry = self.registry.lock().unwrap();
|
let registry = self.registry.lock().unwrap();
|
||||||
registry.keys().cloned().collect()
|
registry.keys().cloned().collect()
|
||||||
}
|
}
|
||||||
@ -73,17 +73,17 @@ impl CommandRegistry {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
registry: CommandRegistry,
|
registry: CommandRegistry,
|
||||||
crate source_map: SourceMap,
|
pub(crate) source_map: SourceMap,
|
||||||
host: Arc<Mutex<dyn Host + Send>>,
|
host: Arc<Mutex<dyn Host + Send>>,
|
||||||
crate shell_manager: ShellManager,
|
pub(crate) shell_manager: ShellManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
crate fn registry(&self) -> &CommandRegistry {
|
pub(crate) fn registry(&self) -> &CommandRegistry {
|
||||||
&self.registry
|
&self.registry
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn basic() -> Result<Context, Box<dyn Error>> {
|
pub(crate) fn basic() -> Result<Context, Box<dyn Error>> {
|
||||||
let registry = CommandRegistry::new();
|
let registry = CommandRegistry::new();
|
||||||
Ok(Context {
|
Ok(Context {
|
||||||
registry: registry.clone(),
|
registry: registry.clone(),
|
||||||
@ -93,7 +93,7 @@ impl Context {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn with_host(&mut self, block: impl FnOnce(&mut dyn Host)) {
|
pub(crate) fn with_host(&mut self, block: impl FnOnce(&mut dyn Host)) {
|
||||||
let mut host = self.host.lock().unwrap();
|
let mut host = self.host.lock().unwrap();
|
||||||
|
|
||||||
block(&mut *host)
|
block(&mut *host)
|
||||||
@ -109,15 +109,15 @@ impl Context {
|
|||||||
self.source_map.insert(uuid, span_source);
|
self.source_map.insert(uuid, span_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn has_command(&self, name: &str) -> bool {
|
pub(crate) fn has_command(&self, name: &str) -> bool {
|
||||||
self.registry.has(name)
|
self.registry.has(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn get_command(&self, name: &str) -> Arc<Command> {
|
pub(crate) fn get_command(&self, name: &str) -> Arc<Command> {
|
||||||
self.registry.get_command(name).unwrap()
|
self.registry.get_command(name).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn run_command<'a>(
|
pub(crate) fn run_command<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
command: Arc<Command>,
|
command: Arc<Command>,
|
||||||
name_span: Span,
|
name_span: Span,
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
crate mod host;
|
pub(crate) mod host;
|
||||||
|
|
||||||
crate use self::host::Host;
|
pub(crate) use self::host::Host;
|
||||||
|
2
src/env/host.rs
vendored
2
src/env/host.rs
vendored
@ -73,7 +73,7 @@ impl Host for BasicHost {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn handle_unexpected<T>(
|
pub(crate) fn handle_unexpected<T>(
|
||||||
host: &mut dyn Host,
|
host: &mut dyn Host,
|
||||||
func: impl FnOnce(&mut dyn Host) -> Result<T, ShellError>,
|
func: impl FnOnce(&mut dyn Host) -> Result<T, ShellError>,
|
||||||
) {
|
) {
|
||||||
|
@ -73,7 +73,7 @@ impl serde::de::Error for ShellError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ShellError {
|
impl ShellError {
|
||||||
crate fn type_error(
|
pub(crate) fn type_error(
|
||||||
expected: impl Into<String>,
|
expected: impl Into<String>,
|
||||||
actual: Tagged<impl Into<String>>,
|
actual: Tagged<impl Into<String>>,
|
||||||
) -> ShellError {
|
) -> ShellError {
|
||||||
@ -84,21 +84,21 @@ impl ShellError {
|
|||||||
.start()
|
.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn syntax_error(problem: Tagged<impl Into<String>>) -> ShellError {
|
pub(crate) fn syntax_error(problem: Tagged<impl Into<String>>) -> ShellError {
|
||||||
ProximateShellError::SyntaxError {
|
ProximateShellError::SyntaxError {
|
||||||
problem: problem.map(|p| p.into()),
|
problem: problem.map(|p| p.into()),
|
||||||
}
|
}
|
||||||
.start()
|
.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn invalid_command(problem: impl Into<Tag>) -> ShellError {
|
pub(crate) fn invalid_command(problem: impl Into<Tag>) -> ShellError {
|
||||||
ProximateShellError::InvalidCommand {
|
ProximateShellError::InvalidCommand {
|
||||||
command: problem.into(),
|
command: problem.into(),
|
||||||
}
|
}
|
||||||
.start()
|
.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn coerce_error(
|
pub(crate) fn coerce_error(
|
||||||
left: Tagged<impl Into<String>>,
|
left: Tagged<impl Into<String>>,
|
||||||
right: Tagged<impl Into<String>>,
|
right: Tagged<impl Into<String>>,
|
||||||
) -> ShellError {
|
) -> ShellError {
|
||||||
@ -109,11 +109,11 @@ impl ShellError {
|
|||||||
.start()
|
.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn missing_property(subpath: Description, expr: Description) -> ShellError {
|
pub(crate) fn missing_property(subpath: Description, expr: Description) -> ShellError {
|
||||||
ProximateShellError::MissingProperty { subpath, expr }.start()
|
ProximateShellError::MissingProperty { subpath, expr }.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn missing_value(span: Option<Span>, reason: impl Into<String>) -> ShellError {
|
pub(crate) fn missing_value(span: Option<Span>, reason: impl Into<String>) -> ShellError {
|
||||||
ProximateShellError::MissingValue {
|
ProximateShellError::MissingValue {
|
||||||
span,
|
span,
|
||||||
reason: reason.into(),
|
reason: reason.into(),
|
||||||
@ -121,7 +121,7 @@ impl ShellError {
|
|||||||
.start()
|
.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn argument_error(
|
pub(crate) fn argument_error(
|
||||||
command: impl Into<String>,
|
command: impl Into<String>,
|
||||||
kind: ArgumentError,
|
kind: ArgumentError,
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -134,7 +134,7 @@ impl ShellError {
|
|||||||
.start()
|
.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn parse_error(
|
pub(crate) fn parse_error(
|
||||||
error: nom::Err<(nom5_locate::LocatedSpan<&str>, nom::error::ErrorKind)>,
|
error: nom::Err<(nom5_locate::LocatedSpan<&str>, nom::error::ErrorKind)>,
|
||||||
) -> ShellError {
|
) -> ShellError {
|
||||||
use language_reporting::*;
|
use language_reporting::*;
|
||||||
@ -158,11 +158,11 @@ impl ShellError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn diagnostic(diagnostic: Diagnostic<Span>) -> ShellError {
|
pub(crate) fn diagnostic(diagnostic: Diagnostic<Span>) -> ShellError {
|
||||||
ProximateShellError::Diagnostic(ShellDiagnostic { diagnostic }).start()
|
ProximateShellError::Diagnostic(ShellDiagnostic { diagnostic }).start()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn to_diagnostic(self) -> Diagnostic<Span> {
|
pub(crate) fn to_diagnostic(self) -> Diagnostic<Span> {
|
||||||
match self.error {
|
match self.error {
|
||||||
ProximateShellError::String(StringError { title, .. }) => {
|
ProximateShellError::String(StringError { title, .. }) => {
|
||||||
Diagnostic::new(Severity::Error, title)
|
Diagnostic::new(Severity::Error, title)
|
||||||
@ -309,11 +309,11 @@ impl ShellError {
|
|||||||
ProximateShellError::String(StringError::new(title.into(), Value::nothing())).start()
|
ProximateShellError::String(StringError::new(title.into(), Value::nothing())).start()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn unimplemented(title: impl Into<String>) -> ShellError {
|
pub(crate) fn unimplemented(title: impl Into<String>) -> ShellError {
|
||||||
ShellError::string(&format!("Unimplemented: {}", title.into()))
|
ShellError::string(&format!("Unimplemented: {}", title.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn unexpected(title: impl Into<String>) -> ShellError {
|
pub(crate) fn unexpected(title: impl Into<String>) -> ShellError {
|
||||||
ShellError::string(&format!("Unexpected: {}", title.into()))
|
ShellError::string(&format!("Unexpected: {}", title.into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -369,12 +369,12 @@ impl ToDebug for ProximateShellError {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct ShellDiagnostic {
|
pub struct ShellDiagnostic {
|
||||||
crate diagnostic: Diagnostic<Span>,
|
pub(crate) diagnostic: Diagnostic<Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShellDiagnostic {
|
impl ShellDiagnostic {
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
crate fn simple_diagnostic(
|
pub(crate) fn simple_diagnostic(
|
||||||
span: impl Into<Span>,
|
span: impl Into<Span>,
|
||||||
source: impl Into<String>,
|
source: impl Into<String>,
|
||||||
) -> ShellDiagnostic {
|
) -> ShellDiagnostic {
|
||||||
|
@ -16,14 +16,14 @@ pub struct Scope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Scope {
|
impl Scope {
|
||||||
crate fn empty() -> Scope {
|
pub(crate) fn empty() -> Scope {
|
||||||
Scope {
|
Scope {
|
||||||
it: Value::nothing().tagged_unknown(),
|
it: Value::nothing().tagged_unknown(),
|
||||||
vars: IndexMap::new(),
|
vars: IndexMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn it_value(value: Tagged<Value>) -> Scope {
|
pub(crate) fn it_value(value: Tagged<Value>) -> Scope {
|
||||||
Scope {
|
Scope {
|
||||||
it: value,
|
it: value,
|
||||||
vars: IndexMap::new(),
|
vars: IndexMap::new(),
|
||||||
@ -31,7 +31,7 @@ impl Scope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn evaluate_baseline_expr(
|
pub(crate) fn evaluate_baseline_expr(
|
||||||
expr: &Expression,
|
expr: &Expression,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
crate mod evaluator;
|
pub(crate) mod evaluator;
|
||||||
|
|
||||||
crate use evaluator::{evaluate_baseline_expr, Scope};
|
pub(crate) use evaluator::{evaluate_baseline_expr, Scope};
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
crate mod entries;
|
pub(crate) mod entries;
|
||||||
crate mod generic;
|
pub(crate) mod generic;
|
||||||
crate mod list;
|
pub(crate) mod list;
|
||||||
crate mod table;
|
pub(crate) mod table;
|
||||||
crate mod vtable;
|
pub(crate) mod vtable;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
crate use entries::EntriesView;
|
pub(crate) use entries::EntriesView;
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
crate use generic::GenericView;
|
pub(crate) use generic::GenericView;
|
||||||
crate use table::TableView;
|
pub(crate) use table::TableView;
|
||||||
crate use vtable::VTableView;
|
pub(crate) use vtable::VTableView;
|
||||||
|
|
||||||
crate trait RenderView {
|
pub(crate) trait RenderView {
|
||||||
fn render_view(&self, host: &mut dyn Host) -> Result<(), ShellError>;
|
fn render_view(&self, host: &mut dyn Host) -> Result<(), ShellError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn print_view(view: &impl RenderView, host: &mut dyn Host) -> Result<(), ShellError> {
|
pub(crate) fn print_view(view: &impl RenderView, host: &mut dyn Host) -> Result<(), ShellError> {
|
||||||
view.render_view(host)
|
view.render_view(host)
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ pub struct EntriesView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EntriesView {
|
impl EntriesView {
|
||||||
crate fn from_value(value: &Value) -> EntriesView {
|
pub(crate) fn from_value(value: &Value) -> EntriesView {
|
||||||
let descs = value.data_descriptors();
|
let descs = value.data_descriptors();
|
||||||
let mut entries = vec![];
|
let mut entries = vec![];
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ pub struct GenericView<'value> {
|
|||||||
value: &'value Value,
|
value: &'value Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderView for GenericView<'value> {
|
impl RenderView for GenericView<'_> {
|
||||||
fn render_view(&self, host: &mut dyn Host) -> Result<(), ShellError> {
|
fn render_view(&self, host: &mut dyn Host) -> Result<(), ShellError> {
|
||||||
match self.value {
|
match self.value {
|
||||||
Value::Primitive(p) => Ok(host.stdout(&p.format(None))),
|
Value::Primitive(p) => Ok(host.stdout(&p.format(None))),
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(in_band_lifetimes)]
|
|
||||||
#![feature(generators)]
|
#![feature(generators)]
|
||||||
#![feature(specialization)]
|
#![feature(specialization)]
|
||||||
#![feature(proc_macro_hygiene)]
|
#![feature(proc_macro_hygiene)]
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
crate mod base;
|
pub(crate) mod base;
|
||||||
crate mod config;
|
pub(crate) mod config;
|
||||||
crate mod dict;
|
pub(crate) mod dict;
|
||||||
crate mod files;
|
pub(crate) mod files;
|
||||||
crate mod into;
|
pub(crate) mod into;
|
||||||
crate mod meta;
|
pub(crate) mod meta;
|
||||||
crate mod process;
|
pub(crate) mod types;
|
||||||
crate mod types;
|
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
crate use base::{Block, Primitive, Switch, Value};
|
pub(crate) use base::{Block, Primitive, Switch, Value};
|
||||||
crate use dict::{Dictionary, TaggedDictBuilder};
|
pub(crate) use dict::{Dictionary, TaggedDictBuilder};
|
||||||
crate use files::dir_entry_dict;
|
pub(crate) use files::dir_entry_dict;
|
||||||
|
@ -16,11 +16,11 @@ use std::time::SystemTime;
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, new, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, new, Serialize, Deserialize)]
|
||||||
pub struct OF64 {
|
pub struct OF64 {
|
||||||
crate inner: OrderedFloat<f64>,
|
pub(crate) inner: OrderedFloat<f64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OF64 {
|
impl OF64 {
|
||||||
crate fn into_inner(&self) -> f64 {
|
pub(crate) fn into_inner(&self) -> f64 {
|
||||||
self.inner.into_inner()
|
self.inner.into_inner()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ pub enum Primitive {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Primitive {
|
impl Primitive {
|
||||||
crate fn type_name(&self) -> String {
|
pub(crate) fn type_name(&self) -> String {
|
||||||
use Primitive::*;
|
use Primitive::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
@ -67,7 +67,7 @@ impl Primitive {
|
|||||||
.to_string()
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
pub(crate) fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use Primitive::*;
|
use Primitive::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
@ -130,16 +130,16 @@ impl Primitive {
|
|||||||
|
|
||||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, new, Serialize)]
|
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, new, Serialize)]
|
||||||
pub struct Operation {
|
pub struct Operation {
|
||||||
crate left: Value,
|
pub(crate) left: Value,
|
||||||
crate operator: Operator,
|
pub(crate) operator: Operator,
|
||||||
crate right: Value,
|
pub(crate) right: Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, Serialize, Deserialize, new)]
|
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, Serialize, Deserialize, new)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
crate expressions: Vec<hir::Expression>,
|
pub(crate) expressions: Vec<hir::Expression>,
|
||||||
crate source: Text,
|
pub(crate) source: Text,
|
||||||
crate span: Span,
|
pub(crate) span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Block {
|
impl Block {
|
||||||
@ -176,7 +176,7 @@ pub enum Value {
|
|||||||
Block(Block),
|
Block(Block),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn debug_list(values: &'a Vec<Tagged<Value>>) -> ValuesDebug<'a> {
|
pub fn debug_list(values: &Vec<Tagged<Value>>) -> ValuesDebug<'_> {
|
||||||
ValuesDebug { values }
|
ValuesDebug { values }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +184,7 @@ pub struct ValuesDebug<'a> {
|
|||||||
values: &'a Vec<Tagged<Value>>,
|
values: &'a Vec<Tagged<Value>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for ValuesDebug<'a> {
|
impl fmt::Debug for ValuesDebug<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
f.debug_list()
|
f.debug_list()
|
||||||
.entries(self.values.iter().map(|i| i.debug()))
|
.entries(self.values.iter().map(|i| i.debug()))
|
||||||
@ -196,7 +196,7 @@ pub struct ValueDebug<'a> {
|
|||||||
value: &'a Tagged<Value>,
|
value: &'a Tagged<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for ValueDebug<'a> {
|
impl fmt::Debug for ValueDebug<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self.value.item() {
|
match self.value.item() {
|
||||||
Value::Primitive(p) => p.debug(f),
|
Value::Primitive(p) => p.debug(f),
|
||||||
@ -209,16 +209,16 @@ impl fmt::Debug for ValueDebug<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Tagged<Value> {
|
impl Tagged<Value> {
|
||||||
crate fn tagged_type_name(&self) -> Tagged<String> {
|
pub(crate) fn tagged_type_name(&self) -> Tagged<String> {
|
||||||
let name = self.type_name();
|
let name = self.type_name();
|
||||||
Tagged::from_item(name, self.tag())
|
Tagged::from_item(name, self.tag())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::convert::TryFrom<&'a Tagged<Value>> for Block {
|
impl std::convert::TryFrom<&Tagged<Value>> for Block {
|
||||||
type Error = ShellError;
|
type Error = ShellError;
|
||||||
|
|
||||||
fn try_from(value: &'a Tagged<Value>) -> Result<Block, ShellError> {
|
fn try_from(value: &Tagged<Value>) -> Result<Block, ShellError> {
|
||||||
match value.item() {
|
match value.item() {
|
||||||
Value::Block(block) => Ok(block.clone()),
|
Value::Block(block) => Ok(block.clone()),
|
||||||
v => Err(ShellError::type_error(
|
v => Err(ShellError::type_error(
|
||||||
@ -229,10 +229,10 @@ impl std::convert::TryFrom<&'a Tagged<Value>> for Block {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::convert::TryFrom<&'a Tagged<Value>> for i64 {
|
impl std::convert::TryFrom<&Tagged<Value>> for i64 {
|
||||||
type Error = ShellError;
|
type Error = ShellError;
|
||||||
|
|
||||||
fn try_from(value: &'a Tagged<Value>) -> Result<i64, ShellError> {
|
fn try_from(value: &Tagged<Value>) -> Result<i64, ShellError> {
|
||||||
match value.item() {
|
match value.item() {
|
||||||
Value::Primitive(Primitive::Int(int)) => Ok(*int),
|
Value::Primitive(Primitive::Int(int)) => Ok(*int),
|
||||||
v => Err(ShellError::type_error(
|
v => Err(ShellError::type_error(
|
||||||
@ -243,10 +243,10 @@ impl std::convert::TryFrom<&'a Tagged<Value>> for i64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::convert::TryFrom<&'a Tagged<Value>> for String {
|
impl std::convert::TryFrom<&Tagged<Value>> for String {
|
||||||
type Error = ShellError;
|
type Error = ShellError;
|
||||||
|
|
||||||
fn try_from(value: &'a Tagged<Value>) -> Result<String, ShellError> {
|
fn try_from(value: &Tagged<Value>) -> Result<String, ShellError> {
|
||||||
match value.item() {
|
match value.item() {
|
||||||
Value::Primitive(Primitive::String(s)) => Ok(s.clone()),
|
Value::Primitive(Primitive::String(s)) => Ok(s.clone()),
|
||||||
v => Err(ShellError::type_error(
|
v => Err(ShellError::type_error(
|
||||||
@ -257,10 +257,10 @@ impl std::convert::TryFrom<&'a Tagged<Value>> for String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::convert::TryFrom<&'a Tagged<Value>> for Vec<u8> {
|
impl std::convert::TryFrom<&Tagged<Value>> for Vec<u8> {
|
||||||
type Error = ShellError;
|
type Error = ShellError;
|
||||||
|
|
||||||
fn try_from(value: &'a Tagged<Value>) -> Result<Vec<u8>, ShellError> {
|
fn try_from(value: &Tagged<Value>) -> Result<Vec<u8>, ShellError> {
|
||||||
match value.item() {
|
match value.item() {
|
||||||
Value::Binary(b) => Ok(b.clone()),
|
Value::Binary(b) => Ok(b.clone()),
|
||||||
v => Err(ShellError::type_error(
|
v => Err(ShellError::type_error(
|
||||||
@ -271,7 +271,7 @@ impl std::convert::TryFrom<&'a Tagged<Value>> for Vec<u8> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::convert::TryFrom<&'a Tagged<Value>> for &'a crate::object::Dictionary {
|
impl<'a> std::convert::TryFrom<&'a Tagged<Value>> for &'a crate::object::Dictionary {
|
||||||
type Error = ShellError;
|
type Error = ShellError;
|
||||||
|
|
||||||
fn try_from(value: &'a Tagged<Value>) -> Result<&'a crate::object::Dictionary, ShellError> {
|
fn try_from(value: &'a Tagged<Value>) -> Result<&'a crate::object::Dictionary, ShellError> {
|
||||||
@ -301,10 +301,10 @@ impl Switch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::convert::TryFrom<Option<&'a Tagged<Value>>> for Switch {
|
impl std::convert::TryFrom<Option<&Tagged<Value>>> for Switch {
|
||||||
type Error = ShellError;
|
type Error = ShellError;
|
||||||
|
|
||||||
fn try_from(value: Option<&'a Tagged<Value>>) -> Result<Switch, ShellError> {
|
fn try_from(value: Option<&Tagged<Value>>) -> Result<Switch, ShellError> {
|
||||||
match value {
|
match value {
|
||||||
None => Ok(Switch::Absent),
|
None => Ok(Switch::Absent),
|
||||||
Some(value) => match value.item() {
|
Some(value) => match value.item() {
|
||||||
@ -319,13 +319,13 @@ impl std::convert::TryFrom<Option<&'a Tagged<Value>>> for Switch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Tagged<Value> {
|
impl Tagged<Value> {
|
||||||
crate fn debug(&'a self) -> ValueDebug<'a> {
|
pub(crate) fn debug(&self) -> ValueDebug<'_> {
|
||||||
ValueDebug { value: self }
|
ValueDebug { value: self }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
crate fn type_name(&self) -> String {
|
pub(crate) fn type_name(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(p) => p.type_name(),
|
Value::Primitive(p) => p.type_name(),
|
||||||
Value::Object(_) => format!("object"),
|
Value::Object(_) => format!("object"),
|
||||||
@ -351,7 +351,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn get_data_by_key(&'a self, name: &str) -> Option<&Tagged<Value>> {
|
pub(crate) fn get_data_by_key(&self, name: &str) -> Option<&Tagged<Value>> {
|
||||||
match self {
|
match self {
|
||||||
Value::Object(o) => o.get_data_by_key(name),
|
Value::Object(o) => o.get_data_by_key(name),
|
||||||
Value::List(l) => {
|
Value::List(l) => {
|
||||||
@ -374,14 +374,14 @@ impl Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
crate fn get_data_by_index(&'a self, idx: usize) -> Option<&Tagged<Value>> {
|
pub(crate) fn get_data_by_index(&self, idx: usize) -> Option<&Tagged<Value>> {
|
||||||
match self {
|
match self {
|
||||||
Value::List(l) => l.iter().nth(idx),
|
Value::List(l) => l.iter().nth(idx),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_data_by_path(&'a self, tag: Tag, path: &str) -> Option<Tagged<&Value>> {
|
pub fn get_data_by_path(&self, tag: Tag, path: &str) -> Option<Tagged<&Value>> {
|
||||||
let mut current = self;
|
let mut current = self;
|
||||||
for p in path.split(".") {
|
for p in path.split(".") {
|
||||||
match current.get_data_by_key(p) {
|
match current.get_data_by_key(p) {
|
||||||
@ -394,7 +394,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_data_at_path(
|
pub fn insert_data_at_path(
|
||||||
&'a self,
|
&self,
|
||||||
tag: Tag,
|
tag: Tag,
|
||||||
path: &str,
|
path: &str,
|
||||||
new_value: Value,
|
new_value: Value,
|
||||||
@ -447,7 +447,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn replace_data_at_path(
|
pub fn replace_data_at_path(
|
||||||
&'a self,
|
&self,
|
||||||
tag: Tag,
|
tag: Tag,
|
||||||
path: &str,
|
path: &str,
|
||||||
replaced_value: Value,
|
replaced_value: Value,
|
||||||
@ -481,7 +481,7 @@ impl Value {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_data(&'a self, desc: &String) -> MaybeOwned<'a, Value> {
|
pub fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value> {
|
||||||
match self {
|
match self {
|
||||||
p @ Value::Primitive(_) => MaybeOwned::Borrowed(p),
|
p @ Value::Primitive(_) => MaybeOwned::Borrowed(p),
|
||||||
Value::Object(o) => o.get_data(desc),
|
Value::Object(o) => o.get_data(desc),
|
||||||
@ -491,7 +491,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn format_leaf(&self, desc: Option<&String>) -> String {
|
pub(crate) fn format_leaf(&self, desc: Option<&String>) -> String {
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(p) => p.format(desc),
|
Value::Primitive(p) => p.format(desc),
|
||||||
Value::Block(b) => itertools::join(
|
Value::Block(b) => itertools::join(
|
||||||
@ -510,7 +510,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn style_leaf(&self) -> &'static str {
|
pub(crate) fn style_leaf(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(p) => p.style(),
|
Value::Primitive(p) => p.style(),
|
||||||
_ => "",
|
_ => "",
|
||||||
@ -518,7 +518,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
crate fn compare(&self, operator: &Operator, other: &Value) -> Result<bool, (String, String)> {
|
pub(crate) fn compare(&self, operator: &Operator, other: &Value) -> Result<bool, (String, String)> {
|
||||||
match operator {
|
match operator {
|
||||||
_ => {
|
_ => {
|
||||||
let coerced = coerce_compare(self, other)?;
|
let coerced = coerce_compare(self, other)?;
|
||||||
@ -545,14 +545,14 @@ impl Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
crate fn is_string(&self, expected: &str) -> bool {
|
pub(crate) fn is_string(&self, expected: &str) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(Primitive::String(s)) if s == expected => true,
|
Value::Primitive(Primitive::String(s)) if s == expected => true,
|
||||||
other => false,
|
other => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// crate fn as_pair(&self) -> Result<(Tagged<Value>, Tagged<Value>), ShellError> {
|
// pub(crate) fn as_pair(&self) -> Result<(Tagged<Value>, Tagged<Value>), ShellError> {
|
||||||
// match self {
|
// match self {
|
||||||
// Value::List(list) if list.len() == 2 => Ok((list[0].clone(), list[1].clone())),
|
// Value::List(list) if list.len() == 2 => Ok((list[0].clone(), list[1].clone())),
|
||||||
// other => Err(ShellError::string(format!(
|
// other => Err(ShellError::string(format!(
|
||||||
@ -562,7 +562,7 @@ impl Value {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
crate fn as_string(&self) -> Result<String, ShellError> {
|
pub(crate) fn as_string(&self) -> Result<String, ShellError> {
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(Primitive::String(s)) => Ok(s.clone()),
|
Value::Primitive(Primitive::String(s)) => Ok(s.clone()),
|
||||||
Value::Primitive(Primitive::Boolean(x)) => Ok(format!("{}", x)),
|
Value::Primitive(Primitive::Boolean(x)) => Ok(format!("{}", x)),
|
||||||
@ -577,7 +577,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn as_i64(&self) -> Result<i64, ShellError> {
|
pub(crate) fn as_i64(&self) -> Result<i64, ShellError> {
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(Primitive::Int(i)) => Ok(*i),
|
Value::Primitive(Primitive::Int(i)) => Ok(*i),
|
||||||
Value::Primitive(Primitive::Bytes(b)) => Ok(*b as i64),
|
Value::Primitive(Primitive::Bytes(b)) => Ok(*b as i64),
|
||||||
@ -589,7 +589,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn is_true(&self) -> bool {
|
pub(crate) fn is_true(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(Primitive::Boolean(true)) => true,
|
Value::Primitive(Primitive::Boolean(true)) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
@ -640,7 +640,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Tagged<Value> {
|
impl Tagged<Value> {
|
||||||
crate fn as_path(&self) -> Result<PathBuf, ShellError> {
|
pub(crate) fn as_path(&self) -> Result<PathBuf, ShellError> {
|
||||||
match self.item() {
|
match self.item() {
|
||||||
Value::Primitive(Primitive::Path(path)) => Ok(path.clone()),
|
Value::Primitive(Primitive::Path(path)) => Ok(path.clone()),
|
||||||
other => Err(ShellError::type_error(
|
other => Err(ShellError::type_error(
|
||||||
@ -651,7 +651,7 @@ impl Tagged<Value> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn select_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Tagged<Value> {
|
pub(crate) fn select_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Tagged<Value> {
|
||||||
let mut out = TaggedDictBuilder::new(tag);
|
let mut out = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
let descs = obj.data_descriptors();
|
let descs = obj.data_descriptors();
|
||||||
@ -666,7 +666,7 @@ crate fn select_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> T
|
|||||||
out.into_tagged_value()
|
out.into_tagged_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn reject_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Tagged<Value> {
|
pub(crate) fn reject_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Tagged<Value> {
|
||||||
let mut out = TaggedDictBuilder::new(tag);
|
let mut out = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
let descs = obj.data_descriptors();
|
let descs = obj.data_descriptors();
|
||||||
@ -683,7 +683,7 @@ crate fn reject_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> T
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
crate fn find(obj: &Value, field: &str, op: &Operator, rhs: &Value) -> bool {
|
pub(crate) fn find(obj: &Value, field: &str, op: &Operator, rhs: &Value) -> bool {
|
||||||
let descs = obj.data_descriptors();
|
let descs = obj.data_descriptors();
|
||||||
match descs.iter().find(|d| *d == field) {
|
match descs.iter().find(|d| *d == field) {
|
||||||
None => false,
|
None => false,
|
||||||
|
@ -22,14 +22,14 @@ struct Config {
|
|||||||
extra: IndexMap<String, Tagged<Value>>,
|
extra: IndexMap<String, Tagged<Value>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn config_path() -> Result<PathBuf, ShellError> {
|
pub(crate) fn config_path() -> Result<PathBuf, ShellError> {
|
||||||
let location = app_root(AppDataType::UserConfig, &APP_INFO)
|
let location = app_root(AppDataType::UserConfig, &APP_INFO)
|
||||||
.map_err(|err| ShellError::string(&format!("Couldn't open config file:\n{}", err)))?;
|
.map_err(|err| ShellError::string(&format!("Couldn't open config file:\n{}", err)))?;
|
||||||
|
|
||||||
Ok(location.join("config.toml"))
|
Ok(location.join("config.toml"))
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn write_config(config: &IndexMap<String, Tagged<Value>>) -> Result<(), ShellError> {
|
pub(crate) fn write_config(config: &IndexMap<String, Tagged<Value>>) -> Result<(), ShellError> {
|
||||||
let location = app_root(AppDataType::UserConfig, &APP_INFO)
|
let location = app_root(AppDataType::UserConfig, &APP_INFO)
|
||||||
.map_err(|err| ShellError::string(&format!("Couldn't open config file:\n{}", err)))?;
|
.map_err(|err| ShellError::string(&format!("Couldn't open config file:\n{}", err)))?;
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ crate fn write_config(config: &IndexMap<String, Tagged<Value>>) -> Result<(), Sh
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn config(span: impl Into<Span>) -> Result<IndexMap<String, Tagged<Value>>, ShellError> {
|
pub(crate) fn config(span: impl Into<Span>) -> Result<IndexMap<String, Tagged<Value>>, ShellError> {
|
||||||
let span = span.into();
|
let span = span.into();
|
||||||
|
|
||||||
let location = app_root(AppDataType::UserConfig, &APP_INFO)
|
let location = app_root(AppDataType::UserConfig, &APP_INFO)
|
||||||
|
@ -72,14 +72,14 @@ impl PartialEq<Value> for Dictionary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Dictionary {
|
impl Dictionary {
|
||||||
pub fn get_data(&'a self, desc: &String) -> MaybeOwned<'a, Value> {
|
pub fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value> {
|
||||||
match self.entries.get(desc) {
|
match self.entries.get(desc) {
|
||||||
Some(v) => MaybeOwned::Borrowed(v),
|
Some(v) => MaybeOwned::Borrowed(v),
|
||||||
None => MaybeOwned::Owned(Value::Primitive(Primitive::Nothing)),
|
None => MaybeOwned::Owned(Value::Primitive(Primitive::Nothing)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn get_data_by_key(&self, name: &str) -> Option<&Tagged<Value>> {
|
pub(crate) fn get_data_by_key(&self, name: &str) -> Option<&Tagged<Value>> {
|
||||||
match self
|
match self
|
||||||
.entries
|
.entries
|
||||||
.iter()
|
.iter()
|
||||||
@ -90,7 +90,7 @@ impl Dictionary {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
pub(crate) fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let mut debug = f.debug_struct("Dictionary");
|
let mut debug = f.debug_struct("Dictionary");
|
||||||
|
|
||||||
for (desc, value) in self.entries.iter() {
|
for (desc, value) in self.entries.iter() {
|
||||||
@ -146,6 +146,13 @@ impl TaggedDictBuilder {
|
|||||||
dict: IndexMap::default(),
|
dict: IndexMap::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_capacity(tag: impl Into<Tag>, n: usize) -> TaggedDictBuilder {
|
||||||
|
TaggedDictBuilder {
|
||||||
|
tag: tag.into(),
|
||||||
|
dict: IndexMap::with_capacity(n),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, key: impl Into<String>, value: impl Into<Value>) {
|
pub fn insert(&mut self, key: impl Into<String>, value: impl Into<Value>) {
|
||||||
self.dict.insert(key.into(), value.into().tagged(self.tag));
|
self.dict.insert(key.into(), value.into().tagged(self.tag));
|
||||||
|
@ -9,7 +9,7 @@ pub enum FileType {
|
|||||||
Symlink,
|
Symlink,
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn dir_entry_dict(
|
pub(crate) fn dir_entry_dict(
|
||||||
filename: &std::path::Path,
|
filename: &std::path::Path,
|
||||||
metadata: &std::fs::Metadata,
|
metadata: &std::fs::Metadata,
|
||||||
tag: impl Into<Tag>,
|
tag: impl Into<Tag>,
|
||||||
|
@ -87,7 +87,7 @@ impl<T> Tagged<T> {
|
|||||||
Tagged::from_item(mapped, tag.clone())
|
Tagged::from_item(mapped, tag.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn copy_span<U>(&self, output: U) -> Tagged<U> {
|
pub(crate) fn copy_span<U>(&self, output: U) -> Tagged<U> {
|
||||||
let span = self.span();
|
let span = self.span();
|
||||||
|
|
||||||
Tagged::from_simple_spanned_item(output, span)
|
Tagged::from_simple_spanned_item(output, span)
|
||||||
@ -224,8 +224,8 @@ impl Tag {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
|
||||||
pub struct Span {
|
pub struct Span {
|
||||||
crate start: usize,
|
pub(crate) start: usize,
|
||||||
crate end: usize,
|
pub(crate) end: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Option<Span>> for Span {
|
impl From<Option<Span>> for Span {
|
||||||
@ -256,7 +256,7 @@ impl Span {
|
|||||||
self.start == 0 && self.end == 0
|
self.start == 0 && self.end == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn slice(&self, source: &'a str) -> &'a str {
|
pub fn slice<'a>(&self, source: &'a str) -> &'a str {
|
||||||
&source[self.start..self.end]
|
&source[self.start..self.end]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
use crate::object::{TaggedDictBuilder, Value};
|
|
||||||
use crate::prelude::*;
|
|
||||||
use itertools::join;
|
|
||||||
use sysinfo::ProcessExt;
|
|
||||||
|
|
||||||
crate fn process_dict(proc: &sysinfo::Process, tag: impl Into<Tag>) -> Tagged<Value> {
|
|
||||||
let mut dict = TaggedDictBuilder::new(tag);
|
|
||||||
|
|
||||||
let cmd = proc.cmd();
|
|
||||||
|
|
||||||
let cmd_value = if cmd.len() == 0 {
|
|
||||||
Value::nothing()
|
|
||||||
} else {
|
|
||||||
Value::string(join(cmd, ""))
|
|
||||||
};
|
|
||||||
|
|
||||||
dict.insert("pid", Value::int(proc.pid() as i64));
|
|
||||||
dict.insert("status", Value::string(proc.status().to_string()));
|
|
||||||
dict.insert("cpu", Value::float(proc.cpu_usage() as f64));
|
|
||||||
//dict.insert("name", Value::string(proc.name()));
|
|
||||||
match cmd_value {
|
|
||||||
Value::Primitive(Primitive::Nothing) => {
|
|
||||||
dict.insert("name", Value::string(proc.name()));
|
|
||||||
}
|
|
||||||
_ => dict.insert("name", cmd_value),
|
|
||||||
}
|
|
||||||
|
|
||||||
dict.into_tagged_value()
|
|
||||||
}
|
|
@ -1,14 +1,9 @@
|
|||||||
use crate::object::base as value;
|
use crate::object::base as value;
|
||||||
use crate::parser::hir;
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
pub trait ExtractType: Sized {
|
pub trait ExtractType: Sized {
|
||||||
fn extract(value: &Tagged<Value>) -> Result<Self, ShellError>;
|
fn extract(value: &Tagged<Value>) -> Result<Self, ShellError>;
|
||||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError>;
|
|
||||||
fn syntax_type() -> hir::SyntaxType {
|
|
||||||
hir::SyntaxType::Any
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ExtractType for T {
|
impl<T> ExtractType for T {
|
||||||
@ -19,14 +14,6 @@ impl<T> ExtractType for T {
|
|||||||
name
|
name
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
default fn check(_value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
|
||||||
Err(ShellError::unimplemented("ExtractType for T"))
|
|
||||||
}
|
|
||||||
|
|
||||||
default fn syntax_type() -> hir::SyntaxType {
|
|
||||||
hir::SyntaxType::Any
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ExtractType> ExtractType for Vec<Tagged<T>> {
|
impl<T: ExtractType> ExtractType for Vec<Tagged<T>> {
|
||||||
@ -50,20 +37,6 @@ impl<T: ExtractType> ExtractType for Vec<Tagged<T>> {
|
|||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
|
||||||
match value.item() {
|
|
||||||
Value::List(_) => Ok(value),
|
|
||||||
other => Err(ShellError::type_error(
|
|
||||||
"Vec",
|
|
||||||
other.type_name().tagged(value.tag()),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn syntax_type() -> hir::SyntaxType {
|
|
||||||
hir::SyntaxType::List
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ExtractType, U: ExtractType> ExtractType for (T, U) {
|
impl<T: ExtractType, U: ExtractType> ExtractType for (T, U) {
|
||||||
@ -107,17 +80,6 @@ impl<T: ExtractType> ExtractType for Option<T> {
|
|||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
|
||||||
match value.item() {
|
|
||||||
Value::Primitive(Primitive::Nothing) => Ok(value),
|
|
||||||
_ => T::check(value),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn syntax_type() -> hir::SyntaxType {
|
|
||||||
T::syntax_type()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ExtractType> ExtractType for Tagged<T> {
|
impl<T: ExtractType> ExtractType for Tagged<T> {
|
||||||
@ -127,14 +89,6 @@ impl<T: ExtractType> ExtractType for Tagged<T> {
|
|||||||
|
|
||||||
Ok(T::extract(value)?.tagged(value.tag()))
|
Ok(T::extract(value)?.tagged(value.tag()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
|
||||||
T::check(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn syntax_type() -> hir::SyntaxType {
|
|
||||||
T::syntax_type()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtractType for Value {
|
impl ExtractType for Value {
|
||||||
@ -143,22 +97,10 @@ impl ExtractType for Value {
|
|||||||
|
|
||||||
Ok(value.item().clone())
|
Ok(value.item().clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn syntax_type() -> hir::SyntaxType {
|
|
||||||
SyntaxType::Any
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtractType for bool {
|
impl ExtractType for bool {
|
||||||
fn syntax_type() -> hir::SyntaxType {
|
fn extract(value: &Tagged<Value>) -> Result<bool, ShellError> {
|
||||||
hir::SyntaxType::Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extract(value: &'a Tagged<Value>) -> Result<bool, ShellError> {
|
|
||||||
trace!("Extracting {:?} for bool", value);
|
trace!("Extracting {:?} for bool", value);
|
||||||
|
|
||||||
match &value {
|
match &value {
|
||||||
@ -173,24 +115,10 @@ impl ExtractType for bool {
|
|||||||
other => Err(ShellError::type_error("Boolean", other.tagged_type_name())),
|
other => Err(ShellError::type_error("Boolean", other.tagged_type_name())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
|
||||||
match &value {
|
|
||||||
value @ Tagged {
|
|
||||||
item: Value::Primitive(Primitive::Boolean(_)),
|
|
||||||
..
|
|
||||||
} => Ok(value),
|
|
||||||
other => Err(ShellError::type_error("Boolean", other.tagged_type_name())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtractType for std::path::PathBuf {
|
impl ExtractType for std::path::PathBuf {
|
||||||
fn syntax_type() -> hir::SyntaxType {
|
fn extract(value: &Tagged<Value>) -> Result<std::path::PathBuf, ShellError> {
|
||||||
hir::SyntaxType::Path
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extract(value: &'a Tagged<Value>) -> Result<std::path::PathBuf, ShellError> {
|
|
||||||
trace!("Extracting {:?} for PathBuf", value);
|
trace!("Extracting {:?} for PathBuf", value);
|
||||||
|
|
||||||
match &value {
|
match &value {
|
||||||
@ -201,16 +129,6 @@ impl ExtractType for std::path::PathBuf {
|
|||||||
other => Err(ShellError::type_error("Path", other.tagged_type_name())),
|
other => Err(ShellError::type_error("Path", other.tagged_type_name())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
|
||||||
match &value {
|
|
||||||
v @ Tagged {
|
|
||||||
item: Value::Primitive(Primitive::Path(_)),
|
|
||||||
..
|
|
||||||
} => Ok(v),
|
|
||||||
other => Err(ShellError::type_error("Path", other.tagged_type_name())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtractType for i64 {
|
impl ExtractType for i64 {
|
||||||
@ -225,16 +143,6 @@ impl ExtractType for i64 {
|
|||||||
other => Err(ShellError::type_error("Integer", other.tagged_type_name())),
|
other => Err(ShellError::type_error("Integer", other.tagged_type_name())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
|
||||||
match value {
|
|
||||||
v @ Tagged {
|
|
||||||
item: Value::Primitive(Primitive::Int(_)),
|
|
||||||
..
|
|
||||||
} => Ok(v),
|
|
||||||
other => Err(ShellError::type_error("Integer", other.tagged_type_name())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtractType for String {
|
impl ExtractType for String {
|
||||||
@ -249,31 +157,9 @@ impl ExtractType for String {
|
|||||||
other => Err(ShellError::type_error("String", other.tagged_type_name())),
|
other => Err(ShellError::type_error("String", other.tagged_type_name())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
|
||||||
match value {
|
|
||||||
v @ Tagged {
|
|
||||||
item: Value::Primitive(Primitive::String(_)),
|
|
||||||
..
|
|
||||||
} => Ok(v),
|
|
||||||
other => Err(ShellError::type_error("String", other.tagged_type_name())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtractType for value::Block {
|
impl ExtractType for value::Block {
|
||||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
|
||||||
trace!("Extracting {:?} for Block", value);
|
|
||||||
|
|
||||||
match value {
|
|
||||||
v @ Tagged {
|
|
||||||
item: Value::Block(_),
|
|
||||||
..
|
|
||||||
} => Ok(v),
|
|
||||||
other => Err(ShellError::type_error("Block", other.tagged_type_name())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extract(value: &Tagged<Value>) -> Result<value::Block, ShellError> {
|
fn extract(value: &Tagged<Value>) -> Result<value::Block, ShellError> {
|
||||||
match value {
|
match value {
|
||||||
Tagged {
|
Tagged {
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
crate mod deserializer;
|
pub(crate) mod deserializer;
|
||||||
crate mod hir;
|
pub(crate) mod hir;
|
||||||
crate mod parse;
|
pub(crate) mod parse;
|
||||||
crate mod parse_command;
|
pub(crate) mod parse_command;
|
||||||
crate mod registry;
|
pub(crate) mod registry;
|
||||||
|
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
|
|
||||||
crate use deserializer::ConfigDeserializer;
|
pub(crate) use deserializer::ConfigDeserializer;
|
||||||
crate use hir::baseline_parse_tokens::baseline_parse_tokens;
|
pub(crate) use hir::baseline_parse_tokens::baseline_parse_tokens;
|
||||||
crate use parse::call_node::CallNode;
|
pub(crate) use parse::call_node::CallNode;
|
||||||
crate use parse::files::Files;
|
pub(crate) use parse::files::Files;
|
||||||
crate use parse::flag::Flag;
|
pub(crate) use parse::flag::Flag;
|
||||||
crate use parse::operator::Operator;
|
pub(crate) use parse::operator::Operator;
|
||||||
crate use parse::parser::{nom_input, pipeline};
|
pub(crate) use parse::parser::{nom_input, pipeline};
|
||||||
crate use parse::pipeline::{Pipeline, PipelineElement};
|
pub(crate) use parse::pipeline::{Pipeline, PipelineElement};
|
||||||
crate use parse::text::Text;
|
pub(crate) use parse::text::Text;
|
||||||
crate use parse::token_tree::{DelimitedNode, Delimiter, PathNode, TokenNode};
|
pub(crate) use parse::token_tree::{DelimitedNode, Delimiter, PathNode, TokenNode};
|
||||||
crate use parse::tokens::{RawToken, Token};
|
pub(crate) use parse::tokens::{RawToken, Token};
|
||||||
crate use parse::unit::Unit;
|
pub(crate) use parse::unit::Unit;
|
||||||
crate use parse_command::parse_command;
|
pub(crate) use parse_command::parse_command;
|
||||||
crate use registry::CommandRegistry;
|
pub(crate) use registry::CommandRegistry;
|
||||||
|
|
||||||
pub fn parse(input: &str) -> Result<TokenNode, ShellError> {
|
pub fn parse(input: &str) -> Result<TokenNode, ShellError> {
|
||||||
let _ = pretty_env_logger::try_init();
|
let _ = pretty_env_logger::try_init();
|
||||||
|
@ -16,7 +16,7 @@ pub struct ConfigDeserializer<'de> {
|
|||||||
position: usize,
|
position: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigDeserializer<'de> {
|
impl<'de> ConfigDeserializer<'de> {
|
||||||
pub fn from_call_info(call: CallInfo) -> ConfigDeserializer<'de> {
|
pub fn from_call_info(call: CallInfo) -> ConfigDeserializer<'de> {
|
||||||
ConfigDeserializer {
|
ConfigDeserializer {
|
||||||
call,
|
call,
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
crate mod baseline_parse;
|
pub(crate) mod baseline_parse;
|
||||||
crate mod baseline_parse_tokens;
|
pub(crate) mod baseline_parse_tokens;
|
||||||
crate mod binary;
|
pub(crate) mod binary;
|
||||||
crate mod external_command;
|
pub(crate) mod external_command;
|
||||||
crate mod named;
|
pub(crate) mod named;
|
||||||
crate mod path;
|
pub(crate) mod path;
|
||||||
|
|
||||||
use crate::parser::{registry, Unit};
|
use crate::parser::{registry, Unit};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
@ -15,15 +15,15 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
use crate::evaluate::Scope;
|
use crate::evaluate::Scope;
|
||||||
|
|
||||||
crate use self::baseline_parse::{
|
pub(crate) use self::baseline_parse::{
|
||||||
baseline_parse_single_token, baseline_parse_token_as_number, baseline_parse_token_as_path,
|
baseline_parse_single_token, baseline_parse_token_as_number, baseline_parse_token_as_path,
|
||||||
baseline_parse_token_as_string,
|
baseline_parse_token_as_string,
|
||||||
};
|
};
|
||||||
crate use self::baseline_parse_tokens::{baseline_parse_next_expr, TokensIterator};
|
pub(crate) use self::baseline_parse_tokens::{baseline_parse_next_expr, TokensIterator};
|
||||||
crate use self::binary::Binary;
|
pub(crate) use self::binary::Binary;
|
||||||
crate use self::external_command::ExternalCommand;
|
pub(crate) use self::external_command::ExternalCommand;
|
||||||
crate use self::named::NamedArguments;
|
pub(crate) use self::named::NamedArguments;
|
||||||
crate use self::path::Path;
|
pub(crate) use self::path::Path;
|
||||||
|
|
||||||
pub use self::baseline_parse_tokens::SyntaxType;
|
pub use self::baseline_parse_tokens::SyntaxType;
|
||||||
|
|
||||||
@ -129,51 +129,51 @@ impl RawExpression {
|
|||||||
pub type Expression = Tagged<RawExpression>;
|
pub type Expression = Tagged<RawExpression>;
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
crate fn int(i: impl Into<i64>, span: impl Into<Span>) -> Expression {
|
pub(crate) fn int(i: impl Into<i64>, span: impl Into<Span>) -> Expression {
|
||||||
Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Integer(i.into())), span)
|
Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Integer(i.into())), span)
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn size(i: impl Into<i64>, unit: impl Into<Unit>, span: impl Into<Span>) -> Expression {
|
pub(crate) fn size(i: impl Into<i64>, unit: impl Into<Unit>, span: impl Into<Span>) -> Expression {
|
||||||
Tagged::from_simple_spanned_item(
|
Tagged::from_simple_spanned_item(
|
||||||
RawExpression::Literal(Literal::Size(i.into(), unit.into())),
|
RawExpression::Literal(Literal::Size(i.into(), unit.into())),
|
||||||
span,
|
span,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn synthetic_string(s: impl Into<String>) -> Expression {
|
pub(crate) fn synthetic_string(s: impl Into<String>) -> Expression {
|
||||||
RawExpression::Synthetic(Synthetic::String(s.into())).tagged_unknown()
|
RawExpression::Synthetic(Synthetic::String(s.into())).tagged_unknown()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn string(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
pub(crate) fn string(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
||||||
Tagged::from_simple_spanned_item(
|
Tagged::from_simple_spanned_item(
|
||||||
RawExpression::Literal(Literal::String(inner.into())),
|
RawExpression::Literal(Literal::String(inner.into())),
|
||||||
outer.into(),
|
outer.into(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn file_path(path: impl Into<PathBuf>, outer: impl Into<Span>) -> Expression {
|
pub(crate) fn file_path(path: impl Into<PathBuf>, outer: impl Into<Span>) -> Expression {
|
||||||
Tagged::from_simple_spanned_item(RawExpression::FilePath(path.into()), outer.into())
|
Tagged::from_simple_spanned_item(RawExpression::FilePath(path.into()), outer.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn bare(span: impl Into<Span>) -> Expression {
|
pub(crate) fn bare(span: impl Into<Span>) -> Expression {
|
||||||
Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Bare), span.into())
|
Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Bare), span.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
pub(crate) fn variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
||||||
Tagged::from_simple_spanned_item(
|
Tagged::from_simple_spanned_item(
|
||||||
RawExpression::Variable(Variable::Other(inner.into())),
|
RawExpression::Variable(Variable::Other(inner.into())),
|
||||||
outer.into(),
|
outer.into(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn external_command(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
pub(crate) fn external_command(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
||||||
Tagged::from_simple_spanned_item(
|
Tagged::from_simple_spanned_item(
|
||||||
RawExpression::ExternalCommand(ExternalCommand::new(inner.into())),
|
RawExpression::ExternalCommand(ExternalCommand::new(inner.into())),
|
||||||
outer.into(),
|
outer.into(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn it_variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
pub(crate) fn it_variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
||||||
Tagged::from_simple_spanned_item(
|
Tagged::from_simple_spanned_item(
|
||||||
RawExpression::Variable(Variable::It(inner.into())),
|
RawExpression::Variable(Variable::It(inner.into())),
|
||||||
outer.into(),
|
outer.into(),
|
||||||
|
@ -331,7 +331,7 @@ pub struct TokensIterator<'a> {
|
|||||||
seen: indexmap::IndexSet<usize>,
|
seen: indexmap::IndexSet<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TokensIterator<'a> {
|
impl TokensIterator<'_> {
|
||||||
pub fn remove(&mut self, position: usize) {
|
pub fn remove(&mut self, position: usize) {
|
||||||
self.seen.insert(position);
|
self.seen.insert(position);
|
||||||
}
|
}
|
||||||
@ -404,7 +404,7 @@ impl TokensIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for TokensIterator<'a> {
|
impl<'a> Iterator for TokensIterator<'a> {
|
||||||
type Item = &'a TokenNode;
|
type Item = &'a TokenNode;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<&'a TokenNode> {
|
fn next(&mut self) -> Option<&'a TokenNode> {
|
||||||
|
@ -19,7 +19,7 @@ pub enum NamedValue {
|
|||||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, new)]
|
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, new)]
|
||||||
pub struct NamedArguments {
|
pub struct NamedArguments {
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
crate named: IndexMap<String, NamedValue>,
|
pub(crate) named: IndexMap<String, NamedValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToDebug for NamedArguments {
|
impl ToDebug for NamedArguments {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
crate mod call_node;
|
pub(crate) mod call_node;
|
||||||
crate mod files;
|
pub(crate) mod files;
|
||||||
crate mod flag;
|
pub(crate) mod flag;
|
||||||
crate mod operator;
|
pub(crate) mod operator;
|
||||||
crate mod parser;
|
pub(crate) mod parser;
|
||||||
crate mod pipeline;
|
pub(crate) mod pipeline;
|
||||||
crate mod text;
|
pub(crate) mod text;
|
||||||
crate mod token_tree;
|
pub(crate) mod token_tree;
|
||||||
crate mod token_tree_builder;
|
pub(crate) mod token_tree_builder;
|
||||||
crate mod tokens;
|
pub(crate) mod tokens;
|
||||||
crate mod unit;
|
pub(crate) mod unit;
|
||||||
crate mod util;
|
pub(crate) mod util;
|
||||||
|
@ -23,7 +23,7 @@ use std::str::FromStr;
|
|||||||
|
|
||||||
pub type NomSpan<'a> = LocatedSpan<&'a str>;
|
pub type NomSpan<'a> = LocatedSpan<&'a str>;
|
||||||
|
|
||||||
pub fn nom_input(s: &'a str) -> NomSpan<'a> {
|
pub fn nom_input(s: &str) -> NomSpan<'_> {
|
||||||
LocatedSpan::new(s)
|
LocatedSpan::new(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@ use getset::Getters;
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, new)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, new)]
|
||||||
pub struct Pipeline {
|
pub struct Pipeline {
|
||||||
crate parts: Vec<PipelineElement>,
|
pub(crate) parts: Vec<PipelineElement>,
|
||||||
crate post_ws: Option<Span>,
|
pub(crate) post_ws: Option<Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Getters, new)]
|
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Getters, new)]
|
||||||
|
@ -213,7 +213,7 @@ impl Serialize for Text {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deserialize<'de> for Text {
|
impl<'de> Deserialize<'de> for Text {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
|
@ -27,7 +27,7 @@ pub struct DebugTokenNode<'a> {
|
|||||||
source: &'a Text,
|
source: &'a Text,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for DebugTokenNode<'a> {
|
impl fmt::Debug for DebugTokenNode<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self.node {
|
match self.node {
|
||||||
TokenNode::Token(t) => write!(f, "{:?}", t.debug(self.source)),
|
TokenNode::Token(t) => write!(f, "{:?}", t.debug(self.source)),
|
||||||
@ -115,7 +115,7 @@ impl TokenNode {
|
|||||||
.to_string()
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn debug(&'a self, source: &'a Text) -> DebugTokenNode<'a> {
|
pub fn debug<'a>(&'a self, source: &'a Text) -> DebugTokenNode<'a> {
|
||||||
DebugTokenNode { node: self, source }
|
DebugTokenNode { node: self, source }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ impl TokenNode {
|
|||||||
self.span().slice(source).to_string()
|
self.span().slice(source).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn source(&self, source: &'a Text) -> &'a str {
|
pub fn source<'a>(&self, source: &'a Text) -> &'a str {
|
||||||
self.span().slice(source)
|
self.span().slice(source)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ impl TokenNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn as_flag(&self, value: &str, source: &Text) -> Option<Tagged<Flag>> {
|
pub(crate) fn as_flag(&self, value: &str, source: &Text) -> Option<Tagged<Flag>> {
|
||||||
match self {
|
match self {
|
||||||
TokenNode::Flag(
|
TokenNode::Flag(
|
||||||
flag @ Tagged {
|
flag @ Tagged {
|
||||||
|
@ -28,7 +28,7 @@ impl RawToken {
|
|||||||
pub type Token = Tagged<RawToken>;
|
pub type Token = Tagged<RawToken>;
|
||||||
|
|
||||||
impl Token {
|
impl Token {
|
||||||
pub fn debug(&self, source: &'a Text) -> DebugToken<'a> {
|
pub fn debug<'a>(&self, source: &'a Text) -> DebugToken<'a> {
|
||||||
DebugToken {
|
DebugToken {
|
||||||
node: *self,
|
node: *self,
|
||||||
source,
|
source,
|
||||||
@ -41,7 +41,7 @@ pub struct DebugToken<'a> {
|
|||||||
source: &'a Text,
|
source: &'a Text,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for DebugToken<'a> {
|
impl fmt::Debug for DebugToken<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}", self.node.span().slice(self.source))
|
write!(f, "{}", self.node.span().slice(self.source))
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ impl Unit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn compute(&self, size: i64) -> Value {
|
pub(crate) fn compute(&self, size: i64) -> Value {
|
||||||
Value::int(match self {
|
Value::int(match self {
|
||||||
Unit::B => size,
|
Unit::B => size,
|
||||||
Unit::KB => size * 1024,
|
Unit::KB => size * 1024,
|
||||||
|
@ -205,7 +205,7 @@ fn extract_switch(name: &str, tokens: &mut hir::TokensIterator<'_>, source: &Tex
|
|||||||
fn extract_mandatory(
|
fn extract_mandatory(
|
||||||
config: &Signature,
|
config: &Signature,
|
||||||
name: &str,
|
name: &str,
|
||||||
tokens: &mut hir::TokensIterator<'a>,
|
tokens: &mut hir::TokensIterator<'_>,
|
||||||
source: &Text,
|
source: &Text,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<(usize, Tagged<Flag>), ShellError> {
|
) -> Result<(usize, Tagged<Flag>), ShellError> {
|
||||||
@ -227,7 +227,7 @@ fn extract_mandatory(
|
|||||||
|
|
||||||
fn extract_optional(
|
fn extract_optional(
|
||||||
name: &str,
|
name: &str,
|
||||||
tokens: &mut hir::TokensIterator<'a>,
|
tokens: &mut hir::TokensIterator<'_>,
|
||||||
source: &Text,
|
source: &Text,
|
||||||
) -> Result<(Option<(usize, Tagged<Flag>)>), ShellError> {
|
) -> Result<(Option<(usize, Tagged<Flag>)>), ShellError> {
|
||||||
let flag = tokens.extract(|t| t.as_flag(name, source));
|
let flag = tokens.extract(|t| t.as_flag(name, source));
|
||||||
@ -241,7 +241,7 @@ fn extract_optional(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trace_remaining(desc: &'static str, tail: hir::TokensIterator<'a>, source: &Text) {
|
pub fn trace_remaining(desc: &'static str, tail: hir::TokensIterator<'_>, source: &Text) {
|
||||||
trace!(
|
trace!(
|
||||||
"{} = {:?}",
|
"{} = {:?}",
|
||||||
desc,
|
desc,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// TODO: Temporary redirect
|
// TODO: Temporary redirect
|
||||||
crate use crate::context::CommandRegistry;
|
pub(crate) use crate::context::CommandRegistry;
|
||||||
use crate::evaluate::{evaluate_baseline_expr, Scope};
|
use crate::evaluate::{evaluate_baseline_expr, Scope};
|
||||||
use crate::parser::{hir, hir::SyntaxType, parse_command, CallNode};
|
use crate::parser::{hir, hir::SyntaxType, parse_command, CallNode};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
@ -46,7 +46,7 @@ impl PositionalType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
crate fn to_coerce_hint(&self) -> Option<SyntaxType> {
|
pub(crate) fn to_coerce_hint(&self) -> Option<SyntaxType> {
|
||||||
match self {
|
match self {
|
||||||
PositionalType::Mandatory(_, SyntaxType::Block)
|
PositionalType::Mandatory(_, SyntaxType::Block)
|
||||||
| PositionalType::Optional(_, SyntaxType::Block) => Some(SyntaxType::Block),
|
| PositionalType::Optional(_, SyntaxType::Block) => Some(SyntaxType::Block),
|
||||||
@ -54,14 +54,14 @@ impl PositionalType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn name(&self) -> &str {
|
pub(crate) fn name(&self) -> &str {
|
||||||
match self {
|
match self {
|
||||||
PositionalType::Mandatory(s, _) => s,
|
PositionalType::Mandatory(s, _) => s,
|
||||||
PositionalType::Optional(s, _) => s,
|
PositionalType::Optional(s, _) => s,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn syntax_type(&self) -> SyntaxType {
|
pub(crate) fn syntax_type(&self) -> SyntaxType {
|
||||||
match *self {
|
match *self {
|
||||||
PositionalType::Mandatory(_, t) => t,
|
PositionalType::Mandatory(_, t) => t,
|
||||||
PositionalType::Optional(_, t) => t,
|
PositionalType::Optional(_, t) => t,
|
||||||
@ -158,7 +158,7 @@ pub struct DebugEvaluatedPositional<'a> {
|
|||||||
positional: &'a Option<Vec<Tagged<Value>>>,
|
positional: &'a Option<Vec<Tagged<Value>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for DebugEvaluatedPositional<'a> {
|
impl fmt::Debug for DebugEvaluatedPositional<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match &self.positional {
|
match &self.positional {
|
||||||
None => write!(f, "None"),
|
None => write!(f, "None"),
|
||||||
@ -175,7 +175,7 @@ pub struct DebugEvaluatedNamed<'a> {
|
|||||||
named: &'a Option<IndexMap<String, Tagged<Value>>>,
|
named: &'a Option<IndexMap<String, Tagged<Value>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for DebugEvaluatedNamed<'a> {
|
impl fmt::Debug for DebugEvaluatedNamed<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match &self.named {
|
match &self.named {
|
||||||
None => write!(f, "None"),
|
None => write!(f, "None"),
|
||||||
@ -191,7 +191,7 @@ pub struct DebugEvaluatedArgs<'a> {
|
|||||||
args: &'a EvaluatedArgs,
|
args: &'a EvaluatedArgs,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for DebugEvaluatedArgs<'a> {
|
impl fmt::Debug for DebugEvaluatedArgs<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let mut s = f.debug_struct("Args");
|
let mut s = f.debug_struct("Args");
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ impl fmt::Debug for DebugEvaluatedArgs<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatedArgs {
|
impl EvaluatedArgs {
|
||||||
pub fn debug(&'a self) -> DebugEvaluatedArgs<'a> {
|
pub fn debug(&self) -> DebugEvaluatedArgs<'_> {
|
||||||
DebugEvaluatedArgs { args: self }
|
DebugEvaluatedArgs { args: self }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,7 +248,7 @@ impl EvaluatedArgs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn positional_iter(&'a self) -> PositionalIter<'a> {
|
pub fn positional_iter(&self) -> PositionalIter<'_> {
|
||||||
match &self.positional {
|
match &self.positional {
|
||||||
None => PositionalIter::Empty,
|
None => PositionalIter::Empty,
|
||||||
Some(v) => {
|
Some(v) => {
|
||||||
@ -264,7 +264,7 @@ pub enum PositionalIter<'a> {
|
|||||||
Array(std::slice::Iter<'a, Tagged<Value>>),
|
Array(std::slice::Iter<'a, Tagged<Value>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for PositionalIter<'a> {
|
impl<'a> Iterator for PositionalIter<'a> {
|
||||||
type Item = &'a Tagged<Value>;
|
type Item = &'a Tagged<Value>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
@ -276,7 +276,7 @@ impl Iterator for PositionalIter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Signature {
|
impl Signature {
|
||||||
crate fn parse_args(
|
pub(crate) fn parse_args(
|
||||||
&self,
|
&self,
|
||||||
call: &Tagged<CallNode>,
|
call: &Tagged<CallNode>,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
@ -290,12 +290,12 @@ impl Signature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
crate fn signature(&self) -> String {
|
pub(crate) fn signature(&self) -> String {
|
||||||
format!("TODO")
|
format!("TODO")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn evaluate_args(
|
pub(crate) fn evaluate_args(
|
||||||
call: &hir::Call,
|
call: &hir::Call,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
|
use std::ffi::OsStr;
|
||||||
|
|
||||||
use futures::executor::block_on;
|
use futures::executor::block_on;
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
use heim::{disk, memory, net};
|
|
||||||
use nu::{
|
use nu::{
|
||||||
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
||||||
Tag, Tagged, TaggedDictBuilder, Value,
|
Tag, Tagged, TaggedDictBuilder, Value,
|
||||||
};
|
};
|
||||||
use std::ffi::OsStr;
|
use heim::{disk, memory, net, sensors, host};
|
||||||
|
use heim::units::{frequency, information, time, thermodynamic_temperature};
|
||||||
|
|
||||||
struct Sys;
|
struct Sys;
|
||||||
impl Sys {
|
impl Sys {
|
||||||
@ -15,52 +17,65 @@ impl Sys {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn cpu(tag: Tag) -> Option<Tagged<Value>> {
|
async fn cpu(tag: Tag) -> Option<Tagged<Value>> {
|
||||||
if let (Ok(num_cpu), Ok(cpu_speed)) = (
|
match futures::future::try_join(
|
||||||
heim::cpu::logical_count().await,
|
heim::cpu::logical_count(),
|
||||||
heim::cpu::frequency().await,
|
heim::cpu::frequency(),
|
||||||
) {
|
).await {
|
||||||
let mut cpu_idx = TaggedDictBuilder::new(tag);
|
Ok((num_cpu, cpu_speed)) => {
|
||||||
cpu_idx.insert("cores", Primitive::Int(num_cpu as i64));
|
let mut cpu_idx = TaggedDictBuilder::with_capacity(tag, 4);
|
||||||
|
cpu_idx.insert("cores", Primitive::Int(num_cpu as i64));
|
||||||
|
|
||||||
let current_speed =
|
let current_speed =
|
||||||
(cpu_speed.current().get() as f64 / 1000000000.0 * 100.0).round() / 100.0;
|
(cpu_speed.current().get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round() / 100.0;
|
||||||
cpu_idx.insert("current ghz", Primitive::Float(current_speed.into()));
|
cpu_idx.insert("current ghz", Primitive::Float(current_speed.into()));
|
||||||
|
|
||||||
if let Some(min_speed) = cpu_speed.min() {
|
if let Some(min_speed) = cpu_speed.min() {
|
||||||
let min_speed = (min_speed.get() as f64 / 1000000000.0 * 100.0).round() / 100.0;
|
let min_speed = (min_speed.get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round() / 100.0;
|
||||||
cpu_idx.insert("min ghz", Primitive::Float(min_speed.into()));
|
cpu_idx.insert("min ghz", Primitive::Float(min_speed.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(max_speed) = cpu_speed.max() {
|
if let Some(max_speed) = cpu_speed.max() {
|
||||||
let max_speed = (max_speed.get() as f64 / 1000000000.0 * 100.0).round() / 100.0;
|
let max_speed = (max_speed.get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round() / 100.0;
|
||||||
cpu_idx.insert("max ghz", Primitive::Float(max_speed.into()));
|
cpu_idx.insert("max ghz", Primitive::Float(max_speed.into()));
|
||||||
}
|
}
|
||||||
Some(cpu_idx.into_tagged_value())
|
|
||||||
} else {
|
Some(cpu_idx.into_tagged_value())
|
||||||
None
|
},
|
||||||
|
Err(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn mem(tag: Tag) -> Tagged<Value> {
|
async fn mem(tag: Tag) -> Tagged<Value> {
|
||||||
let mut dict = TaggedDictBuilder::new(tag);
|
let mut dict = TaggedDictBuilder::with_capacity(tag, 4);
|
||||||
|
|
||||||
if let Ok(memory) = memory::memory().await {
|
let (memory_result, swap_result) = futures::future::join(
|
||||||
dict.insert("total", Value::bytes(memory.total().get()));
|
memory::memory(),
|
||||||
dict.insert("free", Value::bytes(memory.free().get()));
|
memory::swap()
|
||||||
|
).await;
|
||||||
|
|
||||||
|
if let Ok(memory) = memory_result {
|
||||||
|
dict.insert("total", Value::bytes(memory.total().get::<information::byte>()));
|
||||||
|
dict.insert("free", Value::bytes(memory.free().get::<information::byte>()));
|
||||||
}
|
}
|
||||||
if let Ok(swap) = memory::swap().await {
|
|
||||||
dict.insert("swap total", Value::bytes(swap.total().get()));
|
if let Ok(swap) = swap_result {
|
||||||
dict.insert("swap free", Value::bytes(swap.free().get()));
|
dict.insert("swap total", Value::bytes(swap.total().get::<information::byte>()));
|
||||||
|
dict.insert("swap free", Value::bytes(swap.free().get::<information::byte>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
dict.into_tagged_value()
|
dict.into_tagged_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn host(tag: Tag) -> Tagged<Value> {
|
async fn host(tag: Tag) -> Tagged<Value> {
|
||||||
let mut dict = TaggedDictBuilder::new(tag);
|
let mut dict = TaggedDictBuilder::with_capacity(tag, 6);
|
||||||
|
|
||||||
|
let (platform_result, uptime_result) = futures::future::join(
|
||||||
|
host::platform(),
|
||||||
|
host::uptime(),
|
||||||
|
).await;
|
||||||
|
|
||||||
// OS
|
// OS
|
||||||
if let Ok(platform) = heim::host::platform().await {
|
if let Ok(platform) = platform_result {
|
||||||
dict.insert("name", Value::string(platform.system()));
|
dict.insert("name", Value::string(platform.system()));
|
||||||
dict.insert("release", Value::string(platform.release()));
|
dict.insert("release", Value::string(platform.release()));
|
||||||
dict.insert("hostname", Value::string(platform.hostname()));
|
dict.insert("hostname", Value::string(platform.hostname()));
|
||||||
@ -68,10 +83,10 @@ async fn host(tag: Tag) -> Tagged<Value> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Uptime
|
// Uptime
|
||||||
if let Ok(uptime) = heim::host::uptime().await {
|
if let Ok(uptime) = uptime_result {
|
||||||
let mut uptime_dict = TaggedDictBuilder::new(tag);
|
let mut uptime_dict = TaggedDictBuilder::with_capacity(tag, 4);
|
||||||
|
|
||||||
let uptime = uptime.get().round() as i64;
|
let uptime = uptime.get::<time::second>().round() as i64;
|
||||||
let days = uptime / (60 * 60 * 24);
|
let days = uptime / (60 * 60 * 24);
|
||||||
let hours = (uptime - days * 60 * 60 * 24) / (60 * 60);
|
let hours = (uptime - days * 60 * 60 * 24) / (60 * 60);
|
||||||
let minutes = (uptime - days * 60 * 60 * 24 - hours * 60 * 60) / 60;
|
let minutes = (uptime - days * 60 * 60 * 24 - hours * 60 * 60) / 60;
|
||||||
@ -82,11 +97,11 @@ async fn host(tag: Tag) -> Tagged<Value> {
|
|||||||
uptime_dict.insert("mins", Value::int(minutes));
|
uptime_dict.insert("mins", Value::int(minutes));
|
||||||
uptime_dict.insert("secs", Value::int(seconds));
|
uptime_dict.insert("secs", Value::int(seconds));
|
||||||
|
|
||||||
dict.insert_tagged("uptime", uptime_dict.into_tagged_value());
|
dict.insert_tagged("uptime", uptime_dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Users
|
// Users
|
||||||
let mut users = heim::host::users();
|
let mut users = host::users();
|
||||||
let mut user_vec = vec![];
|
let mut user_vec = vec![];
|
||||||
while let Some(user) = users.next().await {
|
while let Some(user) = users.next().await {
|
||||||
if let Ok(user) = user {
|
if let Ok(user) = user {
|
||||||
@ -104,7 +119,7 @@ async fn disks(tag: Tag) -> Option<Value> {
|
|||||||
let mut partitions = disk::partitions_physical();
|
let mut partitions = disk::partitions_physical();
|
||||||
while let Some(part) = partitions.next().await {
|
while let Some(part) = partitions.next().await {
|
||||||
if let Ok(part) = part {
|
if let Ok(part) = part {
|
||||||
let mut dict = TaggedDictBuilder::new(tag);
|
let mut dict = TaggedDictBuilder::with_capacity(tag, 6);
|
||||||
dict.insert(
|
dict.insert(
|
||||||
"device",
|
"device",
|
||||||
Value::string(
|
Value::string(
|
||||||
@ -116,16 +131,18 @@ async fn disks(tag: Tag) -> Option<Value> {
|
|||||||
|
|
||||||
dict.insert("type", Value::string(part.file_system().as_str()));
|
dict.insert("type", Value::string(part.file_system().as_str()));
|
||||||
dict.insert("mount", Value::string(part.mount_point().to_string_lossy()));
|
dict.insert("mount", Value::string(part.mount_point().to_string_lossy()));
|
||||||
|
|
||||||
if let Ok(usage) = disk::usage(part.mount_point().to_path_buf()).await {
|
if let Ok(usage) = disk::usage(part.mount_point().to_path_buf()).await {
|
||||||
dict.insert("total", Value::bytes(usage.total().get()));
|
dict.insert("total", Value::bytes(usage.total().get::<information::byte>()));
|
||||||
dict.insert("used", Value::bytes(usage.used().get()));
|
dict.insert("used", Value::bytes(usage.used().get::<information::byte>()));
|
||||||
dict.insert("free", Value::bytes(usage.free().get()));
|
dict.insert("free", Value::bytes(usage.free().get::<information::byte>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
output.push(dict.into_tagged_value());
|
output.push(dict.into_tagged_value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if output.len() > 0 {
|
if !output.is_empty() {
|
||||||
Some(Value::List(output))
|
Some(Value::List(output))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -167,57 +184,56 @@ async fn battery(tag: Tag) -> Option<Value> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if output.len() > 0 {
|
if !output.is_empty() {
|
||||||
Some(Value::List(output))
|
Some(Value::List(output))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: add back when heim releases new version
|
async fn temp(tag: Tag) -> Option<Value> {
|
||||||
// async fn temp(tag: Tag) -> Option<Value> {
|
let mut output = vec![];
|
||||||
// let mut output = vec![];
|
|
||||||
|
|
||||||
// let mut sensors = sensors::temperatures();
|
let mut sensors = sensors::temperatures();
|
||||||
// while let Some(sensor) = sensors.next().await {
|
while let Some(sensor) = sensors.next().await {
|
||||||
// if let Ok(sensor) = sensor {
|
if let Ok(sensor) = sensor {
|
||||||
// let mut dict = TaggedDictBuilder::new(tag);
|
let mut dict = TaggedDictBuilder::new(tag);
|
||||||
// dict.insert("unit", Value::string(sensor.unit()));
|
dict.insert("unit", Value::string(sensor.unit()));
|
||||||
// if let Some(label) = sensor.label() {
|
if let Some(label) = sensor.label() {
|
||||||
// dict.insert("label", Value::string(label));
|
dict.insert("label", Value::string(label));
|
||||||
// }
|
}
|
||||||
// dict.insert("temp", Value::float(sensor.current().get()));
|
dict.insert("temp", Value::float(sensor.current().get::<thermodynamic_temperature::degree_celsius>() as f64));
|
||||||
// if let Some(high) = sensor.high() {
|
if let Some(high) = sensor.high() {
|
||||||
// dict.insert("high", Value::float(high.get()));
|
dict.insert("high", Value::float(high.get::<thermodynamic_temperature::degree_celsius>() as f64));
|
||||||
// }
|
}
|
||||||
// if let Some(critical) = sensor.critical() {
|
if let Some(critical) = sensor.critical() {
|
||||||
// dict.insert("critical", Value::float(critical.get()));
|
dict.insert("critical", Value::float(critical.get::<thermodynamic_temperature::degree_celsius>() as f64));
|
||||||
// }
|
}
|
||||||
|
|
||||||
// output.push(dict.into_tagged_value());
|
output.push(dict.into_tagged_value());
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if output.len() > 0 {
|
if !output.is_empty() {
|
||||||
// Some(Value::List(output))
|
Some(Value::List(output))
|
||||||
// } else {
|
} else {
|
||||||
// None
|
None
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
async fn net(tag: Tag) -> Option<Value> {
|
async fn net(tag: Tag) -> Option<Value> {
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
let mut io_counters = net::io_counters();
|
let mut io_counters = net::io_counters();
|
||||||
while let Some(nic) = io_counters.next().await {
|
while let Some(nic) = io_counters.next().await {
|
||||||
if let Ok(nic) = nic {
|
if let Ok(nic) = nic {
|
||||||
let mut network_idx = TaggedDictBuilder::new(tag);
|
let mut network_idx = TaggedDictBuilder::with_capacity(tag, 3);
|
||||||
network_idx.insert("name", Value::string(nic.interface()));
|
network_idx.insert("name", Value::string(nic.interface()));
|
||||||
network_idx.insert("sent", Value::bytes(nic.bytes_sent().get()));
|
network_idx.insert("sent", Value::bytes(nic.bytes_sent().get::<information::byte>()));
|
||||||
network_idx.insert("recv", Value::bytes(nic.bytes_recv().get()));
|
network_idx.insert("recv", Value::bytes(nic.bytes_recv().get::<information::byte>()));
|
||||||
output.push(network_idx.into_tagged_value());
|
output.push(network_idx.into_tagged_value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if output.len() > 0 {
|
if !output.is_empty() {
|
||||||
Some(Value::List(output))
|
Some(Value::List(output))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -225,23 +241,35 @@ async fn net(tag: Tag) -> Option<Value> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn sysinfo(tag: Tag) -> Vec<Tagged<Value>> {
|
async fn sysinfo(tag: Tag) -> Vec<Tagged<Value>> {
|
||||||
let mut sysinfo = TaggedDictBuilder::new(tag);
|
let mut sysinfo = TaggedDictBuilder::with_capacity(tag, 7);
|
||||||
|
|
||||||
|
let (host, cpu, disks, memory, temp) = futures::future::join5(
|
||||||
|
host(tag),
|
||||||
|
cpu(tag),
|
||||||
|
disks(tag),
|
||||||
|
mem(tag),
|
||||||
|
temp(tag),
|
||||||
|
).await;
|
||||||
|
let (net, battery) = futures::future::join(
|
||||||
|
net(tag),
|
||||||
|
battery(tag),
|
||||||
|
).await;
|
||||||
|
|
||||||
sysinfo.insert_tagged("host", host(tag).await);
|
sysinfo.insert_tagged("host", host);
|
||||||
if let Some(cpu) = cpu(tag).await {
|
if let Some(cpu) = cpu {
|
||||||
sysinfo.insert_tagged("cpu", cpu);
|
sysinfo.insert_tagged("cpu", cpu);
|
||||||
}
|
}
|
||||||
if let Some(disks) = disks(tag).await {
|
if let Some(disks) = disks {
|
||||||
sysinfo.insert("disks", disks);
|
sysinfo.insert("disks", disks);
|
||||||
}
|
}
|
||||||
sysinfo.insert_tagged("mem", mem(tag).await);
|
sysinfo.insert_tagged("mem", memory);
|
||||||
// if let Some(temp) = temp(tag).await {
|
if let Some(temp) = temp {
|
||||||
// sysinfo.insert("temp", temp);
|
sysinfo.insert("temp", temp);
|
||||||
// }
|
}
|
||||||
if let Some(net) = net(tag).await {
|
if let Some(net) = net {
|
||||||
sysinfo.insert("net", net);
|
sysinfo.insert("net", net);
|
||||||
}
|
}
|
||||||
if let Some(battery) = battery(tag).await {
|
if let Some(battery) = battery {
|
||||||
sysinfo.insert("battery", battery);
|
sysinfo.insert("battery", battery);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +284,7 @@ impl Plugin for Sys {
|
|||||||
fn begin_filter(&mut self, callinfo: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
|
fn begin_filter(&mut self, callinfo: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
|
||||||
Ok(block_on(sysinfo(Tag::unknown_origin(callinfo.name_span)))
|
Ok(block_on(sysinfo(Tag::unknown_origin(callinfo.name_span)))
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x| ReturnSuccess::value(x))
|
.map(ReturnSuccess::value)
|
||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,13 +54,25 @@ fn paint_textview(
|
|||||||
match command {
|
match command {
|
||||||
DrawCommand::DrawString(style, string) => {
|
DrawCommand::DrawString(style, string) => {
|
||||||
for chr in string.chars() {
|
for chr in string.chars() {
|
||||||
frame_buffer.push((
|
if chr == '\t' {
|
||||||
chr,
|
for _ in 0..8 {
|
||||||
style.foreground.r,
|
frame_buffer.push((
|
||||||
style.foreground.g,
|
' ',
|
||||||
style.foreground.b,
|
style.foreground.r,
|
||||||
));
|
style.foreground.g,
|
||||||
pos += 1;
|
style.foreground.b,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
pos += 8;
|
||||||
|
} else {
|
||||||
|
frame_buffer.push((
|
||||||
|
chr,
|
||||||
|
style.foreground.r,
|
||||||
|
style.foreground.g,
|
||||||
|
style.foreground.b,
|
||||||
|
));
|
||||||
|
pos += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DrawCommand::NextLine => {
|
DrawCommand::NextLine => {
|
||||||
|
@ -47,37 +47,38 @@ macro_rules! trace_out_stream {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
crate use crate::cli::MaybeOwned;
|
pub(crate) use crate::cli::MaybeOwned;
|
||||||
crate use crate::commands::command::{
|
pub(crate) use crate::commands::command::{
|
||||||
CallInfo, CommandAction, CommandArgs, ReturnSuccess, ReturnValue, RunnableContext,
|
CallInfo, CommandAction, CommandArgs, ReturnSuccess, ReturnValue, RunnableContext,
|
||||||
};
|
};
|
||||||
crate use crate::commands::{PerItemCommand, RawCommandArgs};
|
pub(crate) use crate::commands::PerItemCommand;
|
||||||
crate use crate::context::CommandRegistry;
|
pub(crate) use crate::commands::RawCommandArgs;
|
||||||
crate use crate::context::{Context, SpanSource};
|
pub(crate) use crate::context::CommandRegistry;
|
||||||
crate use crate::env::host::handle_unexpected;
|
pub(crate) use crate::context::{Context, SpanSource};
|
||||||
crate use crate::env::Host;
|
pub(crate) use crate::env::host::handle_unexpected;
|
||||||
crate use crate::errors::ShellError;
|
pub(crate) use crate::env::Host;
|
||||||
crate use crate::object::base as value;
|
pub(crate) use crate::errors::ShellError;
|
||||||
crate use crate::object::meta::{Tag, Tagged, TaggedItem};
|
pub(crate) use crate::object::base as value;
|
||||||
crate use crate::object::types::ExtractType;
|
pub(crate) use crate::object::meta::{Tag, Tagged, TaggedItem};
|
||||||
crate use crate::object::{Primitive, Value};
|
pub(crate) use crate::object::types::ExtractType;
|
||||||
crate use crate::parser::hir::SyntaxType;
|
pub(crate) use crate::object::{Primitive, Value};
|
||||||
crate use crate::parser::registry::Signature;
|
pub(crate) use crate::parser::hir::SyntaxType;
|
||||||
crate use crate::shell::filesystem_shell::FilesystemShell;
|
pub(crate) use crate::parser::registry::Signature;
|
||||||
crate use crate::shell::shell_manager::ShellManager;
|
pub(crate) use crate::shell::filesystem_shell::FilesystemShell;
|
||||||
crate use crate::shell::value_shell::ValueShell;
|
pub(crate) use crate::shell::shell_manager::ShellManager;
|
||||||
crate use crate::stream::{InputStream, OutputStream};
|
pub(crate) use crate::shell::value_shell::ValueShell;
|
||||||
crate use crate::traits::{HasSpan, ToDebug};
|
pub(crate) use crate::stream::{InputStream, OutputStream};
|
||||||
crate use crate::Span;
|
pub(crate) use crate::traits::{HasSpan, ToDebug};
|
||||||
crate use crate::Text;
|
pub(crate) use crate::Span;
|
||||||
crate use futures::stream::BoxStream;
|
pub(crate) use crate::Text;
|
||||||
crate use futures::{FutureExt, Stream, StreamExt};
|
pub(crate) use futures::stream::BoxStream;
|
||||||
crate use futures_async_stream::async_stream_block;
|
pub(crate) use futures::{FutureExt, Stream, StreamExt};
|
||||||
|
pub(crate) use futures_async_stream::async_stream_block;
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
crate use serde::{Deserialize, Serialize};
|
pub(crate) use serde::{Deserialize, Serialize};
|
||||||
crate use std::collections::VecDeque;
|
pub(crate) use std::collections::VecDeque;
|
||||||
crate use std::future::Future;
|
pub(crate) use std::future::Future;
|
||||||
crate use std::sync::{Arc, Mutex};
|
pub(crate) use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
pub trait FromInputStream {
|
pub trait FromInputStream {
|
||||||
fn from_input_stream(self) -> OutputStream;
|
fn from_input_stream(self) -> OutputStream;
|
||||||
|
14
src/shell.rs
14
src/shell.rs
@ -1,8 +1,8 @@
|
|||||||
crate mod completer;
|
pub(crate) mod completer;
|
||||||
crate mod filesystem_shell;
|
pub(crate) mod filesystem_shell;
|
||||||
crate mod helper;
|
pub(crate) mod helper;
|
||||||
crate mod shell;
|
pub(crate) mod shell;
|
||||||
crate mod shell_manager;
|
pub(crate) mod shell_manager;
|
||||||
crate mod value_shell;
|
pub(crate) mod value_shell;
|
||||||
|
|
||||||
crate use helper::Helper;
|
pub(crate) use helper::Helper;
|
||||||
|
@ -3,7 +3,7 @@ use derive_new::new;
|
|||||||
use rustyline::completion::{Completer, FilenameCompleter};
|
use rustyline::completion::{Completer, FilenameCompleter};
|
||||||
|
|
||||||
#[derive(new)]
|
#[derive(new)]
|
||||||
crate struct NuCompleter {
|
pub(crate) struct NuCompleter {
|
||||||
pub file_completer: FilenameCompleter,
|
pub file_completer: FilenameCompleter,
|
||||||
pub commands: CommandRegistry,
|
pub commands: CommandRegistry,
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ use rustyline::hint::{Hinter, HistoryHinter};
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
pub struct FilesystemShell {
|
pub struct FilesystemShell {
|
||||||
crate path: String,
|
pub(crate) path: String,
|
||||||
completer: NuCompleter,
|
completer: NuCompleter,
|
||||||
hinter: HistoryHinter,
|
hinter: HistoryHinter,
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,12 @@ use rustyline::highlight::Highlighter;
|
|||||||
use rustyline::hint::Hinter;
|
use rustyline::hint::Hinter;
|
||||||
use std::borrow::Cow::{self, Owned};
|
use std::borrow::Cow::{self, Owned};
|
||||||
|
|
||||||
crate struct Helper {
|
pub(crate) struct Helper {
|
||||||
helper: ShellManager,
|
helper: ShellManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Helper {
|
impl Helper {
|
||||||
crate fn new(helper: ShellManager) -> Helper {
|
pub(crate) fn new(helper: ShellManager) -> Helper {
|
||||||
Helper { helper }
|
Helper { helper }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,8 @@ use std::sync::{Arc, Mutex};
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ShellManager {
|
pub struct ShellManager {
|
||||||
crate current_shell: usize,
|
pub(crate) current_shell: usize,
|
||||||
crate shells: Arc<Mutex<Vec<Box<dyn Shell + Send>>>>,
|
pub(crate) shells: Arc<Mutex<Vec<Box<dyn Shell + Send>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShellManager {
|
impl ShellManager {
|
||||||
|
@ -11,8 +11,8 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ValueShell {
|
pub struct ValueShell {
|
||||||
crate path: String,
|
pub(crate) path: String,
|
||||||
crate value: Tagged<Value>,
|
pub(crate) value: Tagged<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValueShell {
|
impl ValueShell {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub struct InputStream {
|
pub struct InputStream {
|
||||||
crate values: BoxStream<'static, Tagged<Value>>,
|
pub(crate) values: BoxStream<'static, Tagged<Value>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputStream {
|
impl InputStream {
|
||||||
@ -49,7 +49,7 @@ impl From<Vec<Tagged<Value>>> for InputStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct OutputStream {
|
pub struct OutputStream {
|
||||||
crate values: BoxStream<'static, ReturnValue>,
|
pub(crate) values: BoxStream<'static, ReturnValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OutputStream {
|
impl OutputStream {
|
||||||
|
@ -6,7 +6,7 @@ pub struct Debuggable<'a, T: ToDebug> {
|
|||||||
source: &'a str,
|
source: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ToDebug> fmt::Display for Debuggable<'a, T> {
|
impl<T: ToDebug> fmt::Display for Debuggable<'_, T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
self.inner.fmt_debug(f, self.source)
|
self.inner.fmt_debug(f, self.source)
|
||||||
}
|
}
|
||||||
@ -17,7 +17,7 @@ pub trait HasSpan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait ToDebug: Sized {
|
pub trait ToDebug: Sized {
|
||||||
fn debug(&'a self, source: &'a str) -> Debuggable<'a, Self> {
|
fn debug<'a>(&'a self, source: &'a str) -> Debuggable<'a, Self> {
|
||||||
Debuggable {
|
Debuggable {
|
||||||
inner: self,
|
inner: self,
|
||||||
source,
|
source,
|
||||||
|
@ -185,7 +185,7 @@ impl FileStructure {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build(&mut self, src: &'a Path, lvl: usize) -> Result<(), ShellError> {
|
fn build(&mut self, src: &Path, lvl: usize) -> Result<(), ShellError> {
|
||||||
let source = dunce::canonicalize(src)?;
|
let source = dunce::canonicalize(src)?;
|
||||||
|
|
||||||
if source.is_dir() {
|
if source.is_dir() {
|
||||||
@ -250,6 +250,10 @@ mod tests {
|
|||||||
loc: fixtures().join("caco3_plastics.csv"),
|
loc: fixtures().join("caco3_plastics.csv"),
|
||||||
at: 0
|
at: 0
|
||||||
},
|
},
|
||||||
|
Res {
|
||||||
|
loc: fixtures().join("caco3_plastics.tsv"),
|
||||||
|
at: 0
|
||||||
|
},
|
||||||
Res {
|
Res {
|
||||||
loc: fixtures().join("cargo_sample.toml"),
|
loc: fixtures().join("cargo_sample.toml"),
|
||||||
at: 0
|
at: 0
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use helpers::in_directory as cwd;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cd_directory_not_found() {
|
fn cd_directory_not_found() {
|
||||||
let actual = nu_error!(cwd("tests/fixtures"), "cd dir_that_does_not_exist");
|
let actual = nu_error!(
|
||||||
|
cwd: "tests/fixtures",
|
||||||
|
"cd dir_that_does_not_exist"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(actual.contains("dir_that_does_not_exist"));
|
assert!(actual.contains("dir_that_does_not_exist"));
|
||||||
assert!(actual.contains("directory not found"));
|
assert!(actual.contains("directory not found"));
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use helpers::{in_directory as cwd, dir_exists_at, file_exists_at, files_exist_at, Playground, Stub::*};
|
|
||||||
use nu::AbsoluteFile;
|
use nu::AbsoluteFile;
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
use helpers::{files_exist_at, Playground, Stub::*};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn copies_a_file() {
|
fn copies_a_file() {
|
||||||
Playground::setup("cp_test_1", |dirs, _| {
|
Playground::setup("cp_test_1", |dirs, _| {
|
||||||
nu!(
|
nu!(
|
||||||
cwd(dirs.root()),
|
cwd: dirs.root(),
|
||||||
"cp {} cp_test_1/sample.ini",
|
"cp {} cp_test_1/sample.ini",
|
||||||
dirs.formats().join("sample.ini")
|
dirs.formats().join("sample.ini")
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(file_exists_at(dirs.test().join("sample.ini")));
|
assert!(dirs.test().join("sample.ini").exists());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,19 +24,22 @@ fn copies_the_file_inside_directory_if_path_to_copy_is_directory() {
|
|||||||
let expected_file = AbsoluteFile::new(dirs.test().join("sample.ini"));
|
let expected_file = AbsoluteFile::new(dirs.test().join("sample.ini"));
|
||||||
|
|
||||||
nu!(
|
nu!(
|
||||||
cwd(dirs.formats()),
|
cwd: dirs.formats(),
|
||||||
"cp ../formats/sample.ini {}",
|
"cp ../formats/sample.ini {}",
|
||||||
expected_file.dir()
|
expected_file.dir()
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(file_exists_at(dirs.test().join("sample.ini")));
|
assert!(dirs.test().join("sample.ini").exists());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn error_if_attempting_to_copy_a_directory_to_another_directory() {
|
fn error_if_attempting_to_copy_a_directory_to_another_directory() {
|
||||||
Playground::setup("cp_test_3", |dirs, _| {
|
Playground::setup("cp_test_3", |dirs, _| {
|
||||||
let actual = nu_error!(dirs.formats(), "cp ../formats {}", dirs.test());
|
let actual = nu_error!(
|
||||||
|
cwd: dirs.formats(),
|
||||||
|
"cp ../formats {}", dirs.test()
|
||||||
|
);
|
||||||
|
|
||||||
assert!(actual.contains("../formats"));
|
assert!(actual.contains("../formats"));
|
||||||
assert!(actual.contains("is a directory (not copied)"));
|
assert!(actual.contains("is a directory (not copied)"));
|
||||||
@ -56,40 +60,25 @@ fn copies_the_directory_inside_directory_if_path_to_copy_is_directory_and_with_r
|
|||||||
|
|
||||||
let expected_dir = dirs.test().join("expected").join("originals");
|
let expected_dir = dirs.test().join("expected").join("originals");
|
||||||
|
|
||||||
nu!(cwd(dirs.test()), "cp originals expected --recursive");
|
nu!(
|
||||||
|
cwd: dirs.test(),
|
||||||
|
"cp originals expected --recursive"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(dir_exists_at(PathBuf::from(&expected_dir)));
|
assert!(expected_dir.exists());
|
||||||
assert!(files_exist_at(
|
assert!(files_exist_at(
|
||||||
vec![
|
vec![
|
||||||
Path::new("yehuda.txt"),
|
Path::new("yehuda.txt"),
|
||||||
Path::new("jonathan.txt"),
|
Path::new("jonathan.txt"),
|
||||||
Path::new("andres.txt")
|
Path::new("andres.txt")
|
||||||
],
|
],
|
||||||
PathBuf::from(&expected_dir)
|
expected_dir
|
||||||
));
|
));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn deep_copies_with_recursive_flag() {
|
fn deep_copies_with_recursive_flag() {
|
||||||
r#"
|
|
||||||
Given these files and directories
|
|
||||||
originals
|
|
||||||
originals/manifest.txt
|
|
||||||
originals/contributors
|
|
||||||
originals/contributors/yehuda.txt
|
|
||||||
originals/contributors/jonathan.txt
|
|
||||||
originals/contributors/andres.txt
|
|
||||||
originals/contributors/jonathan
|
|
||||||
originals/contributors/jonathan/errors.txt
|
|
||||||
originals/contributors/jonathan/multishells.txt
|
|
||||||
originals/contributors/andres
|
|
||||||
originals/contributors/andres/coverage.txt
|
|
||||||
originals/contributors/andres/commands.txt
|
|
||||||
originals/contributors/yehuda
|
|
||||||
originals/contributors/yehuda/defer-evaluation.txt
|
|
||||||
"#;
|
|
||||||
|
|
||||||
Playground::setup("cp_test_5", |dirs, sandbox| {
|
Playground::setup("cp_test_5", |dirs, sandbox| {
|
||||||
sandbox
|
sandbox
|
||||||
.within("originals")
|
.within("originals")
|
||||||
@ -114,20 +103,23 @@ fn deep_copies_with_recursive_flag() {
|
|||||||
let andres_expected_copied_dir = expected_dir.join("contributors").join("andres");
|
let andres_expected_copied_dir = expected_dir.join("contributors").join("andres");
|
||||||
let yehudas_expected_copied_dir = expected_dir.join("contributors").join("yehuda");
|
let yehudas_expected_copied_dir = expected_dir.join("contributors").join("yehuda");
|
||||||
|
|
||||||
nu!(cwd(dirs.test()), "cp originals expected --recursive");
|
nu!(
|
||||||
|
cwd: dirs.test(),
|
||||||
|
"cp originals expected --recursive"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(dir_exists_at(PathBuf::from(&expected_dir)));
|
assert!(expected_dir.exists());
|
||||||
assert!(files_exist_at(
|
assert!(files_exist_at(
|
||||||
vec![Path::new("errors.txt"), Path::new("multishells.txt")],
|
vec![Path::new("errors.txt"), Path::new("multishells.txt")],
|
||||||
PathBuf::from(&jonathans_expected_copied_dir)
|
jonathans_expected_copied_dir
|
||||||
));
|
));
|
||||||
assert!(files_exist_at(
|
assert!(files_exist_at(
|
||||||
vec![Path::new("coverage.txt"), Path::new("commands.txt")],
|
vec![Path::new("coverage.txt"), Path::new("commands.txt")],
|
||||||
PathBuf::from(&andres_expected_copied_dir)
|
andres_expected_copied_dir
|
||||||
));
|
));
|
||||||
assert!(files_exist_at(
|
assert!(files_exist_at(
|
||||||
vec![Path::new("defer-evaluation.txt")],
|
vec![Path::new("defer-evaluation.txt")],
|
||||||
PathBuf::from(&yehudas_expected_copied_dir)
|
yehudas_expected_copied_dir
|
||||||
));
|
));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -135,7 +127,10 @@ fn deep_copies_with_recursive_flag() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn copies_using_path_with_wildcard() {
|
fn copies_using_path_with_wildcard() {
|
||||||
Playground::setup("cp_test_6", |dirs, _| {
|
Playground::setup("cp_test_6", |dirs, _| {
|
||||||
nu!(cwd(dirs.formats()), "cp ../formats/* {}", dirs.test());
|
nu!(
|
||||||
|
cwd: dirs.formats(),
|
||||||
|
"cp ../formats/* {}", dirs.test()
|
||||||
|
);
|
||||||
|
|
||||||
assert!(files_exist_at(
|
assert!(files_exist_at(
|
||||||
vec![
|
vec![
|
||||||
@ -154,7 +149,10 @@ fn copies_using_path_with_wildcard() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn copies_using_a_glob() {
|
fn copies_using_a_glob() {
|
||||||
Playground::setup("cp_test_7", |dirs, _| {
|
Playground::setup("cp_test_7", |dirs, _| {
|
||||||
nu!(cwd(dirs.formats()), "cp * {}", dirs.test());
|
nu!(
|
||||||
|
cwd: dirs.formats(),
|
||||||
|
"cp * {}", dirs.test()
|
||||||
|
);
|
||||||
|
|
||||||
assert!(files_exist_at(
|
assert!(files_exist_at(
|
||||||
vec![
|
vec![
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use h::{in_directory as cwd, Playground, Stub::*};
|
|
||||||
use helpers as h;
|
use helpers as h;
|
||||||
use std::path::{Path, PathBuf};
|
use helpers::{Playground, Stub::*};
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn knows_the_filesystems_entered() {
|
fn knows_the_filesystems_entered() {
|
||||||
@ -28,47 +29,47 @@ fn knows_the_filesystems_entered() {
|
|||||||
let expected_recycled = expected.join("recycled");
|
let expected_recycled = expected.join("recycled");
|
||||||
|
|
||||||
nu!(
|
nu!(
|
||||||
cwd(dirs.test()),
|
cwd: dirs.test(),
|
||||||
r#"
|
r#"
|
||||||
enter expected
|
enter expected
|
||||||
mkdir recycled
|
mkdir recycled
|
||||||
enter ../red_pill
|
enter ../red_pill
|
||||||
mv jonathan.nu ../expected
|
mv jonathan.nu ../expected
|
||||||
enter ../blue_pill
|
enter ../blue_pill
|
||||||
cp *.nxt ../expected/recycled
|
cp *.nxt ../expected/recycled
|
||||||
p
|
p
|
||||||
p
|
p
|
||||||
mv ../red_pill/yehuda.nu .
|
mv ../red_pill/yehuda.nu .
|
||||||
n
|
n
|
||||||
mv andres.nu ../expected/andres.nu
|
mv andres.nu ../expected/andres.nu
|
||||||
exit
|
exit
|
||||||
cd ..
|
cd ..
|
||||||
rm red_pill --recursive
|
rm red_pill --recursive
|
||||||
exit
|
exit
|
||||||
n
|
n
|
||||||
rm blue_pill --recursive
|
rm blue_pill --recursive
|
||||||
exit
|
exit
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(!h::dir_exists_at(PathBuf::from(red_pill_dir)));
|
assert!(!red_pill_dir.exists());
|
||||||
assert!(h::files_exist_at(
|
assert!(h::files_exist_at(
|
||||||
vec![
|
vec![
|
||||||
Path::new("andres.nu"),
|
Path::new("andres.nu"),
|
||||||
Path::new("jonathan.nu"),
|
Path::new("jonathan.nu"),
|
||||||
Path::new("yehuda.nu"),
|
Path::new("yehuda.nu"),
|
||||||
],
|
],
|
||||||
PathBuf::from(&expected)
|
expected
|
||||||
));
|
));
|
||||||
|
|
||||||
assert!(!h::dir_exists_at(PathBuf::from(blue_pill_dir)));
|
assert!(!blue_pill_dir.exists());
|
||||||
assert!(h::files_exist_at(
|
assert!(h::files_exist_at(
|
||||||
vec![
|
vec![
|
||||||
Path::new("bash.nxt"),
|
Path::new("bash.nxt"),
|
||||||
Path::new("korn.nxt"),
|
Path::new("korn.nxt"),
|
||||||
Path::new("powedsh.nxt"),
|
Path::new("powedsh.nxt"),
|
||||||
],
|
],
|
||||||
PathBuf::from(&expected_recycled)
|
expected_recycled
|
||||||
));
|
));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use h::{in_directory as cwd, Playground, Stub::*};
|
|
||||||
use helpers as h;
|
use helpers as h;
|
||||||
|
use helpers::{Playground, Stub::*};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ls_lists_regular_files() {
|
fn ls_lists_regular_files() {
|
||||||
@ -14,17 +14,17 @@ fn ls_lists_regular_files() {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()), h::pipeline(
|
cwd: dirs.test(), h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
ls
|
ls
|
||||||
| get name
|
| get name
|
||||||
| lines
|
| lines
|
||||||
| split-column "."
|
| split-column "."
|
||||||
| get Column2
|
| get Column2
|
||||||
| str --to-int
|
| str --to-int
|
||||||
| sum
|
| sum
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
assert_eq!(actual, "30");
|
assert_eq!(actual, "30");
|
||||||
@ -43,17 +43,17 @@ fn ls_lists_regular_files_using_asterisk_wildcard() {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()), h::pipeline(
|
cwd: dirs.test(), h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
ls *.txt
|
ls *.txt
|
||||||
| get name
|
| get name
|
||||||
| lines
|
| lines
|
||||||
| split-column "."
|
| split-column "."
|
||||||
| get Column2
|
| get Column2
|
||||||
| str --to-int
|
| str --to-int
|
||||||
| sum
|
| sum
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
assert_eq!(actual, "3");
|
assert_eq!(actual, "3");
|
||||||
@ -72,17 +72,17 @@ fn ls_lists_regular_files_using_question_mark_wildcard() {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()), h::pipeline(
|
cwd: dirs.test(), h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
ls *.??.txt
|
ls *.??.txt
|
||||||
| get name
|
| get name
|
||||||
| lines
|
| lines
|
||||||
| split-column "."
|
| split-column "."
|
||||||
| get Column2
|
| get Column2
|
||||||
| str --to-int
|
| str --to-int
|
||||||
| sum
|
| sum
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
assert_eq!(actual, "30");
|
assert_eq!(actual, "30");
|
||||||
|
@ -1,24 +1,31 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use h::{in_directory as cwd, Playground};
|
|
||||||
use helpers as h;
|
use helpers as h;
|
||||||
use std::path::{Path, PathBuf};
|
use helpers::Playground;
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn creates_directory() {
|
fn creates_directory() {
|
||||||
Playground::setup("mkdir_test_1", |dirs, _| {
|
Playground::setup("mkdir_test_1", |dirs, _| {
|
||||||
nu!(cwd(dirs.test()), "mkdir my_new_directory");
|
nu!(
|
||||||
|
cwd: dirs.test(),
|
||||||
|
"mkdir my_new_directory"
|
||||||
|
);
|
||||||
|
|
||||||
let expected = dirs.test().join("my_new_directory");
|
let expected = dirs.test().join("my_new_directory");
|
||||||
|
|
||||||
assert!(h::dir_exists_at(expected));
|
assert!(expected.exists());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn accepts_and_creates_directories() {
|
fn accepts_and_creates_directories() {
|
||||||
Playground::setup("mkdir_test_2", |dirs, _| {
|
Playground::setup("mkdir_test_2", |dirs, _| {
|
||||||
nu!(cwd(dirs.test()), "mkdir dir_1 dir_2 dir_3");
|
nu!(
|
||||||
|
cwd: dirs.test(),
|
||||||
|
"mkdir dir_1 dir_2 dir_3"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(h::files_exist_at(
|
assert!(h::files_exist_at(
|
||||||
vec![Path::new("dir_1"), Path::new("dir_2"), Path::new("dir_3")],
|
vec![Path::new("dir_1"), Path::new("dir_2"), Path::new("dir_3")],
|
||||||
@ -30,11 +37,13 @@ fn accepts_and_creates_directories() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn creates_intermediary_directories() {
|
fn creates_intermediary_directories() {
|
||||||
Playground::setup("mkdir_test_3", |dirs, _| {
|
Playground::setup("mkdir_test_3", |dirs, _| {
|
||||||
nu!(cwd(dirs.test()), "mkdir some_folder/another/deeper_one");
|
nu!(
|
||||||
|
cwd: dirs.test(),
|
||||||
|
"mkdir some_folder/another/deeper_one"
|
||||||
|
);
|
||||||
|
|
||||||
let mut expected = PathBuf::from(dirs.test());
|
let expected = dirs.test().join("some_folder/another/deeper_one");
|
||||||
expected.push("some_folder/another/deeper_one");
|
|
||||||
|
|
||||||
assert!(h::dir_exists_at(expected));
|
assert!(expected.exists());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use h::{in_directory as cwd, Playground, Stub::*};
|
|
||||||
use helpers as h;
|
use helpers as h;
|
||||||
|
use helpers::{Playground, Stub::*};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn moves_a_file() {
|
fn moves_a_file() {
|
||||||
@ -13,10 +13,13 @@ fn moves_a_file() {
|
|||||||
let original = dirs.test().join("andres.txt");
|
let original = dirs.test().join("andres.txt");
|
||||||
let expected = dirs.test().join("expected/yehuda.txt");
|
let expected = dirs.test().join("expected/yehuda.txt");
|
||||||
|
|
||||||
nu!(cwd(dirs.test()), "mv andres.txt expected/yehuda.txt");
|
nu!(
|
||||||
|
cwd: dirs.test(),
|
||||||
|
"mv andres.txt expected/yehuda.txt"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(!h::file_exists_at(original));
|
assert!(!original.exists());
|
||||||
assert!(h::file_exists_at(expected));
|
assert!(expected.exists());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,10 +35,13 @@ fn overwrites_if_moving_to_existing_file() {
|
|||||||
let original = dirs.test().join("andres.txt");
|
let original = dirs.test().join("andres.txt");
|
||||||
let expected = dirs.test().join("jonathan.txt");
|
let expected = dirs.test().join("jonathan.txt");
|
||||||
|
|
||||||
nu!(cwd(dirs.test()), "mv andres.txt jonathan.txt");
|
nu!(
|
||||||
|
cwd: dirs.test(),
|
||||||
|
"mv andres.txt jonathan.txt"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(!h::file_exists_at(original));
|
assert!(!original.exists());
|
||||||
assert!(h::file_exists_at(expected));
|
assert!(expected.exists());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,10 +53,13 @@ fn moves_a_directory() {
|
|||||||
let original_dir = dirs.test().join("empty_dir");
|
let original_dir = dirs.test().join("empty_dir");
|
||||||
let expected = dirs.test().join("renamed_dir");
|
let expected = dirs.test().join("renamed_dir");
|
||||||
|
|
||||||
nu!(cwd(dirs.test()), "mv empty_dir renamed_dir");
|
nu!(
|
||||||
|
cwd: dirs.test(),
|
||||||
|
"mv empty_dir renamed_dir"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(!h::dir_exists_at(original_dir));
|
assert!(!original_dir.exists());
|
||||||
assert!(h::dir_exists_at(expected));
|
assert!(expected.exists());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,10 +73,13 @@ fn moves_the_file_inside_directory_if_path_to_move_is_existing_directory() {
|
|||||||
let original_dir = dirs.test().join("jonathan.txt");
|
let original_dir = dirs.test().join("jonathan.txt");
|
||||||
let expected = dirs.test().join("expected/jonathan.txt");
|
let expected = dirs.test().join("expected/jonathan.txt");
|
||||||
|
|
||||||
nu!(dirs.test(), "mv jonathan.txt expected");
|
nu!(
|
||||||
|
cwd: dirs.test(),
|
||||||
|
"mv jonathan.txt expected"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(!h::file_exists_at(original_dir));
|
assert!(!original_dir.exists());
|
||||||
assert!(h::file_exists_at(expected));
|
assert!(expected.exists());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,10 +94,13 @@ fn moves_the_directory_inside_directory_if_path_to_move_is_existing_directory()
|
|||||||
let original_dir = dirs.test().join("contributors");
|
let original_dir = dirs.test().join("contributors");
|
||||||
let expected = dirs.test().join("expected/contributors");
|
let expected = dirs.test().join("expected/contributors");
|
||||||
|
|
||||||
nu!(dirs.test(), "mv contributors expected");
|
nu!(
|
||||||
|
cwd: dirs.test(),
|
||||||
|
"mv contributors expected"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(!h::dir_exists_at(original_dir));
|
assert!(!original_dir.exists());
|
||||||
assert!(h::file_exists_at(expected));
|
assert!(expected.exists());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +115,7 @@ fn moves_the_directory_inside_directory_if_path_to_move_is_nonexistent_directory
|
|||||||
let original_dir = dirs.test().join("contributors");
|
let original_dir = dirs.test().join("contributors");
|
||||||
|
|
||||||
nu!(
|
nu!(
|
||||||
cwd(dirs.test()),
|
cwd: dirs.test(),
|
||||||
"mv contributors expected/this_dir_exists_now/los_tres_amigos"
|
"mv contributors expected/this_dir_exists_now/los_tres_amigos"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -108,8 +123,8 @@ fn moves_the_directory_inside_directory_if_path_to_move_is_nonexistent_directory
|
|||||||
.test()
|
.test()
|
||||||
.join("expected/this_dir_exists_now/los_tres_amigos");
|
.join("expected/this_dir_exists_now/los_tres_amigos");
|
||||||
|
|
||||||
assert!(!h::dir_exists_at(original_dir));
|
assert!(!original_dir.exists());
|
||||||
assert!(h::file_exists_at(expected));
|
assert!(expected.exists());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +150,10 @@ fn moves_using_path_with_wildcard() {
|
|||||||
let work_dir = dirs.test().join("work_dir");
|
let work_dir = dirs.test().join("work_dir");
|
||||||
let expected = dirs.test().join("expected");
|
let expected = dirs.test().join("expected");
|
||||||
|
|
||||||
nu!(cwd(work_dir), "mv ../originals/*.ini ../expected");
|
nu!(
|
||||||
|
cwd: work_dir,
|
||||||
|
"mv ../originals/*.ini ../expected"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(h::files_exist_at(
|
assert!(h::files_exist_at(
|
||||||
vec!["yehuda.ini", "jonathan.ini", "sample.ini", "andres.ini",],
|
vec!["yehuda.ini", "jonathan.ini", "sample.ini", "andres.ini",],
|
||||||
@ -161,9 +179,12 @@ fn moves_using_a_glob() {
|
|||||||
let work_dir = dirs.test().join("work_dir");
|
let work_dir = dirs.test().join("work_dir");
|
||||||
let expected = dirs.test().join("expected");
|
let expected = dirs.test().join("expected");
|
||||||
|
|
||||||
nu!(cwd(work_dir), "mv ../meals/* ../expected");
|
nu!(
|
||||||
|
cwd: work_dir,
|
||||||
|
"mv ../meals/* ../expected"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(h::dir_exists_at(meal_dir));
|
assert!(meal_dir.exists());
|
||||||
assert!(h::files_exist_at(
|
assert!(h::files_exist_at(
|
||||||
vec!["arepa.txt", "empanada.txt", "taquiza.txt",],
|
vec!["arepa.txt", "empanada.txt", "taquiza.txt",],
|
||||||
expected
|
expected
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use helpers::{in_directory as cwd, Playground, Stub::*};
|
|
||||||
use helpers as h;
|
use helpers as h;
|
||||||
|
use helpers::{Playground, Stub::*};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn recognizes_csv() {
|
fn recognizes_csv() {
|
||||||
@ -18,7 +18,7 @@ fn recognizes_csv() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()), h::pipeline(
|
cwd: dirs.test(), h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open nu.zion.csv
|
open nu.zion.csv
|
||||||
| where author == "Andres N. Robalino"
|
| where author == "Andres N. Robalino"
|
||||||
@ -34,7 +34,7 @@ fn recognizes_csv() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn open_can_parse_bson_1() {
|
fn open_can_parse_bson_1() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats",
|
||||||
"open sample.bson | get root | nth 0 | get b | echo $it"
|
"open sample.bson | get root | nth 0 | get b | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -44,16 +44,16 @@ fn open_can_parse_bson_1() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn open_can_parse_bson_2() {
|
fn open_can_parse_bson_2() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"), h::pipeline(
|
cwd: "tests/fixtures/formats", h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open sample.bson
|
open sample.bson
|
||||||
| get root
|
| get root
|
||||||
| nth 6
|
| nth 6
|
||||||
| get b
|
| get b
|
||||||
| get '$binary_subtype'
|
| get '$binary_subtype'
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
assert_eq!(actual, "function");
|
assert_eq!(actual, "function");
|
||||||
}
|
}
|
||||||
@ -61,17 +61,32 @@ fn open_can_parse_bson_2() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn open_can_parse_toml() {
|
fn open_can_parse_toml() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats",
|
||||||
"open cargo_sample.toml | get package.edition | echo $it"
|
"open cargo_sample.toml | get package.edition | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(actual, "2018");
|
assert_eq!(actual, "2018");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn open_can_parse_tsv() {
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: "tests/fixtures/formats", h::pipeline(
|
||||||
|
r#"
|
||||||
|
open caco3_plastics.tsv
|
||||||
|
| first 1
|
||||||
|
| get origin
|
||||||
|
| echo $it
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
|
assert_eq!(actual, "SPAIN")
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn open_can_parse_json() {
|
fn open_can_parse_json() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"), h::pipeline(
|
cwd: "tests/fixtures/formats", h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open sgml_description.json
|
open sgml_description.json
|
||||||
| get glossary.GlossDiv.GlossList.GlossEntry.GlossSee
|
| get glossary.GlossDiv.GlossList.GlossEntry.GlossSee
|
||||||
@ -85,7 +100,7 @@ fn open_can_parse_json() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn open_can_parse_xml() {
|
fn open_can_parse_xml() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats",
|
||||||
"open jonathan.xml | get rss.channel.item.link | echo $it"
|
"open jonathan.xml | get rss.channel.item.link | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -98,7 +113,7 @@ fn open_can_parse_xml() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn open_can_parse_ini() {
|
fn open_can_parse_ini() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats",
|
||||||
"open sample.ini | get SectionOne.integer | echo $it"
|
"open sample.ini | get SectionOne.integer | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -108,7 +123,7 @@ fn open_can_parse_ini() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn open_can_parse_utf16_ini() {
|
fn open_can_parse_utf16_ini() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats",
|
||||||
"open utf16.ini | get .ShellClassInfo | get IconIndex | echo $it"
|
"open utf16.ini | get .ShellClassInfo | get IconIndex | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -118,7 +133,7 @@ fn open_can_parse_utf16_ini() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn errors_if_file_not_found() {
|
fn errors_if_file_not_found() {
|
||||||
let actual = nu_error!(
|
let actual = nu_error!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats",
|
||||||
"open i_dont_exist.txt | echo $it"
|
"open i_dont_exist.txt | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use h::{in_directory as cwd, Playground, Stub::*};
|
|
||||||
use helpers as h;
|
use helpers as h;
|
||||||
|
use helpers::{Playground, Stub::*};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rm_removes_a_file() {
|
fn rm_removes_a_file() {
|
||||||
@ -10,11 +10,14 @@ fn rm_removes_a_file() {
|
|||||||
.with_files(vec![EmptyFile("i_will_be_deleted.txt")
|
.with_files(vec![EmptyFile("i_will_be_deleted.txt")
|
||||||
]);
|
]);
|
||||||
|
|
||||||
nu!(cwd(dirs.root()), "rm rm_test_1/i_will_be_deleted.txt");
|
nu!(
|
||||||
|
cwd: dirs.root(),
|
||||||
|
"rm rm_test_1/i_will_be_deleted.txt"
|
||||||
|
);
|
||||||
|
|
||||||
let path = dirs.test().join("i_will_be_deleted.txt");
|
let path = dirs.test().join("i_will_be_deleted.txt");
|
||||||
|
|
||||||
assert!(!h::file_exists_at(path));
|
assert!(!path.exists());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +41,10 @@ fn rm_removes_files_with_wildcard() {
|
|||||||
EmptyFile("baseline_parse_tokens.rs")
|
EmptyFile("baseline_parse_tokens.rs")
|
||||||
]);
|
]);
|
||||||
|
|
||||||
nu!(cwd(dirs.test()), r#"rm "src/*/*/*.rs""#);
|
nu!(
|
||||||
|
cwd: dirs.test(),
|
||||||
|
r#"rm "src/*/*/*.rs""#
|
||||||
|
);
|
||||||
|
|
||||||
assert!(!h::files_exist_at(
|
assert!(!h::files_exist_at(
|
||||||
vec![
|
vec![
|
||||||
@ -76,7 +82,10 @@ fn rm_removes_deeply_nested_directories_with_wildcard_and_recursive_flag() {
|
|||||||
EmptyFile("baseline_parse_tokens.rs")
|
EmptyFile("baseline_parse_tokens.rs")
|
||||||
]);
|
]);
|
||||||
|
|
||||||
nu!(cwd(dirs.test()), "rm src/* --recursive");
|
nu!(
|
||||||
|
cwd: dirs.test(),
|
||||||
|
"rm src/* --recursive"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(!h::files_exist_at(
|
assert!(!h::files_exist_at(
|
||||||
vec!["src/parser/parse", "src/parser/hir"],
|
vec!["src/parser/parse", "src/parser/hir"],
|
||||||
@ -88,9 +97,12 @@ fn rm_removes_deeply_nested_directories_with_wildcard_and_recursive_flag() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn rm_removes_directory_contents_without_recursive_flag_if_empty() {
|
fn rm_removes_directory_contents_without_recursive_flag_if_empty() {
|
||||||
Playground::setup("rm_test_4", |dirs, _| {
|
Playground::setup("rm_test_4", |dirs, _| {
|
||||||
nu!(cwd(dirs.root()), "rm rm_test_4");
|
nu!(
|
||||||
|
cwd: dirs.root(),
|
||||||
|
"rm rm_test_4"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(!h::file_exists_at(dirs.test()));
|
assert!(!dirs.test().exists());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,9 +116,12 @@ fn rm_removes_directory_contents_with_recursive_flag() {
|
|||||||
EmptyFile("andres.txt")
|
EmptyFile("andres.txt")
|
||||||
]);
|
]);
|
||||||
|
|
||||||
nu!(cwd(dirs.root()), "rm rm_test_5 --recursive");
|
nu!(
|
||||||
|
cwd: dirs.root(),
|
||||||
|
"rm rm_test_5 --recursive"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(!h::file_exists_at(dirs.test()));
|
assert!(!dirs.test().exists());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,11 +133,11 @@ fn rm_errors_if_attempting_to_delete_a_directory_with_content_without_recursive_
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
let actual = nu_error!(
|
let actual = nu_error!(
|
||||||
cwd(dirs.root()),
|
cwd: dirs.root(),
|
||||||
"rm rm_test_6"
|
"rm rm_test_6"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(h::file_exists_at(dirs.test()));
|
assert!(dirs.test().exists());
|
||||||
assert!(actual.contains("is a directory"));
|
assert!(actual.contains("is a directory"));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -130,7 +145,10 @@ fn rm_errors_if_attempting_to_delete_a_directory_with_content_without_recursive_
|
|||||||
#[test]
|
#[test]
|
||||||
fn rm_errors_if_attempting_to_delete_single_dot_as_argument() {
|
fn rm_errors_if_attempting_to_delete_single_dot_as_argument() {
|
||||||
Playground::setup("rm_test_7", |dirs, _| {
|
Playground::setup("rm_test_7", |dirs, _| {
|
||||||
let actual = nu_error!(cwd(dirs.root()), "rm .");
|
let actual = nu_error!(
|
||||||
|
cwd: dirs.root(),
|
||||||
|
"rm ."
|
||||||
|
);
|
||||||
|
|
||||||
assert!(actual.contains("may not be removed"));
|
assert!(actual.contains("may not be removed"));
|
||||||
})
|
})
|
||||||
@ -139,7 +157,10 @@ fn rm_errors_if_attempting_to_delete_single_dot_as_argument() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn rm_errors_if_attempting_to_delete_two_dot_as_argument() {
|
fn rm_errors_if_attempting_to_delete_two_dot_as_argument() {
|
||||||
Playground::setup("rm_test_8", |dirs, _| {
|
Playground::setup("rm_test_8", |dirs, _| {
|
||||||
let actual = nu_error!(cwd(dirs.root()), "rm ..");
|
let actual = nu_error!(
|
||||||
|
cwd: dirs.root(),
|
||||||
|
"rm .."
|
||||||
|
);
|
||||||
|
|
||||||
assert!(actual.contains("may not be removed"));
|
assert!(actual.contains("may not be removed"));
|
||||||
})
|
})
|
||||||
|
@ -1,14 +1,24 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use h::{in_directory as cwd, Playground, Stub::*};
|
|
||||||
use helpers as h;
|
use helpers as h;
|
||||||
|
use helpers::{Playground, Stub::*};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn lines() {
|
fn lines() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats", h::pipeline(
|
||||||
r#"open cargo_sample.toml --raw | lines | skip-while $it != "[dependencies]" | skip 1 | first 1 | split-column "=" | get Column1 | trim | echo $it"#
|
r#"
|
||||||
);
|
open cargo_sample.toml --raw
|
||||||
|
| lines
|
||||||
|
| skip-while $it != "[dependencies]"
|
||||||
|
| skip 1
|
||||||
|
| first 1
|
||||||
|
| split-column "="
|
||||||
|
| get Column1
|
||||||
|
| trim
|
||||||
|
| echo $it
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
assert_eq!(actual, "rustyline");
|
assert_eq!(actual, "rustyline");
|
||||||
}
|
}
|
||||||
@ -32,7 +42,7 @@ fn save_figures_out_intelligently_where_to_write_out_with_metadata() {
|
|||||||
let subject_file = dirs.test().join("cargo_sample.toml");
|
let subject_file = dirs.test().join("cargo_sample.toml");
|
||||||
|
|
||||||
nu!(
|
nu!(
|
||||||
cwd(dirs.root()),
|
cwd: dirs.root(),
|
||||||
"open save_test_1/cargo_sample.toml | inc package.version --minor | save"
|
"open save_test_1/cargo_sample.toml | inc package.version --minor | save"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -47,7 +57,7 @@ fn save_can_write_out_csv() {
|
|||||||
let expected_file = dirs.test().join("cargo_sample.csv");
|
let expected_file = dirs.test().join("cargo_sample.csv");
|
||||||
|
|
||||||
nu!(
|
nu!(
|
||||||
dirs.root(),
|
cwd: dirs.root(),
|
||||||
"open {}/cargo_sample.toml | inc package.version --minor | get package | save save_test_2/cargo_sample.csv",
|
"open {}/cargo_sample.toml | inc package.version --minor | get package | save save_test_2/cargo_sample.csv",
|
||||||
dirs.formats()
|
dirs.formats()
|
||||||
);
|
);
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use helpers::in_directory as cwd;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn external_command() {
|
fn external_command() {
|
||||||
let actual = nu!(cwd("tests/fixtures"), "echo 1");
|
let actual = nu!(
|
||||||
|
cwd: "tests/fixtures",
|
||||||
|
"echo 1"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(actual.contains("1"));
|
assert!(actual.contains("1"));
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use h::{in_directory as cwd, Playground, Stub::*};
|
use helpers::{Playground, Stub::*};
|
||||||
use helpers as h;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_only_apply_one() {
|
fn can_only_apply_one() {
|
||||||
let actual = nu_error!(
|
let actual = nu_error!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats",
|
||||||
"open cargo_sample.toml | first 1 | inc package.version --major --minor"
|
"open cargo_sample.toml | first 1 | inc package.version --major --minor"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -26,7 +25,7 @@ fn by_one_with_field_passed() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()),
|
cwd: dirs.test(),
|
||||||
"open sample.toml | inc package.edition | get package.edition | echo $it"
|
"open sample.toml | inc package.edition | get package.edition | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -47,7 +46,7 @@ fn by_one_with_no_field_passed() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()),
|
cwd: dirs.test(),
|
||||||
"open sample.toml | get package.contributors | inc | echo $it"
|
"open sample.toml | get package.contributors | inc | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -68,7 +67,7 @@ fn semversion_major_inc() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()),
|
cwd: dirs.test(),
|
||||||
"open sample.toml | inc package.version --major | get package.version | echo $it"
|
"open sample.toml | inc package.version --major | get package.version | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -89,7 +88,7 @@ fn semversion_minor_inc() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()),
|
cwd: dirs.test(),
|
||||||
"open sample.toml | inc package.version --minor | get package.version | echo $it"
|
"open sample.toml | inc package.version --minor | get package.version | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -110,7 +109,7 @@ fn semversion_patch_inc() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()),
|
cwd: dirs.test(),
|
||||||
"open sample.toml | inc package.version --patch | get package.version | echo $it"
|
"open sample.toml | inc package.version --patch | get package.version | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -131,7 +130,7 @@ fn semversion_without_passing_field() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()),
|
cwd: dirs.test(),
|
||||||
"open sample.toml | get package.version | inc --patch | echo $it"
|
"open sample.toml | get package.version | inc --patch | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use h::{in_directory as cwd, Playground, Stub::*};
|
|
||||||
use helpers as h;
|
use helpers as h;
|
||||||
|
use h::{Playground, Stub::*};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_only_apply_one() {
|
fn can_only_apply_one() {
|
||||||
let actual = nu_error!(
|
let actual = nu_error!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats",
|
||||||
"open caco3_plastics.csv | first 1 | str origin --downcase --upcase"
|
"open caco3_plastics.csv | first 1 | str origin --downcase --upcase"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ fn acts_without_passing_field() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()),
|
cwd: dirs.test(),
|
||||||
"open sample.yml | get environment.global.PROJECT_NAME | str --upcase | echo $it"
|
"open sample.yml | get environment.global.PROJECT_NAME | str --upcase | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ fn downcases() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()),
|
cwd: dirs.test(),
|
||||||
"open sample.toml | str dependency.name --downcase | get dependency.name | echo $it"
|
"open sample.toml | str dependency.name --downcase | get dependency.name | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ fn upcases() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()),
|
cwd: dirs.test(),
|
||||||
"open sample.toml | str package.name --upcase | get package.name | echo $it"
|
"open sample.toml | str package.name --upcase | get package.name | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -81,15 +81,15 @@ fn upcases() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn converts_to_int() {
|
fn converts_to_int() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"), h::pipeline(
|
cwd: "tests/fixtures/formats", h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open caco3_plastics.csv
|
open caco3_plastics.csv
|
||||||
| first 1
|
| first 1
|
||||||
| str tariff_item --to-int
|
| str tariff_item --to-int
|
||||||
| where tariff_item == 2509000000
|
| where tariff_item == 2509000000
|
||||||
| get tariff_item
|
| get tariff_item
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
assert_eq!(actual, "2509000000");
|
assert_eq!(actual, "2509000000");
|
||||||
@ -108,7 +108,7 @@ fn replaces() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()), h::pipeline(
|
cwd: dirs.test(), h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open sample.toml
|
open sample.toml
|
||||||
| str package.name --replace wykittenshell
|
| str package.name --replace wykittenshell
|
||||||
@ -134,7 +134,7 @@ fn find_and_replaces() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()), h::pipeline(
|
cwd: dirs.test(), h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open sample.toml
|
open sample.toml
|
||||||
| str fortune.teller.phone --find-replace KATZ "5289"
|
| str fortune.teller.phone --find-replace KATZ "5289"
|
||||||
@ -160,7 +160,7 @@ fn find_and_replaces_without_passing_field() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()), h::pipeline(
|
cwd: dirs.test(), h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open sample.toml
|
open sample.toml
|
||||||
| get fortune.teller.phone
|
| get fortune.teller.phone
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use helpers::{in_directory as cwd, Playground, Stub::*};
|
|
||||||
use helpers as h;
|
use helpers as h;
|
||||||
|
use helpers::{Playground, Stub::*};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_convert_table_to_csv_text_and_from_csv_text_back_into_table() {
|
fn can_convert_table_to_csv_text_and_from_csv_text_back_into_table() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats",
|
||||||
"open caco3_plastics.csv | to-csv | from-csv | first 1 | get origin | echo $it"
|
"open caco3_plastics.csv | to-csv | from-csv | first 1 | get origin | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ fn converts_structured_table_to_csv_text() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()), h::pipeline(
|
cwd: dirs.test(), h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open csv_text_sample.txt
|
open csv_text_sample.txt
|
||||||
| lines
|
| lines
|
||||||
@ -58,7 +58,7 @@ fn converts_structured_table_to_csv_text_skipping_headers_after_conversion() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()), h::pipeline(
|
cwd: dirs.test(), h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open csv_text_sample.txt
|
open csv_text_sample.txt
|
||||||
| lines
|
| lines
|
||||||
@ -88,7 +88,7 @@ fn converts_from_csv_text_to_structured_table() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()), h::pipeline(
|
cwd: dirs.test(), h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open los_tres_amigos.txt
|
open los_tres_amigos.txt
|
||||||
| from-csv
|
| from-csv
|
||||||
@ -118,7 +118,7 @@ fn converts_from_csv_text_skipping_headers_to_structured_table() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()), h::pipeline(
|
cwd: dirs.test(), h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open los_tres_amigos.txt
|
open los_tres_amigos.txt
|
||||||
| from-csv --headerless
|
| from-csv --headerless
|
||||||
@ -136,7 +136,7 @@ fn converts_from_csv_text_skipping_headers_to_structured_table() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn can_convert_table_to_json_text_and_from_json_text_back_into_table() {
|
fn can_convert_table_to_json_text_and_from_json_text_back_into_table() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"), h::pipeline(
|
cwd: "tests/fixtures/formats", h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open sgml_description.json
|
open sgml_description.json
|
||||||
| to-json
|
| to-json
|
||||||
@ -168,7 +168,7 @@ fn converts_from_json_text_to_structured_table() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()),
|
cwd: dirs.test(),
|
||||||
"open katz.txt | from-json | get katz | get rusty_luck | sum | echo $it"
|
"open katz.txt | from-json | get katz | get rusty_luck | sum | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ fn converts_from_json_text_recognizing_objects_independendtly_to_structured_tabl
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()), h::pipeline(
|
cwd: dirs.test(), h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open katz.txt
|
open katz.txt
|
||||||
| from-json --objects
|
| from-json --objects
|
||||||
@ -219,7 +219,7 @@ fn converts_structured_table_to_json_text() {
|
|||||||
)]);
|
)]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd(dirs.test()), h::pipeline(
|
cwd: dirs.test(), h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open sample.txt
|
open sample.txt
|
||||||
| lines
|
| lines
|
||||||
@ -237,10 +237,140 @@ fn converts_structured_table_to_json_text() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_convert_table_to_tsv_text_and_from_tsv_text_back_into_table() {
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: "tests/fixtures/formats",
|
||||||
|
"open caco3_plastics.tsv | to-tsv | from-tsv | first 1 | get origin | echo $it"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(actual, "SPAIN");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn converts_structured_table_to_tsv_text() {
|
||||||
|
Playground::setup("filter_to_tsv_test_1", |dirs, sandbox| {
|
||||||
|
sandbox
|
||||||
|
.with_files(vec![FileWithContentToBeTrimmed(
|
||||||
|
"tsv_text_sample.txt",
|
||||||
|
r#"
|
||||||
|
importer shipper tariff_item name origin
|
||||||
|
Plasticos Rival Reverte 2509000000 Calcium carbonate Spain
|
||||||
|
Tigre Ecuador OMYA Andina 3824909999 Calcium carbonate Colombia
|
||||||
|
"#
|
||||||
|
)]);
|
||||||
|
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: dirs.test(), h::pipeline(
|
||||||
|
r#"
|
||||||
|
open tsv_text_sample.txt
|
||||||
|
| lines
|
||||||
|
| split-column "\t" a b c d origin
|
||||||
|
| last 1
|
||||||
|
| to-tsv
|
||||||
|
| lines
|
||||||
|
| nth 1
|
||||||
|
| echo "$it"
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
|
assert!(actual.contains("Colombia"));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn converts_structured_table_to_tsv_text_skipping_headers_after_conversion() {
|
||||||
|
Playground::setup("filter_to_tsv_test_2", |dirs, sandbox| {
|
||||||
|
sandbox
|
||||||
|
.with_files(vec![FileWithContentToBeTrimmed(
|
||||||
|
"tsv_text_sample.txt",
|
||||||
|
r#"
|
||||||
|
importer shipper tariff_item name origin
|
||||||
|
Plasticos Rival Reverte 2509000000 Calcium carbonate Spain
|
||||||
|
Tigre Ecuador OMYA Andina 3824909999 Calcium carbonate Colombia
|
||||||
|
"#
|
||||||
|
)]);
|
||||||
|
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: dirs.test(), h::pipeline(
|
||||||
|
r#"
|
||||||
|
open tsv_text_sample.txt
|
||||||
|
| lines
|
||||||
|
| split-column "\t" a b c d origin
|
||||||
|
| last 1
|
||||||
|
| to-tsv --headerless
|
||||||
|
| echo "$it"
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
|
assert!(actual.contains("Colombia"));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn converts_from_tsv_text_to_structured_table() {
|
||||||
|
Playground::setup("filter_from_tsv_test_1", |dirs, sandbox| {
|
||||||
|
sandbox
|
||||||
|
.with_files(vec![FileWithContentToBeTrimmed(
|
||||||
|
"los_tres_amigos.txt",
|
||||||
|
r#"
|
||||||
|
first Name Last Name rusty_luck
|
||||||
|
Andrés Robalino 1
|
||||||
|
Jonathan Turner 1
|
||||||
|
Yehuda Katz 1
|
||||||
|
"#,
|
||||||
|
)]);
|
||||||
|
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: dirs.test(), h::pipeline(
|
||||||
|
r#"
|
||||||
|
open los_tres_amigos.txt
|
||||||
|
| from-tsv
|
||||||
|
| get rusty_luck
|
||||||
|
| str --to-int
|
||||||
|
| sum
|
||||||
|
| echo $it
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
|
assert_eq!(actual, "3");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn converts_from_tsv_text_skipping_headers_to_structured_table() {
|
||||||
|
Playground::setup("filter_from_tsv_test_2", |dirs, sandbox| {
|
||||||
|
sandbox
|
||||||
|
.with_files(vec![FileWithContentToBeTrimmed(
|
||||||
|
"los_tres_amigos.txt",
|
||||||
|
r#"
|
||||||
|
first Name Last Name rusty_luck
|
||||||
|
Andrés Robalino 1
|
||||||
|
Jonathan Turner 1
|
||||||
|
Yehuda Katz 1
|
||||||
|
"#,
|
||||||
|
)]);
|
||||||
|
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: dirs.test(), h::pipeline(
|
||||||
|
r#"
|
||||||
|
open los_tres_amigos.txt
|
||||||
|
| from-tsv --headerless
|
||||||
|
| get Column3
|
||||||
|
| str --to-int
|
||||||
|
| sum
|
||||||
|
| echo $it
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
|
assert_eq!(actual, "3");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_convert_json_text_to_bson_and_back_into_table() {
|
fn can_convert_json_text_to_bson_and_back_into_table() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats",
|
||||||
"open sample.bson | to-bson | from-bson | get root | nth 1 | get b | echo $it"
|
"open sample.bson | to-bson | from-bson | get root | nth 1 | get b | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -250,7 +380,7 @@ fn can_convert_json_text_to_bson_and_back_into_table() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn can_convert_table_to_toml_text_and_from_toml_text_back_into_table() {
|
fn can_convert_table_to_toml_text_and_from_toml_text_back_into_table() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats",
|
||||||
"open cargo_sample.toml | to-toml | from-toml | get package.name | echo $it"
|
"open cargo_sample.toml | to-toml | from-toml | get package.name | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -260,7 +390,7 @@ fn can_convert_table_to_toml_text_and_from_toml_text_back_into_table() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn can_convert_table_to_yaml_text_and_from_yaml_text_back_into_table() {
|
fn can_convert_table_to_yaml_text_and_from_yaml_text_back_into_table() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"), h::pipeline(
|
cwd: "tests/fixtures/formats", h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open appveyor.yml
|
open appveyor.yml
|
||||||
| to-yaml
|
| to-yaml
|
||||||
@ -276,7 +406,7 @@ fn can_convert_table_to_yaml_text_and_from_yaml_text_back_into_table() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn can_sort_by_column() {
|
fn can_sort_by_column() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"), h::pipeline(
|
cwd: "tests/fixtures/formats", h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open cargo_sample.toml --raw
|
open cargo_sample.toml --raw
|
||||||
| lines
|
| lines
|
||||||
@ -298,7 +428,7 @@ fn can_sort_by_column() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn can_split_by_column() {
|
fn can_split_by_column() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"), h::pipeline(
|
cwd: "tests/fixtures/formats", h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open cargo_sample.toml --raw
|
open cargo_sample.toml --raw
|
||||||
| lines
|
| lines
|
||||||
@ -317,7 +447,7 @@ fn can_split_by_column() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn can_sum() {
|
fn can_sum() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"), h::pipeline(
|
cwd: "tests/fixtures/formats", h::pipeline(
|
||||||
r#"
|
r#"
|
||||||
open sgml_description.json
|
open sgml_description.json
|
||||||
| get glossary.GlossDiv.GlossList.GlossEntry.Sections
|
| get glossary.GlossDiv.GlossList.GlossEntry.Sections
|
||||||
@ -332,17 +462,17 @@ fn can_sum() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn can_filter_by_unit_size_comparison() {
|
fn can_filter_by_unit_size_comparison() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats",
|
||||||
"ls | where size > 1kb | sort-by size | get name | skip 1 | trim | echo $it"
|
"ls | where size > 1kb | sort-by size | get name | first 1 | trim | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(actual, "caco3_plastics.csv");
|
assert_eq!(actual, "cargo_sample.toml");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_get_last() {
|
fn can_get_last() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats",
|
||||||
"ls | sort-by name | last 1 | get name | trim | echo $it"
|
"ls | sort-by name | last 1 | get name | trim | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -352,7 +482,7 @@ fn can_get_last() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn can_get_reverse_first() {
|
fn can_get_reverse_first() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats",
|
||||||
"ls | sort-by name | reverse | first 1 | get name | trim | echo $it"
|
"ls | sort-by name | reverse | first 1 | get name | trim | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
10
tests/fixtures/formats/caco3_plastics.tsv
vendored
Normal file
10
tests/fixtures/formats/caco3_plastics.tsv
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
importer shipper tariff_item name origin shipped_at arrived_at net_weight fob_price cif_price cif_per_net_weight
|
||||||
|
PLASTICOS RIVAL CIA LTDA S A REVERTE 2509000000 CARBONATO DE CALCIO TIPO CALCIPORE 160 T AL SPAIN 18/03/2016 17/04/2016 81,000.00 14,417.58 18,252.34 0.23
|
||||||
|
MEXICHEM ECUADOR S.A. OMYA ANDINA S A 2836500000 CARBONATO COLOMBIA 07/07/2016 10/07/2016 26,000.00 7,072.00 8,127.18 0.31
|
||||||
|
PLASTIAZUAY SA SA REVERTE 2836500000 CARBONATO DE CALCIO SPAIN 27/07/2016 09/08/2016 81,000.00 8,100.00 11,474.55 0.14
|
||||||
|
PLASTICOS RIVAL CIA LTDA AND ENDUSTRIYEL HAMMADDELER DIS TCARET LTD.STI. 2836500000 CALCIUM CARBONATE ANADOLU ANDCARB CT-1 TURKEY 04/10/2016 11/11/2016 100,000.00 17,500.00 22,533.75 0.23
|
||||||
|
QUIMICA COMERCIAL QUIMICIAL CIA. LTDA. SA REVERTE 2836500000 CARBONATO DE CALCIO SPAIN 24/06/2016 12/07/2016 27,000.00 3,258.90 5,585.00 0.21
|
||||||
|
PICA PLASTICOS INDUSTRIALES C.A. OMYA ANDINA S.A 3824909999 CARBONATO DE CALCIO COLOMBIA 01/01/1900 18/01/2016 66,500.00 12,635.00 18,670.52 0.28
|
||||||
|
PLASTIQUIM S.A. OMYA ANDINA S.A NIT 830.027.386-6 3824909999 CARBONATO DE CALCIO RECUBIERTO CON ACIDO ESTEARICO OMYA CARB 1T CG BBS 1000 COLOMBIA 01/01/1900 25/10/2016 33,000.00 6,270.00 9,999.00 0.30
|
||||||
|
QUIMICOS ANDINOS QUIMANDI S.A. SIBELCO COLOMBIA SAS 3824909999 CARBONATO DE CALCIO RECUBIERTO COLOMBIA 01/11/2016 03/11/2016 52,000.00 8,944.00 13,039.05 0.25
|
||||||
|
TIGRE ECUADOR S.A. ECUATIGRE OMYA ANDINA S.A NIT 830.027.386-6 3824909999 CARBONATO DE CALCIO RECUBIERTO CON ACIDO ESTEARICO OMYACARB 1T CG BPA 25 NO COLOMBIA 01/01/1900 28/10/2016 66,000.00 11,748.00 18,216.00 0.28
|
|
@ -50,7 +50,7 @@ impl DisplayPath for nu::AbsolutePath {
|
|||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! nu {
|
macro_rules! nu {
|
||||||
($cwd:expr, $path:expr, $($part:expr),*) => {{
|
(cwd: $cwd:expr, $path:expr, $($part:expr),*) => {{
|
||||||
use $crate::helpers::DisplayPath;
|
use $crate::helpers::DisplayPath;
|
||||||
|
|
||||||
let path = format!($path, $(
|
let path = format!($path, $(
|
||||||
@ -60,6 +60,10 @@ macro_rules! nu {
|
|||||||
nu!($cwd, &path)
|
nu!($cwd, &path)
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
(cwd: $cwd:expr, $path:expr) => {{
|
||||||
|
nu!($cwd, $path)
|
||||||
|
}};
|
||||||
|
|
||||||
($cwd:expr, $path:expr) => {{
|
($cwd:expr, $path:expr) => {{
|
||||||
pub use std::error::Error;
|
pub use std::error::Error;
|
||||||
pub use std::io::prelude::*;
|
pub use std::io::prelude::*;
|
||||||
@ -101,7 +105,7 @@ macro_rules! nu {
|
|||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! nu_error {
|
macro_rules! nu_error {
|
||||||
($cwd:expr, $path:expr, $($part:expr),*) => {{
|
(cwd: $cwd:expr, $path:expr, $($part:expr),*) => {{
|
||||||
use $crate::helpers::DisplayPath;
|
use $crate::helpers::DisplayPath;
|
||||||
|
|
||||||
let path = format!($path, $(
|
let path = format!($path, $(
|
||||||
@ -111,17 +115,22 @@ macro_rules! nu_error {
|
|||||||
nu_error!($cwd, &path)
|
nu_error!($cwd, &path)
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
(cwd: $cwd:expr, $path:expr) => {{
|
||||||
|
nu_error!($cwd, $path)
|
||||||
|
}};
|
||||||
|
|
||||||
($cwd:expr, $commands:expr) => {{
|
($cwd:expr, $path:expr) => {{
|
||||||
use std::io::prelude::*;
|
pub use std::error::Error;
|
||||||
use std::process::{Command, Stdio};
|
pub use std::io::prelude::*;
|
||||||
|
pub use std::process::{Command, Stdio};
|
||||||
|
|
||||||
let commands = &*format!(
|
let commands = &*format!(
|
||||||
"
|
"
|
||||||
cd {}
|
cd {}
|
||||||
{}
|
{}
|
||||||
exit",
|
exit",
|
||||||
$crate::helpers::in_directory($cwd), $commands
|
$crate::helpers::in_directory($cwd),
|
||||||
|
$crate::helpers::DisplayPath::display_path(&$path)
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut process = Command::new(helpers::executable_path())
|
let mut process = Command::new(helpers::executable_path())
|
||||||
@ -140,7 +149,6 @@ macro_rules! nu_error {
|
|||||||
.expect("couldn't read from stderr");
|
.expect("couldn't read from stderr");
|
||||||
|
|
||||||
let out = String::from_utf8_lossy(&output.stderr);
|
let out = String::from_utf8_lossy(&output.stderr);
|
||||||
|
|
||||||
out.into_owned()
|
out.into_owned()
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
@ -345,14 +353,6 @@ pub fn files_exist_at(files: Vec<impl AsRef<Path>>, path: impl AsRef<Path>) -> b
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_exists_at(path: impl AsRef<Path>) -> bool {
|
|
||||||
path.as_ref().exists()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dir_exists_at(path: impl AsRef<Path>) -> bool {
|
|
||||||
path.as_ref().exists()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete_directory_at(full_path: &str) {
|
pub fn delete_directory_at(full_path: &str) {
|
||||||
std::fs::remove_dir_all(PathBuf::from(full_path)).expect("can not remove directory");
|
std::fs::remove_dir_all(PathBuf::from(full_path)).expect("can not remove directory");
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use helpers::{in_directory as cwd};
|
|
||||||
use helpers as h;
|
use helpers as h;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -21,7 +20,7 @@ fn pipeline_helper() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn external_num() {
|
fn external_num() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats",
|
||||||
"open sgml_description.json | get glossary.GlossDiv.GlossList.GlossEntry.Height | echo $it"
|
"open sgml_description.json | get glossary.GlossDiv.GlossList.GlossEntry.Height | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -30,7 +29,10 @@ fn external_num() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn external_has_correct_quotes() {
|
fn external_has_correct_quotes() {
|
||||||
let actual = nu!(cwd("."), r#"echo "hello world""#);
|
let actual = nu!(
|
||||||
|
cwd: ".",
|
||||||
|
r#"echo "hello world""#
|
||||||
|
);
|
||||||
|
|
||||||
let actual = h::normalize_string(&actual);
|
let actual = h::normalize_string(&actual);
|
||||||
|
|
||||||
@ -40,9 +42,14 @@ fn external_has_correct_quotes() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn add_plugin() {
|
fn add_plugin() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats", h::pipeline(
|
||||||
r#"open cargo_sample.toml | add dev-dependencies.newdep "1" | get dev-dependencies.newdep | echo $it"#
|
r#"
|
||||||
);
|
open cargo_sample.toml
|
||||||
|
| add dev-dependencies.newdep "1"
|
||||||
|
| get dev-dependencies.newdep
|
||||||
|
| echo $it
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
assert_eq!(actual, "1");
|
assert_eq!(actual, "1");
|
||||||
}
|
}
|
||||||
@ -50,9 +57,14 @@ fn add_plugin() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn edit_plugin() {
|
fn edit_plugin() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd("tests/fixtures/formats"),
|
cwd: "tests/fixtures/formats", h::pipeline(
|
||||||
r#"open cargo_sample.toml | edit dev-dependencies.pretty_assertions "7" | get dev-dependencies.pretty_assertions | echo $it"#
|
r#"
|
||||||
);
|
open cargo_sample.toml
|
||||||
|
| edit dev-dependencies.pretty_assertions "7"
|
||||||
|
| get dev-dependencies.pretty_assertions
|
||||||
|
| echo $it
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
assert_eq!(actual, "7");
|
assert_eq!(actual, "7");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user