mirror of
https://github.com/nushell/nushell
synced 2024-12-26 04:53:09 +00:00
Start to Add WASM Support Again (#14418)
<!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> The [nushell/demo](https://github.com/nushell/demo) project successfully demonstrated running Nushell in the browser using WASM. However, the current version of Nushell cannot be easily built for the `wasm32-unknown-unknown` target, the default for `wasm-bindgen`. This PR introduces initial support for the `wasm32-unknown-unknown` target by disabling OS-dependent features such as filesystem access, IO, and platform/system-specific functionality. This separation is achieved using a new `os` feature in the following crates: - `nu-cmd-lang` - `nu-command` - `nu-engine` - `nu-protocol` The `os` feature includes all functionality that interacts with an operating system. It is enabled by default, but can be disabled using `--no-default-features`. All crates that depend on these core crates now use `--no-default-features` to allow compilation for WASM. To demonstrate compatibility, the following script builds all crates expected to work with WASM. Direct user interaction, running external commands, working with plugins, and features requiring `openssl` are out of scope for now due to their complexity or reliance on C libraries, which are difficult to compile and link in a WASM environment. ```nushell [ # compatible crates "nu-cmd-base", "nu-cmd-extra", "nu-cmd-lang", "nu-color-config", "nu-command", "nu-derive-value", "nu-engine", "nu-glob", "nu-json", "nu-parser", "nu-path", "nu-pretty-hex", "nu-protocol", "nu-std", "nu-system", "nu-table", "nu-term-grid", "nu-utils", "nuon" ] | each {cargo build -p $in --target wasm32-unknown-unknown --no-default-features} ``` ## Caveats This PR has a few caveats: 1. **`miette` and `terminal-size` Dependency Issue** `miette` depends on `terminal-size`, which uses `rustix` when the target is not Windows. However, `rustix` requires `std::os::unix`, which is unavailable in WASM. To address this, I opened a [PR](https://github.com/eminence/terminal-size/pull/68) for `terminal-size` to conditionally compile `rustix` only when the target is Unix. For now, the `Cargo.toml` includes patches to: - Use my forked version of `terminal-size`. - ~~Use an unreleased version of `miette` that depends on `terminal-size@0.4`.~~ These patches are temporary and can be removed once the upstream changes are merged and released. 2. **Test Output Adjustments** Due to the slight bump in the `miette` version, one test required adjustments to accommodate minor formatting changes in the error output, such as shifted newlines. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> This shouldn't break anything but allows using some crates for targeting `wasm32-unknown-unknown` to revive the demo page eventually. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass (on Windows make sure to [enable developer mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging)) - `cargo run -- -c "use toolkit.nu; toolkit test stdlib"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> - 🟢 `toolkit fmt` - 🟢 `toolkit clippy` - 🟢 `toolkit test` - 🟢 `toolkit test stdlib` I did not add any extra tests, I just checked that compiling works, also when using the host target but unselecting the `os` feature. # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> ~~Breaking the wasm support can be easily done by adding some `use`s or by adding a new dependency, we should definitely add some CI that also at least builds against wasm to make sure that building for it keep working.~~ I added a job to build wasm. --------- Co-authored-by: Ian Manske <ian.manske@pm.me>
This commit is contained in:
parent
07a37f9b47
commit
3d5f853b03
48 changed files with 490 additions and 234 deletions
31
.github/workflows/ci.yml
vendored
31
.github/workflows/ci.yml
vendored
|
@ -162,3 +162,34 @@ jobs:
|
||||||
else
|
else
|
||||||
echo "no changes in working directory";
|
echo "no changes in working directory";
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
build-wasm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4.1.7
|
||||||
|
|
||||||
|
- name: Setup Rust toolchain and cache
|
||||||
|
uses: actions-rust-lang/setup-rust-toolchain@v1.10.1
|
||||||
|
|
||||||
|
- name: Add wasm32-unknown-unknown target
|
||||||
|
run: rustup target add wasm32-unknown-unknown
|
||||||
|
|
||||||
|
- run: cargo build -p nu-cmd-base --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-cmd-extra --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-cmd-lang --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-color-config --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-command --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-derive-value --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-engine --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-glob --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-json --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-parser --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-path --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-pretty-hex --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-protocol --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-std --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-system --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-table --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-term-grid --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nu-utils --no-default-features --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build -p nuon --no-default-features --target wasm32-unknown-unknown
|
||||||
|
|
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -2647,7 +2647,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
|
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3368,6 +3368,7 @@ dependencies = [
|
||||||
"fancy-regex",
|
"fancy-regex",
|
||||||
"filesize",
|
"filesize",
|
||||||
"filetime",
|
"filetime",
|
||||||
|
"getrandom",
|
||||||
"human-date-parser",
|
"human-date-parser",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"indicatif",
|
"indicatif",
|
||||||
|
@ -3755,6 +3756,7 @@ dependencies = [
|
||||||
name = "nu-utils"
|
name = "nu-utils"
|
||||||
version = "0.100.1"
|
version = "0.100.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"crossterm 0.28.1",
|
||||||
"crossterm_winapi",
|
"crossterm_winapi",
|
||||||
"fancy-regex",
|
"fancy-regex",
|
||||||
"log",
|
"log",
|
||||||
|
@ -6847,9 +6849,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "terminal_size"
|
name = "terminal_size"
|
||||||
version = "0.4.0"
|
version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef"
|
checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustix",
|
"rustix",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
|
@ -7874,7 +7876,7 @@ version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -134,6 +134,7 @@ quickcheck = "1.0"
|
||||||
quickcheck_macros = "1.0"
|
quickcheck_macros = "1.0"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
getrandom = "0.2" # pick same version that rand requires
|
||||||
rand_chacha = "0.3.1"
|
rand_chacha = "0.3.1"
|
||||||
ratatui = "0.26"
|
ratatui = "0.26"
|
||||||
rayon = "1.10"
|
rayon = "1.10"
|
||||||
|
|
|
@ -19,11 +19,11 @@ tempfile = { workspace = true }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-cmd-base = { path = "../nu-cmd-base", version = "0.100.1" }
|
nu-cmd-base = { path = "../nu-cmd-base", version = "0.100.1" }
|
||||||
nu-engine = { path = "../nu-engine", version = "0.100.1" }
|
nu-engine = { path = "../nu-engine", version = "0.100.1", features = ["os"] }
|
||||||
nu-path = { path = "../nu-path", version = "0.100.1" }
|
nu-path = { path = "../nu-path", version = "0.100.1" }
|
||||||
nu-parser = { path = "../nu-parser", version = "0.100.1" }
|
nu-parser = { path = "../nu-parser", version = "0.100.1" }
|
||||||
nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.100.1", optional = true }
|
nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.100.1", optional = true }
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.100.1" }
|
nu-protocol = { path = "../nu-protocol", version = "0.100.1", features = ["os"] }
|
||||||
nu-utils = { path = "../nu-utils", version = "0.100.1" }
|
nu-utils = { path = "../nu-utils", version = "0.100.1" }
|
||||||
nu-color-config = { path = "../nu-color-config", version = "0.100.1" }
|
nu-color-config = { path = "../nu-color-config", version = "0.100.1" }
|
||||||
nu-ansi-term = { workspace = true }
|
nu-ansi-term = { workspace = true }
|
||||||
|
|
|
@ -13,10 +13,10 @@ version = "0.100.1"
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-engine = { path = "../nu-engine", version = "0.100.1" }
|
nu-engine = { path = "../nu-engine", version = "0.100.1", default-features = false }
|
||||||
nu-parser = { path = "../nu-parser", version = "0.100.1" }
|
nu-parser = { path = "../nu-parser", version = "0.100.1" }
|
||||||
nu-path = { path = "../nu-path", version = "0.100.1" }
|
nu-path = { path = "../nu-path", version = "0.100.1" }
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.100.1" }
|
nu-protocol = { path = "../nu-protocol", version = "0.100.1", default-features = false }
|
||||||
|
|
||||||
indexmap = { workspace = true }
|
indexmap = { workspace = true }
|
||||||
miette = { workspace = true }
|
miette = { workspace = true }
|
||||||
|
|
|
@ -17,12 +17,12 @@ workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-cmd-base = { path = "../nu-cmd-base", version = "0.100.1" }
|
nu-cmd-base = { path = "../nu-cmd-base", version = "0.100.1" }
|
||||||
nu-engine = { path = "../nu-engine", version = "0.100.1" }
|
nu-engine = { path = "../nu-engine", version = "0.100.1", default-features = false }
|
||||||
nu-json = { version = "0.100.1", path = "../nu-json" }
|
nu-json = { version = "0.100.1", path = "../nu-json" }
|
||||||
nu-parser = { path = "../nu-parser", version = "0.100.1" }
|
nu-parser = { path = "../nu-parser", version = "0.100.1" }
|
||||||
nu-pretty-hex = { version = "0.100.1", path = "../nu-pretty-hex" }
|
nu-pretty-hex = { version = "0.100.1", path = "../nu-pretty-hex" }
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.100.1" }
|
nu-protocol = { path = "../nu-protocol", version = "0.100.1", default-features = false }
|
||||||
nu-utils = { path = "../nu-utils", version = "0.100.1" }
|
nu-utils = { path = "../nu-utils", version = "0.100.1", default-features = false }
|
||||||
|
|
||||||
# Potential dependencies for extras
|
# Potential dependencies for extras
|
||||||
heck = { workspace = true }
|
heck = { workspace = true }
|
||||||
|
|
|
@ -15,10 +15,10 @@ bench = false
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-engine = { path = "../nu-engine", version = "0.100.1" }
|
nu-engine = { path = "../nu-engine", version = "0.100.1", default-features = false }
|
||||||
nu-parser = { path = "../nu-parser", version = "0.100.1" }
|
nu-parser = { path = "../nu-parser", version = "0.100.1" }
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.100.1" }
|
nu-protocol = { path = "../nu-protocol", version = "0.100.1", default-features = false }
|
||||||
nu-utils = { path = "../nu-utils", version = "0.100.1" }
|
nu-utils = { path = "../nu-utils", version = "0.100.1", default-features = false }
|
||||||
|
|
||||||
itertools = { workspace = true }
|
itertools = { workspace = true }
|
||||||
shadow-rs = { version = "0.36", default-features = false }
|
shadow-rs = { version = "0.36", default-features = false }
|
||||||
|
@ -27,6 +27,17 @@ shadow-rs = { version = "0.36", default-features = false }
|
||||||
shadow-rs = { version = "0.36", default-features = false }
|
shadow-rs = { version = "0.36", default-features = false }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
default = ["os"]
|
||||||
|
os = [
|
||||||
|
"nu-engine/os",
|
||||||
|
"nu-protocol/os",
|
||||||
|
"nu-utils/os",
|
||||||
|
]
|
||||||
|
plugin = [
|
||||||
|
"nu-protocol/plugin",
|
||||||
|
"os",
|
||||||
|
]
|
||||||
|
|
||||||
mimalloc = []
|
mimalloc = []
|
||||||
trash-support = []
|
trash-support = []
|
||||||
sqlite = []
|
sqlite = []
|
||||||
|
|
|
@ -169,6 +169,7 @@ fn run(
|
||||||
let origin = match stream.source() {
|
let origin = match stream.source() {
|
||||||
ByteStreamSource::Read(_) => "unknown",
|
ByteStreamSource::Read(_) => "unknown",
|
||||||
ByteStreamSource::File(_) => "file",
|
ByteStreamSource::File(_) => "file",
|
||||||
|
#[cfg(feature = "os")]
|
||||||
ByteStreamSource::Child(_) => "external",
|
ByteStreamSource::Child(_) => "external",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use nu_engine::{command_prelude::*, get_eval_block_with_early_return, redirect_env};
|
use nu_engine::{command_prelude::*, get_eval_block_with_early_return, redirect_env};
|
||||||
use nu_protocol::{
|
#[cfg(feature = "os")]
|
||||||
engine::Closure,
|
use nu_protocol::process::{ChildPipe, ChildProcess};
|
||||||
process::{ChildPipe, ChildProcess},
|
use nu_protocol::{engine::Closure, ByteStream, ByteStreamSource, OutDest};
|
||||||
ByteStream, ByteStreamSource, OutDest,
|
|
||||||
};
|
|
||||||
use std::{
|
use std::{
|
||||||
io::{Cursor, Read},
|
io::{Cursor, Read},
|
||||||
thread,
|
thread,
|
||||||
|
@ -119,6 +118,13 @@ impl Command for Do {
|
||||||
match result {
|
match result {
|
||||||
Ok(PipelineData::ByteStream(stream, metadata)) if capture_errors => {
|
Ok(PipelineData::ByteStream(stream, metadata)) if capture_errors => {
|
||||||
let span = stream.span();
|
let span = stream.span();
|
||||||
|
#[cfg(not(feature = "os"))]
|
||||||
|
return Err(ShellError::DisabledOsSupport {
|
||||||
|
msg: "Cannot create a thread to receive stdout message.".to_string(),
|
||||||
|
span: Some(span),
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(feature = "os")]
|
||||||
match stream.into_child() {
|
match stream.into_child() {
|
||||||
Ok(mut child) => {
|
Ok(mut child) => {
|
||||||
// Use a thread to receive stdout message.
|
// Use a thread to receive stdout message.
|
||||||
|
@ -196,6 +202,7 @@ impl Command for Do {
|
||||||
OutDest::Pipe | OutDest::PipeSeparate | OutDest::Value
|
OutDest::Pipe | OutDest::PipeSeparate | OutDest::Value
|
||||||
) =>
|
) =>
|
||||||
{
|
{
|
||||||
|
#[cfg(feature = "os")]
|
||||||
if let ByteStreamSource::Child(child) = stream.source_mut() {
|
if let ByteStreamSource::Child(child) = stream.source_mut() {
|
||||||
child.ignore_error(true);
|
child.ignore_error(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ impl Command for Ignore {
|
||||||
mut input: PipelineData,
|
mut input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
if let PipelineData::ByteStream(stream, _) = &mut input {
|
if let PipelineData::ByteStream(stream, _) = &mut input {
|
||||||
|
#[cfg(feature = "os")]
|
||||||
if let ByteStreamSource::Child(child) = stream.source_mut() {
|
if let ByteStreamSource::Child(child) = stream.source_mut() {
|
||||||
child.ignore_error(true);
|
child.ignore_error(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,11 @@ pub fn version(engine_state: &EngineState, span: Span) -> Result<PipelineData, S
|
||||||
Value::string(features_enabled().join(", "), span),
|
Value::string(features_enabled().join(", "), span),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "plugin"))]
|
||||||
|
let _ = engine_state;
|
||||||
|
|
||||||
|
#[cfg(feature = "plugin")]
|
||||||
|
{
|
||||||
// Get a list of plugin names and versions if present
|
// Get a list of plugin names and versions if present
|
||||||
let installed_plugins = engine_state
|
let installed_plugins = engine_state
|
||||||
.plugins()
|
.plugins()
|
||||||
|
@ -134,6 +139,7 @@ pub fn version(engine_state: &EngineState, span: Span) -> Result<PipelineData, S
|
||||||
"installed_plugins",
|
"installed_plugins",
|
||||||
Value::string(installed_plugins.join(", "), span),
|
Value::string(installed_plugins.join(", "), span),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Value::record(record, span).into_pipeline_data())
|
Ok(Value::record(record, span).into_pipeline_data())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![cfg_attr(not(feature = "os"), allow(unused))]
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
mod core_commands;
|
mod core_commands;
|
||||||
mod default_context;
|
mod default_context;
|
||||||
|
|
|
@ -14,8 +14,8 @@ bench = false
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.100.1" }
|
nu-protocol = { path = "../nu-protocol", version = "0.100.1", default-features = false }
|
||||||
nu-engine = { path = "../nu-engine", version = "0.100.1" }
|
nu-engine = { path = "../nu-engine", version = "0.100.1", default-features = false }
|
||||||
nu-json = { path = "../nu-json", version = "0.100.1" }
|
nu-json = { path = "../nu-json", version = "0.100.1" }
|
||||||
nu-ansi-term = { workspace = true }
|
nu-ansi-term = { workspace = true }
|
||||||
|
|
||||||
|
|
|
@ -18,17 +18,17 @@ workspace = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-cmd-base = { path = "../nu-cmd-base", version = "0.100.1" }
|
nu-cmd-base = { path = "../nu-cmd-base", version = "0.100.1" }
|
||||||
nu-color-config = { path = "../nu-color-config", version = "0.100.1" }
|
nu-color-config = { path = "../nu-color-config", version = "0.100.1" }
|
||||||
nu-engine = { path = "../nu-engine", version = "0.100.1" }
|
nu-engine = { path = "../nu-engine", version = "0.100.1", default-features = false }
|
||||||
nu-glob = { path = "../nu-glob", version = "0.100.1" }
|
nu-glob = { path = "../nu-glob", version = "0.100.1" }
|
||||||
nu-json = { path = "../nu-json", version = "0.100.1" }
|
nu-json = { path = "../nu-json", version = "0.100.1" }
|
||||||
nu-parser = { path = "../nu-parser", version = "0.100.1" }
|
nu-parser = { path = "../nu-parser", version = "0.100.1" }
|
||||||
nu-path = { path = "../nu-path", version = "0.100.1" }
|
nu-path = { path = "../nu-path", version = "0.100.1" }
|
||||||
nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.100.1" }
|
nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.100.1" }
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.100.1" }
|
nu-protocol = { path = "../nu-protocol", version = "0.100.1", default-features = false }
|
||||||
nu-system = { path = "../nu-system", version = "0.100.1" }
|
nu-system = { path = "../nu-system", version = "0.100.1" }
|
||||||
nu-table = { path = "../nu-table", version = "0.100.1" }
|
nu-table = { path = "../nu-table", version = "0.100.1" }
|
||||||
nu-term-grid = { path = "../nu-term-grid", version = "0.100.1" }
|
nu-term-grid = { path = "../nu-term-grid", version = "0.100.1" }
|
||||||
nu-utils = { path = "../nu-utils", version = "0.100.1" }
|
nu-utils = { path = "../nu-utils", version = "0.100.1", default-features = false }
|
||||||
nu-ansi-term = { workspace = true }
|
nu-ansi-term = { workspace = true }
|
||||||
nuon = { path = "../nuon", version = "0.100.1" }
|
nuon = { path = "../nuon", version = "0.100.1" }
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ chardetng = { workspace = true }
|
||||||
chrono = { workspace = true, features = ["std", "unstable-locales", "clock"], default-features = false }
|
chrono = { workspace = true, features = ["std", "unstable-locales", "clock"], default-features = false }
|
||||||
chrono-humanize = { workspace = true }
|
chrono-humanize = { workspace = true }
|
||||||
chrono-tz = { workspace = true }
|
chrono-tz = { workspace = true }
|
||||||
crossterm = { workspace = true }
|
crossterm = { workspace = true, optional = true }
|
||||||
csv = { workspace = true }
|
csv = { workspace = true }
|
||||||
dialoguer = { workspace = true, default-features = false, features = ["fuzzy-select"] }
|
dialoguer = { workspace = true, default-features = false, features = ["fuzzy-select"] }
|
||||||
digest = { workspace = true, default-features = false }
|
digest = { workspace = true, default-features = false }
|
||||||
|
@ -61,19 +61,20 @@ lscolors = { workspace = true, default-features = false, features = ["nu-ansi-te
|
||||||
md5 = { workspace = true }
|
md5 = { workspace = true }
|
||||||
mime = { workspace = true }
|
mime = { workspace = true }
|
||||||
mime_guess = { workspace = true }
|
mime_guess = { workspace = true }
|
||||||
multipart-rs = { workspace = true }
|
multipart-rs = { workspace = true, optional = true }
|
||||||
native-tls = { workspace = true }
|
native-tls = { workspace = true, optional = true }
|
||||||
notify-debouncer-full = { workspace = true, default-features = false }
|
notify-debouncer-full = { workspace = true, default-features = false, optional = true }
|
||||||
num-format = { workspace = true }
|
num-format = { workspace = true }
|
||||||
num-traits = { workspace = true }
|
num-traits = { workspace = true }
|
||||||
oem_cp = { workspace = true }
|
oem_cp = { workspace = true }
|
||||||
open = { workspace = true }
|
open = { workspace = true, optional = true }
|
||||||
os_pipe = { workspace = true }
|
os_pipe = { workspace = true, optional = true }
|
||||||
pathdiff = { workspace = true }
|
pathdiff = { workspace = true }
|
||||||
percent-encoding = { workspace = true }
|
percent-encoding = { workspace = true }
|
||||||
print-positions = { workspace = true }
|
print-positions = { workspace = true }
|
||||||
quick-xml = { workspace = true }
|
quick-xml = { workspace = true }
|
||||||
rand = { workspace = true }
|
rand = { workspace = true, optional = true }
|
||||||
|
getrandom = { workspace = true, optional = true }
|
||||||
rayon = { workspace = true }
|
rayon = { workspace = true }
|
||||||
regex = { workspace = true }
|
regex = { workspace = true }
|
||||||
roxmltree = { workspace = true }
|
roxmltree = { workspace = true }
|
||||||
|
@ -89,26 +90,26 @@ tabled = { workspace = true, features = ["ansi"], default-features = false }
|
||||||
titlecase = { workspace = true }
|
titlecase = { workspace = true }
|
||||||
toml = { workspace = true, features = ["preserve_order"] }
|
toml = { workspace = true, features = ["preserve_order"] }
|
||||||
unicode-segmentation = { workspace = true }
|
unicode-segmentation = { workspace = true }
|
||||||
ureq = { workspace = true, default-features = false, features = ["charset", "gzip", "json", "native-tls"] }
|
ureq = { workspace = true, default-features = false, features = ["charset", "gzip", "json"] }
|
||||||
url = { workspace = true }
|
url = { workspace = true }
|
||||||
uu_cp = { workspace = true }
|
uu_cp = { workspace = true, optional = true }
|
||||||
uu_mkdir = { workspace = true }
|
uu_mkdir = { workspace = true, optional = true }
|
||||||
uu_mktemp = { workspace = true }
|
uu_mktemp = { workspace = true, optional = true }
|
||||||
uu_mv = { workspace = true }
|
uu_mv = { workspace = true, optional = true }
|
||||||
uu_touch = { workspace = true }
|
uu_touch = { workspace = true, optional = true }
|
||||||
uu_uname = { workspace = true }
|
uu_uname = { workspace = true, optional = true }
|
||||||
uu_whoami = { workspace = true }
|
uu_whoami = { workspace = true, optional = true }
|
||||||
uuid = { workspace = true, features = ["v4"] }
|
uuid = { workspace = true, features = ["v4"], optional = true }
|
||||||
v_htmlescape = { workspace = true }
|
v_htmlescape = { workspace = true }
|
||||||
wax = { workspace = true }
|
wax = { workspace = true }
|
||||||
which = { workspace = true }
|
which = { workspace = true, optional = true }
|
||||||
unicode-width = { workspace = true }
|
unicode-width = { workspace = true }
|
||||||
data-encoding = { version = "2.6.0", features = ["alloc"] }
|
data-encoding = { version = "2.6.0", features = ["alloc"] }
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winreg = { workspace = true }
|
winreg = { workspace = true }
|
||||||
|
|
||||||
[target.'cfg(not(windows))'.dependencies]
|
[target.'cfg(all(not(windows), not(target_arch = "wasm32")))'.dependencies]
|
||||||
uucore = { workspace = true, features = ["mode"] }
|
uucore = { workspace = true, features = ["mode"] }
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
|
@ -134,7 +135,53 @@ features = [
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
plugin = ["nu-parser/plugin"]
|
default = ["os"]
|
||||||
|
os = [
|
||||||
|
# include other features
|
||||||
|
"js",
|
||||||
|
"network",
|
||||||
|
"nu-protocol/os",
|
||||||
|
"nu-utils/os",
|
||||||
|
|
||||||
|
# os-dependant dependencies
|
||||||
|
"crossterm",
|
||||||
|
"notify-debouncer-full",
|
||||||
|
"open",
|
||||||
|
"os_pipe",
|
||||||
|
"uu_cp",
|
||||||
|
"uu_mkdir",
|
||||||
|
"uu_mktemp",
|
||||||
|
"uu_mv",
|
||||||
|
"uu_touch",
|
||||||
|
"uu_uname",
|
||||||
|
"uu_whoami",
|
||||||
|
"which",
|
||||||
|
]
|
||||||
|
|
||||||
|
# The dependencies listed below need 'getrandom'.
|
||||||
|
# They work with JS (usually with wasm-bindgen) or regular OS support.
|
||||||
|
# Hence they are also put under the 'os' feature to avoid repetition.
|
||||||
|
js = [
|
||||||
|
"getrandom",
|
||||||
|
"getrandom/js",
|
||||||
|
"rand",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
|
# These dependencies require networking capabilities, especially the http
|
||||||
|
# interface requires openssl which is not easy to embed into wasm,
|
||||||
|
# using rustls could solve this issue.
|
||||||
|
network = [
|
||||||
|
"multipart-rs",
|
||||||
|
"native-tls",
|
||||||
|
"ureq/native-tls",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
|
plugin = [
|
||||||
|
"nu-parser/plugin",
|
||||||
|
"os",
|
||||||
|
]
|
||||||
sqlite = ["rusqlite"]
|
sqlite = ["rusqlite"]
|
||||||
trash-support = ["trash"]
|
trash-support = ["trash"]
|
||||||
|
|
||||||
|
|
|
@ -177,4 +177,9 @@ fn get_thread_id() -> u64 {
|
||||||
{
|
{
|
||||||
nix::sys::pthread::pthread_self() as u64
|
nix::sys::pthread::pthread_self() as u64
|
||||||
}
|
}
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
{
|
||||||
|
// wasm doesn't have any threads accessible, so we return 0 as a fallback
|
||||||
|
0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::inspect_table;
|
use super::inspect_table;
|
||||||
use crossterm::terminal::size;
|
|
||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
use nu_utils::terminal_size;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Inspect;
|
pub struct Inspect;
|
||||||
|
@ -38,7 +38,7 @@ impl Command for Inspect {
|
||||||
let original_input = input_val.clone();
|
let original_input = input_val.clone();
|
||||||
let description = input_val.get_type().to_string();
|
let description = input_val.get_type().to_string();
|
||||||
|
|
||||||
let (cols, _rows) = size().unwrap_or((0, 0));
|
let (cols, _rows) = terminal_size().unwrap_or((0, 0));
|
||||||
|
|
||||||
let table = inspect_table::build_table(input_val, description, cols as usize);
|
let table = inspect_table::build_table(input_val, description, cols as usize);
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,10 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filters
|
// Filters
|
||||||
|
#[cfg(feature = "rand")]
|
||||||
|
bind_command! {
|
||||||
|
Shuffle
|
||||||
|
}
|
||||||
bind_command! {
|
bind_command! {
|
||||||
All,
|
All,
|
||||||
Any,
|
Any,
|
||||||
|
@ -72,7 +76,6 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
||||||
Rename,
|
Rename,
|
||||||
Reverse,
|
Reverse,
|
||||||
Select,
|
Select,
|
||||||
Shuffle,
|
|
||||||
Skip,
|
Skip,
|
||||||
SkipUntil,
|
SkipUntil,
|
||||||
SkipWhile,
|
SkipWhile,
|
||||||
|
@ -114,6 +117,7 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
||||||
};
|
};
|
||||||
|
|
||||||
// System
|
// System
|
||||||
|
#[cfg(feature = "os")]
|
||||||
bind_command! {
|
bind_command! {
|
||||||
Complete,
|
Complete,
|
||||||
External,
|
External,
|
||||||
|
@ -161,10 +165,12 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
||||||
ViewSpan,
|
ViewSpan,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(all(feature = "os", windows))]
|
||||||
bind_command! { RegistryQuery }
|
bind_command! { RegistryQuery }
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(all(
|
||||||
|
feature = "os",
|
||||||
|
any(
|
||||||
target_os = "android",
|
target_os = "android",
|
||||||
target_os = "linux",
|
target_os = "linux",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
|
@ -172,6 +178,7 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
||||||
target_os = "openbsd",
|
target_os = "openbsd",
|
||||||
target_os = "macos",
|
target_os = "macos",
|
||||||
target_os = "windows"
|
target_os = "windows"
|
||||||
|
)
|
||||||
))]
|
))]
|
||||||
bind_command! { Ps };
|
bind_command! { Ps };
|
||||||
|
|
||||||
|
@ -219,6 +226,7 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
||||||
};
|
};
|
||||||
|
|
||||||
// FileSystem
|
// FileSystem
|
||||||
|
#[cfg(feature = "os")]
|
||||||
bind_command! {
|
bind_command! {
|
||||||
Cd,
|
Cd,
|
||||||
Ls,
|
Ls,
|
||||||
|
@ -237,6 +245,7 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Platform
|
// Platform
|
||||||
|
#[cfg(feature = "os")]
|
||||||
bind_command! {
|
bind_command! {
|
||||||
Ansi,
|
Ansi,
|
||||||
AnsiLink,
|
AnsiLink,
|
||||||
|
@ -255,7 +264,7 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
||||||
Whoami,
|
Whoami,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(all(unix, feature = "os"))]
|
||||||
bind_command! { ULimit };
|
bind_command! { ULimit };
|
||||||
|
|
||||||
// Date
|
// Date
|
||||||
|
@ -380,6 +389,7 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Network
|
// Network
|
||||||
|
#[cfg(feature = "network")]
|
||||||
bind_command! {
|
bind_command! {
|
||||||
Http,
|
Http,
|
||||||
HttpDelete,
|
HttpDelete,
|
||||||
|
@ -389,6 +399,9 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
||||||
HttpPost,
|
HttpPost,
|
||||||
HttpPut,
|
HttpPut,
|
||||||
HttpOptions,
|
HttpOptions,
|
||||||
|
Port,
|
||||||
|
}
|
||||||
|
bind_command! {
|
||||||
Url,
|
Url,
|
||||||
UrlBuildQuery,
|
UrlBuildQuery,
|
||||||
UrlSplitQuery,
|
UrlSplitQuery,
|
||||||
|
@ -396,10 +409,10 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
||||||
UrlEncode,
|
UrlEncode,
|
||||||
UrlJoin,
|
UrlJoin,
|
||||||
UrlParse,
|
UrlParse,
|
||||||
Port,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Random
|
// Random
|
||||||
|
#[cfg(feature = "rand")]
|
||||||
bind_command! {
|
bind_command! {
|
||||||
Random,
|
Random,
|
||||||
RandomBool,
|
RandomBool,
|
||||||
|
|
80
crates/nu-command/src/env/config/config_.rs
vendored
80
crates/nu-command/src/env/config/config_.rs
vendored
|
@ -1,4 +1,6 @@
|
||||||
use nu_engine::{command_prelude::*, get_full_help};
|
use nu_cmd_base::util::get_editor;
|
||||||
|
use nu_engine::{command_prelude::*, env_to_strings, get_full_help};
|
||||||
|
use nu_system::ForegroundChild;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ConfigMeta;
|
pub struct ConfigMeta;
|
||||||
|
@ -36,3 +38,79 @@ impl Command for ConfigMeta {
|
||||||
vec!["options", "setup"]
|
vec!["options", "setup"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "os"))]
|
||||||
|
pub(super) fn start_editor(
|
||||||
|
_: &'static str,
|
||||||
|
_: &EngineState,
|
||||||
|
_: &mut Stack,
|
||||||
|
call: &Call,
|
||||||
|
) -> Result<PipelineData, ShellError> {
|
||||||
|
Err(ShellError::DisabledOsSupport {
|
||||||
|
msg: "Running external commands is not available without OS support.".to_string(),
|
||||||
|
span: Some(call.head),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "os")]
|
||||||
|
pub(super) fn start_editor(
|
||||||
|
config_path: &'static str,
|
||||||
|
engine_state: &EngineState,
|
||||||
|
stack: &mut Stack,
|
||||||
|
call: &Call,
|
||||||
|
) -> Result<PipelineData, ShellError> {
|
||||||
|
// Find the editor executable.
|
||||||
|
let (editor_name, editor_args) = get_editor(engine_state, stack, call.head)?;
|
||||||
|
let paths = nu_engine::env::path_str(engine_state, stack, call.head)?;
|
||||||
|
let cwd = engine_state.cwd(Some(stack))?;
|
||||||
|
let editor_executable =
|
||||||
|
crate::which(&editor_name, &paths, cwd.as_ref()).ok_or(ShellError::ExternalCommand {
|
||||||
|
label: format!("`{editor_name}` not found"),
|
||||||
|
help: "Failed to find the editor executable".into(),
|
||||||
|
span: call.head,
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let Some(config_path) = engine_state.get_config_path(config_path) else {
|
||||||
|
return Err(ShellError::GenericError {
|
||||||
|
error: format!("Could not find $nu.{config_path}"),
|
||||||
|
msg: format!("Could not find $nu.{config_path}"),
|
||||||
|
span: None,
|
||||||
|
help: None,
|
||||||
|
inner: vec![],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
let config_path = config_path.to_string_lossy().to_string();
|
||||||
|
|
||||||
|
// Create the command.
|
||||||
|
let mut command = std::process::Command::new(editor_executable);
|
||||||
|
|
||||||
|
// Configure PWD.
|
||||||
|
command.current_dir(cwd);
|
||||||
|
|
||||||
|
// Configure environment variables.
|
||||||
|
let envs = env_to_strings(engine_state, stack)?;
|
||||||
|
command.env_clear();
|
||||||
|
command.envs(envs);
|
||||||
|
|
||||||
|
// Configure args.
|
||||||
|
command.arg(config_path);
|
||||||
|
command.args(editor_args);
|
||||||
|
|
||||||
|
// Spawn the child process. On Unix, also put the child process to
|
||||||
|
// foreground if we're in an interactive session.
|
||||||
|
#[cfg(windows)]
|
||||||
|
let child = ForegroundChild::spawn(command)?;
|
||||||
|
#[cfg(unix)]
|
||||||
|
let child = ForegroundChild::spawn(
|
||||||
|
command,
|
||||||
|
engine_state.is_interactive,
|
||||||
|
&engine_state.pipeline_externals_state,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Wrap the output into a `PipelineData::ByteStream`.
|
||||||
|
let child = nu_protocol::process::ChildProcess::new(child, None, false, call.head)?;
|
||||||
|
Ok(PipelineData::ByteStream(
|
||||||
|
ByteStream::child(child, call.head),
|
||||||
|
None,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
61
crates/nu-command/src/env/config/config_env.rs
vendored
61
crates/nu-command/src/env/config/config_env.rs
vendored
|
@ -1,7 +1,4 @@
|
||||||
use nu_cmd_base::util::get_editor;
|
use nu_engine::command_prelude::*;
|
||||||
use nu_engine::{command_prelude::*, env_to_strings};
|
|
||||||
use nu_protocol::{process::ChildProcess, ByteStream};
|
|
||||||
use nu_system::ForegroundChild;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ConfigEnv;
|
pub struct ConfigEnv;
|
||||||
|
@ -81,60 +78,6 @@ impl Command for ConfigEnv {
|
||||||
return Ok(Value::string(nu_utils::get_sample_env(), head).into_pipeline_data());
|
return Ok(Value::string(nu_utils::get_sample_env(), head).into_pipeline_data());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the editor executable.
|
super::config_::start_editor("env-path", engine_state, stack, call)
|
||||||
let (editor_name, editor_args) = get_editor(engine_state, stack, call.head)?;
|
|
||||||
let paths = nu_engine::env::path_str(engine_state, stack, call.head)?;
|
|
||||||
let cwd = engine_state.cwd(Some(stack))?;
|
|
||||||
let editor_executable = crate::which(&editor_name, &paths, cwd.as_ref()).ok_or(
|
|
||||||
ShellError::ExternalCommand {
|
|
||||||
label: format!("`{editor_name}` not found"),
|
|
||||||
help: "Failed to find the editor executable".into(),
|
|
||||||
span: call.head,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let Some(env_path) = engine_state.get_config_path("env-path") else {
|
|
||||||
return Err(ShellError::GenericError {
|
|
||||||
error: "Could not find $nu.env-path".into(),
|
|
||||||
msg: "Could not find $nu.env-path".into(),
|
|
||||||
span: None,
|
|
||||||
help: None,
|
|
||||||
inner: vec![],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
let env_path = env_path.to_string_lossy().to_string();
|
|
||||||
|
|
||||||
// Create the command.
|
|
||||||
let mut command = std::process::Command::new(editor_executable);
|
|
||||||
|
|
||||||
// Configure PWD.
|
|
||||||
command.current_dir(cwd);
|
|
||||||
|
|
||||||
// Configure environment variables.
|
|
||||||
let envs = env_to_strings(engine_state, stack)?;
|
|
||||||
command.env_clear();
|
|
||||||
command.envs(envs);
|
|
||||||
|
|
||||||
// Configure args.
|
|
||||||
command.arg(env_path);
|
|
||||||
command.args(editor_args);
|
|
||||||
|
|
||||||
// Spawn the child process. On Unix, also put the child process to
|
|
||||||
// foreground if we're in an interactive session.
|
|
||||||
#[cfg(windows)]
|
|
||||||
let child = ForegroundChild::spawn(command)?;
|
|
||||||
#[cfg(unix)]
|
|
||||||
let child = ForegroundChild::spawn(
|
|
||||||
command,
|
|
||||||
engine_state.is_interactive,
|
|
||||||
&engine_state.pipeline_externals_state,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Wrap the output into a `PipelineData::ByteStream`.
|
|
||||||
let child = ChildProcess::new(child, None, false, call.head)?;
|
|
||||||
Ok(PipelineData::ByteStream(
|
|
||||||
ByteStream::child(child, call.head),
|
|
||||||
None,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
61
crates/nu-command/src/env/config/config_nu.rs
vendored
61
crates/nu-command/src/env/config/config_nu.rs
vendored
|
@ -1,7 +1,4 @@
|
||||||
use nu_cmd_base::util::get_editor;
|
use nu_engine::command_prelude::*;
|
||||||
use nu_engine::{command_prelude::*, env_to_strings};
|
|
||||||
use nu_protocol::{process::ChildProcess, ByteStream};
|
|
||||||
use nu_system::ForegroundChild;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ConfigNu;
|
pub struct ConfigNu;
|
||||||
|
@ -83,60 +80,6 @@ impl Command for ConfigNu {
|
||||||
return Ok(Value::string(nu_utils::get_sample_config(), head).into_pipeline_data());
|
return Ok(Value::string(nu_utils::get_sample_config(), head).into_pipeline_data());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the editor executable.
|
super::config_::start_editor("config-path", engine_state, stack, call)
|
||||||
let (editor_name, editor_args) = get_editor(engine_state, stack, call.head)?;
|
|
||||||
let paths = nu_engine::env::path_str(engine_state, stack, call.head)?;
|
|
||||||
let cwd = engine_state.cwd(Some(stack))?;
|
|
||||||
let editor_executable = crate::which(&editor_name, &paths, cwd.as_ref()).ok_or(
|
|
||||||
ShellError::ExternalCommand {
|
|
||||||
label: format!("`{editor_name}` not found"),
|
|
||||||
help: "Failed to find the editor executable".into(),
|
|
||||||
span: call.head,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let Some(config_path) = engine_state.get_config_path("config-path") else {
|
|
||||||
return Err(ShellError::GenericError {
|
|
||||||
error: "Could not find $nu.config-path".into(),
|
|
||||||
msg: "Could not find $nu.config-path".into(),
|
|
||||||
span: None,
|
|
||||||
help: None,
|
|
||||||
inner: vec![],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
let config_path = config_path.to_string_lossy().to_string();
|
|
||||||
|
|
||||||
// Create the command.
|
|
||||||
let mut command = std::process::Command::new(editor_executable);
|
|
||||||
|
|
||||||
// Configure PWD.
|
|
||||||
command.current_dir(cwd);
|
|
||||||
|
|
||||||
// Configure environment variables.
|
|
||||||
let envs = env_to_strings(engine_state, stack)?;
|
|
||||||
command.env_clear();
|
|
||||||
command.envs(envs);
|
|
||||||
|
|
||||||
// Configure args.
|
|
||||||
command.arg(config_path);
|
|
||||||
command.args(editor_args);
|
|
||||||
|
|
||||||
// Spawn the child process. On Unix, also put the child process to
|
|
||||||
// foreground if we're in an interactive session.
|
|
||||||
#[cfg(windows)]
|
|
||||||
let child = ForegroundChild::spawn(command)?;
|
|
||||||
#[cfg(unix)]
|
|
||||||
let child = ForegroundChild::spawn(
|
|
||||||
command,
|
|
||||||
engine_state.is_interactive,
|
|
||||||
&engine_state.pipeline_externals_state,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Wrap the output into a `PipelineData::ByteStream`.
|
|
||||||
let child = ChildProcess::new(child, None, false, call.head)?;
|
|
||||||
Ok(PipelineData::ByteStream(
|
|
||||||
ByteStream::child(child, call.head),
|
|
||||||
None,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,3 +103,9 @@ fn is_root_impl() -> bool {
|
||||||
|
|
||||||
elevated
|
elevated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
fn is_root_impl() -> bool {
|
||||||
|
// in wasm we don't have a user system, so technically we are never root
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
|
@ -102,6 +102,7 @@ impl Command for Save {
|
||||||
ByteStreamSource::File(source) => {
|
ByteStreamSource::File(source) => {
|
||||||
stream_to_file(source, size, signals, file, span, progress)?;
|
stream_to_file(source, size, signals, file, span, progress)?;
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "os")]
|
||||||
ByteStreamSource::Child(mut child) => {
|
ByteStreamSource::Child(mut child) => {
|
||||||
fn write_or_consume_stderr(
|
fn write_or_consume_stderr(
|
||||||
stderr: ChildPipe,
|
stderr: ChildPipe,
|
||||||
|
|
|
@ -37,6 +37,7 @@ mod reject;
|
||||||
mod rename;
|
mod rename;
|
||||||
mod reverse;
|
mod reverse;
|
||||||
mod select;
|
mod select;
|
||||||
|
#[cfg(feature = "rand")]
|
||||||
mod shuffle;
|
mod shuffle;
|
||||||
mod skip;
|
mod skip;
|
||||||
mod sort;
|
mod sort;
|
||||||
|
@ -95,6 +96,7 @@ pub use reject::Reject;
|
||||||
pub use rename::Rename;
|
pub use rename::Rename;
|
||||||
pub use reverse::Reverse;
|
pub use reverse::Reverse;
|
||||||
pub use select::Select;
|
pub use select::Select;
|
||||||
|
#[cfg(feature = "rand")]
|
||||||
pub use shuffle::Shuffle;
|
pub use shuffle::Shuffle;
|
||||||
pub use skip::*;
|
pub use skip::*;
|
||||||
pub use sort::Sort;
|
pub use sort::Sort;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use nu_engine::{command_prelude::*, get_eval_block_with_early_return};
|
use nu_engine::{command_prelude::*, get_eval_block_with_early_return};
|
||||||
|
#[cfg(feature = "os")]
|
||||||
|
use nu_protocol::process::ChildPipe;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
byte_stream::copy_with_signals, engine::Closure, process::ChildPipe, report_shell_error,
|
byte_stream::copy_with_signals, engine::Closure, report_shell_error, ByteStream,
|
||||||
ByteStream, ByteStreamSource, OutDest, PipelineMetadata, Signals,
|
ByteStreamSource, OutDest, PipelineMetadata, Signals,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
io::{self, Read, Write},
|
io::{self, Read, Write},
|
||||||
|
@ -152,6 +154,7 @@ use it in your pipeline."#
|
||||||
metadata,
|
metadata,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "os")]
|
||||||
ByteStreamSource::Child(mut child) => {
|
ByteStreamSource::Child(mut child) => {
|
||||||
let stderr_thread = if use_stderr {
|
let stderr_thread = if use_stderr {
|
||||||
let stderr_thread = if let Some(stderr) = child.stderr.take() {
|
let stderr_thread = if let Some(stderr) = child.stderr.take() {
|
||||||
|
@ -454,6 +457,7 @@ fn copy(src: impl Read, dest: impl Write, info: &StreamInfo) -> Result<(), Shell
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "os")]
|
||||||
fn copy_pipe(pipe: ChildPipe, dest: impl Write, info: &StreamInfo) -> Result<(), ShellError> {
|
fn copy_pipe(pipe: ChildPipe, dest: impl Write, info: &StreamInfo) -> Result<(), ShellError> {
|
||||||
match pipe {
|
match pipe {
|
||||||
ChildPipe::Pipe(pipe) => copy(pipe, dest, info),
|
ChildPipe::Pipe(pipe) => copy(pipe, dest, info),
|
||||||
|
@ -477,6 +481,7 @@ fn copy_on_thread(
|
||||||
.map_err(|e| e.into_spanned(span).into())
|
.map_err(|e| e.into_spanned(span).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "os")]
|
||||||
fn copy_pipe_on_thread(
|
fn copy_pipe_on_thread(
|
||||||
pipe: ChildPipe,
|
pipe: ChildPipe,
|
||||||
dest: impl Write + Send + 'static,
|
dest: impl Write + Send + 'static,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![cfg_attr(not(feature = "os"), allow(unused))]
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
mod bytes;
|
mod bytes;
|
||||||
mod charting;
|
mod charting;
|
||||||
|
@ -8,6 +9,7 @@ mod default_context;
|
||||||
mod env;
|
mod env;
|
||||||
mod example_test;
|
mod example_test;
|
||||||
mod experimental;
|
mod experimental;
|
||||||
|
#[cfg(feature = "os")]
|
||||||
mod filesystem;
|
mod filesystem;
|
||||||
mod filters;
|
mod filters;
|
||||||
mod formats;
|
mod formats;
|
||||||
|
@ -18,8 +20,10 @@ mod math;
|
||||||
mod misc;
|
mod misc;
|
||||||
mod network;
|
mod network;
|
||||||
mod path;
|
mod path;
|
||||||
|
#[cfg(feature = "os")]
|
||||||
mod platform;
|
mod platform;
|
||||||
mod progress_bar;
|
mod progress_bar;
|
||||||
|
#[cfg(feature = "rand")]
|
||||||
mod random;
|
mod random;
|
||||||
mod removed;
|
mod removed;
|
||||||
mod shells;
|
mod shells;
|
||||||
|
@ -27,6 +31,7 @@ mod sort_utils;
|
||||||
#[cfg(feature = "sqlite")]
|
#[cfg(feature = "sqlite")]
|
||||||
mod stor;
|
mod stor;
|
||||||
mod strings;
|
mod strings;
|
||||||
|
#[cfg(feature = "os")]
|
||||||
mod system;
|
mod system;
|
||||||
mod viewers;
|
mod viewers;
|
||||||
|
|
||||||
|
@ -40,6 +45,7 @@ pub use env::*;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub use example_test::{test_examples, test_examples_with_commands};
|
pub use example_test::{test_examples, test_examples_with_commands};
|
||||||
pub use experimental::*;
|
pub use experimental::*;
|
||||||
|
#[cfg(feature = "os")]
|
||||||
pub use filesystem::*;
|
pub use filesystem::*;
|
||||||
pub use filters::*;
|
pub use filters::*;
|
||||||
pub use formats::*;
|
pub use formats::*;
|
||||||
|
@ -50,7 +56,9 @@ pub use math::*;
|
||||||
pub use misc::*;
|
pub use misc::*;
|
||||||
pub use network::*;
|
pub use network::*;
|
||||||
pub use path::*;
|
pub use path::*;
|
||||||
|
#[cfg(feature = "os")]
|
||||||
pub use platform::*;
|
pub use platform::*;
|
||||||
|
#[cfg(feature = "rand")]
|
||||||
pub use random::*;
|
pub use random::*;
|
||||||
pub use removed::*;
|
pub use removed::*;
|
||||||
pub use shells::*;
|
pub use shells::*;
|
||||||
|
@ -58,6 +66,7 @@ pub use sort_utils::*;
|
||||||
#[cfg(feature = "sqlite")]
|
#[cfg(feature = "sqlite")]
|
||||||
pub use stor::*;
|
pub use stor::*;
|
||||||
pub use strings::*;
|
pub use strings::*;
|
||||||
|
#[cfg(feature = "os")]
|
||||||
pub use system::*;
|
pub use system::*;
|
||||||
pub use viewers::*;
|
pub use viewers::*;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
|
#[cfg(feature = "network")]
|
||||||
mod http;
|
mod http;
|
||||||
|
#[cfg(feature = "network")]
|
||||||
mod port;
|
mod port;
|
||||||
mod url;
|
mod url;
|
||||||
|
|
||||||
|
#[cfg(feature = "network")]
|
||||||
pub use self::http::*;
|
pub use self::http::*;
|
||||||
pub use self::url::*;
|
pub use self::url::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "network")]
|
||||||
pub use port::SubCommand as Port;
|
pub use port::SubCommand as Port;
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
// use super::icons::{icon_for_file, iconify_style_ansi_to_nu};
|
// use super::icons::{icon_for_file, iconify_style_ansi_to_nu};
|
||||||
use super::icons::icon_for_file;
|
use super::icons::icon_for_file;
|
||||||
use crossterm::terminal::size;
|
|
||||||
use lscolors::Style;
|
use lscolors::Style;
|
||||||
use nu_engine::{command_prelude::*, env_to_string};
|
use nu_engine::{command_prelude::*, env_to_string};
|
||||||
use nu_protocol::Config;
|
use nu_protocol::Config;
|
||||||
use nu_term_grid::grid::{Alignment, Cell, Direction, Filling, Grid, GridOptions};
|
use nu_term_grid::grid::{Alignment, Cell, Direction, Filling, Grid, GridOptions};
|
||||||
use nu_utils::get_ls_colors;
|
use nu_utils::{get_ls_colors, terminal_size};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -192,7 +191,7 @@ fn create_grid_output(
|
||||||
|
|
||||||
let cols = if let Some(col) = width_param {
|
let cols = if let Some(col) = width_param {
|
||||||
col as u16
|
col as u16
|
||||||
} else if let Ok((w, _h)) = size() {
|
} else if let Ok((w, _h)) = terminal_size() {
|
||||||
w
|
w
|
||||||
} else {
|
} else {
|
||||||
80u16
|
80u16
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
// overall reduce the redundant calls to StyleComputer etc.
|
// overall reduce the redundant calls to StyleComputer etc.
|
||||||
// the goal is to configure it once...
|
// the goal is to configure it once...
|
||||||
|
|
||||||
use crossterm::terminal::size;
|
|
||||||
use lscolors::{LsColors, Style};
|
use lscolors::{LsColors, Style};
|
||||||
use nu_color_config::{color_from_hex, StyleComputer, TextStyle};
|
use nu_color_config::{color_from_hex, StyleComputer, TextStyle};
|
||||||
use nu_engine::{command_prelude::*, env_to_string};
|
use nu_engine::{command_prelude::*, env_to_string};
|
||||||
|
@ -15,7 +14,7 @@ use nu_table::{
|
||||||
common::create_nu_table_config, CollapsedTable, ExpandedTable, JustTable, NuTable, NuTableCell,
|
common::create_nu_table_config, CollapsedTable, ExpandedTable, JustTable, NuTable, NuTableCell,
|
||||||
StringResult, TableOpts, TableOutput,
|
StringResult, TableOpts, TableOutput,
|
||||||
};
|
};
|
||||||
use nu_utils::get_ls_colors;
|
use nu_utils::{get_ls_colors, terminal_size};
|
||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
io::{IsTerminal, Read},
|
io::{IsTerminal, Read},
|
||||||
|
@ -30,7 +29,7 @@ const STREAM_PAGE_SIZE: usize = 1000;
|
||||||
fn get_width_param(width_param: Option<i64>) -> usize {
|
fn get_width_param(width_param: Option<i64>) -> usize {
|
||||||
if let Some(col) = width_param {
|
if let Some(col) = width_param {
|
||||||
col as usize
|
col as usize
|
||||||
} else if let Ok((w, _h)) = size() {
|
} else if let Ok((w, _h)) = terminal_size() {
|
||||||
w as usize
|
w as usize
|
||||||
} else {
|
} else {
|
||||||
80
|
80
|
||||||
|
@ -712,6 +711,13 @@ fn make_clickable_link(
|
||||||
) -> String {
|
) -> String {
|
||||||
// uri's based on this https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
|
// uri's based on this https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
|
||||||
|
|
||||||
|
#[cfg(any(
|
||||||
|
unix,
|
||||||
|
windows,
|
||||||
|
target_os = "redox",
|
||||||
|
target_os = "wasi",
|
||||||
|
target_os = "hermit"
|
||||||
|
))]
|
||||||
if show_clickable_links {
|
if show_clickable_links {
|
||||||
format!(
|
format!(
|
||||||
"\x1b]8;;{}\x1b\\{}\x1b]8;;\x1b\\",
|
"\x1b]8;;{}\x1b\\{}\x1b]8;;\x1b\\",
|
||||||
|
@ -727,6 +733,18 @@ fn make_clickable_link(
|
||||||
None => full_path,
|
None => full_path,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(
|
||||||
|
unix,
|
||||||
|
windows,
|
||||||
|
target_os = "redox",
|
||||||
|
target_os = "wasi",
|
||||||
|
target_os = "hermit"
|
||||||
|
)))]
|
||||||
|
match link_name {
|
||||||
|
Some(link_name) => link_name.to_string(),
|
||||||
|
None => full_path,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PagingTableCreator {
|
struct PagingTableCreator {
|
||||||
|
|
|
@ -14,12 +14,20 @@ bench = false
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-protocol = { path = "../nu-protocol", features = ["plugin"], version = "0.100.1" }
|
nu-protocol = { path = "../nu-protocol", version = "0.100.1", default-features = false }
|
||||||
nu-path = { path = "../nu-path", version = "0.100.1" }
|
nu-path = { path = "../nu-path", version = "0.100.1" }
|
||||||
nu-glob = { path = "../nu-glob", version = "0.100.1" }
|
nu-glob = { path = "../nu-glob", version = "0.100.1" }
|
||||||
nu-utils = { path = "../nu-utils", version = "0.100.1" }
|
nu-utils = { path = "../nu-utils", version = "0.100.1", default-features = false }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
terminal_size = { workspace = true }
|
terminal_size = { workspace = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
plugin = []
|
default = ["os"]
|
||||||
|
os = [
|
||||||
|
"nu-protocol/os",
|
||||||
|
"nu-utils/os",
|
||||||
|
]
|
||||||
|
plugin = [
|
||||||
|
"nu-protocol/plugin",
|
||||||
|
"os",
|
||||||
|
]
|
||||||
|
|
|
@ -8,9 +8,9 @@ use nu_protocol::{
|
||||||
Argument, Closure, EngineState, ErrorHandler, Matcher, Redirection, Stack, StateWorkingSet,
|
Argument, Closure, EngineState, ErrorHandler, Matcher, Redirection, Stack, StateWorkingSet,
|
||||||
},
|
},
|
||||||
ir::{Call, DataSlice, Instruction, IrAstRef, IrBlock, Literal, RedirectMode},
|
ir::{Call, DataSlice, Instruction, IrAstRef, IrBlock, Literal, RedirectMode},
|
||||||
ByteStreamSource, DataSource, DeclId, ErrSpan, Flag, IntoPipelineData, IntoSpanned, ListStream,
|
DataSource, DeclId, ErrSpan, Flag, IntoPipelineData, IntoSpanned, ListStream, OutDest,
|
||||||
OutDest, PipelineData, PipelineMetadata, PositionalArg, Range, Record, RegId, ShellError,
|
PipelineData, PipelineMetadata, PositionalArg, Range, Record, RegId, ShellError, Signals,
|
||||||
Signals, Signature, Span, Spanned, Type, Value, VarId, ENV_VARIABLE_ID,
|
Signature, Span, Spanned, Type, Value, VarId, ENV_VARIABLE_ID,
|
||||||
};
|
};
|
||||||
use nu_utils::IgnoreCaseExt;
|
use nu_utils::IgnoreCaseExt;
|
||||||
|
|
||||||
|
@ -478,8 +478,9 @@ fn eval_instruction<D: DebugContext>(
|
||||||
Ok(Continue)
|
Ok(Continue)
|
||||||
}
|
}
|
||||||
Instruction::CheckErrRedirected { src } => match ctx.borrow_reg(*src) {
|
Instruction::CheckErrRedirected { src } => match ctx.borrow_reg(*src) {
|
||||||
|
#[cfg(feature = "os")]
|
||||||
PipelineData::ByteStream(stream, _)
|
PipelineData::ByteStream(stream, _)
|
||||||
if matches!(stream.source(), ByteStreamSource::Child(_)) =>
|
if matches!(stream.source(), nu_protocol::ByteStreamSource::Child(_)) =>
|
||||||
{
|
{
|
||||||
Ok(Continue)
|
Ok(Continue)
|
||||||
}
|
}
|
||||||
|
@ -513,7 +514,7 @@ fn eval_instruction<D: DebugContext>(
|
||||||
span: Some(*span),
|
span: Some(*span),
|
||||||
})?;
|
})?;
|
||||||
let is_external = if let PipelineData::ByteStream(stream, ..) = &src {
|
let is_external = if let PipelineData::ByteStream(stream, ..) = &src {
|
||||||
matches!(stream.source(), ByteStreamSource::Child(..))
|
stream.source().is_external()
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,11 +15,11 @@ bench = false
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-engine = { path = "../nu-engine", version = "0.100.1" }
|
nu-engine = { path = "../nu-engine", version = "0.100.1", default-features = false }
|
||||||
nu-path = { path = "../nu-path", version = "0.100.1" }
|
nu-path = { path = "../nu-path", version = "0.100.1" }
|
||||||
nu-plugin-engine = { path = "../nu-plugin-engine", optional = true, version = "0.100.1" }
|
nu-plugin-engine = { path = "../nu-plugin-engine", optional = true, version = "0.100.1" }
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.100.1" }
|
nu-protocol = { path = "../nu-protocol", version = "0.100.1", default-features = false }
|
||||||
nu-utils = { path = "../nu-utils", version = "0.100.1" }
|
nu-utils = { path = "../nu-utils", version = "0.100.1", default-features = false }
|
||||||
|
|
||||||
bytesize = { workspace = true }
|
bytesize = { workspace = true }
|
||||||
chrono = { default-features = false, features = ['std'], workspace = true }
|
chrono = { default-features = false, features = ['std'], workspace = true }
|
||||||
|
|
|
@ -60,6 +60,7 @@ fn expand_tilde_with_home(path: impl AsRef<Path>, home: Option<PathBuf>) -> Path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
fn fallback_home_dir(username: &str) -> PathBuf {
|
fn fallback_home_dir(username: &str) -> PathBuf {
|
||||||
PathBuf::from_iter([FALLBACK_USER_HOME_BASE_DIR, username])
|
PathBuf::from_iter([FALLBACK_USER_HOME_BASE_DIR, username])
|
||||||
}
|
}
|
||||||
|
@ -110,6 +111,13 @@ fn user_home_dir(username: &str) -> PathBuf {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
fn user_home_dir(_: &str) -> PathBuf {
|
||||||
|
// if WASI is used, we try to get a home dir via HOME env, otherwise we don't have a home dir
|
||||||
|
let home = std::env::var("HOME").unwrap_or_else(|_| "/".to_string());
|
||||||
|
PathBuf::from(home)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if the shell is running inside the Termux terminal emulator
|
/// Returns true if the shell is running inside the Termux terminal emulator
|
||||||
/// app.
|
/// app.
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
|
|
|
@ -36,6 +36,13 @@ pub fn has_trailing_slash(path: &Path) -> bool {
|
||||||
last == Some(&b'/')
|
last == Some(&b'/')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `true` if the path has a trailing slash, including if it's the root directory.
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
pub fn has_trailing_slash(path: &Path) -> bool {
|
||||||
|
// in the web paths are often just URLs, they are separated by forward slashes
|
||||||
|
path.to_str().map_or(false, |s| s.ends_with('/'))
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -14,8 +14,8 @@ bench = false
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-engine = { path = "../nu-engine", version = "0.100.1" }
|
nu-engine = { path = "../nu-engine", version = "0.100.1", features = ["plugin"] }
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.100.1" }
|
nu-protocol = { path = "../nu-protocol", version = "0.100.1", features = ["plugin"] }
|
||||||
nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.100.1" }
|
nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.100.1" }
|
||||||
nu-plugin-core = { path = "../nu-plugin-core", version = "0.100.1", default-features = false }
|
nu-plugin-core = { path = "../nu-plugin-core", version = "0.100.1", default-features = false }
|
||||||
nu-utils = { path = "../nu-utils", version = "0.100.1" }
|
nu-utils = { path = "../nu-utils", version = "0.100.1" }
|
||||||
|
|
|
@ -16,7 +16,7 @@ bench = false
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-utils = { path = "../nu-utils", version = "0.100.1" }
|
nu-utils = { path = "../nu-utils", version = "0.100.1", default-features = false }
|
||||||
nu-path = { path = "../nu-path", version = "0.100.1" }
|
nu-path = { path = "../nu-path", version = "0.100.1" }
|
||||||
nu-system = { path = "../nu-system", version = "0.100.1" }
|
nu-system = { path = "../nu-system", version = "0.100.1" }
|
||||||
nu-derive-value = { path = "../nu-derive-value", version = "0.100.1" }
|
nu-derive-value = { path = "../nu-derive-value", version = "0.100.1" }
|
||||||
|
@ -38,7 +38,7 @@ serde = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
typetag = "0.2"
|
typetag = "0.2"
|
||||||
os_pipe = { workspace = true, features = ["io_safety"] }
|
os_pipe = { workspace = true, optional = true, features = ["io_safety"] }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
|
@ -49,8 +49,15 @@ dirs-sys = { workspace = true }
|
||||||
windows-sys = { workspace = true }
|
windows-sys = { workspace = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
default = ["os"]
|
||||||
|
os = [
|
||||||
|
"nu-utils/os",
|
||||||
|
"os_pipe",
|
||||||
|
]
|
||||||
|
|
||||||
plugin = [
|
plugin = [
|
||||||
"brotli",
|
"brotli",
|
||||||
|
"os",
|
||||||
"rmp-serde",
|
"rmp-serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -1458,6 +1458,17 @@ On Windows, this would be %USERPROFILE%\AppData\Roaming"#
|
||||||
#[label = "while running this code"]
|
#[label = "while running this code"]
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
#[error("OS feature is disabled: {msg}")]
|
||||||
|
#[diagnostic(
|
||||||
|
code(nu::shell::os_disabled),
|
||||||
|
help("You're probably running outside an OS like a browser, we cannot support this")
|
||||||
|
)]
|
||||||
|
DisabledOsSupport {
|
||||||
|
msg: String,
|
||||||
|
#[label = "while running this code"]
|
||||||
|
span: Option<Span>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShellError {
|
impl ShellError {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![cfg_attr(not(feature = "os"), allow(unused))]
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
mod alias;
|
mod alias;
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
|
@ -17,6 +18,7 @@ pub mod parser_path;
|
||||||
mod pipeline;
|
mod pipeline;
|
||||||
#[cfg(feature = "plugin")]
|
#[cfg(feature = "plugin")]
|
||||||
mod plugin;
|
mod plugin;
|
||||||
|
#[cfg(feature = "os")]
|
||||||
pub mod process;
|
pub mod process;
|
||||||
mod signature;
|
mod signature;
|
||||||
pub mod span;
|
pub mod span;
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
//! Module managing the streaming of raw bytes between pipeline elements
|
//! Module managing the streaming of raw bytes between pipeline elements
|
||||||
use crate::{
|
#[cfg(feature = "os")]
|
||||||
process::{ChildPipe, ChildProcess},
|
use crate::process::{ChildPipe, ChildProcess};
|
||||||
ErrSpan, IntoSpanned, PipelineData, ShellError, Signals, Span, Type, Value,
|
use crate::{ErrSpan, IntoSpanned, PipelineData, ShellError, Signals, Span, Type, Value};
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use std::os::fd::OwnedFd;
|
use std::os::fd::OwnedFd;
|
||||||
|
@ -24,6 +23,7 @@ use std::{
|
||||||
pub enum ByteStreamSource {
|
pub enum ByteStreamSource {
|
||||||
Read(Box<dyn Read + Send + 'static>),
|
Read(Box<dyn Read + Send + 'static>),
|
||||||
File(File),
|
File(File),
|
||||||
|
#[cfg(feature = "os")]
|
||||||
Child(Box<ChildProcess>),
|
Child(Box<ChildProcess>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ impl ByteStreamSource {
|
||||||
match self {
|
match self {
|
||||||
ByteStreamSource::Read(read) => Some(SourceReader::Read(read)),
|
ByteStreamSource::Read(read) => Some(SourceReader::Read(read)),
|
||||||
ByteStreamSource::File(file) => Some(SourceReader::File(file)),
|
ByteStreamSource::File(file) => Some(SourceReader::File(file)),
|
||||||
|
#[cfg(feature = "os")]
|
||||||
ByteStreamSource::Child(mut child) => child.stdout.take().map(|stdout| match stdout {
|
ByteStreamSource::Child(mut child) => child.stdout.take().map(|stdout| match stdout {
|
||||||
ChildPipe::Pipe(pipe) => SourceReader::File(convert_file(pipe)),
|
ChildPipe::Pipe(pipe) => SourceReader::File(convert_file(pipe)),
|
||||||
ChildPipe::Tee(tee) => SourceReader::Read(tee),
|
ChildPipe::Tee(tee) => SourceReader::Read(tee),
|
||||||
|
@ -40,9 +41,16 @@ impl ByteStreamSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Source is a `Child` or `File`, rather than `Read`. Currently affects trimming
|
/// Source is a `Child` or `File`, rather than `Read`. Currently affects trimming
|
||||||
fn is_external(&self) -> bool {
|
#[cfg(feature = "os")]
|
||||||
|
pub fn is_external(&self) -> bool {
|
||||||
matches!(self, ByteStreamSource::Child(..))
|
matches!(self, ByteStreamSource::Child(..))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "os"))]
|
||||||
|
pub fn is_external(&self) -> bool {
|
||||||
|
// without os support we never have externals
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for ByteStreamSource {
|
impl Debug for ByteStreamSource {
|
||||||
|
@ -50,6 +58,7 @@ impl Debug for ByteStreamSource {
|
||||||
match self {
|
match self {
|
||||||
ByteStreamSource::Read(_) => f.debug_tuple("Read").field(&"..").finish(),
|
ByteStreamSource::Read(_) => f.debug_tuple("Read").field(&"..").finish(),
|
||||||
ByteStreamSource::File(file) => f.debug_tuple("File").field(file).finish(),
|
ByteStreamSource::File(file) => f.debug_tuple("File").field(file).finish(),
|
||||||
|
#[cfg(feature = "os")]
|
||||||
ByteStreamSource::Child(child) => f.debug_tuple("Child").field(child).finish(),
|
ByteStreamSource::Child(child) => f.debug_tuple("Child").field(child).finish(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,6 +256,7 @@ impl ByteStream {
|
||||||
///
|
///
|
||||||
/// The type is implicitly `Unknown`, as it's not typically known whether child processes will
|
/// The type is implicitly `Unknown`, as it's not typically known whether child processes will
|
||||||
/// return text or binary.
|
/// return text or binary.
|
||||||
|
#[cfg(feature = "os")]
|
||||||
pub fn child(child: ChildProcess, span: Span) -> Self {
|
pub fn child(child: ChildProcess, span: Span) -> Self {
|
||||||
Self::new(
|
Self::new(
|
||||||
ByteStreamSource::Child(Box::new(child)),
|
ByteStreamSource::Child(Box::new(child)),
|
||||||
|
@ -260,6 +270,7 @@ impl ByteStream {
|
||||||
///
|
///
|
||||||
/// The type is implicitly `Unknown`, as it's not typically known whether stdin is text or
|
/// The type is implicitly `Unknown`, as it's not typically known whether stdin is text or
|
||||||
/// binary.
|
/// binary.
|
||||||
|
#[cfg(feature = "os")]
|
||||||
pub fn stdin(span: Span) -> Result<Self, ShellError> {
|
pub fn stdin(span: Span) -> Result<Self, ShellError> {
|
||||||
let stdin = os_pipe::dup_stdin().err_span(span)?;
|
let stdin = os_pipe::dup_stdin().err_span(span)?;
|
||||||
let source = ByteStreamSource::File(convert_file(stdin));
|
let source = ByteStreamSource::File(convert_file(stdin));
|
||||||
|
@ -271,6 +282,14 @@ impl ByteStream {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "os"))]
|
||||||
|
pub fn stdin(span: Span) -> Result<Self, ShellError> {
|
||||||
|
Err(ShellError::DisabledOsSupport {
|
||||||
|
msg: "Stdin is not supported".to_string(),
|
||||||
|
span: Some(span),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a [`ByteStream`] from a generator function that writes data to the given buffer
|
/// Create a [`ByteStream`] from a generator function that writes data to the given buffer
|
||||||
/// when called, and returns `Ok(false)` on end of stream.
|
/// when called, and returns `Ok(false)` on end of stream.
|
||||||
pub fn from_fn(
|
pub fn from_fn(
|
||||||
|
@ -432,6 +451,7 @@ impl ByteStream {
|
||||||
match self.stream {
|
match self.stream {
|
||||||
ByteStreamSource::Read(..) => Err(self),
|
ByteStreamSource::Read(..) => Err(self),
|
||||||
ByteStreamSource::File(file) => Ok(file.into()),
|
ByteStreamSource::File(file) => Ok(file.into()),
|
||||||
|
#[cfg(feature = "os")]
|
||||||
ByteStreamSource::Child(child) => {
|
ByteStreamSource::Child(child) => {
|
||||||
if let ChildProcess {
|
if let ChildProcess {
|
||||||
stdout: Some(ChildPipe::Pipe(stdout)),
|
stdout: Some(ChildPipe::Pipe(stdout)),
|
||||||
|
@ -453,6 +473,7 @@ impl ByteStream {
|
||||||
///
|
///
|
||||||
/// This will only succeed if the [`ByteStreamSource`] of the [`ByteStream`] is [`Child`](ByteStreamSource::Child).
|
/// This will only succeed if the [`ByteStreamSource`] of the [`ByteStream`] is [`Child`](ByteStreamSource::Child).
|
||||||
/// All other cases return an `Err` with the original [`ByteStream`] in it.
|
/// All other cases return an `Err` with the original [`ByteStream`] in it.
|
||||||
|
#[cfg(feature = "os")]
|
||||||
pub fn into_child(self) -> Result<ChildProcess, Self> {
|
pub fn into_child(self) -> Result<ChildProcess, Self> {
|
||||||
if let ByteStreamSource::Child(child) = self.stream {
|
if let ByteStreamSource::Child(child) = self.stream {
|
||||||
Ok(*child)
|
Ok(*child)
|
||||||
|
@ -477,6 +498,7 @@ impl ByteStream {
|
||||||
file.read_to_end(&mut buf).err_span(self.span)?;
|
file.read_to_end(&mut buf).err_span(self.span)?;
|
||||||
Ok(buf)
|
Ok(buf)
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "os")]
|
||||||
ByteStreamSource::Child(child) => child.into_bytes(),
|
ByteStreamSource::Child(child) => child.into_bytes(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -551,6 +573,7 @@ impl ByteStream {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
ByteStreamSource::File(_) => Ok(()),
|
ByteStreamSource::File(_) => Ok(()),
|
||||||
|
#[cfg(feature = "os")]
|
||||||
ByteStreamSource::Child(child) => child.wait(),
|
ByteStreamSource::Child(child) => child.wait(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -575,6 +598,7 @@ impl ByteStream {
|
||||||
ByteStreamSource::File(file) => {
|
ByteStreamSource::File(file) => {
|
||||||
copy_with_signals(file, dest, span, signals)?;
|
copy_with_signals(file, dest, span, signals)?;
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "os")]
|
||||||
ByteStreamSource::Child(mut child) => {
|
ByteStreamSource::Child(mut child) => {
|
||||||
// All `OutDest`s except `OutDest::PipeSeparate` will cause `stderr` to be `None`.
|
// All `OutDest`s except `OutDest::PipeSeparate` will cause `stderr` to be `None`.
|
||||||
// Only `save`, `tee`, and `complete` set the stderr `OutDest` to `OutDest::PipeSeparate`,
|
// Only `save`, `tee`, and `complete` set the stderr `OutDest` to `OutDest::PipeSeparate`,
|
||||||
|
|
|
@ -9,8 +9,8 @@ version = "0.100.1"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-parser = { version = "0.100.1", path = "../nu-parser" }
|
nu-parser = { version = "0.100.1", path = "../nu-parser" }
|
||||||
nu-protocol = { version = "0.100.1", path = "../nu-protocol" }
|
nu-protocol = { version = "0.100.1", path = "../nu-protocol", default-features = false }
|
||||||
nu-engine = { version = "0.100.1", path = "../nu-engine" }
|
nu-engine = { version = "0.100.1", path = "../nu-engine", default-features = false }
|
||||||
miette = { workspace = true, features = ["fancy-no-backtrace"] }
|
miette = { workspace = true, features = ["fancy-no-backtrace"] }
|
||||||
|
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
|
@ -14,9 +14,9 @@ bench = false
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.100.1" }
|
nu-protocol = { path = "../nu-protocol", version = "0.100.1", default-features = false }
|
||||||
nu-utils = { path = "../nu-utils", version = "0.100.1" }
|
nu-utils = { path = "../nu-utils", version = "0.100.1", default-features = false }
|
||||||
nu-engine = { path = "../nu-engine", version = "0.100.1" }
|
nu-engine = { path = "../nu-engine", version = "0.100.1", default-features = false }
|
||||||
nu-color-config = { path = "../nu-color-config", version = "0.100.1" }
|
nu-color-config = { path = "../nu-color-config", version = "0.100.1" }
|
||||||
nu-ansi-term = { workspace = true }
|
nu-ansi-term = { workspace = true }
|
||||||
fancy-regex = { workspace = true }
|
fancy-regex = { workspace = true }
|
||||||
|
|
|
@ -14,6 +14,6 @@ bench = false
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-utils = { path = "../nu-utils", version = "0.100.1" }
|
nu-utils = { path = "../nu-utils", version = "0.100.1", default-features = false }
|
||||||
|
|
||||||
unicode-width = { workspace = true }
|
unicode-width = { workspace = true }
|
|
@ -17,6 +17,7 @@ bench = false
|
||||||
bench = false
|
bench = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
crossterm = { workspace = true, optional = true }
|
||||||
fancy-regex = { workspace = true }
|
fancy-regex = { workspace = true }
|
||||||
lscolors = { workspace = true, default-features = false, features = ["nu-ansi-term"] }
|
lscolors = { workspace = true, default-features = false, features = ["nu-ansi-term"] }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
|
@ -26,6 +27,10 @@ serde = { workspace = true }
|
||||||
sys-locale = "0.3"
|
sys-locale = "0.3"
|
||||||
unicase = "2.8.0"
|
unicase = "2.8.0"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["os"]
|
||||||
|
os = ["crossterm"]
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
crossterm_winapi = "0.9"
|
crossterm_winapi = "0.9"
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#[cfg(any(windows, unix))]
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use {
|
use {
|
||||||
|
|
|
@ -12,7 +12,7 @@ pub use locale::get_system_locale;
|
||||||
pub use utils::{
|
pub use utils::{
|
||||||
enable_vt_processing, get_default_config, get_default_env, get_ls_colors, get_sample_config,
|
enable_vt_processing, get_default_config, get_default_env, get_ls_colors, get_sample_config,
|
||||||
get_sample_env, get_scaffold_config, get_scaffold_env, stderr_write_all_and_flush,
|
get_sample_env, get_scaffold_config, get_scaffold_env, stderr_write_all_and_flush,
|
||||||
stdout_write_all_and_flush,
|
stdout_write_all_and_flush, terminal_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use casing::IgnoreCaseExt;
|
pub use casing::IgnoreCaseExt;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use crossterm_winapi::{ConsoleMode, Handle};
|
use crossterm_winapi::{ConsoleMode, Handle};
|
||||||
use lscolors::LsColors;
|
use lscolors::LsColors;
|
||||||
use std::io::{Result, Write};
|
use std::io::{self, Result, Write};
|
||||||
|
|
||||||
pub fn enable_vt_processing() -> Result<()> {
|
pub fn enable_vt_processing() -> Result<()> {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
@ -474,3 +474,17 @@ macro_rules! perf {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the terminal size (columns, rows).
|
||||||
|
///
|
||||||
|
/// This utility variant allows getting a fallback value when compiling for wasm32 without having
|
||||||
|
/// to rearrange other bits of the codebase.
|
||||||
|
///
|
||||||
|
/// See [`crossterm::terminal::size`].
|
||||||
|
pub fn terminal_size() -> io::Result<(u16, u16)> {
|
||||||
|
#[cfg(feature = "os")]
|
||||||
|
return crossterm::terminal::size();
|
||||||
|
|
||||||
|
#[cfg(not(feature = "os"))]
|
||||||
|
return Err(io::Error::from(io::ErrorKind::Unsupported));
|
||||||
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ name = "nu_plugin_custom_values"
|
||||||
bench = false
|
bench = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-plugin = { path = "../nu-plugin", version = "0.100.1" }
|
nu-plugin = { path = "../nu-plugin", version = "0.100.1", features = [] }
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.100.1", features = ["plugin"] }
|
nu-protocol = { path = "../nu-protocol", version = "0.100.1", features = ["plugin"] }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
typetag = "0.2"
|
typetag = "0.2"
|
||||||
|
|
|
@ -11,9 +11,9 @@ version = "0.100.1"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-parser = { path = "../nu-parser", version = "0.100.1" }
|
nu-parser = { path = "../nu-parser", version = "0.100.1" }
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.100.1" }
|
nu-protocol = { path = "../nu-protocol", version = "0.100.1", default-features = false }
|
||||||
nu-engine = { path = "../nu-engine", version = "0.100.1" }
|
nu-engine = { path = "../nu-engine", version = "0.100.1", default-features = false }
|
||||||
nu-utils = { path = "../nu-utils", version = "0.100.1" }
|
nu-utils = { path = "../nu-utils", version = "0.100.1", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
chrono = { workspace = true }
|
chrono = { workspace = true }
|
||||||
|
|
34
toolkit.nu
34
toolkit.nu
|
@ -363,6 +363,40 @@ export def build [
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# build crates for wasm
|
||||||
|
export def "build wasm" [] {
|
||||||
|
^rustup target add wasm32-unknown-unknown
|
||||||
|
|
||||||
|
# these crates should compile for wasm
|
||||||
|
let compatible_crates = [
|
||||||
|
"nu-cmd-base",
|
||||||
|
"nu-cmd-extra",
|
||||||
|
"nu-cmd-lang",
|
||||||
|
"nu-color-config",
|
||||||
|
"nu-command",
|
||||||
|
"nu-derive-value",
|
||||||
|
"nu-engine",
|
||||||
|
"nu-glob",
|
||||||
|
"nu-json",
|
||||||
|
"nu-parser",
|
||||||
|
"nu-path",
|
||||||
|
"nu-pretty-hex",
|
||||||
|
"nu-protocol",
|
||||||
|
"nu-std",
|
||||||
|
"nu-system",
|
||||||
|
"nu-table",
|
||||||
|
"nu-term-grid",
|
||||||
|
"nu-utils",
|
||||||
|
"nuon"
|
||||||
|
]
|
||||||
|
|
||||||
|
for crate in $compatible_crates {
|
||||||
|
print $'(char nl)Building ($crate) for wasm'
|
||||||
|
print '----------------------------'
|
||||||
|
^cargo build -p $crate --target wasm32-unknown-unknown --no-default-features
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def "nu-complete list features" [] {
|
def "nu-complete list features" [] {
|
||||||
open Cargo.toml | get features | transpose feature dependencies | get feature
|
open Cargo.toml | get features | transpose feature dependencies | get feature
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue