Remove old nushell/merge engine-q

This commit is contained in:
JT 2022-02-07 14:54:06 -05:00
parent 10c4c50f1f
commit d70d91e559
430 changed files with 14543 additions and 7865 deletions

2996
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
[package]
<<<<<<< HEAD
authors = ["The Nu Project Contributors"]
default-run = "nu"
description = "A new type of shell"
@ -11,149 +10,7 @@ license = "MIT"
name = "nu"
readme = "README.md"
repository = "https://github.com/nushell/nushell"
version = "0.43.0"
[workspace]
members = ["crates/*/"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nu-cli = { version = "0.43.0", path="./crates/nu-cli", default-features=false }
nu-command = { version = "0.43.0", path="./crates/nu-command" }
nu-completion = { version = "0.43.0", path="./crates/nu-completion" }
nu-data = { version = "0.43.0", path="./crates/nu-data" }
nu-engine = { version = "0.43.0", path="./crates/nu-engine" }
nu-errors = { version = "0.43.0", path="./crates/nu-errors" }
nu-parser = { version = "0.43.0", path="./crates/nu-parser" }
nu-path = { version = "0.43.0", path="./crates/nu-path" }
nu-plugin = { version = "0.43.0", path="./crates/nu-plugin" }
nu-protocol = { version = "0.43.0", path="./crates/nu-protocol" }
nu-source = { version = "0.43.0", path="./crates/nu-source" }
nu-value-ext = { version = "0.43.0", path="./crates/nu-value-ext" }
nu_plugin_binaryview = { version = "0.43.0", path="./crates/nu_plugin_binaryview", optional=true }
nu_plugin_chart = { version = "0.43.0", path="./crates/nu_plugin_chart", optional=true }
nu_plugin_from_bson = { version = "0.43.0", path="./crates/nu_plugin_from_bson", optional=true }
nu_plugin_from_sqlite = { version = "0.43.0", path="./crates/nu_plugin_from_sqlite", optional=true }
nu_plugin_inc = { version = "0.43.0", path="./crates/nu_plugin_inc", optional=true }
nu_plugin_match = { version = "0.43.0", path="./crates/nu_plugin_match", optional=true }
nu_plugin_query_json = { version = "0.43.0", path="./crates/nu_plugin_query_json", optional=true }
nu_plugin_s3 = { version = "0.43.0", path="./crates/nu_plugin_s3", optional=true }
nu_plugin_selector = { version = "0.43.0", path="./crates/nu_plugin_selector", optional=true }
nu_plugin_start = { version = "0.43.0", path="./crates/nu_plugin_start", optional=true }
nu_plugin_textview = { version = "0.43.0", path="./crates/nu_plugin_textview", optional=true }
nu_plugin_to_bson = { version = "0.43.0", path="./crates/nu_plugin_to_bson", optional=true }
nu_plugin_to_sqlite = { version = "0.43.0", path="./crates/nu_plugin_to_sqlite", optional=true }
nu_plugin_tree = { version = "0.43.0", path="./crates/nu_plugin_tree", optional=true }
nu_plugin_xpath = { version = "0.43.0", path="./crates/nu_plugin_xpath", optional=true }
# Required to bootstrap the main binary
ctrlc = { version="3.1.7", optional=true }
futures = { version="0.3.12", features=["compat", "io-compat"] }
itertools = "0.10.0"
[dev-dependencies]
nu-test-support = { version = "0.43.0", path="./crates/nu-test-support" }
serial_test = "0.5.1"
hamcrest2 = "0.3.0"
rstest = "0.10.0"
[build-dependencies]
[features]
fetch-support = ["nu-command/fetch", "nu-command/post"]
sys-support = ["nu-command/sys", "nu-command/ps"]
ctrlc-support = ["nu-cli/ctrlc", "nu-command/ctrlc"]
rustyline-support = ["nu-cli/rustyline-support", "nu-command/rustyline-support"]
term-support = ["nu-command/term"]
uuid-support = ["nu-command/uuid_crate"]
which-support = ["nu-command/which", "nu-engine/which"]
default = [
"nu-cli/shadow-rs",
"sys-support",
"ctrlc-support",
"which-support",
"term-support",
"rustyline-support",
"match",
"fetch-support",
"zip-support",
"dataframe",
]
stable = ["default"]
extra = [
"default",
"binaryview",
"inc",
"tree",
"textview",
"trash-support",
"uuid-support",
"start",
"bson",
"sqlite",
"s3",
"chart",
"xpath",
"selector",
"query-json",
]
wasi = ["inc", "match", "match", "tree", "rustyline-support"]
# Stable (Default)
inc = ["nu_plugin_inc"]
match = ["nu_plugin_match"]
textview = ["nu_plugin_textview"]
# Extra
binaryview = ["nu_plugin_binaryview"]
bson = ["nu_plugin_from_bson", "nu_plugin_to_bson"]
chart = ["nu_plugin_chart"]
query-json = ["nu_plugin_query_json"]
s3 = ["nu_plugin_s3"]
selector = ["nu_plugin_selector"]
sqlite = ["nu_plugin_from_sqlite", "nu_plugin_to_sqlite"]
start = ["nu_plugin_start"]
trash-support = [
"nu-command/trash-support",
"nu-engine/trash-support",
]
tree = ["nu_plugin_tree"]
xpath = ["nu_plugin_xpath"]
zip-support = ["nu-command/zip"]
#dataframe feature for nushell
dataframe = [
"nu-engine/dataframe",
"nu-protocol/dataframe",
"nu-command/dataframe",
"nu-value-ext/dataframe",
"nu-data/dataframe",
"nu_plugin_to_bson/dataframe",
]
[profile.release]
opt-level = "s" # Optimize for size.
# Core plugins that ship with `cargo install nu` by default
# Currently, Cargo limits us to installing only one binary
# unless we use [[bin]], so we use this as a workaround
[[bin]]
name = "nu_plugin_core_textview"
path = "src/plugins/nu_plugin_core_textview.rs"
required-features = ["textview"]
[[bin]]
name = "nu_plugin_core_inc"
=======
name = "nu"
version = "0.1.0"
edition = "2021"
default-run = "nu"
version = "0.59.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -176,21 +33,23 @@ members = [
reedline = { git = "https://github.com/nushell/reedline", branch = "main" }
crossterm = "0.22.*"
nu-cli = { path="./crates/nu-cli" }
nu-command = { path="./crates/nu-command" }
nu-engine = { path="./crates/nu-engine" }
nu-json = { path="./crates/nu-json" }
nu-parser = { path="./crates/nu-parser" }
nu-path = { path="./crates/nu-path" }
nu-pretty-hex = { path = "./crates/nu-pretty-hex" }
nu-protocol = { path = "./crates/nu-protocol" }
nu-plugin = { path = "./crates/nu-plugin", optional = true }
nu-system = { path = "./crates/nu-system"}
nu-table = { path = "./crates/nu-table" }
nu-term-grid = { path = "./crates/nu-term-grid" }
nu-cli = { path="./crates/nu-cli", version = "0.59.0" }
nu-command = { path="./crates/nu-command", version = "0.59.0" }
nu-engine = { path="./crates/nu-engine", version = "0.59.0" }
nu-json = { path="./crates/nu-json", version = "0.59.0" }
nu-parser = { path="./crates/nu-parser", version = "0.59.0" }
nu-path = { path="./crates/nu-path", version = "0.59.0" }
nu-pretty-hex = { path = "./crates/nu-pretty-hex", version = "0.59.0" }
nu-protocol = { path = "./crates/nu-protocol", version = "0.59.0" }
nu-plugin = { path = "./crates/nu-plugin", optional = true, version = "0.59.0" }
nu-system = { path = "./crates/nu-system", version = "0.59.0" }
nu-table = { path = "./crates/nu-table", version = "0.59.0" }
nu-term-grid = { path = "./crates/nu-term-grid", version = "0.59.0" }
# nu-ansi-term = { path = "./crates/nu-ansi-term", version = "0.59.0" }
nu-ansi-term = "0.42.0"
nu-color-config = { path = "./crates/nu-color-config" }
nu-color-config = { path = "./crates/nu-color-config", version = "0.59.0" }
miette = "3.0.0"
ctrlc = "3.2.1"
crossterm_winapi = "0.9.0"
@ -199,10 +58,10 @@ pretty_env_logger = "0.4.0"
# mimalloc = { version = "*", default-features = false }
nu_plugin_inc = { version = "0.1.0", path = "./crates/nu_plugin_inc", optional = true }
nu_plugin_example = { version = "0.1.0", path = "./crates/nu_plugin_example", optional = true }
nu_plugin_gstat = { version = "0.1.0", path = "./crates/nu_plugin_gstat", optional = true }
nu_plugin_query = { version = "0.1.0", path = "./crates/nu_plugin_query", optional = true }
nu_plugin_inc = { version = "0.59.0", path = "./crates/nu_plugin_inc", optional = true }
nu_plugin_example = { version = "0.59.0", path = "./crates/nu_plugin_example", optional = true }
nu_plugin_gstat = { version = "0.59.0", path = "./crates/nu_plugin_gstat", optional = true }
nu_plugin_query = { version = "0.59.0", path = "./crates/nu_plugin_query", optional = true }
[dev-dependencies]
nu-test-support = { path="./crates/nu-test-support" }
@ -254,83 +113,10 @@ opt-level = "s" # Optimize for size
# Build plugins
[[bin]]
name = "nu_plugin_inc"
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
path = "src/plugins/nu_plugin_core_inc.rs"
required-features = ["inc"]
[[bin]]
<<<<<<< HEAD
name = "nu_plugin_core_match"
path = "src/plugins/nu_plugin_core_match.rs"
required-features = ["match"]
# Extra plugins
[[bin]]
name = "nu_plugin_extra_binaryview"
path = "src/plugins/nu_plugin_extra_binaryview.rs"
required-features = ["binaryview"]
[[bin]]
name = "nu_plugin_extra_tree"
path = "src/plugins/nu_plugin_extra_tree.rs"
required-features = ["tree"]
[[bin]]
name = "nu_plugin_extra_query_json"
path = "src/plugins/nu_plugin_extra_query_json.rs"
required-features = ["query-json"]
[[bin]]
name = "nu_plugin_extra_start"
path = "src/plugins/nu_plugin_extra_start.rs"
required-features = ["start"]
[[bin]]
name = "nu_plugin_extra_s3"
path = "src/plugins/nu_plugin_extra_s3.rs"
required-features = ["s3"]
[[bin]]
name = "nu_plugin_extra_chart_bar"
path = "src/plugins/nu_plugin_extra_chart_bar.rs"
required-features = ["chart"]
[[bin]]
name = "nu_plugin_extra_chart_line"
path = "src/plugins/nu_plugin_extra_chart_line.rs"
required-features = ["chart"]
[[bin]]
name = "nu_plugin_extra_xpath"
path = "src/plugins/nu_plugin_extra_xpath.rs"
required-features = ["xpath"]
[[bin]]
name = "nu_plugin_extra_selector"
path = "src/plugins/nu_plugin_extra_selector.rs"
required-features = ["selector"]
[[bin]]
name = "nu_plugin_extra_from_bson"
path = "src/plugins/nu_plugin_extra_from_bson.rs"
required-features = ["bson"]
[[bin]]
name = "nu_plugin_extra_to_bson"
path = "src/plugins/nu_plugin_extra_to_bson.rs"
required-features = ["bson"]
[[bin]]
name = "nu_plugin_extra_from_sqlite"
path = "src/plugins/nu_plugin_extra_from_sqlite.rs"
required-features = ["sqlite"]
[[bin]]
name = "nu_plugin_extra_to_sqlite"
path = "src/plugins/nu_plugin_extra_to_sqlite.rs"
required-features = ["sqlite"]
=======
name = "nu_plugin_example"
path = "src/plugins/nu_plugin_core_example.rs"
required-features = ["example"]
@ -345,7 +131,6 @@ required-features = ["gstat"]
name = "nu_plugin_query"
path = "src/plugins/nu_plugin_extra_query.rs"
required-features = ["query"]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
# Main nu binary
[[bin]]

229
Cargo.toml.old Normal file
View File

@ -0,0 +1,229 @@
[package]
authors = ["The Nu Project Contributors"]
default-run = "nu"
description = "A new type of shell"
documentation = "https://www.nushell.sh/book/"
edition = "2018"
exclude = ["images"]
homepage = "https://www.nushell.sh"
license = "MIT"
name = "nu"
readme = "README.md"
repository = "https://github.com/nushell/nushell"
version = "0.59.0"
[workspace]
members = ["crates/*/"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nu-cli = { version = "0.59.0", path="./crates/nu-cli", default-features=false }
nu-command = { version = "0.59.0", path="./crates/nu-command" }
nu-completion = { version = "0.59.0", path="./crates/nu-completion" }
nu-data = { version = "0.59.0", path="./crates/nu-data" }
nu-engine = { version = "0.59.0", path="./crates/nu-engine" }
nu-errors = { version = "0.59.0", path="./crates/nu-errors" }
nu-parser = { version = "0.59.0", path="./crates/nu-parser" }
nu-path = { version = "0.59.0", path="./crates/nu-path" }
nu-plugin = { version = "0.59.0", path="./crates/nu-plugin" }
nu-protocol = { version = "0.59.0", path="./crates/nu-protocol" }
nu-source = { version = "0.59.0", path="./crates/nu-source" }
nu-value-ext = { version = "0.59.0", path="./crates/nu-value-ext" }
# nu_plugin_binaryview = { version = "0.59.0", path="./crates/nu_plugin_binaryview", optional=true }
# nu_plugin_chart = { version = "0.59.0", path="./crates/nu_plugin_chart", optional=true }
# nu_plugin_from_bson = { version = "0.59.0", path="./crates/nu_plugin_from_bson", optional=true }
# nu_plugin_from_sqlite = { version = "0.59.0", path="./crates/nu_plugin_from_sqlite", optional=true }
# nu_plugin_inc = { version = "0.59.0", path="./crates/nu_plugin_inc", optional=true }
# nu_plugin_match = { version = "0.59.0", path="./crates/nu_plugin_match", optional=true }
# nu_plugin_query_json = { version = "0.59.0", path="./crates/nu_plugin_query_json", optional=true }
# nu_plugin_s3 = { version = "0.59.0", path="./crates/nu_plugin_s3", optional=true }
# nu_plugin_selector = { version = "0.59.0", path="./crates/nu_plugin_selector", optional=true }
# nu_plugin_start = { version = "0.59.0", path="./crates/nu_plugin_start", optional=true }
# nu_plugin_textview = { version = "0.59.0", path="./crates/nu_plugin_textview", optional=true }
# nu_plugin_to_bson = { version = "0.59.0", path="./crates/nu_plugin_to_bson", optional=true }
# nu_plugin_to_sqlite = { version = "0.59.0", path="./crates/nu_plugin_to_sqlite", optional=true }
# nu_plugin_tree = { version = "0.59.0", path="./crates/nu_plugin_tree", optional=true }
# nu_plugin_xpath = { version = "0.59.0", path="./crates/nu_plugin_xpath", optional=true }
# Required to bootstrap the main binary
ctrlc = { version="3.1.7", optional=true }
futures = { version="0.3.12", features=["compat", "io-compat"] }
itertools = "0.10.0"
[dev-dependencies]
nu-test-support = { version = "0.59.0", path="./crates/nu-test-support" }
serial_test = "0.5.1"
hamcrest2 = "0.3.0"
rstest = "0.10.0"
[build-dependencies]
[features]
fetch-support = ["nu-command/fetch", "nu-command/post"]
sys-support = ["nu-command/sys", "nu-command/ps"]
ctrlc-support = ["nu-cli/ctrlc", "nu-command/ctrlc"]
rustyline-support = ["nu-cli/rustyline-support", "nu-command/rustyline-support"]
term-support = ["nu-command/term"]
uuid-support = ["nu-command/uuid_crate"]
which-support = ["nu-command/which", "nu-engine/which"]
default = [
"nu-cli/shadow-rs",
"sys-support",
"ctrlc-support",
"which-support",
"term-support",
"rustyline-support",
# "match",
"fetch-support",
"zip-support",
"dataframe",
]
stable = ["default"]
extra = [
"default",
# "binaryview",
# "inc",
# "tree",
# "textview",
"trash-support",
"uuid-support",
# "start",
# "bson",
# "sqlite",
# "s3",
# "chart",
# "xpath",
# "selector",
# "query-json",
]
# wasi = ["inc", "match", "match", "tree", "rustyline-support"]
# Stable (Default)
# inc = ["nu_plugin_inc"]
# match = ["nu_plugin_match"]
# textview = ["nu_plugin_textview"]
# Extra
# binaryview = ["nu_plugin_binaryview"]
# bson = ["nu_plugin_from_bson", "nu_plugin_to_bson"]
# chart = ["nu_plugin_chart"]
# query-json = ["nu_plugin_query_json"]
# s3 = ["nu_plugin_s3"]
# selector = ["nu_plugin_selector"]
# sqlite = ["nu_plugin_from_sqlite", "nu_plugin_to_sqlite"]
# start = ["nu_plugin_start"]
trash-support = [
"nu-command/trash-support",
"nu-engine/trash-support",
]
# tree = ["nu_plugin_tree"]
# xpath = ["nu_plugin_xpath"]
zip-support = ["nu-command/zip"]
#dataframe feature for nushell
dataframe = [
"nu-engine/dataframe",
"nu-protocol/dataframe",
"nu-command/dataframe",
"nu-value-ext/dataframe",
"nu-data/dataframe",
# "nu_plugin_to_bson/dataframe",
]
[profile.release]
opt-level = "s" # Optimize for size.
# Core plugins that ship with `cargo install nu` by default
# Currently, Cargo limits us to installing only one binary
# unless we use [[bin]], so we use this as a workaround
# [[bin]]
# name = "nu_plugin_core_textview"
# path = "src/plugins/nu_plugin_core_textview.rs"
# required-features = ["textview"]
#
# [[bin]]
# name = "nu_plugin_core_inc"
# path = "src/plugins/nu_plugin_core_inc.rs"
# required-features = ["inc"]
#
# [[bin]]
# name = "nu_plugin_core_match"
# path = "src/plugins/nu_plugin_core_match.rs"
# required-features = ["match"]
#
# # Extra plugins
#
# [[bin]]
# name = "nu_plugin_extra_binaryview"
# path = "src/plugins/nu_plugin_extra_binaryview.rs"
# required-features = ["binaryview"]
#
# [[bin]]
# name = "nu_plugin_extra_tree"
# path = "src/plugins/nu_plugin_extra_tree.rs"
# required-features = ["tree"]
#
# [[bin]]
# name = "nu_plugin_extra_query_json"
# path = "src/plugins/nu_plugin_extra_query_json.rs"
# required-features = ["query-json"]
#
# [[bin]]
# name = "nu_plugin_extra_start"
# path = "src/plugins/nu_plugin_extra_start.rs"
# required-features = ["start"]
#
# [[bin]]
# name = "nu_plugin_extra_s3"
# path = "src/plugins/nu_plugin_extra_s3.rs"
# required-features = ["s3"]
#
# [[bin]]
# name = "nu_plugin_extra_chart_bar"
# path = "src/plugins/nu_plugin_extra_chart_bar.rs"
# required-features = ["chart"]
#
# [[bin]]
# name = "nu_plugin_extra_chart_line"
# path = "src/plugins/nu_plugin_extra_chart_line.rs"
# required-features = ["chart"]
#
# [[bin]]
# name = "nu_plugin_extra_xpath"
# path = "src/plugins/nu_plugin_extra_xpath.rs"
# required-features = ["xpath"]
#
# [[bin]]
# name = "nu_plugin_extra_selector"
# path = "src/plugins/nu_plugin_extra_selector.rs"
# required-features = ["selector"]
#
# [[bin]]
# name = "nu_plugin_extra_from_bson"
# path = "src/plugins/nu_plugin_extra_from_bson.rs"
# required-features = ["bson"]
#
# [[bin]]
# name = "nu_plugin_extra_to_bson"
# path = "src/plugins/nu_plugin_extra_to_bson.rs"
# required-features = ["bson"]
#
# [[bin]]
# name = "nu_plugin_extra_from_sqlite"
# path = "src/plugins/nu_plugin_extra_from_sqlite.rs"
# required-features = ["sqlite"]
#
# [[bin]]
# name = "nu_plugin_extra_to_sqlite"
# path = "src/plugins/nu_plugin_extra_to_sqlite.rs"
# required-features = ["sqlite"]
#
# Main nu binary
[[bin]]
name = "nu"
path = "src/main.rs"

View File

@ -281,7 +281,3 @@ Thanks to all the people who already contributed!
## License
The project is made available under the MIT license. See the `LICENSE` file for more information.
=======
# NOTE: Engine-q is merged into Nushell
Please use https://github.com/nushell/nushell

13
crates/README.md Normal file
View File

@ -0,0 +1,13 @@
# Nushell core libraries and plugins
These sub-crates form both the foundation for Nu and a set of plugins which extend Nu with additional functionality.
Foundational libraries are split into two kinds of crates:
* Core crates - those crates that work together to build the Nushell language engine
* Support crates - a set of crates that support the engine with additional features like JSON support, ANSI support, and more.
Plugins are likewise also split into two types:
* Core plugins - plugins that provide part of the default experience of Nu, including access to the system properties, processes, and web-connectivity features.
* Extra plugins - these plugins run a wide range of different capabilities like working with different file types, charting, viewing binary data, and more.

2
crates/nu-ansi-term/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
target
Cargo.lock

View File

@ -0,0 +1,39 @@
[package]
authors = [
"ogham@bsago.me",
"Ryan Scheel (Havvy) <ryan.havvy@gmail.com>",
"Josh Triplett <josh@joshtriplett.org>",
"The Nu Project Contributors",
]
description = "Library for ANSI terminal colors and styles (bold, underline)"
edition = "2018"
license = "MIT"
name = "nu-ansi-term"
version = "0.42.0"
[lib]
doctest = false
# name = "nu-ansi-term"
[features]
derive_serde_style = ["serde"]
[dependencies]
overload = "0.1.1"
serde = { version="1.0.90", features=["derive"], optional=true }
# [dependencies.serde]
# version = "1.0.90"
# features = ["derive"]
# optional = true
[target.'cfg(target_os="windows")'.dependencies.winapi]
version = "0.3.4"
features = ["consoleapi", "errhandlingapi", "fileapi", "handleapi", "processenv"]
[dev-dependencies]
doc-comment = "0.3"
regex = "1.1.9"
[dev-dependencies.serde_json]
version = "1.0.39"

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Benjamin Sago
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,182 @@
# nu-ansi-term
> This is a copy of rust-ansi-term but with Color change to Color and light foreground colors added (90-97) as well as light background colors added (100-107).
This is a library for controlling colors and formatting, such as red bold text or blue underlined text, on ANSI terminals.
### [View the Rustdoc](https://docs.rs/nu_ansi_term/)
# Installation
This crate works with [Cargo](http://crates.io). Add the following to your `Cargo.toml` dependencies section:
```toml
[dependencies]
nu_ansi_term = "0.13"
```
## Basic usage
There are three main types in this crate that you need to be concerned with: `ANSIString`, `Style`, and `Color`.
A `Style` holds stylistic information: foreground and background colors, whether the text should be bold, or blinking, or other properties.
The `Color` enum represents the available colors.
And an `ANSIString` is a string paired with a `Style`.
`Color` is also available as an alias to `Color`.
To format a string, call the `paint` method on a `Style` or a `Color`, passing in the string you want to format as the argument.
For example, heres how to get some red text:
```rust
use nu_ansi_term::Color::Red;
println!("This is in red: {}", Red.paint("a red string"));
```
Its important to note that the `paint` method does _not_ actually return a string with the ANSI control characters surrounding it.
Instead, it returns an `ANSIString` value that has a `Display` implementation that, when formatted, returns the characters.
This allows strings to be printed with a minimum of `String` allocations being performed behind the scenes.
If you _do_ want to get at the escape codes, then you can convert the `ANSIString` to a string as you would any other `Display` value:
```rust
use nu_ansi_term::Color::Red;
let red_string = Red.paint("a red string").to_string();
```
**Note for Windows 10 users:** On Windows 10, the application must enable ANSI support first:
```rust,ignore
let enabled = nu_ansi_term::enable_ansi_support();
```
## Bold, underline, background, and other styles
For anything more complex than plain foreground color changes, you need to construct `Style` values themselves, rather than beginning with a `Color`.
You can do this by chaining methods based on a new `Style`, created with `Style::new()`.
Each method creates a new style that has that specific property set.
For example:
```rust
use nu_ansi_term::Style;
println!("How about some {} and {}?",
Style::new().bold().paint("bold"),
Style::new().underline().paint("underline"));
```
For brevity, these methods have also been implemented for `Color` values, so you can give your styles a foreground color without having to begin with an empty `Style` value:
```rust
use nu_ansi_term::Color::{Blue, Yellow};
println!("Demonstrating {} and {}!",
Blue.bold().paint("blue bold"),
Yellow.underline().paint("yellow underline"));
println!("Yellow on blue: {}", Yellow.on(Blue).paint("wow!"));
```
The complete list of styles you can use are:
`bold`, `dimmed`, `italic`, `underline`, `blink`, `reverse`, `hidden`, and `on` for background colors.
In some cases, you may find it easier to change the foreground on an existing `Style` rather than starting from the appropriate `Color`.
You can do this using the `fg` method:
```rust
use nu_ansi_term::Style;
use nu_ansi_term::Color::{Blue, Cyan, Yellow};
println!("Yellow on blue: {}", Style::new().on(Blue).fg(Yellow).paint("yow!"));
println!("Also yellow on blue: {}", Cyan.on(Blue).fg(Yellow).paint("zow!"));
```
You can turn a `Color` into a `Style` with the `normal` method.
This will produce the exact same `ANSIString` as if you just used the `paint` method on the `Color` directly, but its useful in certain cases: for example, you may have a method that returns `Styles`, and need to represent both the “red bold” and “red, but not bold” styles with values of the same type. The `Style` struct also has a `Default` implementation if you want to have a style with _nothing_ set.
```rust
use nu_ansi_term::Style;
use nu_ansi_term::Color::Red;
Red.normal().paint("yet another red string");
Style::default().paint("a completely regular string");
```
## Extended colors
You can access the extended range of 256 colors by using the `Color::Fixed` variant, which takes an argument of the color number to use.
This can be included wherever you would use a `Color`:
```rust
use nu_ansi_term::Color::Fixed;
Fixed(134).paint("A sort of light purple");
Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup");
```
The first sixteen of these values are the same as the normal and bold standard color variants.
Theres nothing stopping you from using these as `Fixed` colors instead, but theres nothing to be gained by doing so either.
You can also access full 24-bit color by using the `Color::RGB` variant, which takes separate `u8` arguments for red, green, and blue:
```rust
use nu_ansi_term::Color::RGB;
RGB(70, 130, 180).paint("Steel blue");
```
## Combining successive coloured strings
The benefit of writing ANSI escape codes to the terminal is that they _stack_: you do not need to end every coloured string with a reset code if the text that follows it is of a similar style.
For example, if you want to have some blue text followed by some blue bold text, its possible to send the ANSI code for blue, followed by the ANSI code for bold, and finishing with a reset code without having to have an extra one between the two strings.
This crate can optimise the ANSI codes that get printed in situations like this, making life easier for your terminal renderer.
The `ANSIStrings` struct takes a slice of several `ANSIString` values, and will iterate over each of them, printing only the codes for the styles that need to be updated as part of its formatting routine.
The following code snippet uses this to enclose a binary number displayed in red bold text inside some red, but not bold, brackets:
```rust
use nu_ansi_term::Color::Red;
use nu_ansi_term::{ANSIString, ANSIStrings};
let some_value = format!("{:b}", 42);
let strings: &[ANSIString<'static>] = &[
Red.paint("["),
Red.bold().paint(some_value),
Red.paint("]"),
];
println!("Value: {}", ANSIStrings(strings));
```
There are several things to note here.
Firstly, the `paint` method can take _either_ an owned `String` or a borrowed `&str`.
Internally, an `ANSIString` holds a copy-on-write (`Cow`) string value to deal with both owned and borrowed strings at the same time.
This is used here to display a `String`, the result of the `format!` call, using the same mechanism as some statically-available `&str` slices.
Secondly, that the `ANSIStrings` value works in the same way as its singular counterpart, with a `Display` implementation that only performs the formatting when required.
## Byte strings
This library also supports formatting `[u8]` byte strings; this supports applications working with text in an unknown encoding.
`Style` and `Color` support painting `[u8]` values, resulting in an `ANSIByteString`.
This type does not implement `Display`, as it may not contain UTF-8, but it does provide a method `write_to` to write the result to any value that implements `Write`:
```rust
use nu_ansi_term::Color::Green;
Green.paint("user data".as_bytes()).write_to(&mut std::io::stdout()).unwrap();
```
Similarly, the type `ANSIByteStrings` supports writing a list of `ANSIByteString` values with minimal escape sequences:
```rust
use nu_ansi_term::Color::Green;
use nu_ansi_term::ANSIByteStrings;
ANSIByteStrings(&[
Green.paint("user data 1\n".as_bytes()),
Green.bold().paint("user data 2\n".as_bytes()),
]).write_to(&mut std::io::stdout()).unwrap();
```

View File

@ -0,0 +1,72 @@
extern crate nu_ansi_term;
use nu_ansi_term::Color;
// This example prints out the 256 colors.
// They're arranged like this:
//
// - 0 to 8 are the eight standard colors.
// - 9 to 15 are the eight bold colors.
// - 16 to 231 are six blocks of six-by-six color squares.
// - 232 to 255 are shades of grey.
fn main() {
// First two lines
for c in 0..8 {
glow(c, c != 0);
print!(" ");
}
println!();
for c in 8..16 {
glow(c, c != 8);
print!(" ");
}
println!("\n");
// Six lines of the first three squares
for row in 0..6 {
for square in 0..3 {
for column in 0..6 {
glow(16 + square * 36 + row * 6 + column, row >= 3);
print!(" ");
}
print!(" ");
}
println!();
}
println!();
// Six more lines of the other three squares
for row in 0..6 {
for square in 0..3 {
for column in 0..6 {
glow(124 + square * 36 + row * 6 + column, row >= 3);
print!(" ");
}
print!(" ");
}
println!();
}
println!();
// The last greyscale lines
for c in 232..=243 {
glow(c, false);
print!(" ");
}
println!();
for c in 244..=255 {
glow(c, true);
print!(" ");
}
println!();
}
fn glow(c: u8, light_bg: bool) {
let base = if light_bg { Color::Black } else { Color::White };
let style = base.on(Color::Fixed(c));
print!("{}", style.paint(&format!(" {:3} ", c)));
}

View File

@ -0,0 +1,18 @@
extern crate nu_ansi_term;
use nu_ansi_term::{Color::*, Style};
// This example prints out the 16 basic colors.
fn main() {
let normal = Style::default();
println!("{} {}", normal.paint("Normal"), normal.bold().paint("bold"));
println!("{} {}", Black.paint("Black"), Black.bold().paint("bold"));
println!("{} {}", Red.paint("Red"), Red.bold().paint("bold"));
println!("{} {}", Green.paint("Green"), Green.bold().paint("bold"));
println!("{} {}", Yellow.paint("Yellow"), Yellow.bold().paint("bold"));
println!("{} {}", Blue.paint("Blue"), Blue.bold().paint("bold"));
println!("{} {}", Purple.paint("Purple"), Purple.bold().paint("bold"));
println!("{} {}", Cyan.paint("Cyan"), Cyan.bold().paint("bold"));
println!("{} {}", White.paint("White"), White.bold().paint("bold"));
}

View File

@ -0,0 +1,37 @@
use nu_ansi_term::{build_all_gradient_text, Color, Gradient, Rgb, TargetGround};
fn main() {
let text = "lorem ipsum quia dolor sit amet, consectetur, adipisci velit";
// a gradient from hex colors
let start = Rgb::from_hex(0x40c9ff);
let end = Rgb::from_hex(0xe81cff);
let grad0 = Gradient::new(start, end);
// a gradient from color::rgb()
let start = Color::Rgb(64, 201, 255);
let end = Color::Rgb(232, 28, 255);
let gradient = Gradient::from_color_rgb(start, end);
// a slightly different gradient
let start2 = Color::Rgb(128, 64, 255);
let end2 = Color::Rgb(0, 28, 255);
let gradient2 = Gradient::from_color_rgb(start2, end2);
// reverse the gradient
let gradient3 = gradient.reverse();
let build_fg = gradient.build(text, TargetGround::Foreground);
println!("{}", build_fg);
let build_bg = gradient.build(text, TargetGround::Background);
println!("{}", build_bg);
let bgt = build_all_gradient_text(text, gradient, gradient2);
println!("{}", bgt);
let bgt2 = build_all_gradient_text(text, gradient, gradient3);
println!("{}", bgt2);
println!(
"{}",
grad0.build("nushell is awesome", TargetGround::Foreground)
);
}

View File

@ -0,0 +1,23 @@
extern crate nu_ansi_term;
use nu_ansi_term::{Color, Style};
// This example prints out a color gradient in a grid by calculating each
// characters red, green, and blue components, and using 24-bit color codes
// to display them.
const WIDTH: i32 = 80;
const HEIGHT: i32 = 24;
fn main() {
for row in 0..HEIGHT {
for col in 0..WIDTH {
let r = (row * 255 / HEIGHT) as u8;
let g = (col * 255 / WIDTH) as u8;
let b = 128;
print!("{}", Style::default().on(Color::Rgb(r, g, b)).paint(" "));
}
println!();
}
}

View File

@ -0,0 +1,405 @@
#![allow(missing_docs)]
use crate::style::{Color, Style};
use crate::write::AnyWrite;
use std::fmt;
impl Style {
/// Write any bytes that go *before* a piece of text to the given writer.
fn write_prefix<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
// If there are actually no styles here, then dont write *any* codes
// as the prefix. An empty ANSI code may not affect the terminal
// output at all, but a user may just want a code-free string.
if self.is_plain() {
return Ok(());
}
// Write the codes prefix, then write numbers, separated by
// semicolons, for each text style we want to apply.
write!(f, "\x1B[")?;
let mut written_anything = false;
{
let mut write_char = |c| {
if written_anything {
write!(f, ";")?;
}
written_anything = true;
write!(f, "{}", c)?;
Ok(())
};
if self.is_bold {
write_char('1')?
}
if self.is_dimmed {
write_char('2')?
}
if self.is_italic {
write_char('3')?
}
if self.is_underline {
write_char('4')?
}
if self.is_blink {
write_char('5')?
}
if self.is_reverse {
write_char('7')?
}
if self.is_hidden {
write_char('8')?
}
if self.is_strikethrough {
write_char('9')?
}
}
// The foreground and background colors, if specified, need to be
// handled specially because the number codes are more complicated.
// (see `write_background_code` and `write_foreground_code`)
if let Some(bg) = self.background {
if written_anything {
write!(f, ";")?;
}
written_anything = true;
bg.write_background_code(f)?;
}
if let Some(fg) = self.foreground {
if written_anything {
write!(f, ";")?;
}
fg.write_foreground_code(f)?;
}
// All the codes end with an `m`, because reasons.
write!(f, "m")?;
Ok(())
}
/// Write any bytes that go *after* a piece of text to the given writer.
fn write_suffix<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
if self.is_plain() {
Ok(())
} else {
write!(f, "{}", RESET)
}
}
}
/// The code to send to reset all styles and return to `Style::default()`.
pub static RESET: &str = "\x1B[0m";
impl Color {
fn write_foreground_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
match self {
Color::Black => write!(f, "30"),
Color::Red => write!(f, "31"),
Color::Green => write!(f, "32"),
Color::Yellow => write!(f, "33"),
Color::Blue => write!(f, "34"),
Color::Purple => write!(f, "35"),
Color::Magenta => write!(f, "35"),
Color::Cyan => write!(f, "36"),
Color::White => write!(f, "37"),
Color::Fixed(num) => write!(f, "38;5;{}", num),
Color::Rgb(r, g, b) => write!(f, "38;2;{};{};{}", r, g, b),
Color::DarkGray => write!(f, "90"),
Color::LightRed => write!(f, "91"),
Color::LightGreen => write!(f, "92"),
Color::LightYellow => write!(f, "93"),
Color::LightBlue => write!(f, "94"),
Color::LightPurple => write!(f, "95"),
Color::LightMagenta => write!(f, "95"),
Color::LightCyan => write!(f, "96"),
Color::LightGray => write!(f, "97"),
}
}
fn write_background_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
match self {
Color::Black => write!(f, "40"),
Color::Red => write!(f, "41"),
Color::Green => write!(f, "42"),
Color::Yellow => write!(f, "43"),
Color::Blue => write!(f, "44"),
Color::Purple => write!(f, "45"),
Color::Magenta => write!(f, "45"),
Color::Cyan => write!(f, "46"),
Color::White => write!(f, "47"),
Color::Fixed(num) => write!(f, "48;5;{}", num),
Color::Rgb(r, g, b) => write!(f, "48;2;{};{};{}", r, g, b),
Color::DarkGray => write!(f, "100"),
Color::LightRed => write!(f, "101"),
Color::LightGreen => write!(f, "102"),
Color::LightYellow => write!(f, "103"),
Color::LightBlue => write!(f, "104"),
Color::LightPurple => write!(f, "105"),
Color::LightMagenta => write!(f, "105"),
Color::LightCyan => write!(f, "106"),
Color::LightGray => write!(f, "107"),
}
}
}
/// Like `ANSIString`, but only displays the style prefix.
///
/// This type implements the `Display` trait, meaning it can be written to a
/// `std::fmt` formatting without doing any extra allocation, and written to a
/// string with the `.to_string()` method. For examples, see
/// [`Style::prefix`](struct.Style.html#method.prefix).
#[derive(Clone, Copy, Debug)]
pub struct Prefix(Style);
/// Like `ANSIString`, but only displays the difference between two
/// styles.
///
/// This type implements the `Display` trait, meaning it can be written to a
/// `std::fmt` formatting without doing any extra allocation, and written to a
/// string with the `.to_string()` method. For examples, see
/// [`Style::infix`](struct.Style.html#method.infix).
#[derive(Clone, Copy, Debug)]
pub struct Infix(Style, Style);
/// Like `ANSIString`, but only displays the style suffix.
///
/// This type implements the `Display` trait, meaning it can be written to a
/// `std::fmt` formatting without doing any extra allocation, and written to a
/// string with the `.to_string()` method. For examples, see
/// [`Style::suffix`](struct.Style.html#method.suffix).
#[derive(Clone, Copy, Debug)]
pub struct Suffix(Style);
impl Style {
/// The prefix bytes for this style. These are the bytes that tell the
/// terminal to use a different color or font style.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::{Style, Color::Blue};
///
/// let style = Style::default().bold();
/// assert_eq!("\x1b[1m",
/// style.prefix().to_string());
///
/// let style = Blue.bold();
/// assert_eq!("\x1b[1;34m",
/// style.prefix().to_string());
///
/// let style = Style::default();
/// assert_eq!("",
/// style.prefix().to_string());
/// ```
pub fn prefix(self) -> Prefix {
Prefix(self)
}
/// The infix bytes between this style and `next` style. These are the bytes
/// that tell the terminal to change the style to `next`. These may include
/// a reset followed by the next color and style, depending on the two styles.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::{Style, Color::Green};
///
/// let style = Style::default().bold();
/// assert_eq!("\x1b[32m",
/// style.infix(Green.bold()).to_string());
///
/// let style = Green.normal();
/// assert_eq!("\x1b[1m",
/// style.infix(Green.bold()).to_string());
///
/// let style = Style::default();
/// assert_eq!("",
/// style.infix(style).to_string());
/// ```
pub fn infix(self, next: Style) -> Infix {
Infix(self, next)
}
/// The suffix for this style. These are the bytes that tell the terminal
/// to reset back to its normal color and font style.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::{Style, Color::Green};
///
/// let style = Style::default().bold();
/// assert_eq!("\x1b[0m",
/// style.suffix().to_string());
///
/// let style = Green.normal().bold();
/// assert_eq!("\x1b[0m",
/// style.suffix().to_string());
///
/// let style = Style::default();
/// assert_eq!("",
/// style.suffix().to_string());
/// ```
pub fn suffix(self) -> Suffix {
Suffix(self)
}
}
impl Color {
/// The prefix bytes for this color as a `Style`. These are the bytes
/// that tell the terminal to use a different color or font style.
///
/// See also [`Style::prefix`](struct.Style.html#method.prefix).
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color::Green;
///
/// assert_eq!("\x1b[0m",
/// Green.suffix().to_string());
/// ```
pub fn prefix(self) -> Prefix {
Prefix(self.normal())
}
/// The infix bytes between this color and `next` color. These are the bytes
/// that tell the terminal to use the `next` color, or to do nothing if
/// the two colors are equal.
///
/// See also [`Style::infix`](struct.Style.html#method.infix).
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color::{Red, Yellow};
///
/// assert_eq!("\x1b[33m",
/// Red.infix(Yellow).to_string());
/// ```
pub fn infix(self, next: Color) -> Infix {
Infix(self.normal(), next.normal())
}
/// The suffix for this color as a `Style`. These are the bytes that
/// tell the terminal to reset back to its normal color and font style.
///
/// See also [`Style::suffix`](struct.Style.html#method.suffix).
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color::Purple;
///
/// assert_eq!("\x1b[0m",
/// Purple.suffix().to_string());
/// ```
pub fn suffix(self) -> Suffix {
Suffix(self.normal())
}
}
impl fmt::Display for Prefix {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let f: &mut dyn fmt::Write = f;
self.0.write_prefix(f)
}
}
impl fmt::Display for Infix {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use crate::difference::Difference;
match Difference::between(&self.0, &self.1) {
Difference::ExtraStyles(style) => {
let f: &mut dyn fmt::Write = f;
style.write_prefix(f)
}
Difference::Reset => {
let f: &mut dyn fmt::Write = f;
write!(f, "{}{}", RESET, self.1.prefix())
}
Difference::Empty => {
Ok(()) // nothing to write
}
}
}
}
impl fmt::Display for Suffix {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let f: &mut dyn fmt::Write = f;
self.0.write_suffix(f)
}
}
#[cfg(test)]
mod test {
use crate::style::Color::*;
use crate::style::Style;
macro_rules! test {
($name: ident: $style: expr; $input: expr => $result: expr) => {
#[test]
fn $name() {
assert_eq!($style.paint($input).to_string(), $result.to_string());
let mut v = Vec::new();
$style.paint($input.as_bytes()).write_to(&mut v).unwrap();
assert_eq!(v.as_slice(), $result.as_bytes());
}
};
}
test!(plain: Style::default(); "text/plain" => "text/plain");
test!(red: Red; "hi" => "\x1B[31mhi\x1B[0m");
test!(black: Black.normal(); "hi" => "\x1B[30mhi\x1B[0m");
test!(yellow_bold: Yellow.bold(); "hi" => "\x1B[1;33mhi\x1B[0m");
test!(yellow_bold_2: Yellow.normal().bold(); "hi" => "\x1B[1;33mhi\x1B[0m");
test!(blue_underline: Blue.underline(); "hi" => "\x1B[4;34mhi\x1B[0m");
test!(green_bold_ul: Green.bold().underline(); "hi" => "\x1B[1;4;32mhi\x1B[0m");
test!(green_bold_ul_2: Green.underline().bold(); "hi" => "\x1B[1;4;32mhi\x1B[0m");
test!(purple_on_white: Purple.on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(purple_on_white_2: Purple.normal().on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(yellow_on_blue: Style::new().on(Blue).fg(Yellow); "hi" => "\x1B[44;33mhi\x1B[0m");
test!(magenta_on_white: Magenta.on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(magenta_on_white_2: Magenta.normal().on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(yellow_on_blue_2: Cyan.on(Blue).fg(Yellow); "hi" => "\x1B[44;33mhi\x1B[0m");
test!(cyan_bold_on_white: Cyan.bold().on(White); "hi" => "\x1B[1;47;36mhi\x1B[0m");
test!(cyan_ul_on_white: Cyan.underline().on(White); "hi" => "\x1B[4;47;36mhi\x1B[0m");
test!(cyan_bold_ul_on_white: Cyan.bold().underline().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m");
test!(cyan_ul_bold_on_white: Cyan.underline().bold().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m");
test!(fixed: Fixed(100); "hi" => "\x1B[38;5;100mhi\x1B[0m");
test!(fixed_on_purple: Fixed(100).on(Purple); "hi" => "\x1B[45;38;5;100mhi\x1B[0m");
test!(fixed_on_fixed: Fixed(100).on(Fixed(200)); "hi" => "\x1B[48;5;200;38;5;100mhi\x1B[0m");
test!(rgb: Rgb(70,130,180); "hi" => "\x1B[38;2;70;130;180mhi\x1B[0m");
test!(rgb_on_blue: Rgb(70,130,180).on(Blue); "hi" => "\x1B[44;38;2;70;130;180mhi\x1B[0m");
test!(blue_on_rgb: Blue.on(Rgb(70,130,180)); "hi" => "\x1B[48;2;70;130;180;34mhi\x1B[0m");
test!(rgb_on_rgb: Rgb(70,130,180).on(Rgb(5,10,15)); "hi" => "\x1B[48;2;5;10;15;38;2;70;130;180mhi\x1B[0m");
test!(bold: Style::new().bold(); "hi" => "\x1B[1mhi\x1B[0m");
test!(underline: Style::new().underline(); "hi" => "\x1B[4mhi\x1B[0m");
test!(bunderline: Style::new().bold().underline(); "hi" => "\x1B[1;4mhi\x1B[0m");
test!(dimmed: Style::new().dimmed(); "hi" => "\x1B[2mhi\x1B[0m");
test!(italic: Style::new().italic(); "hi" => "\x1B[3mhi\x1B[0m");
test!(blink: Style::new().blink(); "hi" => "\x1B[5mhi\x1B[0m");
test!(reverse: Style::new().reverse(); "hi" => "\x1B[7mhi\x1B[0m");
test!(hidden: Style::new().hidden(); "hi" => "\x1B[8mhi\x1B[0m");
test!(stricken: Style::new().strikethrough(); "hi" => "\x1B[9mhi\x1B[0m");
test!(lr_on_lr: LightRed.on(LightRed); "hi" => "\x1B[101;91mhi\x1B[0m");
#[test]
fn test_infix() {
assert_eq!(
Style::new().dimmed().infix(Style::new()).to_string(),
"\x1B[0m"
);
assert_eq!(
White.dimmed().infix(White.normal()).to_string(),
"\x1B[0m\x1B[37m"
);
assert_eq!(White.normal().infix(White.bold()).to_string(), "\x1B[1m");
assert_eq!(White.normal().infix(Blue.normal()).to_string(), "\x1B[34m");
assert_eq!(Blue.bold().infix(Blue.bold()).to_string(), "");
}
}

View File

@ -0,0 +1,152 @@
use crate::style::Style;
use std::fmt;
/// Styles have a special `Debug` implementation that only shows the fields that
/// are set. Fields that havent been touched arent included in the output.
///
/// This behaviour gets bypassed when using the alternate formatting mode
/// `format!("{:#?}")`.
///
/// use nu_ansi_term::Color::{Red, Blue};
/// assert_eq!("Style { fg(Red), on(Blue), bold, italic }",
/// format!("{:?}", Red.on(Blue).bold().italic()));
impl fmt::Debug for Style {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
if fmt.alternate() {
fmt.debug_struct("Style")
.field("foreground", &self.foreground)
.field("background", &self.background)
.field("blink", &self.is_blink)
.field("bold", &self.is_bold)
.field("dimmed", &self.is_dimmed)
.field("hidden", &self.is_hidden)
.field("italic", &self.is_italic)
.field("reverse", &self.is_reverse)
.field("strikethrough", &self.is_strikethrough)
.field("underline", &self.is_underline)
.finish()
} else if self.is_plain() {
fmt.write_str("Style {}")
} else {
fmt.write_str("Style { ")?;
let mut written_anything = false;
if let Some(fg) = self.foreground {
if written_anything {
fmt.write_str(", ")?
}
written_anything = true;
write!(fmt, "fg({:?})", fg)?
}
if let Some(bg) = self.background {
if written_anything {
fmt.write_str(", ")?
}
written_anything = true;
write!(fmt, "on({:?})", bg)?
}
{
let mut write_flag = |name| {
if written_anything {
fmt.write_str(", ")?
}
written_anything = true;
fmt.write_str(name)
};
if self.is_blink {
write_flag("blink")?
}
if self.is_bold {
write_flag("bold")?
}
if self.is_dimmed {
write_flag("dimmed")?
}
if self.is_hidden {
write_flag("hidden")?
}
if self.is_italic {
write_flag("italic")?
}
if self.is_reverse {
write_flag("reverse")?
}
if self.is_strikethrough {
write_flag("strikethrough")?
}
if self.is_underline {
write_flag("underline")?
}
}
write!(fmt, " }}")
}
}
}
#[cfg(test)]
mod test {
use crate::style::Color::*;
use crate::style::Style;
fn style() -> Style {
Style::new()
}
macro_rules! test {
($name: ident: $obj: expr => $result: expr) => {
#[test]
fn $name() {
assert_eq!($result, format!("{:?}", $obj));
}
};
}
test!(empty: style() => "Style {}");
test!(bold: style().bold() => "Style { bold }");
test!(italic: style().italic() => "Style { italic }");
test!(both: style().bold().italic() => "Style { bold, italic }");
test!(red: Red.normal() => "Style { fg(Red) }");
test!(redblue: Red.normal().on(Rgb(3, 2, 4)) => "Style { fg(Red), on(Rgb(3, 2, 4)) }");
test!(everything:
Red.on(Blue).blink().bold().dimmed().hidden().italic().reverse().strikethrough().underline() =>
"Style { fg(Red), on(Blue), blink, bold, dimmed, hidden, italic, reverse, strikethrough, underline }");
#[test]
fn long_and_detailed() {
extern crate regex;
let expected_debug = "Style { fg(Blue), bold }";
let expected_pretty_repat = r##"(?x)
Style\s+\{\s+
foreground:\s+Some\(\s+
Blue,?\s+
\),\s+
background:\s+None,\s+
blink:\s+false,\s+
bold:\s+true,\s+
dimmed:\s+false,\s+
hidden:\s+false,\s+
italic:\s+false,\s+
reverse:\s+false,\s+
strikethrough:\s+
false,\s+
underline:\s+false,?\s+
\}"##;
let re = regex::Regex::new(expected_pretty_repat).unwrap();
let style = Blue.bold();
let style_fmt_debug = format!("{:?}", style);
let style_fmt_pretty = format!("{:#?}", style);
println!("style_fmt_debug:\n{}", style_fmt_debug);
println!("style_fmt_pretty:\n{}", style_fmt_pretty);
assert_eq!(expected_debug, style_fmt_debug);
assert!(re.is_match(&style_fmt_pretty));
}
}

View File

@ -0,0 +1,174 @@
use super::Style;
/// When printing out one colored string followed by another, use one of
/// these rules to figure out which *extra* control codes need to be sent.
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum Difference {
/// Print out the control codes specified by this style to end up looking
/// like the second string's styles.
ExtraStyles(Style),
/// Converting between these two is impossible, so just send a reset
/// command and then the second string's styles.
Reset,
/// The before style is exactly the same as the after style, so no further
/// control codes need to be printed.
Empty,
}
impl Difference {
/// Compute the 'style difference' required to turn an existing style into
/// the given, second style.
///
/// For example, to turn green text into green bold text, it's redundant
/// to write a reset command then a second green+bold command, instead of
/// just writing one bold command. This method should see that both styles
/// use the foreground color green, and reduce it to a single command.
///
/// This method returns an enum value because it's not actually always
/// possible to turn one style into another: for example, text could be
/// made bold and underlined, but you can't remove the bold property
/// without also removing the underline property. So when this has to
/// happen, this function returns None, meaning that the entire set of
/// styles should be reset and begun again.
pub fn between(first: &Style, next: &Style) -> Difference {
use self::Difference::*;
// XXX(Havvy): This algorithm is kind of hard to replicate without
// having the Plain/Foreground enum variants, so I'm just leaving
// it commented out for now, and defaulting to Reset.
if first == next {
return Empty;
}
// Cannot un-bold, so must Reset.
if first.is_bold && !next.is_bold {
return Reset;
}
if first.is_dimmed && !next.is_dimmed {
return Reset;
}
if first.is_italic && !next.is_italic {
return Reset;
}
// Cannot un-underline, so must Reset.
if first.is_underline && !next.is_underline {
return Reset;
}
if first.is_blink && !next.is_blink {
return Reset;
}
if first.is_reverse && !next.is_reverse {
return Reset;
}
if first.is_hidden && !next.is_hidden {
return Reset;
}
if first.is_strikethrough && !next.is_strikethrough {
return Reset;
}
// Cannot go from foreground to no foreground, so must Reset.
if first.foreground.is_some() && next.foreground.is_none() {
return Reset;
}
// Cannot go from background to no background, so must Reset.
if first.background.is_some() && next.background.is_none() {
return Reset;
}
let mut extra_styles = Style::default();
if first.is_bold != next.is_bold {
extra_styles.is_bold = true;
}
if first.is_dimmed != next.is_dimmed {
extra_styles.is_dimmed = true;
}
if first.is_italic != next.is_italic {
extra_styles.is_italic = true;
}
if first.is_underline != next.is_underline {
extra_styles.is_underline = true;
}
if first.is_blink != next.is_blink {
extra_styles.is_blink = true;
}
if first.is_reverse != next.is_reverse {
extra_styles.is_reverse = true;
}
if first.is_hidden != next.is_hidden {
extra_styles.is_hidden = true;
}
if first.is_strikethrough != next.is_strikethrough {
extra_styles.is_strikethrough = true;
}
if first.foreground != next.foreground {
extra_styles.foreground = next.foreground;
}
if first.background != next.background {
extra_styles.background = next.background;
}
ExtraStyles(extra_styles)
}
}
#[cfg(test)]
mod test {
use super::Difference::*;
use super::*;
use crate::style::Color::*;
use crate::style::Style;
fn style() -> Style {
Style::new()
}
macro_rules! test {
($name: ident: $first: expr; $next: expr => $result: expr) => {
#[test]
fn $name() {
assert_eq!($result, Difference::between(&$first, &$next));
}
};
}
test!(nothing: Green.normal(); Green.normal() => Empty);
test!(uppercase: Green.normal(); Green.bold() => ExtraStyles(style().bold()));
test!(lowercase: Green.bold(); Green.normal() => Reset);
test!(nothing2: Green.bold(); Green.bold() => Empty);
test!(color_change: Red.normal(); Blue.normal() => ExtraStyles(Blue.normal()));
test!(addition_of_blink: style(); style().blink() => ExtraStyles(style().blink()));
test!(addition_of_dimmed: style(); style().dimmed() => ExtraStyles(style().dimmed()));
test!(addition_of_hidden: style(); style().hidden() => ExtraStyles(style().hidden()));
test!(addition_of_reverse: style(); style().reverse() => ExtraStyles(style().reverse()));
test!(addition_of_strikethrough: style(); style().strikethrough() => ExtraStyles(style().strikethrough()));
test!(removal_of_strikethrough: style().strikethrough(); style() => Reset);
test!(removal_of_reverse: style().reverse(); style() => Reset);
test!(removal_of_hidden: style().hidden(); style() => Reset);
test!(removal_of_dimmed: style().dimmed(); style() => Reset);
test!(removal_of_blink: style().blink(); style() => Reset);
}

View File

@ -0,0 +1,303 @@
use crate::ansi::RESET;
use crate::difference::Difference;
use crate::style::{Color, Style};
use crate::write::AnyWrite;
use std::borrow::Cow;
use std::fmt;
use std::io;
use std::ops::Deref;
/// An `ANSIGenericString` includes a generic string type and a `Style` to
/// display that string. `ANSIString` and `ANSIByteString` are aliases for
/// this type on `str` and `\[u8]`, respectively.
#[derive(PartialEq, Debug)]
pub struct AnsiGenericString<'a, S: 'a + ToOwned + ?Sized>
where
<S as ToOwned>::Owned: fmt::Debug,
{
style: Style,
string: Cow<'a, S>,
}
/// Cloning an `ANSIGenericString` will clone its underlying string.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::ANSIString;
///
/// let plain_string = ANSIString::from("a plain string");
/// let clone_string = plain_string.clone();
/// assert_eq!(clone_string, plain_string);
/// ```
impl<'a, S: 'a + ToOwned + ?Sized> Clone for AnsiGenericString<'a, S>
where
<S as ToOwned>::Owned: fmt::Debug,
{
fn clone(&self) -> AnsiGenericString<'a, S> {
AnsiGenericString {
style: self.style,
string: self.string.clone(),
}
}
}
// You might think that the hand-written Clone impl above is the same as the
// one that gets generated with #[derive]. But its not *quite* the same!
//
// `str` is not Clone, and the derived Clone implementation puts a Clone
// constraint on the S type parameter (generated using --pretty=expanded):
//
// ↓_________________↓
// impl <'a, S: ::std::clone::Clone + 'a + ToOwned + ?Sized> ::std::clone::Clone
// for ANSIGenericString<'a, S> where
// <S as ToOwned>::Owned: fmt::Debug { ... }
//
// This resulted in compile errors when you tried to derive Clone on a type
// that used it:
//
// #[derive(PartialEq, Debug, Clone, Default)]
// pub struct TextCellContents(Vec<ANSIString<'static>>);
// ^^^^^^^^^^^^^^^^^^^^^^^^^
// error[E0277]: the trait `std::clone::Clone` is not implemented for `str`
//
// The hand-written impl above can ignore that constraint and still compile.
/// An ANSI String is a string coupled with the `Style` to display it
/// in a terminal.
///
/// Although not technically a string itself, it can be turned into
/// one with the `to_string` method.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::ANSIString;
/// use nu_ansi_term::Color::Red;
///
/// let red_string = Red.paint("a red string");
/// println!("{}", red_string);
/// ```
///
/// ```
/// use nu_ansi_term::ANSIString;
///
/// let plain_string = ANSIString::from("a plain string");
/// assert_eq!(&*plain_string, "a plain string");
/// ```
pub type AnsiString<'a> = AnsiGenericString<'a, str>;
/// An `AnsiByteString` represents a formatted series of bytes. Use
/// `AnsiByteString` when styling text with an unknown encoding.
pub type AnsiByteString<'a> = AnsiGenericString<'a, [u8]>;
impl<'a, I, S: 'a + ToOwned + ?Sized> From<I> for AnsiGenericString<'a, S>
where
I: Into<Cow<'a, S>>,
<S as ToOwned>::Owned: fmt::Debug,
{
fn from(input: I) -> AnsiGenericString<'a, S> {
AnsiGenericString {
string: input.into(),
style: Style::default(),
}
}
}
impl<'a, S: 'a + ToOwned + ?Sized> AnsiGenericString<'a, S>
where
<S as ToOwned>::Owned: fmt::Debug,
{
/// Directly access the style
pub fn style_ref(&self) -> &Style {
&self.style
}
/// Directly access the style mutably
pub fn style_ref_mut(&mut self) -> &mut Style {
&mut self.style
}
}
impl<'a, S: 'a + ToOwned + ?Sized> Deref for AnsiGenericString<'a, S>
where
<S as ToOwned>::Owned: fmt::Debug,
{
type Target = S;
fn deref(&self) -> &S {
self.string.deref()
}
}
/// A set of `AnsiGenericStrings`s collected together, in order to be
/// written with a minimum of control characters.
#[derive(Debug, PartialEq)]
pub struct AnsiGenericStrings<'a, S: 'a + ToOwned + ?Sized>(pub &'a [AnsiGenericString<'a, S>])
where
<S as ToOwned>::Owned: fmt::Debug,
S: PartialEq;
/// A set of `AnsiString`s collected together, in order to be written with a
/// minimum of control characters.
pub type AnsiStrings<'a> = AnsiGenericStrings<'a, str>;
/// A function to construct an `AnsiStrings` instance.
#[allow(non_snake_case)]
pub fn AnsiStrings<'a>(arg: &'a [AnsiString<'a>]) -> AnsiStrings<'a> {
AnsiGenericStrings(arg)
}
/// A set of `AnsiByteString`s collected together, in order to be
/// written with a minimum of control characters.
pub type AnsiByteStrings<'a> = AnsiGenericStrings<'a, [u8]>;
/// A function to construct an `ANSIByteStrings` instance.
#[allow(non_snake_case)]
pub fn ANSIByteStrings<'a>(arg: &'a [AnsiByteString<'a>]) -> AnsiByteStrings<'a> {
AnsiGenericStrings(arg)
}
// ---- paint functions ----
impl Style {
/// Paints the given text with this color, returning an ANSI string.
#[must_use]
pub fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> AnsiGenericString<'a, S>
where
I: Into<Cow<'a, S>>,
<S as ToOwned>::Owned: fmt::Debug,
{
AnsiGenericString {
string: input.into(),
style: self,
}
}
}
impl Color {
/// Paints the given text with this color, returning an ANSI string.
/// This is a short-cut so you dont have to use `Blue.normal()` just
/// to get blue text.
///
/// ```
/// use nu_ansi_term::Color::Blue;
/// println!("{}", Blue.paint("da ba dee"));
/// ```
#[must_use]
pub fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> AnsiGenericString<'a, S>
where
I: Into<Cow<'a, S>>,
<S as ToOwned>::Owned: fmt::Debug,
{
AnsiGenericString {
string: input.into(),
style: self.normal(),
}
}
}
// ---- writers for individual ANSI strings ----
impl<'a> fmt::Display for AnsiString<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let w: &mut dyn fmt::Write = f;
self.write_to_any(w)
}
}
impl<'a> AnsiByteString<'a> {
/// Write an `ANSIByteString` to an `io::Write`. This writes the escape
/// sequences for the associated `Style` around the bytes.
pub fn write_to<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
let w: &mut dyn io::Write = w;
self.write_to_any(w)
}
}
impl<'a, S: 'a + ToOwned + ?Sized> AnsiGenericString<'a, S>
where
<S as ToOwned>::Owned: fmt::Debug,
&'a S: AsRef<[u8]>,
{
fn write_to_any<W: AnyWrite<Wstr = S> + ?Sized>(&self, w: &mut W) -> Result<(), W::Error> {
write!(w, "{}", self.style.prefix())?;
w.write_str(self.string.as_ref())?;
write!(w, "{}", self.style.suffix())
}
}
// ---- writers for combined ANSI strings ----
impl<'a> fmt::Display for AnsiStrings<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let f: &mut dyn fmt::Write = f;
self.write_to_any(f)
}
}
impl<'a> AnsiByteStrings<'a> {
/// Write `ANSIByteStrings` to an `io::Write`. This writes the minimal
/// escape sequences for the associated `Style`s around each set of
/// bytes.
pub fn write_to<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
let w: &mut dyn io::Write = w;
self.write_to_any(w)
}
}
impl<'a, S: 'a + ToOwned + ?Sized + PartialEq> AnsiGenericStrings<'a, S>
where
<S as ToOwned>::Owned: fmt::Debug,
&'a S: AsRef<[u8]>,
{
fn write_to_any<W: AnyWrite<Wstr = S> + ?Sized>(&self, w: &mut W) -> Result<(), W::Error> {
use self::Difference::*;
let first = match self.0.first() {
None => return Ok(()),
Some(f) => f,
};
write!(w, "{}", first.style.prefix())?;
w.write_str(first.string.as_ref())?;
for window in self.0.windows(2) {
match Difference::between(&window[0].style, &window[1].style) {
ExtraStyles(style) => write!(w, "{}", style.prefix())?,
Reset => write!(w, "{}{}", RESET, window[1].style.prefix())?,
Empty => { /* Do nothing! */ }
}
w.write_str(&window[1].string)?;
}
// Write the final reset string after all of the ANSIStrings have been
// written, *except* if the last one has no styles, because it would
// have already been written by this point.
if let Some(last) = self.0.last() {
if !last.style.is_plain() {
write!(w, "{}", RESET)?;
}
}
Ok(())
}
}
// ---- tests ----
#[cfg(test)]
mod tests {
pub use super::super::AnsiStrings;
pub use crate::style::Color::*;
pub use crate::style::Style;
#[test]
fn no_control_codes_for_plain() {
let one = Style::default().paint("one");
let two = Style::default().paint("two");
let output = AnsiStrings(&[one, two]).to_string();
assert_eq!(output, "onetwo");
}
}

View File

@ -0,0 +1,105 @@
use crate::{rgb::Rgb, Color};
/// Linear color gradient between two color stops
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Gradient {
/// Start Color of Gradient
pub start: Rgb,
/// End Color of Gradient
pub end: Rgb,
}
impl Gradient {
/// Creates a new [Gradient] with two [Rgb] colors, `start` and `end`
#[inline]
pub const fn new(start: Rgb, end: Rgb) -> Self {
Self { start, end }
}
pub const fn from_color_rgb(start: Color, end: Color) -> Self {
let start_grad = match start {
Color::Rgb(r, g, b) => Rgb { r, g, b },
_ => Rgb { r: 0, g: 0, b: 0 },
};
let end_grad = match end {
Color::Rgb(r, g, b) => Rgb { r, g, b },
_ => Rgb { r: 0, g: 0, b: 0 },
};
Self {
start: start_grad,
end: end_grad,
}
}
/// Computes the [Rgb] color between `start` and `end` for `t`
pub fn at(&self, t: f32) -> Rgb {
self.start.lerp(self.end, t)
}
/// Returns the reverse of `self`
#[inline]
pub const fn reverse(&self) -> Self {
Self::new(self.end, self.start)
}
#[allow(dead_code)]
pub fn build(&self, text: &str, target: TargetGround) -> String {
let delta = 1.0 / text.len() as f32;
let mut result = text.char_indices().fold(String::new(), |mut acc, (i, c)| {
let temp = format!(
"\x1B[{}m{}",
self.at(i as f32 * delta).ansi_color_code(target),
c
);
acc.push_str(&temp);
acc
});
result.push_str("\x1B[0m");
result
}
}
#[allow(dead_code)]
pub fn build_all_gradient_text(text: &str, foreground: Gradient, background: Gradient) -> String {
let delta = 1.0 / text.len() as f32;
let mut result = text.char_indices().fold(String::new(), |mut acc, (i, c)| {
let step = i as f32 * delta;
let temp = format!(
"\x1B[{};{}m{}",
foreground
.at(step)
.ansi_color_code(TargetGround::Foreground),
background
.at(step)
.ansi_color_code(TargetGround::Background),
c
);
acc.push_str(&temp);
acc
});
result.push_str("\x1B[0m");
result
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TargetGround {
Foreground,
Background,
}
impl TargetGround {
#[inline]
pub const fn code(&self) -> u8 {
match self {
Self::Foreground => 30,
Self::Background => 40,
}
}
}
pub trait ANSIColorCode {
fn ansi_color_code(&self, target: TargetGround) -> String;
}

View File

@ -0,0 +1,272 @@
//! This is a library for controlling colors and formatting, such as
//! red bold text or blue underlined text, on ANSI terminals.
//!
//!
//! ## Basic usage
//!
//! There are three main types in this crate that you need to be
//! concerned with: [`ANSIString`], [`Style`], and [`Color`].
//!
//! A `Style` holds stylistic information: foreground and background colors,
//! whether the text should be bold, or blinking, or other properties. The
//! [`Color`] enum represents the available colors. And an [`ANSIString`] is a
//! string paired with a [`Style`].
//!
//! [`Color`] is also available as an alias to `Color`.
//!
//! To format a string, call the `paint` method on a `Style` or a `Color`,
//! passing in the string you want to format as the argument. For example,
//! heres how to get some red text:
//!
//! ```
//! use nu_ansi_term::Color::Red;
//!
//! println!("This is in red: {}", Red.paint("a red string"));
//! ```
//!
//! Its important to note that the `paint` method does *not* actually return a
//! string with the ANSI control characters surrounding it. Instead, it returns
//! an [`ANSIString`] value that has a [`Display`] implementation that, when
//! formatted, returns the characters. This allows strings to be printed with a
//! minimum of [`String`] allocations being performed behind the scenes.
//!
//! If you *do* want to get at the escape codes, then you can convert the
//! [`ANSIString`] to a string as you would any other `Display` value:
//!
//! ```
//! use nu_ansi_term::Color::Red;
//!
//! let red_string = Red.paint("a red string").to_string();
//! ```
//!
//!
//! ## Bold, underline, background, and other styles
//!
//! For anything more complex than plain foreground color changes, you need to
//! construct `Style` values themselves, rather than beginning with a `Color`.
//! You can do this by chaining methods based on a new `Style`, created with
//! [`Style::new()`]. Each method creates a new style that has that specific
//! property set. For example:
//!
//! ```
//! use nu_ansi_term::Style;
//!
//! println!("How about some {} and {}?",
//! Style::new().bold().paint("bold"),
//! Style::new().underline().paint("underline"));
//! ```
//!
//! For brevity, these methods have also been implemented for `Color` values,
//! so you can give your styles a foreground color without having to begin with
//! an empty `Style` value:
//!
//! ```
//! use nu_ansi_term::Color::{Blue, Yellow};
//!
//! println!("Demonstrating {} and {}!",
//! Blue.bold().paint("blue bold"),
//! Yellow.underline().paint("yellow underline"));
//!
//! println!("Yellow on blue: {}", Yellow.on(Blue).paint("wow!"));
//! ```
//!
//! The complete list of styles you can use are: [`bold`], [`dimmed`], [`italic`],
//! [`underline`], [`blink`], [`reverse`], [`hidden`], [`strikethrough`], and [`on`] for
//! background colors.
//!
//! In some cases, you may find it easier to change the foreground on an
//! existing `Style` rather than starting from the appropriate `Color`.
//! You can do this using the [`fg`] method:
//!
//! ```
//! use nu_ansi_term::Style;
//! use nu_ansi_term::Color::{Blue, Cyan, Yellow};
//!
//! println!("Yellow on blue: {}", Style::new().on(Blue).fg(Yellow).paint("yow!"));
//! println!("Also yellow on blue: {}", Cyan.on(Blue).fg(Yellow).paint("zow!"));
//! ```
//!
//! You can turn a `Color` into a `Style` with the [`normal`] method.
//! This will produce the exact same `ANSIString` as if you just used the
//! `paint` method on the `Color` directly, but its useful in certain cases:
//! for example, you may have a method that returns `Styles`, and need to
//! represent both the “red bold” and “red, but not bold” styles with values of
//! the same type. The `Style` struct also has a [`Default`] implementation if you
//! want to have a style with *nothing* set.
//!
//! ```
//! use nu_ansi_term::Style;
//! use nu_ansi_term::Color::Red;
//!
//! Red.normal().paint("yet another red string");
//! Style::default().paint("a completely regular string");
//! ```
//!
//!
//! ## Extended colors
//!
//! You can access the extended range of 256 colors by using the `Color::Fixed`
//! variant, which takes an argument of the color number to use. This can be
//! included wherever you would use a `Color`:
//!
//! ```
//! use nu_ansi_term::Color::Fixed;
//!
//! Fixed(134).paint("A sort of light purple");
//! Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup");
//! ```
//!
//! The first sixteen of these values are the same as the normal and bold
//! standard color variants. Theres nothing stopping you from using these as
//! `Fixed` colors instead, but theres nothing to be gained by doing so
//! either.
//!
//! You can also access full 24-bit color by using the `Color::Rgb` variant,
//! which takes separate `u8` arguments for red, green, and blue:
//!
//! ```
//! use nu_ansi_term::Color::Rgb;
//!
//! Rgb(70, 130, 180).paint("Steel blue");
//! ```
//!
//! ## Combining successive colored strings
//!
//! The benefit of writing ANSI escape codes to the terminal is that they
//! *stack*: you do not need to end every colored string with a reset code if
//! the text that follows it is of a similar style. For example, if you want to
//! have some blue text followed by some blue bold text, its possible to send
//! the ANSI code for blue, followed by the ANSI code for bold, and finishing
//! with a reset code without having to have an extra one between the two
//! strings.
//!
//! This crate can optimise the ANSI codes that get printed in situations like
//! this, making life easier for your terminal renderer. The [`ANSIStrings`]
//! type takes a slice of several [`ANSIString`] values, and will iterate over
//! each of them, printing only the codes for the styles that need to be updated
//! as part of its formatting routine.
//!
//! The following code snippet uses this to enclose a binary number displayed in
//! red bold text inside some red, but not bold, brackets:
//!
//! ```
//! use nu_ansi_term::Color::Red;
//! use nu_ansi_term::{ANSIString, ANSIStrings};
//!
//! let some_value = format!("{:b}", 42);
//! let strings: &[ANSIString<'static>] = &[
//! Red.paint("["),
//! Red.bold().paint(some_value),
//! Red.paint("]"),
//! ];
//!
//! println!("Value: {}", ANSIStrings(strings));
//! ```
//!
//! There are several things to note here. Firstly, the [`paint`] method can take
//! *either* an owned [`String`] or a borrowed [`&str`]. Internally, an [`ANSIString`]
//! holds a copy-on-write ([`Cow`]) string value to deal with both owned and
//! borrowed strings at the same time. This is used here to display a `String`,
//! the result of the `format!` call, using the same mechanism as some
//! statically-available `&str` slices. Secondly, that the [`ANSIStrings`] value
//! works in the same way as its singular counterpart, with a [`Display`]
//! implementation that only performs the formatting when required.
//!
//! ## Byte strings
//!
//! This library also supports formatting `\[u8]` byte strings; this supports
//! applications working with text in an unknown encoding. [`Style`] and
//! [`Color`] support painting `\[u8]` values, resulting in an [`ANSIByteString`].
//! This type does not implement [`Display`], as it may not contain UTF-8, but
//! it does provide a method [`write_to`] to write the result to any value that
//! implements [`Write`]:
//!
//! ```
//! use nu_ansi_term::Color::Green;
//!
//! Green.paint("user data".as_bytes()).write_to(&mut std::io::stdout()).unwrap();
//! ```
//!
//! Similarly, the type [`ANSIByteStrings`] supports writing a list of
//! [`ANSIByteString`] values with minimal escape sequences:
//!
//! ```
//! use nu_ansi_term::Color::Green;
//! use nu_ansi_term::ANSIByteStrings;
//!
//! ANSIByteStrings(&[
//! Green.paint("user data 1\n".as_bytes()),
//! Green.bold().paint("user data 2\n".as_bytes()),
//! ]).write_to(&mut std::io::stdout()).unwrap();
//! ```
//!
//! [`Cow`]: https://doc.rust-lang.org/std/borrow/enum.Cow.html
//! [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
//! [`Default`]: https://doc.rust-lang.org/std/default/trait.Default.html
//! [`String`]: https://doc.rust-lang.org/std/string/struct.String.html
//! [`&str`]: https://doc.rust-lang.org/std/primitive.str.html
//! [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
//! [`Style`]: struct.Style.html
//! [`Style::new()`]: struct.Style.html#method.new
//! [`Color`]: enum.Color.html
//! [`Color`]: enum.Color.html
//! [`ANSIString`]: type.ANSIString.html
//! [`ANSIStrings`]: type.ANSIStrings.html
//! [`ANSIByteString`]: type.ANSIByteString.html
//! [`ANSIByteStrings`]: type.ANSIByteStrings.html
//! [`write_to`]: type.ANSIByteString.html#method.write_to
//! [`paint`]: type.ANSIByteString.html#method.write_to
//! [`normal`]: enum.Color.html#method.normal
//!
//! [`bold`]: struct.Style.html#method.bold
//! [`dimmed`]: struct.Style.html#method.dimmed
//! [`italic`]: struct.Style.html#method.italic
//! [`underline`]: struct.Style.html#method.underline
//! [`blink`]: struct.Style.html#method.blink
//! [`reverse`]: struct.Style.html#method.reverse
//! [`hidden`]: struct.Style.html#method.hidden
//! [`strikethrough`]: struct.Style.html#method.strikethrough
//! [`fg`]: struct.Style.html#method.fg
//! [`on`]: struct.Style.html#method.on
#![crate_name = "nu_ansi_term"]
#![crate_type = "rlib"]
#![warn(missing_copy_implementations)]
// #![warn(missing_docs)]
#![warn(trivial_casts, trivial_numeric_casts)]
// #![warn(unused_extern_crates, unused_qualifications)]
#[cfg(target_os = "windows")]
extern crate winapi;
#[cfg(test)]
#[macro_use]
extern crate doc_comment;
#[cfg(test)]
doctest!("../README.md");
pub mod ansi;
pub use ansi::{Infix, Prefix, Suffix};
mod style;
pub use style::{Color, Style};
mod difference;
mod display;
pub use display::*;
mod write;
mod windows;
pub use windows::*;
mod util;
pub use util::*;
mod debug;
pub mod gradient;
pub use gradient::*;
mod rgb;
pub use rgb::*;

View File

@ -0,0 +1,173 @@
// Code liberally borrowed from here
// https://github.com/navierr/coloriz
use std::ops;
use std::u32;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Rgb {
/// Red
pub r: u8,
/// Green
pub g: u8,
/// Blue
pub b: u8,
}
impl Rgb {
/// Creates a new [Rgb] color
#[inline]
pub const fn new(r: u8, g: u8, b: u8) -> Self {
Self { r, g, b }
}
/// Creates a new [Rgb] color with a hex code
#[inline]
pub const fn from_hex(hex: u32) -> Self {
Self::new((hex >> 16) as u8, (hex >> 8) as u8, hex as u8)
}
pub fn from_hex_string(hex: String) -> Self {
if hex.chars().count() == 8 && hex.starts_with("0x") {
// eprintln!("hex:{:?}", hex);
let (_, value_string) = hex.split_at(2);
// eprintln!("value_string:{:?}", value_string);
let int_val = u64::from_str_radix(value_string, 16);
match int_val {
Ok(num) => Self::new(
((num & 0xff0000) >> 16) as u8,
((num & 0xff00) >> 8) as u8,
(num & 0xff) as u8,
),
// Don't fail, just make the color black
// Should we fail?
_ => Self::new(0, 0, 0),
}
} else {
// Don't fail, just make the color black.
// Should we fail?
Self::new(0, 0, 0)
}
}
/// Creates a new [Rgb] color with three [f32] values
pub fn from_f32(r: f32, g: f32, b: f32) -> Self {
Self::new(
(r.clamp(0.0, 1.0) * 255.0) as u8,
(g.clamp(0.0, 1.0) * 255.0) as u8,
(b.clamp(0.0, 1.0) * 255.0) as u8,
)
}
/// Creates a grayscale [Rgb] color
#[inline]
pub const fn gray(x: u8) -> Self {
Self::new(x, x, x)
}
/// Creates a grayscale [Rgb] color with a [f32] value
pub fn gray_f32(x: f32) -> Self {
Self::from_f32(x, x, x)
}
/// Creates a new [Rgb] color from a [HSL] color
// pub fn from_hsl(hsl: HSL) -> Self {
// if hsl.s == 0.0 {
// return Self::gray_f32(hsl.l);
// }
// let q = if hsl.l < 0.5 {
// hsl.l * (1.0 + hsl.s)
// } else {
// hsl.l + hsl.s - hsl.l * hsl.s
// };
// let p = 2.0 * hsl.l - q;
// let h2c = |t: f32| {
// let t = t.clamp(0.0, 1.0);
// if 6.0 * t < 1.0 {
// p + 6.0 * (q - p) * t
// } else if t < 0.5 {
// q
// } else if 1.0 < 1.5 * t {
// p + 6.0 * (q - p) * (1.0 / 1.5 - t)
// } else {
// p
// }
// };
// Self::from_f32(h2c(hsl.h + 1.0 / 3.0), h2c(hsl.h), h2c(hsl.h - 1.0 / 3.0))
// }
/// Computes the linear interpolation between `self` and `other` for `t`
pub fn lerp(&self, other: Self, t: f32) -> Self {
let t = t.clamp(0.0, 1.0);
self * (1.0 - t) + other * t
}
}
impl From<(u8, u8, u8)> for Rgb {
fn from((r, g, b): (u8, u8, u8)) -> Self {
Self::new(r, g, b)
}
}
impl From<(f32, f32, f32)> for Rgb {
fn from((r, g, b): (f32, f32, f32)) -> Self {
Self::from_f32(r, g, b)
}
}
use crate::ANSIColorCode;
use crate::TargetGround;
impl ANSIColorCode for Rgb {
fn ansi_color_code(&self, target: TargetGround) -> String {
format!("{};2;{};{};{}", target.code() + 8, self.r, self.g, self.b)
}
}
overload::overload!(
(lhs: ?Rgb) + (rhs: ?Rgb) -> Rgb {
Rgb::new(
lhs.r.saturating_add(rhs.r),
lhs.g.saturating_add(rhs.g),
lhs.b.saturating_add(rhs.b)
)
}
);
overload::overload!(
(lhs: ?Rgb) - (rhs: ?Rgb) -> Rgb {
Rgb::new(
lhs.r.saturating_sub(rhs.r),
lhs.g.saturating_sub(rhs.g),
lhs.b.saturating_sub(rhs.b)
)
}
);
overload::overload!(
(lhs: ?Rgb) * (rhs: ?f32) -> Rgb {
Rgb::new(
(lhs.r as f32 * rhs.clamp(0.0, 1.0)) as u8,
(lhs.g as f32 * rhs.clamp(0.0, 1.0)) as u8,
(lhs.b as f32 * rhs.clamp(0.0, 1.0)) as u8
)
}
);
overload::overload!(
(lhs: ?f32) * (rhs: ?Rgb) -> Rgb {
Rgb::new(
(rhs.r as f32 * lhs.clamp(0.0, 1.0)) as u8,
(rhs.g as f32 * lhs.clamp(0.0, 1.0)) as u8,
(rhs.b as f32 * lhs.clamp(0.0, 1.0)) as u8
)
}
);
overload::overload!(
-(rgb: ?Rgb) -> Rgb {
Rgb::new(
255 - rgb.r,
255 - rgb.g,
255 - rgb.b)
}
);

View File

@ -0,0 +1,626 @@
/// A style is a collection of properties that can format a string
/// using ANSI escape codes.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::{Style, Color};
///
/// let style = Style::new().bold().on(Color::Black);
/// println!("{}", style.paint("Bold on black"));
/// ```
#[derive(PartialEq, Clone, Copy)]
#[cfg_attr(
feature = "derive_serde_style",
derive(serde::Deserialize, serde::Serialize)
)]
pub struct Style {
/// The style's foreground color, if it has one.
pub foreground: Option<Color>,
/// The style's background color, if it has one.
pub background: Option<Color>,
/// Whether this style is bold.
pub is_bold: bool,
/// Whether this style is dimmed.
pub is_dimmed: bool,
/// Whether this style is italic.
pub is_italic: bool,
/// Whether this style is underlined.
pub is_underline: bool,
/// Whether this style is blinking.
pub is_blink: bool,
/// Whether this style has reverse colors.
pub is_reverse: bool,
/// Whether this style is hidden.
pub is_hidden: bool,
/// Whether this style is struckthrough.
pub is_strikethrough: bool,
}
impl Style {
/// Creates a new Style with no properties set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new();
/// println!("{}", style.paint("hi"));
/// ```
pub fn new() -> Style {
Style::default()
}
/// Returns a `Style` with the bold property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().bold();
/// println!("{}", style.paint("hey"));
/// ```
pub fn bold(&self) -> Style {
Style {
is_bold: true,
..*self
}
}
/// Returns a `Style` with the dimmed property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().dimmed();
/// println!("{}", style.paint("sup"));
/// ```
pub fn dimmed(&self) -> Style {
Style {
is_dimmed: true,
..*self
}
}
/// Returns a `Style` with the italic property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().italic();
/// println!("{}", style.paint("greetings"));
/// ```
pub fn italic(&self) -> Style {
Style {
is_italic: true,
..*self
}
}
/// Returns a `Style` with the underline property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().underline();
/// println!("{}", style.paint("salutations"));
/// ```
pub fn underline(&self) -> Style {
Style {
is_underline: true,
..*self
}
}
/// Returns a `Style` with the blink property set.
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().blink();
/// println!("{}", style.paint("wazzup"));
/// ```
pub fn blink(&self) -> Style {
Style {
is_blink: true,
..*self
}
}
/// Returns a `Style` with the reverse property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().reverse();
/// println!("{}", style.paint("aloha"));
/// ```
pub fn reverse(&self) -> Style {
Style {
is_reverse: true,
..*self
}
}
/// Returns a `Style` with the hidden property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().hidden();
/// println!("{}", style.paint("ahoy"));
/// ```
pub fn hidden(&self) -> Style {
Style {
is_hidden: true,
..*self
}
}
/// Returns a `Style` with the strikethrough property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().strikethrough();
/// println!("{}", style.paint("yo"));
/// ```
pub fn strikethrough(&self) -> Style {
Style {
is_strikethrough: true,
..*self
}
}
/// Returns a `Style` with the foreground color property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::{Style, Color};
///
/// let style = Style::new().fg(Color::Yellow);
/// println!("{}", style.paint("hi"));
/// ```
pub fn fg(&self, foreground: Color) -> Style {
Style {
foreground: Some(foreground),
..*self
}
}
/// Returns a `Style` with the background color property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::{Style, Color};
///
/// let style = Style::new().on(Color::Blue);
/// println!("{}", style.paint("eyyyy"));
/// ```
pub fn on(&self, background: Color) -> Style {
Style {
background: Some(background),
..*self
}
}
/// Return true if this `Style` has no actual styles, and can be written
/// without any control characters.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// assert_eq!(true, Style::default().is_plain());
/// assert_eq!(false, Style::default().bold().is_plain());
/// ```
pub fn is_plain(self) -> bool {
self == Style::default()
}
}
impl Default for Style {
/// Returns a style with *no* properties set. Formatting text using this
/// style returns the exact same text.
///
/// ```
/// use nu_ansi_term::Style;
/// assert_eq!(None, Style::default().foreground);
/// assert_eq!(None, Style::default().background);
/// assert_eq!(false, Style::default().is_bold);
/// assert_eq!("txt", Style::default().paint("txt").to_string());
/// ```
fn default() -> Style {
Style {
foreground: None,
background: None,
is_bold: false,
is_dimmed: false,
is_italic: false,
is_underline: false,
is_blink: false,
is_reverse: false,
is_hidden: false,
is_strikethrough: false,
}
}
}
// ---- colors ----
/// A color is one specific type of ANSI escape code, and can refer
/// to either the foreground or background color.
///
/// These use the standard numeric sequences.
/// See <http://invisible-island.net/xterm/ctlseqs/ctlseqs.html>
#[derive(PartialEq, Clone, Copy, Debug)]
#[cfg_attr(
feature = "derive_serde_style",
derive(serde::Deserialize, serde::Serialize)
)]
pub enum Color {
/// Color #0 (foreground code `30`, background code `40`).
///
/// This is not necessarily the background color, and using it as one may
/// render the text hard to read on terminals with dark backgrounds.
Black,
/// Color #0 (foreground code `90`, background code `100`).
DarkGray,
/// Color #1 (foreground code `31`, background code `41`).
Red,
/// Color #1 (foreground code `91`, background code `101`).
LightRed,
/// Color #2 (foreground code `32`, background code `42`).
Green,
/// Color #2 (foreground code `92`, background code `102`).
LightGreen,
/// Color #3 (foreground code `33`, background code `43`).
Yellow,
/// Color #3 (foreground code `93`, background code `103`).
LightYellow,
/// Color #4 (foreground code `34`, background code `44`).
Blue,
/// Color #4 (foreground code `94`, background code `104`).
LightBlue,
/// Color #5 (foreground code `35`, background code `45`).
Purple,
/// Color #5 (foreground code `95`, background code `105`).
LightPurple,
/// Color #5 (foreground code `35`, background code `45`).
Magenta,
/// Color #5 (foreground code `95`, background code `105`).
LightMagenta,
/// Color #6 (foreground code `36`, background code `46`).
Cyan,
/// Color #6 (foreground code `96`, background code `106`).
LightCyan,
/// Color #7 (foreground code `37`, background code `47`).
///
/// As above, this is not necessarily the foreground color, and may be
/// hard to read on terminals with light backgrounds.
White,
/// Color #7 (foreground code `97`, background code `107`).
LightGray,
/// A color number from 0 to 255, for use in 256-color terminal
/// environments.
///
/// - colors 0 to 7 are the `Black` to `White` variants respectively.
/// These colors can usually be changed in the terminal emulator.
/// - colors 8 to 15 are brighter versions of the eight colors above.
/// These can also usually be changed in the terminal emulator, or it
/// could be configured to use the original colors and show the text in
/// bold instead. It varies depending on the program.
/// - colors 16 to 231 contain several palettes of bright colors,
/// arranged in six squares measuring six by six each.
/// - colors 232 to 255 are shades of grey from black to white.
///
/// It might make more sense to look at a [color chart][cc].
///
/// [cc]: https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg
Fixed(u8),
/// A 24-bit Rgb color, as specified by ISO-8613-3.
Rgb(u8, u8, u8),
}
impl Default for Color {
fn default() -> Self {
Color::White
}
}
impl Color {
/// Returns a `Style` with the foreground color set to this color.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Red.normal();
/// println!("{}", style.paint("hi"));
/// ```
pub fn normal(self) -> Style {
Style {
foreground: Some(self),
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// bold property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Green.bold();
/// println!("{}", style.paint("hey"));
/// ```
pub fn bold(self) -> Style {
Style {
foreground: Some(self),
is_bold: true,
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// dimmed property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Yellow.dimmed();
/// println!("{}", style.paint("sup"));
/// ```
pub fn dimmed(self) -> Style {
Style {
foreground: Some(self),
is_dimmed: true,
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// italic property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Blue.italic();
/// println!("{}", style.paint("greetings"));
/// ```
pub fn italic(self) -> Style {
Style {
foreground: Some(self),
is_italic: true,
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// underline property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Purple.underline();
/// println!("{}", style.paint("salutations"));
/// ```
pub fn underline(self) -> Style {
Style {
foreground: Some(self),
is_underline: true,
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// blink property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Cyan.blink();
/// println!("{}", style.paint("wazzup"));
/// ```
pub fn blink(self) -> Style {
Style {
foreground: Some(self),
is_blink: true,
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// reverse property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Black.reverse();
/// println!("{}", style.paint("aloha"));
/// ```
pub fn reverse(self) -> Style {
Style {
foreground: Some(self),
is_reverse: true,
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// hidden property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::White.hidden();
/// println!("{}", style.paint("ahoy"));
/// ```
pub fn hidden(self) -> Style {
Style {
foreground: Some(self),
is_hidden: true,
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// strikethrough property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Fixed(244).strikethrough();
/// println!("{}", style.paint("yo"));
/// ```
pub fn strikethrough(self) -> Style {
Style {
foreground: Some(self),
is_strikethrough: true,
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// background color property set to the given color.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Rgb(31, 31, 31).on(Color::White);
/// println!("{}", style.paint("eyyyy"));
/// ```
pub fn on(self, background: Color) -> Style {
Style {
foreground: Some(self),
background: Some(background),
..Style::default()
}
}
}
impl From<Color> for Style {
/// You can turn a `Color` into a `Style` with the foreground color set
/// with the `From` trait.
///
/// ```
/// use nu_ansi_term::{Style, Color};
/// let green_foreground = Style::default().fg(Color::Green);
/// assert_eq!(green_foreground, Color::Green.normal());
/// assert_eq!(green_foreground, Color::Green.into());
/// assert_eq!(green_foreground, Style::from(Color::Green));
/// ```
fn from(color: Color) -> Style {
color.normal()
}
}
#[cfg(test)]
#[cfg(feature = "derive_serde_style")]
mod serde_json_tests {
use super::{Color, Style};
#[test]
fn color_serialization() {
let colors = &[
Color::Red,
Color::Blue,
Color::Rgb(123, 123, 123),
Color::Fixed(255),
];
assert_eq!(
serde_json::to_string(&colors).unwrap(),
String::from("[\"Red\",\"Blue\",{\"Rgb\":[123,123,123]},{\"Fixed\":255}]")
);
}
#[test]
fn color_deserialization() {
let colors = [
Color::Red,
Color::Blue,
Color::Rgb(123, 123, 123),
Color::Fixed(255),
];
for color in colors {
let serialized = serde_json::to_string(&color).unwrap();
let deserialized: Color = serde_json::from_str(&serialized).unwrap();
assert_eq!(color, deserialized);
}
}
#[test]
fn style_serialization() {
let style = Style::default();
assert_eq!(serde_json::to_string(&style).unwrap(), "{\"foreground\":null,\"background\":null,\"is_bold\":false,\"is_dimmed\":false,\"is_italic\":false,\"is_underline\":false,\"is_blink\":false,\"is_reverse\":false,\"is_hidden\":false,\"is_strikethrough\":false}".to_string());
}
}

View File

@ -0,0 +1,80 @@
use crate::display::{AnsiString, AnsiStrings};
use std::ops::Deref;
/// Return a substring of the given ANSIStrings sequence, while keeping the formatting.
pub fn sub_string<'a>(
start: usize,
len: usize,
strs: &AnsiStrings<'a>,
) -> Vec<AnsiString<'static>> {
let mut vec = Vec::new();
let mut pos = start;
let mut len_rem = len;
for i in strs.0.iter() {
let fragment = i.deref();
let frag_len = fragment.len();
if pos >= frag_len {
pos -= frag_len;
continue;
}
if len_rem == 0 {
break;
}
let end = pos + len_rem;
let pos_end = if end >= frag_len { frag_len } else { end };
vec.push(i.style_ref().paint(String::from(&fragment[pos..pos_end])));
if end <= frag_len {
break;
}
len_rem -= pos_end - pos;
pos = 0;
}
vec
}
/// Return a concatenated copy of `strs` without the formatting, as an allocated `String`.
pub fn unstyle(strs: &AnsiStrings) -> String {
let mut s = String::new();
for i in strs.0.iter() {
s += i.deref();
}
s
}
/// Return the unstyled length of ANSIStrings. This is equaivalent to `unstyle(strs).len()`.
pub fn unstyled_len(strs: &AnsiStrings) -> usize {
let mut l = 0;
for i in strs.0.iter() {
l += i.deref().len();
}
l
}
#[cfg(test)]
mod test {
use super::*;
use crate::Color::*;
#[test]
fn test() {
let l = [
Black.paint("first"),
Red.paint("-second"),
White.paint("-third"),
];
let a = AnsiStrings(&l);
assert_eq!(unstyle(&a), "first-second-third");
assert_eq!(unstyled_len(&a), 18);
let l2 = [Black.paint("st"), Red.paint("-second"), White.paint("-t")];
assert_eq!(sub_string(3, 11, &a), l2);
}
}

View File

@ -0,0 +1,62 @@
/// Enables ANSI code support on Windows 10.
///
/// This uses Windows API calls to alter the properties of the console that
/// the program is running in.
///
/// https://msdn.microsoft.com/en-us/library/windows/desktop/mt638032(v=vs.85).aspx
///
/// Returns a `Result` with the Windows error code if unsuccessful.
#[cfg(windows)]
pub fn enable_ansi_support() -> Result<(), u32> {
// ref: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#EXAMPLE_OF_ENABLING_VIRTUAL_TERMINAL_PROCESSING @@ https://archive.is/L7wRJ#76%
use std::ffi::OsStr;
use std::iter::once;
use std::os::windows::ffi::OsStrExt;
use std::ptr::null_mut;
use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode};
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING};
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::winnt::{FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE};
const ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32 = 0x0004;
unsafe {
// ref: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
// Using `CreateFileW("CONOUT$", ...)` to retrieve the console handle works correctly even if STDOUT and/or STDERR are redirected
let console_out_name: Vec<u16> =
OsStr::new("CONOUT$").encode_wide().chain(once(0)).collect();
let console_handle = CreateFileW(
console_out_name.as_ptr(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE,
null_mut(),
OPEN_EXISTING,
0,
null_mut(),
);
if console_handle == INVALID_HANDLE_VALUE {
return Err(GetLastError());
}
// ref: https://docs.microsoft.com/en-us/windows/console/getconsolemode
let mut console_mode: u32 = 0;
if 0 == GetConsoleMode(console_handle, &mut console_mode) {
return Err(GetLastError());
}
// VT processing not already enabled?
if console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0 {
// https://docs.microsoft.com/en-us/windows/console/setconsolemode
if 0 == SetConsoleMode(
console_handle,
console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING,
) {
return Err(GetLastError());
}
}
}
Ok(())
}

View File

@ -0,0 +1,37 @@
use std::fmt;
use std::io;
pub trait AnyWrite {
type Wstr: ?Sized;
type Error;
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Self::Error>;
fn write_str(&mut self, s: &Self::Wstr) -> Result<(), Self::Error>;
}
impl<'a> AnyWrite for dyn fmt::Write + 'a {
type Wstr = str;
type Error = fmt::Error;
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Self::Error> {
fmt::Write::write_fmt(self, fmt)
}
fn write_str(&mut self, s: &Self::Wstr) -> Result<(), Self::Error> {
fmt::Write::write_str(self, s)
}
}
impl<'a> AnyWrite for dyn io::Write + 'a {
type Wstr = [u8];
type Error = io::Error;
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Self::Error> {
io::Write::write_fmt(self, fmt)
}
fn write_str(&mut self, s: &Self::Wstr) -> Result<(), Self::Error> {
io::Write::write_all(self, s)
}
}

View File

@ -1,59 +1,16 @@
[package]
<<<<<<< HEAD
authors = ["The Nu Project Contributors"]
description = "CLI for nushell"
edition = "2018"
license = "MIT"
name = "nu-cli"
version = "0.43.0"
build = "build.rs"
[lib]
doctest = false
[dependencies]
nu-completion = { version = "0.43.0", path="../nu-completion" }
nu-command = { version = "0.43.0", path="../nu-command" }
nu-data = { version = "0.43.0", path="../nu-data" }
nu-engine = { version = "0.43.0", path="../nu-engine" }
nu-errors = { version = "0.43.0", path="../nu-errors" }
nu-parser = { version = "0.43.0", path="../nu-parser" }
nu-protocol = { version = "0.43.0", path="../nu-protocol" }
nu-source = { version = "0.43.0", path="../nu-source" }
nu-stream = { version = "0.43.0", path="../nu-stream" }
nu-ansi-term = { version = "0.43.0", path="../nu-ansi-term" }
nu-path = { version = "0.43.0", path="../nu-path" }
indexmap ="1.6.1"
log = "0.4.14"
pretty_env_logger = "0.4.0"
strip-ansi-escapes = "0.1.0"
rustyline = { version="9.0.0", optional=true }
ctrlc = { version="3.1.7", optional=true }
shadow-rs = { version = "0.8.1", default-features = false, optional = true }
serde = { version="1.0.123", features=["derive"] }
serde_yaml = "0.8.16"
lazy_static = "1.4.0"
[build-dependencies]
shadow-rs = "0.8.1"
[features]
default = ["shadow-rs"]
rustyline-support = ["rustyline", "nu-engine/rustyline-support"]
stable = []
=======
name = "nu-cli"
version = "0.1.0"
version = "0.59.0"
edition = "2021"
[dependencies]
nu-engine = { path = "../nu-engine" }
nu-path = { path = "../nu-path" }
nu-parser = { path = "../nu-parser" }
nu-protocol = { path = "../nu-protocol" }
# nu-ansi-term = { path = "../nu-ansi-term" }
nu-engine = { path = "../nu-engine", version = "0.59.0" }
nu-path = { path = "../nu-path", version = "0.59.0" }
nu-parser = { path = "../nu-parser", version = "0.59.0" }
nu-protocol = { path = "../nu-protocol", version = "0.59.0" }
# nu-ansi-term = { path = "../nu-ansi-term", version = "0.59.0" }
nu-ansi-term = "0.42.0"
nu-color-config = { path = "../nu-color-config" }
miette = { version = "3.0.0", features = ["fancy"] }
@ -62,4 +19,3 @@ reedline = { git = "https://github.com/nushell/reedline", branch = "main" }
log = "0.4"
is_executable = "1.0.1"
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce

View File

@ -1,20 +1,3 @@
<<<<<<< HEAD
pub mod app;
mod cli;
#[cfg(feature = "rustyline-support")]
mod keybinding;
mod line_editor;
#[cfg(feature = "rustyline-support")]
mod shell;
#[cfg(feature = "rustyline-support")]
pub use crate::cli::cli;
pub use crate::app::App;
pub use crate::cli::{parse_and_eval, register_plugins, run_script_file};
pub use nu_command::create_default_context;
=======
mod completions;
mod errors;
mod nu_highlight;
@ -28,4 +11,3 @@ pub use nu_highlight::NuHighlight;
pub use prompt::NushellPrompt;
pub use syntax_highlight::NuHighlighter;
pub use validation::NuValidator;
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce

View File

@ -1,13 +1,14 @@
[package]
name = "nu-color-config"
version = "0.1.0"
version = "0.59.0"
edition = "2021"
[dependencies]
nu-protocol = { path = "../nu-protocol" }
# nu-ansi-term = { path = "../nu-ansi-term" }
nu-protocol = { path = "../nu-protocol", version = "0.59.0" }
# nu-ansi-term = { path = "../nu-ansi-term", version = "0.59.0" }
nu-ansi-term = "0.42.0"
nu-json = { path = "../nu-json" }
nu-table = { path = "../nu-table" }
nu-json = { path = "../nu-json", version = "0.59.0" }
nu-table = { path = "../nu-table", version = "0.59.0" }
serde = { version="1.0.123", features=["derive"] }

View File

@ -1,55 +1,6 @@
[package]
<<<<<<< HEAD
authors = ["The Nu Project Contributors"]
build = "build.rs"
description = "Commands for Nushell"
edition = "2018"
license = "MIT"
name = "nu-command"
version = "0.43.0"
[lib]
doctest = false
[dependencies]
nu-data = { version = "0.43.0", path="../nu-data" }
nu-engine = { version = "0.43.0", path="../nu-engine" }
nu-errors = { version = "0.43.0", path="../nu-errors" }
nu-json = { version = "0.43.0", path="../nu-json" }
nu-path = { version = "0.43.0", path="../nu-path" }
nu-parser = { version = "0.43.0", path="../nu-parser" }
nu-plugin = { version = "0.43.0", path="../nu-plugin" }
nu-protocol = { version = "0.43.0", path="../nu-protocol" }
nu-serde = { version = "0.43.0", path="../nu-serde" }
nu-source = { version = "0.43.0", path="../nu-source" }
nu-stream = { version = "0.43.0", path="../nu-stream" }
nu-table = { version = "0.43.0", path="../nu-table" }
nu-test-support = { version = "0.43.0", path="../nu-test-support" }
nu-value-ext = { version = "0.43.0", path="../nu-value-ext" }
nu-ansi-term = { version = "0.43.0", path="../nu-ansi-term" }
nu-pretty-hex = { version = "0.43.0", path="../nu-pretty-hex" }
url = "2.2.1"
mime = "0.3.16"
heck = "0.4.0"
base64 = "0.13.0"
bigdecimal = { version = "0.3.0", features = ["serde"] }
calamine = "0.18.0"
chrono = { version="0.4.19", features=["serde"] }
chrono-tz = "0.5.3"
crossterm = { version="0.19.0", optional=true }
csv = "1.1.3"
ctrlc = { version="3.1.7", optional=true }
derive-new = "0.5.8"
dirs-next = "2.0.0"
dtparse = "1.2.0"
eml-parser = "0.1.0"
encoding_rs = "0.8.28"
filesize = "0.2.0"
futures = { version="0.3.12", features=["compat", "io-compat"] }
=======
name = "nu-command"
version = "0.1.0"
version = "0.59.0"
edition = "2021"
build = "build.rs"
@ -57,18 +8,20 @@ build = "build.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
# nu-ansi-term = {path = "../nu-ansi-term", version = "0.59.0" }
nu-ansi-term = "0.42.0"
nu-color-config = { path = "../nu-color-config" }
nu-engine = { path = "../nu-engine" }
nu-json = { path = "../nu-json" }
nu-parser = { path = "../nu-parser" }
nu-path = { path = "../nu-path" }
nu-pretty-hex = { path = "../nu-pretty-hex" }
nu-protocol = { path = "../nu-protocol" }
nu-system = { path = "../nu-system" }
nu-table = { path = "../nu-table" }
nu-term-grid = { path = "../nu-term-grid" }
nu-test-support = { path = "../nu-test-support" }
nu-color-config = { path = "../nu-color-config", version = "0.59.0" }
nu-engine = { path = "../nu-engine", version = "0.59.0" }
nu-json = { path = "../nu-json", version = "0.59.0" }
nu-parser = { path = "../nu-parser", version = "0.59.0" }
nu-path = { path = "../nu-path", version = "0.59.0" }
nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.59.0" }
nu-protocol = { path = "../nu-protocol", version = "0.59.0" }
nu-system = { path = "../nu-system", version = "0.59.0" }
nu-table = { path = "../nu-table", version = "0.59.0" }
nu-term-grid = { path = "../nu-term-grid", version = "0.59.0" }
nu-test-support = { path = "../nu-test-support", version = "0.59.0" }
# Potential dependencies for extras
base64 = "0.13.0"
@ -85,55 +38,10 @@ dtparse = "1.2.0"
eml-parser = "0.1.0"
encoding_rs = "0.8.30"
filesize = "0.2.0"
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
glob = "0.3.0"
htmlescape = "0.3.1"
ical = "0.7.0"
indexmap = { version="1.7", features=["serde-1"] }
<<<<<<< HEAD
itertools = "0.10.0"
lazy_static = "1.*"
log = "0.4.14"
md-5 = "0.9.1"
meval = "0.2.0"
num-bigint = { version="0.4.3", features=["serde"] }
num-format = { version="0.4.0", features=["with-num-bigint"] }
num-traits = "0.2.14"
parking_lot = "0.11.1"
quick-xml = "0.22"
rand = "0.8"
regex = "1.4.3"
reqwest = {version = "0.11", optional = true }
roxmltree = "0.14.0"
rust-embed = "5.9.0"
rustyline = { version="9.0.0", optional=true }
serde = { version="1.0.123", features=["derive"] }
serde_ini = "0.2.0"
serde_json = "1.0.61"
serde_urlencoded = "0.7.0"
serde_yaml = "0.8.16"
sha2 = "0.9.3"
strip-ansi-escapes = "0.1.0"
sysinfo = { version = "0.23.0", optional = true }
thiserror = "1.0.26"
term = { version="0.7.0", optional=true }
term_size = "0.3.2"
titlecase = "1.1.0"
tokio = { version = "1", features = ["rt-multi-thread"], optional = true }
toml = "0.5.8"
trash = { version = "2.0.2", optional = true }
unicode-segmentation = "1.8"
uuid_crate = { package="uuid", version="0.8.2", features=["v4"], optional=true }
which = { version="4.1.0", optional=true }
zip = { version="0.5.9", optional=true }
digest = "0.9.0"
[dependencies.polars]
version = "0.17.0"
optional = true
default-features = false
features = ["docs", "zip_with", "csv-file", "temporal", "performant", "pretty_fmt", "dtype-slim", "parquet", "json", "random", "pivot", "strings", "is_in", "cum_agg", "rolling_window"]
=======
Inflector = "0.11"
itertools = "0.10.0"
lazy_static = "1.4.0"
@ -170,19 +78,11 @@ uuid = { version = "0.8.2", features = ["v4"] }
which = { version = "4.2.2", optional = true }
reedline = { git = "https://github.com/nushell/reedline", branch = "main" }
zip = { version="0.5.9", optional = true }
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
[target.'cfg(unix)'.dependencies]
umask = "1.0.0"
users = "0.11.0"
<<<<<<< HEAD
# TODO this will be possible with new dependency resolver
# (currently on nightly behind -Zfeatures=itarget):
# https://github.com/rust-lang/cargo/issues/7914
# [target.'cfg(not(windows))'.dependencies]
# num-format = { version = "0.4", features = ["with-system-locale"] }
=======
[dependencies.polars]
version = "0.18.0"
optional = true
@ -196,29 +96,12 @@ features = [
trash-support = ["trash"]
plugin = ["nu-parser/plugin"]
dataframe = ["polars", "num"]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
[build-dependencies]
shadow-rs = "0.8.1"
[dev-dependencies]
<<<<<<< HEAD
quickcheck = "1.0.3"
quickcheck_macros = "1.0.0"
hamcrest2 = "0.3.0"
[features]
rustyline-support = ["rustyline"]
stable = []
trash-support = ["trash"]
dataframe = ["nu-protocol/dataframe", "polars"]
fetch = ["reqwest", "tokio"]
post = ["reqwest", "tokio"]
sys = ["sysinfo"]
ps = ["sysinfo"]
=======
hamcrest2 = "0.3.0"
dirs-next = "2.0.0"
quickcheck = "1.0.3"
quickcheck_macros = "1.0.0"
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce

Binary file not shown.

View File

@ -0,0 +1,3 @@
fn main() -> shadow_rs::SdResult<()> {
shadow_rs::new()
}

View File

@ -1,376 +1,3 @@
<<<<<<< HEAD
use crate::prelude::*;
use nu_engine::whole_stream_command;
use std::error::Error;
pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Box<dyn Error>> {
let context = EvaluationContext::basic();
{
use crate::commands::*;
context.add_commands(vec![
// Fundamentals
whole_stream_command(NuPlugin),
whole_stream_command(Let),
whole_stream_command(LetEnv),
whole_stream_command(UnletEnv),
whole_stream_command(LoadEnv),
whole_stream_command(Def),
whole_stream_command(Source),
whole_stream_command(Alias),
whole_stream_command(Unalias),
whole_stream_command(Ignore),
whole_stream_command(Tutor),
whole_stream_command(Find),
// System/file operations
whole_stream_command(ErrorMake),
whole_stream_command(Exec),
whole_stream_command(Pwd),
whole_stream_command(Ls),
whole_stream_command(Du),
whole_stream_command(Cd),
whole_stream_command(Remove),
whole_stream_command(Open),
whole_stream_command(Pathvar),
whole_stream_command(PathvarAdd),
whole_stream_command(PathvarRemove),
whole_stream_command(PathvarReset),
whole_stream_command(PathvarAppend),
whole_stream_command(PathvarSave),
whole_stream_command(Config),
whole_stream_command(ConfigGet),
whole_stream_command(ConfigSet),
whole_stream_command(ConfigSetInto),
whole_stream_command(ConfigClear),
whole_stream_command(ConfigRemove),
whole_stream_command(ConfigPath),
whole_stream_command(Help),
whole_stream_command(History),
whole_stream_command(Save),
whole_stream_command(Touch),
whole_stream_command(Cpy),
whole_stream_command(Date),
whole_stream_command(DateListTimeZone),
whole_stream_command(DateNow),
whole_stream_command(DateToTable),
whole_stream_command(DateToTimeZone),
whole_stream_command(DateFormat),
whole_stream_command(DateHumanize),
whole_stream_command(Cal),
whole_stream_command(Mkdir),
whole_stream_command(Mv),
whole_stream_command(Kill),
whole_stream_command(Version),
whole_stream_command(Clear),
whole_stream_command(Describe),
whole_stream_command(Which),
whole_stream_command(Debug),
whole_stream_command(WithEnv),
whole_stream_command(Do),
whole_stream_command(Sleep),
// Statistics
whole_stream_command(Size),
whole_stream_command(Length),
whole_stream_command(Benchmark),
// Metadata
whole_stream_command(Tags),
// Shells
whole_stream_command(Next),
whole_stream_command(Previous),
whole_stream_command(Goto),
whole_stream_command(Shells),
whole_stream_command(Enter),
whole_stream_command(Exit),
// Viz
whole_stream_command(Chart),
// Viewers
whole_stream_command(Autoview),
whole_stream_command(Table),
// Text manipulation
whole_stream_command(Hash),
whole_stream_command(HashBase64),
whole_stream_command(HashMd5::default()),
whole_stream_command(HashSha256::default()),
whole_stream_command(Split),
whole_stream_command(SplitColumn),
whole_stream_command(SplitRow),
whole_stream_command(SplitChars),
whole_stream_command(Lines),
whole_stream_command(Echo),
whole_stream_command(Parse),
whole_stream_command(Str),
whole_stream_command(StrToDecimal),
whole_stream_command(StrToInteger),
whole_stream_command(StrDowncase),
whole_stream_command(StrUpcase),
whole_stream_command(StrCapitalize),
whole_stream_command(StrFindReplace),
whole_stream_command(StrSubstring),
whole_stream_command(StrToDatetime),
whole_stream_command(StrContains),
whole_stream_command(StrIndexOf),
whole_stream_command(StrTrim),
whole_stream_command(StrStartsWith),
whole_stream_command(StrEndsWith),
whole_stream_command(StrCollect),
whole_stream_command(StrLength),
whole_stream_command(StrLPad),
whole_stream_command(StrReverse),
whole_stream_command(StrRPad),
whole_stream_command(StrCamelCase),
whole_stream_command(StrPascalCase),
whole_stream_command(StrKebabCase),
whole_stream_command(StrSnakeCase),
whole_stream_command(StrScreamingSnakeCase),
whole_stream_command(BuildString),
whole_stream_command(Ansi),
whole_stream_command(AnsiStrip),
whole_stream_command(AnsiGradient),
whole_stream_command(Char),
whole_stream_command(DetectColumns),
// Column manipulation
whole_stream_command(DropColumn),
whole_stream_command(MoveColumn),
whole_stream_command(Reject),
whole_stream_command(Select),
whole_stream_command(Get),
whole_stream_command(Update),
whole_stream_command(UpdateCells),
whole_stream_command(Insert),
whole_stream_command(Into),
whole_stream_command(IntoBinary),
whole_stream_command(IntoColumnPath),
whole_stream_command(IntoInt),
whole_stream_command(IntoFilepath),
whole_stream_command(IntoFilesize),
whole_stream_command(IntoString),
whole_stream_command(SplitBy),
// Row manipulation
whole_stream_command(All),
whole_stream_command(Any),
whole_stream_command(Reverse),
whole_stream_command(Append),
whole_stream_command(Prepend),
whole_stream_command(SortBy),
whole_stream_command(GroupBy),
whole_stream_command(GroupByDate),
whole_stream_command(First),
whole_stream_command(Last),
whole_stream_command(Every),
whole_stream_command(Nth),
whole_stream_command(Drop),
whole_stream_command(DropNth),
whole_stream_command(Format),
whole_stream_command(FileSize),
whole_stream_command(Where),
whole_stream_command(If),
whole_stream_command(Compact),
whole_stream_command(Default),
whole_stream_command(Skip),
whole_stream_command(SkipUntil),
whole_stream_command(SkipWhile),
whole_stream_command(Keep),
whole_stream_command(KeepUntil),
whole_stream_command(KeepWhile),
whole_stream_command(Range),
whole_stream_command(Rename),
whole_stream_command(Uniq),
whole_stream_command(Each),
whole_stream_command(EachGroup),
whole_stream_command(EachWindow),
whole_stream_command(Empty),
whole_stream_command(ForIn),
// Table manipulation
whole_stream_command(Flatten),
whole_stream_command(Merge),
whole_stream_command(Shuffle),
whole_stream_command(Wrap),
whole_stream_command(Pivot),
whole_stream_command(Headers),
whole_stream_command(Reduce),
whole_stream_command(Roll),
whole_stream_command(RollColumn),
whole_stream_command(RollUp),
whole_stream_command(Rotate),
whole_stream_command(RotateCounterClockwise),
whole_stream_command(Zip),
whole_stream_command(Collect),
// Data processing
whole_stream_command(Histogram),
whole_stream_command(Autoenv),
whole_stream_command(AutoenvTrust),
whole_stream_command(AutoenvUntrust),
whole_stream_command(Math),
whole_stream_command(MathAbs),
whole_stream_command(MathAverage),
whole_stream_command(MathEval),
whole_stream_command(MathMedian),
whole_stream_command(MathMinimum),
whole_stream_command(MathMode),
whole_stream_command(MathMaximum),
whole_stream_command(MathStddev),
whole_stream_command(MathSummation),
whole_stream_command(MathVariance),
whole_stream_command(MathProduct),
whole_stream_command(MathRound),
whole_stream_command(MathFloor),
whole_stream_command(MathCeil),
whole_stream_command(MathSqrt),
// File format output
whole_stream_command(To),
whole_stream_command(ToCsv),
whole_stream_command(ToHtml),
whole_stream_command(ToJson),
whole_stream_command(ToMarkdown),
whole_stream_command(ToToml),
whole_stream_command(ToTsv),
whole_stream_command(ToUrl),
whole_stream_command(ToYaml),
whole_stream_command(ToXml),
// File format input
whole_stream_command(From),
whole_stream_command(FromCsv),
whole_stream_command(FromEml),
whole_stream_command(FromTsv),
whole_stream_command(FromSsv),
whole_stream_command(FromIni),
whole_stream_command(FromJson),
whole_stream_command(FromOds),
whole_stream_command(FromToml),
whole_stream_command(FromUrl),
whole_stream_command(FromXlsx),
whole_stream_command(FromXml),
whole_stream_command(FromYaml),
whole_stream_command(FromYml),
whole_stream_command(FromIcs),
whole_stream_command(FromVcf),
// "Private" commands (not intended to be accessed directly)
whole_stream_command(RunExternalCommand { interactive }),
// Random value generation
whole_stream_command(Random),
whole_stream_command(RandomBool),
whole_stream_command(RandomDice),
#[cfg(feature = "uuid_crate")]
whole_stream_command(RandomUUID),
whole_stream_command(RandomInteger),
whole_stream_command(RandomDecimal),
whole_stream_command(RandomChars),
// Path
whole_stream_command(PathBasename),
whole_stream_command(PathCommand),
whole_stream_command(PathDirname),
whole_stream_command(PathExists),
whole_stream_command(PathExpand),
whole_stream_command(PathJoin),
whole_stream_command(PathParse),
whole_stream_command(PathRelativeTo),
whole_stream_command(PathSplit),
whole_stream_command(PathType),
// Url
whole_stream_command(UrlCommand),
whole_stream_command(UrlScheme),
whole_stream_command(UrlPath),
whole_stream_command(UrlHost),
whole_stream_command(UrlQuery),
whole_stream_command(Seq),
whole_stream_command(SeqDates),
whole_stream_command(TermSize),
// Network
#[cfg(feature = "fetch")]
whole_stream_command(Fetch),
#[cfg(feature = "post")]
whole_stream_command(Post),
// System
#[cfg(feature = "ps")]
whole_stream_command(Ps),
#[cfg(feature = "sys")]
whole_stream_command(Sys),
]);
//Dataframe commands
#[cfg(feature = "dataframe")]
context.add_commands(vec![
whole_stream_command(DataFrame),
whole_stream_command(DataFrameOpen),
whole_stream_command(DataFrameList),
whole_stream_command(DataFrameGroupBy),
whole_stream_command(DataFrameAggregate),
whole_stream_command(DataFrameShow),
whole_stream_command(DataFrameSample),
whole_stream_command(DataFrameJoin),
whole_stream_command(DataFrameDrop),
whole_stream_command(DataFrameSelect),
whole_stream_command(DataFrameDTypes),
whole_stream_command(DataFrameDummies),
whole_stream_command(DataFrameFirst),
whole_stream_command(DataFrameLast),
whole_stream_command(DataFrameSlice),
whole_stream_command(DataFrameMelt),
whole_stream_command(DataFramePivot),
whole_stream_command(DataFrameWhere),
whole_stream_command(DataFrameToDF),
whole_stream_command(DataFrameToParquet),
whole_stream_command(DataFrameToCsv),
whole_stream_command(DataFrameSort),
whole_stream_command(DataFrameGet),
whole_stream_command(DataFrameDropDuplicates),
whole_stream_command(DataFrameDropNulls),
whole_stream_command(DataFrameColumn),
whole_stream_command(DataFrameWithColumn),
whole_stream_command(DataFrameFilter),
whole_stream_command(DataFrameSeriesRename),
whole_stream_command(DataFrameValueCounts),
whole_stream_command(DataFrameIsNull),
whole_stream_command(DataFrameIsNotNull),
whole_stream_command(DataFrameAllTrue),
whole_stream_command(DataFrameAllFalse),
whole_stream_command(DataFrameArgMax),
whole_stream_command(DataFrameArgMin),
whole_stream_command(DataFrameArgTrue),
whole_stream_command(DataFrameArgUnique),
whole_stream_command(DataFrameArgSort),
whole_stream_command(DataFrameUnique),
whole_stream_command(DataFrameNUnique),
whole_stream_command(DataFrameNNull),
whole_stream_command(DataFrameIsUnique),
whole_stream_command(DataFrameIsDuplicated),
whole_stream_command(DataFrameIsIn),
whole_stream_command(DataFrameShift),
whole_stream_command(DataFrameSet),
whole_stream_command(DataFrameNot),
whole_stream_command(DataFrameTake),
whole_stream_command(DataFrameSetWithIdx),
whole_stream_command(DataFrameShape),
whole_stream_command(DataFrameReplace),
whole_stream_command(DataFrameReplaceAll),
whole_stream_command(DataFrameStringLengths),
whole_stream_command(DataFrameContains),
whole_stream_command(DataFrameToLowercase),
whole_stream_command(DataFrameToUppercase),
whole_stream_command(DataFrameStringSlice),
whole_stream_command(DataFrameConcatenate),
whole_stream_command(DataFrameAppend),
whole_stream_command(DataFrameGetHour),
whole_stream_command(DataFrameGetMinute),
whole_stream_command(DataFrameGetSecond),
whole_stream_command(DataFrameGetDay),
whole_stream_command(DataFrameGetMonth),
whole_stream_command(DataFrameGetYear),
whole_stream_command(DataFrameGetWeek),
whole_stream_command(DataFrameGetWeekDay),
whole_stream_command(DataFrameGetOrdinal),
whole_stream_command(DataFrameGetNanoSecond),
whole_stream_command(DataFrameStrFTime),
whole_stream_command(DataFrameDescribe),
whole_stream_command(DataFrameRolling),
whole_stream_command(DataFrameCumulative),
whole_stream_command(DataFrameRename),
]);
}
Ok(context)
=======
use nu_protocol::engine::{EngineState, StateWorkingSet};
use std::path::Path;
@ -729,5 +356,4 @@ pub fn create_default_context(cwd: impl AsRef<Path>) -> EngineState {
let _ = engine_state.merge_delta(delta, None, &cwd);
engine_state
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}

View File

@ -1,9 +1,10 @@
use itertools::Either;
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::ast::{Call, RangeInclusion};
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Category, Example, IntoInterruptiblePipelineData, PipelineData, PipelineIterator, ShellError,
Signature, Span, SyntaxShape, Value,
Category, Example, FromValue, IntoInterruptiblePipelineData, PipelineData, PipelineIterator,
Range, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
};
#[derive(Clone)]
@ -16,7 +17,13 @@ impl Command for DropNth {
fn signature(&self) -> Signature {
Signature::build("drop nth")
.rest("rest", SyntaxShape::Int, "the number of the row to drop")
.required(
"row number or row range",
// FIXME: we can make this accept either Int or Range when we can compose SyntaxShapes
SyntaxShape::Any,
"the number of the row to drop or a range to drop consecutive rows",
)
.rest("rest", SyntaxShape::Any, "the number of the row to drop")
.category(Category::Filters)
}
@ -58,6 +65,14 @@ impl Command for DropNth {
span: Span::test_data(),
}),
},
Example {
description: "Drop range rows from second to fourth",
example: "echo [first second third fourth fifth] | drop nth (1..3)",
result: Some(Value::List {
vals: vec![Value::test_string("first"), Value::test_string("fifth")],
span: Span::test_data(),
}),
},
]
}
@ -68,12 +83,34 @@ impl Command for DropNth {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let mut rows: Vec<usize> = call.rest(engine_state, stack, 0)?;
rows.sort_unstable();
let pipeline_iter: PipelineIterator = input.into_iter();
// let mut rows: Vec<usize> = call.rest(engine_state, stack, 0)?;
// rows.sort_unstable();
// let pipeline_iter: PipelineIterator = input.into_iter();
let number_or_range = extract_int_or_range(engine_state, stack, call)?;
let rows = match number_or_range {
Either::Left(row_number) => {
let and_rows: Vec<Spanned<i64>> = call.rest(engine_state, stack, 1)?;
let mut rows: Vec<_> = and_rows.into_iter().map(|x| x.item as usize).collect();
rows.push(row_number as usize);
rows.sort_unstable();
rows
}
Either::Right(row_range) => {
let from = row_range.from.as_integer()? as usize;
let to = row_range.to.as_integer()? as usize;
if matches!(row_range.inclusion, RangeInclusion::Inclusive) {
(from..=to).collect()
} else {
(from..to).collect()
}
}
};
Ok(DropNthIterator {
input: pipeline_iter,
input: input.into_iter(),
rows,
current: 0,
}
@ -81,6 +118,26 @@ impl Command for DropNth {
}
}
fn extract_int_or_range(
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
) -> Result<Either<i64, Range>, ShellError> {
let value = call.req::<Value>(engine_state, stack, 0)?;
let int_opt = value.as_integer().map(Either::Left).ok();
let range_opt: Result<nu_protocol::Range, ShellError> = FromValue::from_value(&value);
let range_opt = range_opt.map(Either::Right).ok();
int_opt.or(range_opt).ok_or_else(|| {
ShellError::TypeMismatch(
"int or range".into(),
value.span().unwrap_or_else(|_| Span::new(0, 0)),
)
})
}
struct DropNthIterator {
input: PipelineIterator,
rows: Vec<usize>,

View File

@ -1,32 +1,3 @@
<<<<<<< HEAD
#![recursion_limit = "2048"]
#[cfg(test)]
#[macro_use]
extern crate indexmap;
#[macro_use]
mod prelude;
mod classified;
pub mod commands;
mod default_context;
pub mod utils;
#[cfg(test)]
mod examples;
pub use crate::default_context::create_default_context;
pub use nu_data::config;
pub use nu_data::dict::TaggedListBuilder;
pub use nu_data::primitive;
pub use nu_data::value;
pub use nu_stream::{ActionStream, InputStream, InterruptibleStream};
pub use nu_value_ext::ValueExt;
pub use num_traits::cast::ToPrimitive;
// TODO: Temporary redirect
pub use nu_protocol::{did_you_mean, TaggedDictBuilder};
=======
mod conversions;
mod core_commands;
mod date;
@ -77,4 +48,3 @@ mod dataframe;
#[cfg(feature = "dataframe")]
pub use dataframe::*;
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce

View File

@ -1,24 +1,3 @@
<<<<<<< HEAD
use nu_test_support::pipeline as input;
use nu_test_support::playground::{says, Playground};
use hamcrest2::assert_that;
use hamcrest2::prelude::*;
#[test]
fn checks_all_rows_are_true() {
Playground::setup("all_test_1", |_, nu| {
assert_that!(
nu.pipeline(&input(
r#"
echo [ "Andrés", "Andrés", "Andrés" ]
| all? $it == "Andrés"
"#
)),
says().stdout("true")
);
})
=======
use nu_test_support::{nu, pipeline};
#[test]
@ -32,23 +11,10 @@ fn checks_all_rows_are_true() {
));
assert_eq!(actual.out, "true");
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
#[test]
fn checks_all_rows_are_false_with_param() {
<<<<<<< HEAD
Playground::setup("all_test_1", |_, nu| {
assert_that!(
nu.pipeline(&input(
r#"
[1, 2, 3, 4] | all? { |a| $a >= 5 }
"#
)),
says().stdout("false")
);
})
=======
let actual = nu!(
cwd: ".", pipeline(
r#"
@ -57,23 +23,10 @@ fn checks_all_rows_are_false_with_param() {
));
assert_eq!(actual.out, "false");
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
#[test]
fn checks_all_rows_are_true_with_param() {
<<<<<<< HEAD
Playground::setup("all_test_1", |_, nu| {
assert_that!(
nu.pipeline(&input(
r#"
[1, 2, 3, 4] | all? { |a| $a < 5 }
"#
)),
says().stdout("true")
);
})
=======
let actual = nu!(
cwd: ".", pipeline(
r#"
@ -82,21 +35,13 @@ fn checks_all_rows_are_true_with_param() {
));
assert_eq!(actual.out, "true");
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
#[test]
fn checks_all_columns_of_a_table_is_true() {
<<<<<<< HEAD
Playground::setup("any_test_1", |_, nu| {
assert_that!(
nu.pipeline(&input(
r#"
=======
let actual = nu!(
cwd: ".", pipeline(
r#"
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
echo [
[ first_name, last_name, rusty_at, likes ];
[ Andrés, Robalino, 10/11/2013, 1 ]
@ -105,16 +50,8 @@ fn checks_all_columns_of_a_table_is_true() {
[ Yehuda, Katz, 10/11/2013, 1 ]
]
| all? likes > 0
<<<<<<< HEAD
"#
)),
says().stdout("true")
);
})
=======
"#
));
assert_eq!(actual.out, "true");
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}

View File

@ -1,24 +1,3 @@
<<<<<<< HEAD
use nu_test_support::pipeline as input;
use nu_test_support::playground::{says, Playground};
use hamcrest2::assert_that;
use hamcrest2::prelude::*;
#[test]
fn checks_any_row_is_true() {
Playground::setup("any_test_1", |_, nu| {
assert_that!(
nu.pipeline(&input(
r#"
echo [ "Ecuador", "USA", "New Zealand" ]
| any? $it == "New Zealand"
"#
)),
says().stdout("true")
);
})
=======
use nu_test_support::{nu, pipeline};
#[test]
@ -32,21 +11,13 @@ fn checks_any_row_is_true() {
));
assert_eq!(actual.out, "true");
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
#[test]
fn checks_any_column_of_a_table_is_true() {
<<<<<<< HEAD
Playground::setup("any_test_1", |_, nu| {
assert_that!(
nu.pipeline(&input(
r#"
=======
let actual = nu!(
cwd: ".", pipeline(
r#"
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
echo [
[ first_name, last_name, rusty_at, likes ];
[ Andrés, Robalino, 10/11/2013, 1 ]
@ -55,16 +26,8 @@ fn checks_any_column_of_a_table_is_true() {
[ Yehuda, Katz, 10/11/2013, 1 ]
]
| any? rusty_at == 10/12/2013
<<<<<<< HEAD
"#
)),
says().stdout("true")
);
})
=======
"#
));
assert_eq!(actual.out, "true");
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}

View File

@ -1,25 +1,3 @@
<<<<<<< HEAD
use nu_test_support::pipeline as input;
use nu_test_support::playground::{says, Playground};
use hamcrest2::assert_that;
use hamcrest2::prelude::*;
#[test]
fn adds_a_row_to_the_end() {
Playground::setup("append_test_1", |_, nu| {
assert_that!(
nu.pipeline(&input(
r#"
echo [ "Andrés N. Robalino", "Jonathan Turner", "Yehuda Katz" ]
| append "pollo loco"
| nth 3
"#
)),
says().stdout("pollo loco")
);
})
=======
use nu_test_support::{nu, pipeline};
#[test]
@ -34,5 +12,4 @@ fn adds_a_row_to_the_end() {
));
assert_eq!(actual.out, "pollo loco");
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}

View File

@ -5,19 +5,11 @@ fn cal_full_year() {
let actual = nu!(
cwd: ".", pipeline(
r#"
<<<<<<< HEAD
cal -y --full-year 2010 | first | to json
"#
));
let first_week_2010_json = r#"{"year":2010,"sunday":null,"monday":null,"tuesday":null,"wednesday":null,"thursday":null,"friday":1,"saturday":2}"#;
=======
cal -y --full-year 2010 | first | to json -r
"#
));
let first_week_2010_json = r#"{"year": 2010,"sunday": null,"monday": null,"tuesday": null,"wednesday": null,"thursday": null,"friday": 1,"saturday": 2}"#;
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
assert_eq!(actual.out, first_week_2010_json);
}
@ -27,19 +19,11 @@ fn cal_february_2020_leap_year() {
let actual = nu!(
cwd: ".", pipeline(
r#"
<<<<<<< HEAD
cal -ym --full-year 2020 --month-names | where month == "february" | to json
"#
));
let cal_february_json = r#"[{"year":2020,"month":"february","sunday":null,"monday":null,"tuesday":null,"wednesday":null,"thursday":null,"friday":null,"saturday":1},{"year":2020,"month":"february","sunday":2,"monday":3,"tuesday":4,"wednesday":5,"thursday":6,"friday":7,"saturday":8},{"year":2020,"month":"february","sunday":9,"monday":10,"tuesday":11,"wednesday":12,"thursday":13,"friday":14,"saturday":15},{"year":2020,"month":"february","sunday":16,"monday":17,"tuesday":18,"wednesday":19,"thursday":20,"friday":21,"saturday":22},{"year":2020,"month":"february","sunday":23,"monday":24,"tuesday":25,"wednesday":26,"thursday":27,"friday":28,"saturday":29}]"#;
=======
cal -ym --full-year 2020 --month-names | where month == "february" | to json -r
"#
));
let cal_february_json = r#"[{"year": 2020,"month": "february","sunday": null,"monday": null,"tuesday": null,"wednesday": null,"thursday": null,"friday": null,"saturday": 1},{"year": 2020,"month": "february","sunday": 2,"monday": 3,"tuesday": 4,"wednesday": 5,"thursday": 6,"friday": 7,"saturday": 8},{"year": 2020,"month": "february","sunday": 9,"monday": 10,"tuesday": 11,"wednesday": 12,"thursday": 13,"friday": 14,"saturday": 15},{"year": 2020,"month": "february","sunday": 16,"monday": 17,"tuesday": 18,"wednesday": 19,"thursday": 20,"friday": 21,"saturday": 22},{"year": 2020,"month": "february","sunday": 23,"monday": 24,"tuesday": 25,"wednesday": 26,"thursday": 27,"friday": 28,"saturday": 29}]"#;
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
assert_eq!(actual.out, cal_february_json);
}
@ -73,19 +57,11 @@ fn cal_week_day_start_monday() {
let actual = nu!(
cwd: ".", pipeline(
r#"
<<<<<<< HEAD
cal --full-year 2020 -m --month-names --week-start monday | where month == january | to json
"#
));
let cal_january_json = r#"[{"month":"january","monday":null,"tuesday":null,"wednesday":1,"thursday":2,"friday":3,"saturday":4,"sunday":5},{"month":"january","monday":6,"tuesday":7,"wednesday":8,"thursday":9,"friday":10,"saturday":11,"sunday":12},{"month":"january","monday":13,"tuesday":14,"wednesday":15,"thursday":16,"friday":17,"saturday":18,"sunday":19},{"month":"january","monday":20,"tuesday":21,"wednesday":22,"thursday":23,"friday":24,"saturday":25,"sunday":26},{"month":"january","monday":27,"tuesday":28,"wednesday":29,"thursday":30,"friday":31,"saturday":null,"sunday":null}]"#;
=======
cal --full-year 2020 -m --month-names --week-start monday | where month == january | to json -r
"#
));
let cal_january_json = r#"[{"month": "january","monday": null,"tuesday": null,"wednesday": 1,"thursday": 2,"friday": 3,"saturday": 4,"sunday": 5},{"month": "january","monday": 6,"tuesday": 7,"wednesday": 8,"thursday": 9,"friday": 10,"saturday": 11,"sunday": 12},{"month": "january","monday": 13,"tuesday": 14,"wednesday": 15,"thursday": 16,"friday": 17,"saturday": 18,"sunday": 19},{"month": "january","monday": 20,"tuesday": 21,"wednesday": 22,"thursday": 23,"friday": 24,"saturday": 25,"sunday": 26},{"month": "january","monday": 27,"tuesday": 28,"wednesday": 29,"thursday": 30,"friday": 31,"saturday": null,"sunday": null}]"#;
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
assert_eq!(actual.out, cal_january_json);
}
@ -95,17 +71,9 @@ fn cal_sees_pipeline_year() {
let actual = nu!(
cwd: ".", pipeline(
r#"
<<<<<<< HEAD
cal --full-year 1020 | get monday | first 3 | to json
"#
));
assert_eq!(actual.out, "[3,10,17]");
=======
cal --full-year 1020 | get monday | first 4 | to json -r
"#
));
assert_eq!(actual.out, "[null,3,10,17]");
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}

View File

@ -1,17 +1,10 @@
<<<<<<< HEAD
use nu_test_support::fs::{Stub::EmptyFile, Stub::FileWithContent};
=======
use nu_test_support::fs::Stub::EmptyFile;
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
use nu_test_support::nu;
use nu_test_support::playground::Playground;
use std::path::PathBuf;
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn filesystem_change_from_current_directory_using_relative_path() {
Playground::setup("cd_test_1", |dirs, _| {
@ -27,11 +20,8 @@ fn filesystem_change_from_current_directory_using_relative_path() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn filesystem_change_from_current_directory_using_absolute_path() {
Playground::setup("cd_test_2", |dirs, _| {
@ -48,11 +38,8 @@ fn filesystem_change_from_current_directory_using_absolute_path() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn filesystem_switch_back_to_previous_working_directory() {
Playground::setup("cd_test_3", |dirs, sandbox| {
@ -72,11 +59,8 @@ fn filesystem_switch_back_to_previous_working_directory() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn filesytem_change_from_current_directory_using_relative_path_and_dash() {
Playground::setup("cd_test_4", |dirs, sandbox| {
@ -97,11 +81,8 @@ fn filesytem_change_from_current_directory_using_relative_path_and_dash() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn filesystem_change_current_directory_to_parent_directory() {
Playground::setup("cd_test_5", |dirs, _| {
@ -117,11 +98,8 @@ fn filesystem_change_current_directory_to_parent_directory() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn filesystem_change_current_directory_to_two_parents_up_using_multiple_dots() {
Playground::setup("cd_test_6", |dirs, sandbox| {
@ -139,11 +117,8 @@ fn filesystem_change_current_directory_to_two_parents_up_using_multiple_dots() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn filesystem_change_current_directory_to_parent_directory_after_delete_cwd() {
Playground::setup("cd_test_7", |dirs, sandbox| {
@ -166,11 +141,8 @@ fn filesystem_change_current_directory_to_parent_directory_after_delete_cwd() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn filesystem_change_to_home_directory() {
Playground::setup("cd_test_8", |dirs, _| {
@ -186,11 +158,8 @@ fn filesystem_change_to_home_directory() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn filesystem_change_to_a_directory_containing_spaces() {
Playground::setup("cd_test_9", |dirs, sandbox| {
@ -211,11 +180,8 @@ fn filesystem_change_to_a_directory_containing_spaces() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn filesystem_not_a_directory() {
Playground::setup("cd_test_10", |dirs, sandbox| {
@ -239,11 +205,8 @@ fn filesystem_not_a_directory() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn filesystem_directory_not_found() {
Playground::setup("cd_test_11", |dirs, _| {
@ -266,11 +229,8 @@ fn filesystem_directory_not_found() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn filesystem_change_directory_to_symlink_relative() {
Playground::setup("cd_test_12", |dirs, sandbox| {
@ -290,218 +250,8 @@ fn filesystem_change_directory_to_symlink_relative() {
})
}
<<<<<<< HEAD
#[test]
fn valuesystem_change_from_current_path_using_relative_path() {
Playground::setup("cd_test_13", |dirs, sandbox| {
sandbox.with_files(vec![FileWithContent(
"sample.toml",
r#"
[[bin]]
path = "src/plugins/turner.rs"
[[bin]]
path = "src/plugins/robalino.rs"
[[bin]]
path = "src/plugins/katz.rs"
"#,
)]);
let actual = nu!(
cwd: dirs.test(),
r#"
enter sample.toml
cd bin
pwd
exit
"#
);
assert_eq!(PathBuf::from(actual.out), PathBuf::from("/bin"));
})
}
#[test]
fn valuesystem_change_from_current_path_using_absolute_path() {
Playground::setup("cd_test_14", |dirs, sandbox| {
sandbox.with_files(vec![FileWithContent(
"sample.toml",
r#"
[dependencies]
turner-ts = "0.1.1"
robalino-tkd = "0.0.1"
katz-ember = "0.2.3"
[[bin]]
path = "src/plugins/arepa.rs"
[[bin]]
path = "src/plugins/bbq.rs"
"#,
)]);
let actual = nu!(
cwd: dirs.test(),
r#"
enter sample.toml
cd bin
cd /dependencies
pwd
exit
"#
);
assert_eq!(PathBuf::from(actual.out), PathBuf::from("/dependencies"));
})
}
#[test]
fn valuesystem_switch_back_to_previous_working_path() {
Playground::setup("cd_test_15", |dirs, sandbox| {
sandbox.with_files(vec![FileWithContent(
"sample.toml",
r#"
[dependencies]
turner-ts = "0.1.1"
robalino-tkd = "0.0.1"
katz-ember = "0.2.3"
odin-gf = "0.2.1"
[[bin]]
path = "src/plugins/arepa.rs"
[[bin]]
path = "src/plugins/bbq.rs"
"#,
)]);
let actual = nu!(
cwd: dirs.test(),
r#"
enter sample.toml
cd dependencies
cd /bin
cd -
pwd
exit
"#
);
assert_eq!(PathBuf::from(actual.out), PathBuf::from("/dependencies"));
})
}
#[test]
fn valuesystem_change_from_current_path_using_relative_path_and_dash() {
Playground::setup("cd_test_16", |dirs, sandbox| {
sandbox
.with_files(vec![FileWithContent(
"sample.toml",
r#"
[package]
- = ["Yehuda Katz <wycats@gmail.com>", "Jonathan Turner <jonathan.d.turner@gmail.com>", "Andrés N. Robalino <andres@androbtech.com>"]
[[bin]]
path = "src/plugins/arepa.rs"
[[bin]]
path = "src/plugins/bbq.rs"
"#
)]);
let actual = nu!(
cwd: dirs.test(),
r#"
enter sample.toml
cd package/-
cd /bin
cd -
pwd
exit
"#
);
assert_eq!(PathBuf::from(actual.out), PathBuf::from("/package/-"));
})
}
#[test]
fn valuesystem_change_current_path_to_parent_path() {
Playground::setup("cd_test_17", |dirs, sandbox| {
sandbox
.with_files(vec![FileWithContent(
"sample.toml",
r#"
[package]
emberenios = ["Yehuda Katz <wycats@gmail.com>", "Jonathan Turner <jonathan.d.turner@gmail.com>", "Andrés N. Robalino <andres@androbtech.com>"]
"#
)]);
let actual = nu!(
cwd: dirs.test(),
r#"
enter sample.toml
cd package/emberenios
cd ..
pwd
exit
"#
);
assert_eq!(PathBuf::from(actual.out), PathBuf::from("/package"));
})
}
#[test]
fn valuesystem_change_to_a_path_containing_spaces() {
Playground::setup("cd_test_18", |dirs, sandbox| {
sandbox.with_files(vec![FileWithContent(
"sample.toml",
r#"
["pa que te"]
el = "pollo loco"
"#,
)]);
let actual = nu!(
cwd: dirs.test(),
r#"
enter sample.toml
cd "pa que te"
pwd
exit
"#
);
assert_eq!(
PathBuf::from(actual.out),
PathBuf::from("/").join("pa que te")
);
})
}
#[test]
fn valuesystem_path_not_found() {
Playground::setup("cd_test_19", |dirs, _| {
let actual = nu!(
cwd: dirs.formats(),
r#"
enter cargo_sample.toml
cd im_a_path_that_does_not_exist
exit
"#
);
assert!(actual.err.contains("Can not change to path inside"));
assert!(actual.err.contains("No such path exists"));
})
}
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[cfg(target_os = "windows")]
#[test]
fn test_change_windows_drive() {

View File

@ -0,0 +1,50 @@
use nu_test_support::fs::Stub::FileWithContentToBeTrimmed;
use nu_test_support::playground::Playground;
use nu_test_support::{nu, pipeline};
#[test]
fn discards_rows_where_given_column_is_empty() {
Playground::setup("compact_test_1", |dirs, sandbox| {
sandbox.with_files(vec![FileWithContentToBeTrimmed(
"los_tres_amigos.json",
r#"
{
"amigos": [
{"name": "Yehuda", "rusty_luck": 1},
{"name": "Jonathan", "rusty_luck": 1},
{"name": "Andres", "rusty_luck": 1},
{"name":"GorbyPuff"}
]
}
"#,
)]);
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
open los_tres_amigos.json
| get amigos
| compact rusty_luck
| length
"#
));
assert_eq!(actual.out, "3");
});
}
#[test]
fn discards_empty_rows_by_default() {
Playground::setup("compact_test_2", |dirs, _| {
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
echo "[1,2,3,14,null]"
| from json
| compact
| length
"#
));
assert_eq!(actual.out, "4");
});
}

View File

@ -31,11 +31,8 @@ fn copies_the_file_inside_directory_if_path_to_copy_is_directory() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn error_if_attempting_to_copy_a_directory_to_another_directory() {
Playground::setup("cp_test_3", |dirs, _| {
@ -80,11 +77,8 @@ fn copies_the_directory_inside_directory_if_path_to_copy_is_directory_and_with_r
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn deep_copies_with_recursive_flag() {
Playground::setup("cp_test_5", |dirs, sandbox| {

View File

@ -1,12 +1,9 @@
use nu_test_support::nu;
use nu_test_support::playground::Playground;
use std::fs;
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn def_with_comment() {
Playground::setup("def_with_comment", |dirs, _| {

View File

@ -0,0 +1,35 @@
use nu_test_support::fs::Stub::FileWithContentToBeTrimmed;
use nu_test_support::playground::Playground;
use nu_test_support::{nu, pipeline};
#[test]
fn adds_row_data_if_column_missing() {
Playground::setup("default_test_1", |dirs, sandbox| {
sandbox.with_files(vec![FileWithContentToBeTrimmed(
"los_tres_amigos.json",
r#"
{
"amigos": [
{"name": "Yehuda"},
{"name": "Jonathan", "rusty_luck": 0},
{"name": "Andres", "rusty_luck": 0},
{"name":"GorbyPuff"}
]
}
"#,
)]);
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
open los_tres_amigos.json
| get amigos
| default rusty_luck 1
| where rusty_luck == 1
| length
"#
));
assert_eq!(actual.out, "2");
});
}

View File

@ -1,10 +1,7 @@
use nu_test_support::{nu, pipeline};
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn columns() {
let actual = nu!(
@ -25,11 +22,8 @@ fn columns() {
assert_eq!(actual.out, "1");
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn more_columns_than_table_has() {
let actual = nu!(
@ -76,18 +70,17 @@ fn more_rows_than_table_has() {
assert_eq!(actual.out, "0");
}
<<<<<<< HEAD
#[test]
fn nth_range_inclusive() {
let actual = nu!(cwd: ".", "echo 10..15 | drop nth (2..3) | to json");
let actual = nu!(cwd: ".", "echo 10..15 | drop nth (2..3) | to json --raw");
assert_eq!(actual.out, "[10,11,14,15]");
}
#[test]
fn nth_range_exclusive() {
let actual = nu!(cwd: ".", "echo 10..15 | drop nth (1..<3) | to json");
let actual = nu!(cwd: ".", "echo 10..15 | drop nth (1..<3) | to json --raw");
assert_eq!(actual.out, "[10,13,14,15]");
}
@ -96,8 +89,5 @@ fn nth_range_exclusive() {
fn nth_missing_first_argument() {
let actual = nu!(cwd: ".", "echo 10..15 | drop nth \"\"");
assert!(actual.err.contains("Expected int or range"));
assert!(actual.err.contains("found string"));
assert!(actual.err.contains("int or range"));
}
=======
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce

View File

@ -5,11 +5,7 @@ fn each_works_separately() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
<<<<<<< HEAD
echo [1 2 3] | each { echo $it 10 | math sum } | to json
=======
echo [1 2 3] | each { echo $it 10 | math sum } | to json -r
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));
@ -21,11 +17,7 @@ fn each_group_works() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
<<<<<<< HEAD
echo [1 2 3 4 5 6] | each group 3 { $it } | to json
=======
echo [1 2 3 4 5 6] | each group 3 { $it } | to json --raw
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));
@ -37,11 +29,7 @@ fn each_window() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
<<<<<<< HEAD
echo [1 2 3 4] | each window 3 { $it } | to json
=======
echo [1 2 3 4] | each window 3 { $it } | to json --raw
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));
@ -53,11 +41,7 @@ fn each_window_stride() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
<<<<<<< HEAD
echo [1 2 3 4 5 6] | each window 3 -s 2 { echo $it } | to json
=======
echo [1 2 3 4 5 6] | each window 3 -s 2 { echo $it } | to json --raw
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));
@ -69,19 +53,11 @@ fn each_no_args_in_block() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
<<<<<<< HEAD
echo [[foo bar]; [a b] [c d] [e f]] | each { to json } | nth 1 | str collect
"#
));
assert_eq!(actual.out, r#"{"foo":"c","bar":"d"}"#);
=======
echo [[foo bar]; [a b] [c d] [e f]] | each {|i| $i | to json -r } | nth 1
"#
));
assert_eq!(actual.out, r#"{"foo": "c","bar": "d"}"#);
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
#[test]

View File

@ -5,11 +5,7 @@ fn echo_range_is_lazy() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
<<<<<<< HEAD
echo 1..10000000000 | first 3 | to json
=======
echo 1..10000000000 | first 3 | to json --raw
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));
@ -21,11 +17,7 @@ fn echo_range_handles_inclusive() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
<<<<<<< HEAD
echo 1..3 | to json
=======
echo 1..3 | each { $it } | to json --raw
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));
@ -37,11 +29,7 @@ fn echo_range_handles_exclusive() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
<<<<<<< HEAD
echo 1..<3 | to json
=======
echo 1..<3 | each { $it } | to json --raw
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));
@ -53,11 +41,7 @@ fn echo_range_handles_inclusive_down() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
<<<<<<< HEAD
echo 3..1 | to json
=======
echo 3..1 | each { $it } | to json --raw
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));
@ -69,11 +53,7 @@ fn echo_range_handles_exclusive_down() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
<<<<<<< HEAD
echo 3..<1 | to json
=======
echo 3..<1 | each { $it } | to json --raw
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));

View File

@ -1,10 +1,7 @@
use nu_test_support::{nu, pipeline};
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn reports_emptiness() {
let actual = nu!(
@ -25,11 +22,8 @@ fn reports_emptiness() {
assert_eq!(actual.out, "3");
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn sets_block_run_value_for_an_empty_column() {
let actual = nu!(
@ -51,11 +45,8 @@ fn sets_block_run_value_for_an_empty_column() {
assert_eq!(actual.out, "4");
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn sets_block_run_value_for_many_empty_columns() {
let actual = nu!(
@ -76,11 +67,8 @@ fn sets_block_run_value_for_many_empty_columns() {
assert_eq!(actual.out, "6");
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn passing_a_block_will_set_contents_on_empty_cells_and_leave_non_empty_ones_untouched() {
let actual = nu!(

View File

@ -71,18 +71,3 @@ fn knows_the_filesystems_entered() {
));
})
}
<<<<<<< HEAD
#[test]
fn errors_if_file_not_found() {
Playground::setup("enter_test_2", |dirs, _| {
let actual = nu!(
cwd: dirs.test(),
"enter i_dont_exist.csv"
);
assert!(actual.err.contains("Cannot find file"));
})
}
=======
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce

View File

@ -18,11 +18,7 @@ fn gets_all_rows_by_every_zero() {
ls
| get name
| every 0
<<<<<<< HEAD
| to json
=======
| to json --raw
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));
@ -49,19 +45,11 @@ fn gets_no_rows_by_every_skip_zero() {
ls
| get name
| every 0 --skip
<<<<<<< HEAD
| to json
"#
));
assert_eq!(actual.out, "");
=======
| to json --raw
"#
));
assert_eq!(actual.out, "[]");
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
})
}
@ -81,11 +69,7 @@ fn gets_all_rows_by_every_one() {
ls
| get name
| every 1
<<<<<<< HEAD
| to json
=======
| to json --raw
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));
@ -96,11 +80,8 @@ fn gets_all_rows_by_every_one() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn gets_no_rows_by_every_skip_one() {
Playground::setup("every_test_4", |dirs, sandbox| {
@ -117,11 +98,7 @@ fn gets_no_rows_by_every_skip_one() {
ls
| get name
| every 1 --skip
<<<<<<< HEAD
| to json
=======
| to json --raw
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));
@ -175,11 +152,7 @@ fn gets_all_rows_except_first_by_every_skip_too_much() {
ls
| get name
| every 999 --skip
<<<<<<< HEAD
| to json
=======
| to json --raw
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));
@ -204,11 +177,7 @@ fn gets_every_third_row() {
ls
| get name
| every 3
<<<<<<< HEAD
| to json
=======
| to json --raw
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));
@ -233,11 +202,7 @@ fn skips_every_third_row() {
ls
| get name
| every 3 --skip
<<<<<<< HEAD
| to json
=======
| to json --raw
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));

View File

@ -19,11 +19,7 @@ fn find_with_list_search_with_char() {
let actual = nu!(
cwd: ".", pipeline(
r#"
<<<<<<< HEAD
[moe larry curly] | find l | to json
=======
[moe larry curly] | find l | to json -r
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));
@ -82,19 +78,11 @@ fn find_with_filepath_search_with_string() {
ls
| get name
| find arep
<<<<<<< HEAD
| to json
"#
));
assert_eq!(actual.out, r#""arepas.clu""#);
=======
| to json -r
"#
));
assert_eq!(actual.out, r#"["arepas.clu"]"#);
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
})
}
@ -114,11 +102,7 @@ fn find_with_filepath_search_with_multiple_patterns() {
ls
| get name
| find arep ami
<<<<<<< HEAD
| to json
=======
| to json -r
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));

View File

@ -0,0 +1,67 @@
use nu_test_support::fs::Stub::EmptyFile;
use nu_test_support::playground::Playground;
use nu_test_support::{nu, pipeline};
#[test]
fn gets_first_rows_by_amount() {
Playground::setup("first_test_1", |dirs, sandbox| {
sandbox.with_files(vec![
EmptyFile("los.txt"),
EmptyFile("tres.txt"),
EmptyFile("amigos.txt"),
EmptyFile("arepas.clu"),
]);
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
ls
| first 3
| length
"#
));
assert_eq!(actual.out, "3");
})
}
#[test]
fn gets_all_rows_if_amount_higher_than_all_rows() {
Playground::setup("first_test_2", |dirs, sandbox| {
sandbox.with_files(vec![
EmptyFile("los.txt"),
EmptyFile("tres.txt"),
EmptyFile("amigos.txt"),
EmptyFile("arepas.clu"),
]);
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
ls
| first 99
| length
"#
));
assert_eq!(actual.out, "4");
})
}
#[test]
fn gets_first_row_when_no_amount_given() {
Playground::setup("first_test_3", |dirs, sandbox| {
sandbox.with_files(vec![EmptyFile("caballeros.txt"), EmptyFile("arepas.clu")]);
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
ls
| first
| length
"#
));
assert_eq!(actual.out, "1");
})
}

View File

@ -2,11 +2,8 @@ use nu_test_support::fs::Stub::FileWithContentToBeTrimmed;
use nu_test_support::playground::Playground;
use nu_test_support::{nu, pipeline};
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn flatten_nested_tables_with_columns() {
let actual = nu!(
@ -23,11 +20,8 @@ fn flatten_nested_tables_with_columns() {
assert_eq!(actual.out, "Andres,nuno");
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn flatten_nested_tables_that_have_many_columns() {
let actual = nu!(
@ -88,11 +82,8 @@ fn flatten_row_column_explicitly() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn flatten_row_columns_having_same_column_names_flats_separately() {
Playground::setup("flatten_test_2", |dirs, sandbox| {
@ -127,11 +118,8 @@ fn flatten_row_columns_having_same_column_names_flats_separately() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn flatten_table_columns_explicitly() {
Playground::setup("flatten_test_3", |dirs, sandbox| {

View File

@ -16,11 +16,8 @@ fn creates_the_resulting_string_from_the_given_fields() {
assert_eq!(actual.out, "nu has license ISC");
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn given_fields_can_be_column_paths() {
let actual = nu!(
@ -34,11 +31,8 @@ fn given_fields_can_be_column_paths() {
assert_eq!(actual.out, "nu is a new type of shell");
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn can_use_variables() {
let actual = nu!(
@ -52,11 +46,8 @@ fn can_use_variables() {
assert_eq!(actual.out, "nu is a new type of shell");
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn format_filesize_works() {
Playground::setup("format_filesize_test_1", |dirs, sandbox| {
@ -80,11 +71,8 @@ fn format_filesize_works() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn format_filesize_works_with_nonempty_files() {
Playground::setup(

View File

@ -130,11 +130,8 @@ fn fetches_more_than_one_column_path() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn errors_fetching_by_column_not_present() {
Playground::setup("get_test_6", |dirs, sandbox| {
@ -165,11 +162,8 @@ fn errors_fetching_by_column_not_present() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn errors_fetching_by_column_using_a_number() {
Playground::setup("get_test_7", |dirs, sandbox| {
@ -196,12 +190,9 @@ fn errors_fetching_by_column_using_a_number() {
.contains("Appears to contain columns. Columns available: 0"),)
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn errors_fetching_by_index_out_of_bounds() {
Playground::setup("get_test_8", |dirs, sandbox| {

View File

@ -71,11 +71,8 @@ fn errors_if_given_unknown_column_name() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn errors_if_block_given_evaluates_more_than_one_row() {
Playground::setup("group_by_test_3", |dirs, sandbox| {

View File

@ -26,11 +26,8 @@ fn base64_encode_characterset_binhex() {
assert_eq!(actual.out, "F@0NEPjJD97kE\'&bEhFZEP3");
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn error_when_invalid_character_set_given() {
let actual = nu!(
@ -46,11 +43,8 @@ fn error_when_invalid_character_set_given() {
.contains("this is invalid is not a valid character-set"));
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn base64_decode_characterset_binhex() {
let actual = nu!(
@ -94,11 +88,8 @@ fn error_use_both_flags() {
.contains("only one of --decode and --encode flags can be used"));
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn md5_works_with_file() {
let actual = nu!(
@ -112,11 +103,8 @@ fn md5_works_with_file() {
assert_eq!(actual.out, "4de97601d232c427977ef11db396c951");
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn sha256_works_with_file() {
let actual = nu!(

View File

@ -1,10 +1,7 @@
use nu_test_support::{nu, pipeline};
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn headers_uses_first_row_as_header() {
let actual = nu!(
@ -20,11 +17,8 @@ fn headers_uses_first_row_as_header() {
assert_eq!(actual.out, "r1c0r2c0")
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn headers_adds_missing_column_name() {
let actual = nu!(

View File

@ -15,11 +15,8 @@ fn help_commands_length() {
assert!(is_positive);
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn help_generate_docs_length() {
let actual = nu!(

View File

@ -2,11 +2,8 @@ use nu_test_support::fs::Stub::FileWithContentToBeTrimmed;
use nu_test_support::playground::Playground;
use nu_test_support::{nu, pipeline};
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn summarizes_by_column_given() {
Playground::setup("histogram_test_1", |dirs, sandbox| {
@ -38,11 +35,8 @@ fn summarizes_by_column_given() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn summarizes_by_values() {
Playground::setup("histogram_test_2", |dirs, sandbox| {
@ -71,11 +65,8 @@ fn summarizes_by_values() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn help() {
Playground::setup("histogram_test_3", |dirs, _sandbox| {
@ -105,11 +96,8 @@ fn help() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn count() {
let actual = nu!(

View File

@ -33,11 +33,7 @@ fn into_filesize_str() {
"#
));
<<<<<<< HEAD
assert!(actual.out.contains("2.0 KB"));
=======
assert!(actual.out.contains("2.0 KiB"));
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
#[test]
@ -45,21 +41,12 @@ fn into_filesize_str_newline() {
let actual = nu!(
cwd: ".", pipeline(
r#"
<<<<<<< HEAD
'2000
' | into filesize
"#
));
assert!(actual.out.contains("2.0 KB"));
=======
"2000
" | into filesize
"#
));
assert!(actual.out.contains("2.0 KiB"));
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
#[test]
@ -67,15 +54,6 @@ fn into_filesize_str_many_newlines() {
let actual = nu!(
cwd: ".", pipeline(
r#"
<<<<<<< HEAD
'2000
' | into filesize
"#
));
assert!(actual.out.contains("2.0 KB"));
=======
"2000
" | into filesize
@ -83,7 +61,6 @@ fn into_filesize_str_many_newlines() {
));
assert!(actual.out.contains("2.0 KiB"));
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
#[test]
@ -91,17 +68,9 @@ fn into_filesize_filesize() {
let actual = nu!(
cwd: ".", pipeline(
r#"
<<<<<<< HEAD
3kb | into filesize
"#
));
assert!(actual.out.contains("3.0 KB"));
=======
3kib | into filesize
"#
));
assert!(actual.out.contains("3.0 KiB"));
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}

View File

@ -0,0 +1,37 @@
use nu_test_support::{nu, pipeline};
#[test]
fn into_int_filesize() {
let actual = nu!(
cwd: ".", pipeline(
r#"
echo 1kb | into int | each { $it / 1000 }
"#
));
assert!(actual.out.contains('1'));
}
#[test]
fn into_int_filesize2() {
let actual = nu!(
cwd: ".", pipeline(
r#"
echo 1kib | into int | each { $it / 1024 }
"#
));
assert!(actual.out.contains('1'));
}
#[test]
fn into_int_int() {
let actual = nu!(
cwd: ".", pipeline(
r#"
echo 1024 | into int | each { $it / 1024 }
"#
));
assert!(actual.out.contains('1'));
}

View File

@ -0,0 +1,3 @@
mod rows;
mod until;
mod while_;

View File

@ -0,0 +1,31 @@
use nu_test_support::fs::Stub::FileWithContentToBeTrimmed;
use nu_test_support::playground::Playground;
use nu_test_support::{nu, pipeline};
#[test]
fn rows() {
Playground::setup("keep_test_1", |dirs, sandbox| {
sandbox.with_files(vec![FileWithContentToBeTrimmed(
"caballeros.csv",
r#"
name,lucky_code
Andrés,1
Jonathan,1
Jason,2
Yehuda,1
"#,
)]);
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
open caballeros.csv
| keep 3
| get lucky_code
| math sum
"#
));
assert_eq!(actual.out, "4");
})
}

View File

@ -10,11 +10,7 @@ fn condition_is_met() {
r#"
CHICKEN SUMMARY report date: April 29th, 2020
--------------------------------------------------------------------
<<<<<<< HEAD
Chicken Collection,29/04/2020,30/04/2020,31/04/2020,
=======
Chicken Collection,29/04/2020,30/04/2020,31/04/2020
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
Yellow Chickens,,,
Andrés,1,1,1
Jonathan,1,1,1
@ -37,16 +33,6 @@ fn condition_is_met() {
cwd: dirs.test(), pipeline(
r#"
open --raw caballeros.txt
<<<<<<< HEAD
| lines
| skip 2
| split column ','
| headers
| skip while "Chicken Collection" != "Blue Chickens"
| keep until "Chicken Collection" == "Red Chickens"
| skip 1
| str to-int "31/04/2020"
=======
| lines
| skip 2
| str trim
@ -56,7 +42,6 @@ fn condition_is_met() {
| keep until "Chicken Collection" == "Red Chickens"
| skip 1
| into int "31/04/2020"
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
| get "31/04/2020"
| math sum
"#

View File

@ -10,11 +10,7 @@ fn condition_is_met() {
r#"
CHICKEN SUMMARY report date: April 29th, 2020
--------------------------------------------------------------------
<<<<<<< HEAD
Chicken Collection,29/04/2020,30/04/2020,31/04/2020,
=======
Chicken Collection,29/04/2020,30/04/2020,31/04/2020
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
Yellow Chickens,,,
Andrés,1,1,1
Jonathan,1,1,1
@ -37,15 +33,6 @@ fn condition_is_met() {
cwd: dirs.test(), pipeline(
r#"
open --raw caballeros.txt
<<<<<<< HEAD
| lines
| skip 2
| split column ','
| headers
| skip 1
| keep while "Chicken Collection" != "Blue Chickens"
| str to-int "31/04/2020"
=======
| lines
| skip 2
| str trim
@ -54,7 +41,6 @@ fn condition_is_met() {
| skip 1
| keep while "Chicken Collection" != "Blue Chickens"
| into int "31/04/2020"
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
| get "31/04/2020"
| math sum
"#

View File

@ -0,0 +1,66 @@
use nu_test_support::fs::Stub::EmptyFile;
use nu_test_support::playground::Playground;
use nu_test_support::{nu, pipeline};
#[test]
fn gets_the_last_row() {
let actual = nu!(
cwd: "tests/fixtures/formats",
"ls | sort-by name | last 1 | get name | str trim"
);
assert_eq!(actual.out, "utf16.ini");
}
#[test]
fn gets_last_rows_by_amount() {
Playground::setup("last_test_1", |dirs, sandbox| {
sandbox.with_files(vec![
EmptyFile("los.txt"),
EmptyFile("tres.txt"),
EmptyFile("amigos.txt"),
EmptyFile("arepas.clu"),
]);
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
ls
| last 3
| length
"#
));
assert_eq!(actual.out, "3");
})
}
#[test]
fn gets_last_row_when_no_amount_given() {
Playground::setup("last_test_2", |dirs, sandbox| {
sandbox.with_files(vec![EmptyFile("caballeros.txt"), EmptyFile("arepas.clu")]);
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
ls
| last
| length
"#
));
assert_eq!(actual.out, "1");
})
}
#[test]
fn requests_more_rows_than_table_has() {
let actual = nu!(
cwd: ".", pipeline(
r#"
date | last 50 | length
"#
));
assert_eq!(actual.out, "1");
}

View File

@ -0,0 +1,25 @@
use nu_test_support::{nu, pipeline};
#[test]
fn length_columns_in_cal_table() {
let actual = nu!(
cwd: ".", pipeline(
r#"
cal | length -c
"#
));
assert_eq!(actual.out, "7");
}
#[test]
fn length_columns_no_rows() {
let actual = nu!(
cwd: ".", pipeline(
r#"
echo [] | length -c
"#
));
assert_eq!(actual.out, "0");
}

View File

@ -27,11 +27,7 @@ fn lines_proper_buffering() {
open lines_test.txt -r
| lines
| str length
<<<<<<< HEAD
| to json
=======
| to json -r
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));
@ -50,9 +46,5 @@ fn lines_multi_value_split() {
"#
));
<<<<<<< HEAD
assert_eq!(actual.out, "5");
=======
assert_eq!(actual.out, "6");
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}

View File

@ -88,11 +88,7 @@ fn lists_all_files_in_directories_from_stream() {
r#"
echo dir_a dir_b
| each { ls $it }
<<<<<<< HEAD
| length
=======
| flatten | length
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"#
));
@ -304,22 +300,14 @@ fn list_all_columns() {
// Normal Operation
let actual = nu!(
cwd: dirs.test(),
<<<<<<< HEAD
"ls | get | to md"
=======
"ls | columns | to md"
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
);
let expected = ["name", "type", "size", "modified"].join("");
assert_eq!(actual.out, expected, "column names are incorrect for ls");
// Long
let actual = nu!(
cwd: dirs.test(),
<<<<<<< HEAD
"ls -l | get | to md"
=======
"ls -l | columns | to md"
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
);
let expected = {
#[cfg(unix)]
@ -328,17 +316,10 @@ fn list_all_columns() {
"name",
"type",
"target",
<<<<<<< HEAD
"num_links",
"inode",
"readonly",
"mode",
=======
"readonly",
"mode",
"num_links",
"inode",
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
"uid",
"group",
"size",

View File

@ -18,15 +18,8 @@ fn can_average_numbers() {
fn can_average_bytes() {
let actual = nu!(
cwd: "tests/fixtures/formats",
<<<<<<< HEAD
"ls | sort-by name | skip 1 | first 2 | get size | math avg | format \"{$it}\" "
);
assert_eq!(actual.out, "1.6 KB");
=======
"ls | sort-by name | skip 1 | first 2 | get size | math avg | to json -r"
);
assert_eq!(actual.out, "1600");
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}

View File

@ -1,10 +1,7 @@
use nu_test_support::{nu, pipeline};
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn evaluates_two_plus_two() {
let actual = nu!(
@ -17,11 +14,8 @@ fn evaluates_two_plus_two() {
assert!(actual.out.contains("4.0"));
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn evaluates_two_to_the_power_four() {
let actual = nu!(
@ -34,11 +28,8 @@ fn evaluates_two_to_the_power_four() {
assert!(actual.out.contains("16.0"));
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn evaluates_three_multiplied_by_five() {
let actual = nu!(
@ -51,11 +42,8 @@ fn evaluates_three_multiplied_by_five() {
assert!(actual.out.contains("15.0"));
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn evaluates_twenty_four_divided_by_two() {
let actual = nu!(

View File

@ -0,0 +1,40 @@
use nu_test_support::{nu, pipeline};
#[test]
fn median_numbers_with_even_rows() {
let actual = nu!(
cwd: ".", pipeline(
r#"
echo [10 6 19 21 4]
| math median
"#
));
assert_eq!(actual.out, "10")
}
#[test]
fn median_numbers_with_odd_rows() {
let actual = nu!(
cwd: ".", pipeline(
r#"
echo [3 8 9 12 12 15]
| math median
"#
));
assert_eq!(actual.out, "10.5")
}
#[test]
fn median_mixed_numbers() {
let actual = nu!(
cwd: ".", pipeline(
r#"
echo [-11.5 -13.5 10]
| math median
"#
));
assert_eq!(actual.out, "-11.5")
}

View File

@ -236,21 +236,6 @@ fn duration_math_with_negative() {
}
#[test]
<<<<<<< HEAD
fn duration_math_shell_error_on_big_numbers() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
(date now) + 100000000000000day
"#
));
assert!(actual.err.contains("Duration overflow"));
}
#[test]
=======
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
fn compound_comparison() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
@ -279,19 +264,11 @@ fn compound_where() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
<<<<<<< HEAD
echo '[{"a": 1, "b": 1}, {"a": 2, "b": 1}, {"a": 2, "b": 2}]' | from json | where a == 2 && b == 1 | to json
"#
));
assert_eq!(actual.out, r#"{"a":2,"b":1}"#);
=======
echo '[{"a": 1, "b": 1}, {"a": 2, "b": 1}, {"a": 2, "b": 2}]' | from json | where a == 2 && b == 1 | to json -r
"#
));
assert_eq!(actual.out, r#"[{"a": 2,"b": 1}]"#);
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
#[test]
@ -299,17 +276,9 @@ fn compound_where_paren() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
<<<<<<< HEAD
echo '[{"a": 1, "b": 1}, {"a": 2, "b": 1}, {"a": 2, "b": 2}]' | from json | where ($it.a == 2 && $it.b == 1) || $it.b == 2 | to json
"#
));
assert_eq!(actual.out, r#"[{"a":2,"b":1},{"a":2,"b":2}]"#);
=======
echo '[{"a": 1, "b": 1}, {"a": 2, "b": 1}, {"a": 2, "b": 2}]' | from json | where ($it.a == 2 && $it.b == 1) || $it.b == 2 | to json -r
"#
));
assert_eq!(actual.out, r#"[{"a": 2,"b": 1},{"a": 2,"b": 2}]"#);
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}

View File

@ -0,0 +1,21 @@
use nu_test_support::nu;
#[test]
fn can_round_very_large_numbers() {
let actual = nu!(
cwd: ".",
"echo 18.1372544780074142289927665486772012345 | math round"
);
assert_eq!(actual.out, "18")
}
#[test]
fn can_round_very_large_numbers_with_precision() {
let actual = nu!(
cwd: ".",
"echo 18.13725447800741422899276654867720121457878988 | math round -p 10"
);
assert_eq!(actual.out, "18.137254478")
}

View File

@ -1,10 +1,7 @@
use nu_test_support::nu;
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn can_sqrt_numbers() {
let actual = nu!(
@ -15,11 +12,8 @@ fn can_sqrt_numbers() {
assert_eq!(actual.out, "3.914213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573");
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn can_sqrt_irrational() {
let actual = nu!(

View File

@ -75,11 +75,8 @@ fn compute_sum_of_table() -> Result<(), String> {
Ok(())
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn sum_of_a_row_containing_a_table_is_an_error() {
let actual = nu!(

View File

@ -2,11 +2,8 @@ use nu_test_support::fs::Stub::FileWithContentToBeTrimmed;
use nu_test_support::playground::Playground;
use nu_test_support::{nu, pipeline};
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn row() {
Playground::setup("merge_test_1", |dirs, sandbox| {

View File

@ -0,0 +1,84 @@
use nu_test_support::fs::files_exist_at;
use nu_test_support::playground::Playground;
use nu_test_support::{nu, pipeline};
use std::path::Path;
#[test]
fn creates_directory() {
Playground::setup("mkdir_test_1", |dirs, _| {
nu!(
cwd: dirs.test(),
"mkdir my_new_directory"
);
let expected = dirs.test().join("my_new_directory");
assert!(expected.exists());
})
}
#[test]
fn accepts_and_creates_directories() {
Playground::setup("mkdir_test_2", |dirs, _| {
nu!(
cwd: dirs.test(),
"mkdir dir_1 dir_2 dir_3"
);
assert!(files_exist_at(
vec![Path::new("dir_1"), Path::new("dir_2"), Path::new("dir_3")],
dirs.test()
));
})
}
#[test]
fn creates_intermediary_directories() {
Playground::setup("mkdir_test_3", |dirs, _| {
nu!(
cwd: dirs.test(),
"mkdir some_folder/another/deeper_one"
);
let expected = dirs.test().join("some_folder/another/deeper_one");
assert!(expected.exists());
})
}
#[test]
fn create_directory_two_parents_up_using_multiple_dots() {
Playground::setup("mkdir_test_4", |dirs, sandbox| {
sandbox.within("foo").mkdir("bar");
nu!(
cwd: dirs.test().join("foo/bar"),
"mkdir .../boo"
);
let expected = dirs.test().join("boo");
assert!(expected.exists());
})
}
#[test]
fn show_created_paths() {
Playground::setup("mkdir_test_2", |dirs, _| {
let actual = nu!(
cwd: dirs.test(),
pipeline(
r#"
mkdir -s dir_1 dir_2 dir_3
| length
"#
));
assert!(files_exist_at(
vec![Path::new("dir_1"), Path::new("dir_2"), Path::new("dir_3")],
dirs.test()
));
assert_eq!(actual.out, "3");
})
}

View File

@ -4,10 +4,6 @@ mod append;
mod cal;
mod cd;
mod compact;
<<<<<<< HEAD
mod config;
=======
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
mod cp;
mod def;
mod default;
@ -27,10 +23,6 @@ mod hash_;
mod headers;
mod help;
mod histogram;
<<<<<<< HEAD
mod insert;
=======
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
mod into_filesize;
mod into_int;
mod keep;
@ -42,17 +34,10 @@ mod math;
mod merge;
mod mkdir;
mod move_;
<<<<<<< HEAD
mod open;
mod parse;
mod path;
mod pathvar;
=======
mod nth;
mod open;
mod parse;
mod path;
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
mod prepend;
mod random;
mod range;

View File

@ -34,11 +34,8 @@ fn moves_a_column_before() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn moves_columns_before() {
Playground::setup("move_column_test_2", |dirs, sandbox| {
@ -73,11 +70,8 @@ fn moves_columns_before() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn moves_a_column_after() {
Playground::setup("move_column_test_3", |dirs, sandbox| {
@ -113,11 +107,8 @@ fn moves_a_column_after() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn moves_columns_after() {
Playground::setup("move_column_test_4", |dirs, sandbox| {

View File

@ -0,0 +1,2 @@
mod column;
mod mv;

View File

@ -195,11 +195,8 @@ fn moves_a_directory_with_files() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn errors_if_source_doesnt_exist() {
Playground::setup("mv_test_10", |dirs, sandbox| {
@ -212,11 +209,8 @@ fn errors_if_source_doesnt_exist() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn errors_if_destination_doesnt_exist() {
Playground::setup("mv_test_10_1", |dirs, sandbox| {
@ -231,11 +225,8 @@ fn errors_if_destination_doesnt_exist() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn errors_if_multiple_sources_but_destination_not_a_directory() {
Playground::setup("mv_test_10_2", |dirs, sandbox| {
@ -256,11 +247,8 @@ fn errors_if_multiple_sources_but_destination_not_a_directory() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn errors_if_renaming_directory_to_an_existing_file() {
Playground::setup("mv_test_10_3", |dirs, sandbox| {
@ -277,11 +265,8 @@ fn errors_if_renaming_directory_to_an_existing_file() {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn errors_if_moving_to_itself() {
Playground::setup("mv_test_10_4", |dirs, sandbox| {

View File

@ -1,10 +1,7 @@
<<<<<<< HEAD
=======
use nu_test_support::fs::Stub::EmptyFile;
use nu_test_support::playground::Playground;
use nu_test_support::{nu, pipeline};
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn selects_a_row() {
Playground::setup("nth_test_1", |dirs, sandbox| {

View File

@ -185,22 +185,6 @@ fn parses_json() {
}
#[test]
<<<<<<< HEAD
fn parses_xml() {
let actual = nu!(
cwd: "tests/fixtures/formats",
"open jonathan.xml | get rss.children.channel.children | get item.children | get link.children.0"
);
assert_eq!(
actual.out,
"http://www.jonathanturner.org/2015/10/off-to-new-adventures.html"
)
}
#[test]
=======
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
fn parses_ini() {
let actual = nu!(
cwd: "tests/fixtures/formats",
@ -214,21 +198,14 @@ fn parses_ini() {
fn parses_utf16_ini() {
let actual = nu!(
cwd: "tests/fixtures/formats",
<<<<<<< HEAD
"open utf16.ini | rename info | get info | get IconIndex"
=======
"open ./utf16.ini --raw | decode utf-16 | from ini | rename info | get info | get IconIndex"
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
);
assert_eq!(actual.out, "-236")
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn errors_if_file_not_found() {
let actual = nu!(
@ -244,11 +221,8 @@ fn errors_if_file_not_found() {
);
}
<<<<<<< HEAD
=======
// FIXME: jt: I think `open` on a directory is confusing. We should make discuss this one a bit more
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn open_dir_is_ls() {
Playground::setup("open_dir", |dirs, sandbox| {

View File

@ -5,11 +5,8 @@ use nu_test_support::{nu, pipeline};
mod simple {
use super::*;
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn extracts_fields_from_the_given_the_pattern() {
Playground::setup("parse_test_1", |dirs, sandbox| {
@ -86,11 +83,8 @@ mod simple {
})
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn errors_when_missing_closing_brace() {
Playground::setup("parse_test_regex_5", |dirs, _sandbox| {

View File

@ -0,0 +1,83 @@
use nu_test_support::{nu, pipeline};
use super::join_path_sep;
#[test]
fn returns_basename_of_empty_input() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo ""
| path basename
"#
));
assert_eq!(actual.out, "");
}
#[test]
fn replaces_basename_of_empty_input() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo ""
| path basename -r newname.txt
"#
));
assert_eq!(actual.out, "newname.txt");
}
#[test]
fn returns_basename_of_path_ending_with_dot() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo "some/file.txt/."
| path basename
"#
));
assert_eq!(actual.out, "file.txt");
}
#[test]
fn replaces_basename_of_path_ending_with_dot() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo "some/file.txt/."
| path basename -r viking.txt
"#
));
let expected = join_path_sep(&["some", "viking.txt"]);
assert_eq!(actual.out, expected);
}
#[test]
fn returns_basename_of_path_ending_with_double_dot() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo "some/file.txt/.."
| path basename
"#
));
assert_eq!(actual.out, "");
}
#[test]
fn replaces_basename_of_path_ending_with_double_dot() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo "some/file.txt/.."
| path basename -r eggs
"#
));
let expected = join_path_sep(&["some/file.txt/..", "eggs"]);
assert_eq!(actual.out, expected);
}

View File

@ -0,0 +1,137 @@
use nu_test_support::{nu, pipeline};
use super::join_path_sep;
#[test]
fn returns_dirname_of_empty_input() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo ""
| path dirname
"#
));
assert_eq!(actual.out, "");
}
#[test]
fn replaces_dirname_of_empty_input() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo ""
| path dirname -r newdir
"#
));
assert_eq!(actual.out, "newdir");
}
#[test]
fn returns_dirname_of_path_ending_with_dot() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo "some/dir/."
| path dirname
"#
));
assert_eq!(actual.out, "some");
}
#[test]
fn replaces_dirname_of_path_ending_with_dot() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo "some/dir/."
| path dirname -r eggs
"#
));
let expected = join_path_sep(&["eggs", "dir"]);
assert_eq!(actual.out, expected);
}
#[test]
fn returns_dirname_of_path_ending_with_double_dot() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo "some/dir/.."
| path dirname
"#
));
assert_eq!(actual.out, "some/dir");
}
#[test]
fn replaces_dirname_of_path_with_double_dot() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo "some/dir/.."
| path dirname -r eggs
"#
));
let expected = join_path_sep(&["eggs", ".."]);
assert_eq!(actual.out, expected);
}
#[test]
fn returns_dirname_of_zero_levels() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo "some/dir/with/spam.txt"
| path dirname -n 0
"#
));
assert_eq!(actual.out, "some/dir/with/spam.txt");
}
#[test]
fn replaces_dirname_of_zero_levels_with_empty_string() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo "some/dir/with/spam.txt"
| path dirname -n 0 -r ""
"#
));
assert_eq!(actual.out, "");
}
#[test]
fn replaces_dirname_of_more_levels() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo "some/dir/with/spam.txt"
| path dirname -r eggs -n 2
"#
));
let expected = join_path_sep(&["eggs", "with/spam.txt"]);
assert_eq!(actual.out, expected);
}
#[test]
fn replaces_dirname_of_way_too_many_levels() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo "some/dir/with/spam.txt"
| path dirname -r eggs -n 999
"#
));
let expected = join_path_sep(&["eggs", "some/dir/with/spam.txt"]);
assert_eq!(actual.out, expected);
}

View File

@ -2,11 +2,8 @@ use nu_test_support::fs::Stub::EmptyFile;
use nu_test_support::nu;
use nu_test_support::playground::Playground;
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn checks_if_existing_file_exists() {
Playground::setup("path_exists_1", |dirs, sandbox| {

View File

@ -0,0 +1,78 @@
use nu_test_support::fs::Stub::EmptyFile;
use nu_test_support::playground::Playground;
use nu_test_support::{nu, pipeline};
use std::path::PathBuf;
#[test]
fn expands_path_with_dot() {
Playground::setup("path_expand_1", |dirs, sandbox| {
sandbox
.within("menu")
.with_files(vec![EmptyFile("spam.txt")]);
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
echo "menu/./spam.txt"
| path expand
"#
));
let expected = dirs.test.join("menu").join("spam.txt");
assert_eq!(PathBuf::from(actual.out), expected);
})
}
#[test]
fn expands_path_with_double_dot() {
Playground::setup("path_expand_2", |dirs, sandbox| {
sandbox
.within("menu")
.with_files(vec![EmptyFile("spam.txt")]);
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
echo "menu/../menu/spam.txt"
| path expand
"#
));
let expected = dirs.test.join("menu").join("spam.txt");
assert_eq!(PathBuf::from(actual.out), expected);
})
}
#[cfg(windows)]
mod windows {
use super::*;
#[test]
fn expands_path_with_tilde_backward_slash() {
Playground::setup("path_expand_2", |dirs, _| {
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
echo "~\tmp.txt" | path expand
"#
));
assert!(!PathBuf::from(actual.out).starts_with("~"));
})
}
#[test]
fn win_expands_path_with_tilde_forward_slash() {
Playground::setup("path_expand_2", |dirs, _| {
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
echo "~/tmp.txt" | path expand
"#
));
assert!(!PathBuf::from(actual.out).starts_with("~"));
})
}
}

View File

@ -0,0 +1,59 @@
use nu_test_support::{nu, pipeline};
use super::join_path_sep;
#[test]
fn returns_path_joined_with_column_path() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo [ [name]; [eggs] ]
| path join spam.txt -c [ name ]
| get name
"#
));
let expected = join_path_sep(&["eggs", "spam.txt"]);
assert_eq!(actual.out, expected);
}
#[test]
fn returns_path_joined_from_list() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo [ home viking spam.txt ]
| path join
"#
));
let expected = join_path_sep(&["home", "viking", "spam.txt"]);
assert_eq!(actual.out, expected);
}
#[test]
fn appends_slash_when_joined_with_empty_path() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo "/some/dir"
| path join ''
"#
));
let expected = join_path_sep(&["/some/dir", ""]);
assert_eq!(actual.out, expected);
}
#[test]
fn returns_joined_path_when_joining_empty_path() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo ""
| path join foo.txt
"#
));
assert_eq!(actual.out, "foo.txt");
}

View File

@ -0,0 +1,34 @@
mod basename;
mod dirname;
mod exists;
mod expand;
mod join;
mod parse;
mod split;
mod type_;
use std::path::MAIN_SEPARATOR;
/// Helper function that joins string literals with '/' or '\', based on host OS
fn join_path_sep(pieces: &[&str]) -> String {
let sep_string = String::from(MAIN_SEPARATOR);
pieces.join(&sep_string)
}
#[cfg(windows)]
#[test]
fn joins_path_on_windows() {
let pieces = ["sausage", "bacon", "spam"];
let actual = join_path_sep(&pieces);
assert_eq!(&actual, "sausage\\bacon\\spam");
}
#[cfg(not(windows))]
#[test]
fn joins_path_on_other_than_windows() {
let pieces = ["sausage", "bacon", "spam"];
let actual = join_path_sep(&pieces);
assert_eq!(&actual, "sausage/bacon/spam");
}

View File

@ -114,11 +114,8 @@ fn parses_column_path_extension() {
assert_eq!(actual.out, "png");
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn parses_into_correct_number_of_columns() {
let actual = nu!(

View File

@ -17,11 +17,7 @@ fn splits_correctly_single_path() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
<<<<<<< HEAD
echo ['home/viking/spam.txt']
=======
'home/viking/spam.txt'
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
| path split
| last
"#
@ -43,10 +39,7 @@ fn splits_correctly_with_column_path() {
]
| path split -c [ home barn ]
| get barn
<<<<<<< HEAD
=======
| flatten
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
| length
"#
));

View File

@ -15,11 +15,8 @@ fn returns_type_of_missing_file() {
assert_eq!(actual.out, "");
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn returns_type_of_existing_file() {
Playground::setup("path_expand_1", |dirs, sandbox| {
@ -35,19 +32,12 @@ fn returns_type_of_existing_file() {
"#
));
<<<<<<< HEAD
assert_eq!(actual.out, "Dir");
})
}
=======
assert_eq!(actual.out, "dir");
})
}
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn returns_type_of_existing_directory() {
Playground::setup("path_expand_1", |dirs, sandbox| {
@ -63,10 +53,6 @@ fn returns_type_of_existing_directory() {
"#
));
<<<<<<< HEAD
assert_eq!(actual.out, "File");
=======
assert_eq!(actual.out, "file");
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
})
}

View File

@ -0,0 +1,29 @@
use nu_test_support::fs::Stub::FileWithContentToBeTrimmed;
use nu_test_support::playground::Playground;
use nu_test_support::{nu, pipeline};
#[test]
fn adds_a_row_to_the_beginning() {
Playground::setup("prepend_test_1", |dirs, sandbox| {
sandbox.with_files(vec![FileWithContentToBeTrimmed(
"los_tres_caballeros.txt",
r#"
Andrés N. Robalino
Jonathan Turner
Yehuda Katz
"#,
)]);
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
open los_tres_caballeros.txt
| lines
| prepend "pollo loco"
| nth 0
"#
));
assert_eq!(actual.out, "pollo loco");
})
}

View File

@ -0,0 +1,16 @@
use nu_test_support::{nu, pipeline};
#[test]
fn generates_a_bool() {
let actual = nu!(
cwd: ".", pipeline(
r#"
random bool
"#
));
let output = actual.out;
let is_boolean_output = output == "true" || output == "false";
assert!(is_boolean_output);
}

View File

@ -0,0 +1,14 @@
use nu_test_support::{nu, pipeline};
#[test]
fn generates_chars_of_specified_length() {
let actual = nu!(
cwd: ".", pipeline(
r#"
random chars -l 15 | size | get chars
"#
));
let result = actual.out;
assert_eq!(result, "15");
}

View File

@ -1,10 +1,7 @@
use nu_test_support::{nu, pipeline};
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn generates_an_decimal() {
let actual = nu!(
@ -17,11 +14,8 @@ fn generates_an_decimal() {
assert!(actual.out.contains("42") || actual.out.contains("43"));
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn generates_55() {
let actual = nu!(
@ -34,11 +28,8 @@ fn generates_55() {
assert!(actual.out.contains("55"));
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn generates_0() {
let actual = nu!(

View File

@ -0,0 +1,13 @@
use nu_test_support::{nu, pipeline};
#[test]
fn rolls_4_roll() {
let actual = nu!(
cwd: ".", pipeline(
r#"
random dice -d 4 -s 10 | length
"#
));
assert_eq!(actual.out, "4");
}

View File

@ -24,11 +24,8 @@ fn generates_55() {
assert!(actual.out.contains("55"));
}
<<<<<<< HEAD
=======
// FIXME: jt: needs more work
#[ignore]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[test]
fn generates_0() {
let actual = nu!(

View File

@ -0,0 +1,7 @@
mod bool;
mod chars;
mod decimal;
mod dice;
mod integer;
#[cfg(feature = "uuid_crate")]
mod uuid;

Some files were not shown because too many files have changed in this diff Show More