forked from extern/nushell
replace codespan-reporting with miette 3.0
This commit is contained in:
parent
cbe85cbeaf
commit
a1d6cefdf8
219
Cargo.lock
generated
219
Cargo.lock
generated
@ -34,6 +34,17 @@ dependencies = [
|
|||||||
"wait-timeout",
|
"wait-timeout",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atty"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@ -77,13 +88,12 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "codespan-reporting"
|
name = "ci_info"
|
||||||
version = "0.11.1"
|
version = "0.14.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
|
checksum = "1f0e2864372242f01b92c1b882a904f6fb8b57f16e81e148a35b6368b1ea7323"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"termcolor",
|
"envmnt",
|
||||||
"unicode-width",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -140,6 +150,12 @@ version = "0.3.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dunce"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.6.1"
|
version = "1.6.1"
|
||||||
@ -151,7 +167,7 @@ name = "engine-q"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
"codespan-reporting",
|
"miette",
|
||||||
"nu-cli",
|
"nu-cli",
|
||||||
"nu-command",
|
"nu-command",
|
||||||
"nu-engine",
|
"nu-engine",
|
||||||
@ -163,6 +179,25 @@ dependencies = [
|
|||||||
"tempfile",
|
"tempfile",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "envmnt"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f96dd862f12fac698dec3932dff0e6fb34bffeb5515ae5932d620cfe076571e"
|
||||||
|
dependencies = [
|
||||||
|
"fsio",
|
||||||
|
"indexmap",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fsio"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09e87827efaf94c7a44b562ff57de06930712fe21b530c3797cdede26e6377eb"
|
||||||
|
dependencies = [
|
||||||
|
"dunce",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
@ -180,6 +215,31 @@ version = "0.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "instant"
|
name = "instant"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
@ -234,6 +294,38 @@ version = "2.4.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miette"
|
||||||
|
version = "3.0.0-alpha.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "043a986fa0bf30fe00f6720e5c298ed1d67fe30ae77659744cbac206e8d2554c"
|
||||||
|
dependencies = [
|
||||||
|
"atty",
|
||||||
|
"ci_info",
|
||||||
|
"itertools",
|
||||||
|
"miette-derive",
|
||||||
|
"once_cell",
|
||||||
|
"owo-colors",
|
||||||
|
"supports-color",
|
||||||
|
"supports-hyperlinks",
|
||||||
|
"supports-unicode",
|
||||||
|
"term_size",
|
||||||
|
"textwrap",
|
||||||
|
"thiserror",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miette-derive"
|
||||||
|
version = "3.0.0-alpha.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "db3027fb091be28062da879441b2ab8f43d0013d7cde5fcc3a48fb9da7e22a01"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.7.13"
|
version = "0.7.13"
|
||||||
@ -280,12 +372,13 @@ dependencies = [
|
|||||||
name = "nu-cli"
|
name = "nu-cli"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"codespan-reporting",
|
"miette",
|
||||||
"nu-ansi-term",
|
"nu-ansi-term",
|
||||||
"nu-engine",
|
"nu-engine",
|
||||||
"nu-parser",
|
"nu-parser",
|
||||||
"nu-protocol",
|
"nu-protocol",
|
||||||
"reedline",
|
"reedline",
|
||||||
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -310,15 +403,17 @@ dependencies = [
|
|||||||
name = "nu-parser"
|
name = "nu-parser"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"codespan-reporting",
|
"miette",
|
||||||
"nu-protocol",
|
"nu-protocol",
|
||||||
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nu-protocol"
|
name = "nu-protocol"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"codespan-reporting",
|
"miette",
|
||||||
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -349,6 +444,12 @@ dependencies = [
|
|||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "output_vt100"
|
name = "output_vt100"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
@ -364,6 +465,12 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "owo-colors"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f2fe43bf372b08cc9ccee5144715db59c79ab00168bbe4cf0d274dc0d5f64d7f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
@ -608,6 +715,42 @@ version = "1.6.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
|
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smawk"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "supports-color"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "40bc06147993f379a124cc6373ad4022f5d9fd4a80019217c773f81a38e9023c"
|
||||||
|
dependencies = [
|
||||||
|
"atty",
|
||||||
|
"ci_info",
|
||||||
|
"lazy_static",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "supports-hyperlinks"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "590b34f7c5f01ecc9d78dba4b3f445f31df750a67621cf31626f3b7441ce6406"
|
||||||
|
dependencies = [
|
||||||
|
"atty",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "supports-unicode"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d5fa283a620b255940913bd962cda2e6320e3799041f96ac0d7191ff2b4622f"
|
||||||
|
dependencies = [
|
||||||
|
"atty",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.76"
|
version = "1.0.76"
|
||||||
@ -634,12 +777,44 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "term_size"
|
||||||
version = "1.1.2"
|
version = "0.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
|
checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi-util",
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "textwrap"
|
||||||
|
version = "0.14.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
|
||||||
|
dependencies = [
|
||||||
|
"smawk",
|
||||||
|
"unicode-linebreak",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.29"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.29"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -659,6 +834,15 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41"
|
checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-linebreak"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3a52dcaab0c48d931f7cc8ef826fa51690a08e1ea55117ef26f89864f532383f"
|
||||||
|
dependencies = [
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-segmentation"
|
name = "unicode-segmentation"
|
||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
@ -708,15 +892,6 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-util"
|
|
||||||
version = "0.1.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
|
||||||
dependencies = [
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -10,14 +10,13 @@ members = ["crates/nu-cli", "crates/nu-engine", "crates/nu-parser", "crates/nu-c
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
reedline = { git = "https://github.com/jntrnr/reedline", branch = "main" }
|
reedline = { git = "https://github.com/jntrnr/reedline", branch = "main" }
|
||||||
codespan-reporting = "0.11.1"
|
|
||||||
nu-cli = { path="./crates/nu-cli" }
|
nu-cli = { path="./crates/nu-cli" }
|
||||||
nu-command = { path="./crates/nu-command" }
|
nu-command = { path="./crates/nu-command" }
|
||||||
nu-engine = { path="./crates/nu-engine" }
|
nu-engine = { path="./crates/nu-engine" }
|
||||||
nu-parser = { path="./crates/nu-parser" }
|
nu-parser = { path="./crates/nu-parser" }
|
||||||
nu-protocol = { path = "./crates/nu-protocol" }
|
nu-protocol = { path = "./crates/nu-protocol" }
|
||||||
nu-table = { path = "./crates/nu-table" }
|
nu-table = { path = "./crates/nu-table" }
|
||||||
|
miette = { version = "3.0.0-alpha.0" }
|
||||||
# mimalloc = { version = "*", default-features = false }
|
# mimalloc = { version = "*", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@ -7,6 +7,7 @@ edition = "2018"
|
|||||||
nu-engine = { path = "../nu-engine" }
|
nu-engine = { path = "../nu-engine" }
|
||||||
nu-parser = { path = "../nu-parser" }
|
nu-parser = { path = "../nu-parser" }
|
||||||
nu-protocol = { path = "../nu-protocol" }
|
nu-protocol = { path = "../nu-protocol" }
|
||||||
codespan-reporting = "0.11.1"
|
miette = { version = "3.0.0-alpha.0", features = ["fancy"] }
|
||||||
|
thiserror = "1.0.29"
|
||||||
nu-ansi-term = "0.36.0"
|
nu-ansi-term = "0.36.0"
|
||||||
reedline = { git = "https://github.com/jntrnr/reedline", branch = "main" }
|
reedline = { git = "https://github.com/jntrnr/reedline", branch = "main" }
|
||||||
|
@ -1,414 +1,53 @@
|
|||||||
use core::ops::Range;
|
use miette::{LabeledSpan, MietteHandler, ReportHandler, Severity, SourceCode};
|
||||||
|
use nu_protocol::engine::StateWorkingSet;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
/// This error exists so that we can defer SourceCode handling. It simply
|
||||||
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
/// forwards most methods, except for `.source_code()`, which we provide.
|
||||||
use nu_parser::ParseError;
|
#[derive(Error)]
|
||||||
use nu_protocol::{engine::StateWorkingSet, ShellError, Span};
|
#[error("{0}")]
|
||||||
|
struct CliError<'src>(
|
||||||
|
&'src (dyn miette::Diagnostic + Send + Sync + 'static),
|
||||||
|
&'src StateWorkingSet<'src>,
|
||||||
|
);
|
||||||
|
|
||||||
fn convert_span_to_diag(
|
impl std::fmt::Debug for CliError<'_> {
|
||||||
working_set: &StateWorkingSet,
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
span: &Span,
|
MietteHandler::default().debug(self, f)?;
|
||||||
) -> Result<(usize, Range<usize>), Box<dyn std::error::Error>> {
|
Ok(())
|
||||||
for (file_id, (_, start, end)) in working_set.files().enumerate() {
|
}
|
||||||
if span.start >= *start && span.end <= *end {
|
}
|
||||||
let new_start = span.start - start;
|
|
||||||
let new_end = span.end - start;
|
|
||||||
|
|
||||||
return Ok((file_id, new_start..new_end));
|
impl<'src> miette::Diagnostic for CliError<'src> {
|
||||||
}
|
fn code<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {
|
||||||
|
self.0.code()
|
||||||
}
|
}
|
||||||
|
|
||||||
if span.start == working_set.next_span_start() {
|
fn severity(&self) -> Option<Severity> {
|
||||||
// We're trying to highlight the space after the end
|
self.0.severity()
|
||||||
if let Some((file_id, (_, _, end))) = working_set.files().enumerate().last() {
|
|
||||||
return Ok((file_id, *end..(*end + 1)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
panic!(
|
fn help<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {
|
||||||
"internal error: can't find span in parser state: {:?}",
|
self.0.help()
|
||||||
span
|
}
|
||||||
)
|
|
||||||
|
fn url<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {
|
||||||
|
self.0.url()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn labels<'a>(&'a self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + 'a>> {
|
||||||
|
self.0.labels()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, we redirect the source_code method to our own source.
|
||||||
|
fn source_code(&self) -> Option<&dyn SourceCode> {
|
||||||
|
Some(&self.1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn report_parsing_error(
|
pub fn report_error(
|
||||||
working_set: &StateWorkingSet,
|
working_set: &StateWorkingSet,
|
||||||
error: &ParseError,
|
error: &(dyn miette::Diagnostic + Send + Sync + 'static),
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) {
|
||||||
let writer = StandardStream::stderr(ColorChoice::Always);
|
eprintln!("Error: {:?}", CliError(error, working_set));
|
||||||
let config = codespan_reporting::term::Config::default();
|
|
||||||
|
|
||||||
let diagnostic =
|
|
||||||
match error {
|
|
||||||
ParseError::Mismatch(expected, found, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Type mismatch during operation")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message(format!("expected {}, found {}", expected, found))])
|
|
||||||
}
|
|
||||||
ParseError::ExtraTokens(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Extra tokens in code")
|
|
||||||
.with_labels(vec![
|
|
||||||
Label::primary(diag_file_id, diag_range).with_message("extra tokens")
|
|
||||||
])
|
|
||||||
}
|
|
||||||
ParseError::ExtraPositional(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Extra positional argument")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message("extra positional argument")])
|
|
||||||
}
|
|
||||||
ParseError::UnexpectedEof(s, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Unexpected end of code")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message(format!("expected {}", s))])
|
|
||||||
}
|
|
||||||
ParseError::Unclosed(delim, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Unclosed delimiter")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message(format!("unclosed {}", delim))])
|
|
||||||
}
|
|
||||||
ParseError::UnknownStatement(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Unknown statement")
|
|
||||||
.with_labels(vec![
|
|
||||||
Label::primary(diag_file_id, diag_range).with_message("unknown statement")
|
|
||||||
])
|
|
||||||
}
|
|
||||||
ParseError::MultipleRestParams(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Multiple rest params")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message("multiple rest params")])
|
|
||||||
}
|
|
||||||
ParseError::VariableNotFound(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Variable not found")
|
|
||||||
.with_labels(vec![
|
|
||||||
Label::primary(diag_file_id, diag_range).with_message("variable not found")
|
|
||||||
])
|
|
||||||
}
|
|
||||||
ParseError::UnknownCommand(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Unknown command")
|
|
||||||
.with_labels(vec![
|
|
||||||
Label::primary(diag_file_id, diag_range).with_message("unknown command")
|
|
||||||
])
|
|
||||||
}
|
|
||||||
ParseError::UnknownFlag(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Unknown flag")
|
|
||||||
.with_labels(vec![
|
|
||||||
Label::primary(diag_file_id, diag_range).with_message("unknown flag")
|
|
||||||
])
|
|
||||||
}
|
|
||||||
ParseError::UnknownType(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Unknown type")
|
|
||||||
.with_labels(vec![
|
|
||||||
Label::primary(diag_file_id, diag_range).with_message("unknown type")
|
|
||||||
])
|
|
||||||
}
|
|
||||||
ParseError::MissingFlagParam(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Missing flag param")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message("flag missing parameter")])
|
|
||||||
}
|
|
||||||
ParseError::ShortFlagBatchCantTakeArg(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Batches of short flags can't take arguments")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message("short flag batches can't take args")])
|
|
||||||
}
|
|
||||||
ParseError::KeywordMissingArgument(name, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message(format!("Missing argument to {}", name))
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message(format!("missing value that follows {}", name))])
|
|
||||||
}
|
|
||||||
ParseError::MissingPositional(name, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Missing required positional arg")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message(format!("missing {}", name))])
|
|
||||||
}
|
|
||||||
ParseError::MissingType(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Missing type")
|
|
||||||
.with_labels(vec![
|
|
||||||
Label::primary(diag_file_id, diag_range).with_message("expected type")
|
|
||||||
])
|
|
||||||
}
|
|
||||||
ParseError::MissingColumns(count, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Missing columns")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range).with_message(
|
|
||||||
format!(
|
|
||||||
"expected {} column{}",
|
|
||||||
count,
|
|
||||||
if *count == 1 { "" } else { "s" }
|
|
||||||
),
|
|
||||||
)])
|
|
||||||
}
|
|
||||||
ParseError::ExtraColumns(count, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Extra columns")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range).with_message(
|
|
||||||
format!(
|
|
||||||
"expected {} column{}",
|
|
||||||
count,
|
|
||||||
if *count == 1 { "" } else { "s" }
|
|
||||||
),
|
|
||||||
)])
|
|
||||||
}
|
|
||||||
ParseError::TypeMismatch(expected, found, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Type mismatch")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message(format!("expected {:?}, found {:?}", expected, found))])
|
|
||||||
}
|
|
||||||
ParseError::MissingRequiredFlag(name, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Missing required flag")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message(format!("missing required flag {}", name))])
|
|
||||||
}
|
|
||||||
ParseError::IncompleteMathExpression(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Incomplete math expresssion")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message("incomplete math expression")])
|
|
||||||
}
|
|
||||||
ParseError::UnknownState(name, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Unknown state")
|
|
||||||
.with_labels(vec![
|
|
||||||
Label::primary(diag_file_id, diag_range).with_message(name.to_string())
|
|
||||||
])
|
|
||||||
}
|
|
||||||
ParseError::NonUtf8(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Non-UTF8 code")
|
|
||||||
.with_labels(vec![
|
|
||||||
Label::primary(diag_file_id, diag_range).with_message("non-UTF8 code")
|
|
||||||
])
|
|
||||||
}
|
|
||||||
ParseError::Expected(expected, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Parse mismatch during operation")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message(format!("expected {}", expected))])
|
|
||||||
}
|
|
||||||
ParseError::UnsupportedOperation(op_span, lhs_span, lhs_ty, rhs_span, rhs_ty) => {
|
|
||||||
let (lhs_file_id, lhs_range) = convert_span_to_diag(working_set, lhs_span)?;
|
|
||||||
let (rhs_file_id, rhs_range) = convert_span_to_diag(working_set, rhs_span)?;
|
|
||||||
let (op_file_id, op_range) = convert_span_to_diag(working_set, op_span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Unsupported operation")
|
|
||||||
.with_labels(vec![
|
|
||||||
Label::primary(op_file_id, op_range)
|
|
||||||
.with_message("doesn't support these values"),
|
|
||||||
Label::secondary(lhs_file_id, lhs_range).with_message(lhs_ty.to_string()),
|
|
||||||
Label::secondary(rhs_file_id, rhs_range).with_message(rhs_ty.to_string()),
|
|
||||||
])
|
|
||||||
}
|
|
||||||
ParseError::ExpectedKeyword(expected, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Expected keyword")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message(format!("expected {}", expected))])
|
|
||||||
}
|
|
||||||
ParseError::IncompleteParser(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Parser incomplete")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message("parser support missing for this expression")])
|
|
||||||
}
|
|
||||||
ParseError::RestNeedsName(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Rest parameter needs a name")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message("needs a parameter name")])
|
|
||||||
}
|
|
||||||
ParseError::AssignmentMismatch(msg, label, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message(msg)
|
|
||||||
.with_labels(vec![
|
|
||||||
Label::primary(diag_file_id, diag_range).with_message(label)
|
|
||||||
])
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// println!("DIAG");
|
|
||||||
// println!("{:?}", diagnostic);
|
|
||||||
codespan_reporting::term::emit(&mut writer.lock(), &config, working_set, &diagnostic)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn report_shell_error(
|
|
||||||
working_set: &StateWorkingSet,
|
|
||||||
error: &ShellError,
|
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
let writer = StandardStream::stderr(ColorChoice::Always);
|
|
||||||
let config = codespan_reporting::term::Config::default();
|
|
||||||
|
|
||||||
let diagnostic =
|
|
||||||
match error {
|
|
||||||
ShellError::OperatorMismatch {
|
|
||||||
op_span,
|
|
||||||
lhs_ty,
|
|
||||||
lhs_span,
|
|
||||||
rhs_ty,
|
|
||||||
rhs_span,
|
|
||||||
} => {
|
|
||||||
let (lhs_file_id, lhs_range) = convert_span_to_diag(working_set, lhs_span)?;
|
|
||||||
let (rhs_file_id, rhs_range) = convert_span_to_diag(working_set, rhs_span)?;
|
|
||||||
let (op_file_id, op_range) = convert_span_to_diag(working_set, op_span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Type mismatch during operation")
|
|
||||||
.with_labels(vec![
|
|
||||||
Label::primary(op_file_id, op_range)
|
|
||||||
.with_message("type mismatch for operator"),
|
|
||||||
Label::secondary(lhs_file_id, lhs_range).with_message(lhs_ty.to_string()),
|
|
||||||
Label::secondary(rhs_file_id, rhs_range).with_message(rhs_ty.to_string()),
|
|
||||||
])
|
|
||||||
}
|
|
||||||
ShellError::UnsupportedOperator(op, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message(format!("Unsupported operator: {}", op))
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message("unsupported operator")])
|
|
||||||
}
|
|
||||||
ShellError::UnknownOperator(op, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message(format!("Unsupported operator: {}", op))
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message("unsupported operator")])
|
|
||||||
}
|
|
||||||
ShellError::ExternalNotSupported(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("External commands not yet supported")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message("external not supported")])
|
|
||||||
}
|
|
||||||
ShellError::InternalError(s) => {
|
|
||||||
Diagnostic::error().with_message(format!("Internal error: {}", s))
|
|
||||||
}
|
|
||||||
ShellError::VariableNotFoundAtRuntime(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Variable not found")
|
|
||||||
.with_labels(vec![
|
|
||||||
Label::primary(diag_file_id, diag_range).with_message("variable not found")
|
|
||||||
])
|
|
||||||
}
|
|
||||||
ShellError::CantConvert(s, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message(format!("Can't convert to {}", s))
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message(format!("can't convert to {}", s))])
|
|
||||||
}
|
|
||||||
ShellError::CannotCreateRange(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Can't convert range to countable values")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message("can't convert to countable values")])
|
|
||||||
}
|
|
||||||
ShellError::DivisionByZero(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Division by zero")
|
|
||||||
.with_labels(vec![
|
|
||||||
Label::primary(diag_file_id, diag_range).with_message("division by zero")
|
|
||||||
])
|
|
||||||
}
|
|
||||||
ShellError::AccessBeyondEnd(len, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Row number too large")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message(format!("row number too large (max: {})", *len))])
|
|
||||||
}
|
|
||||||
ShellError::AccessBeyondEndOfStream(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Row number too large")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message("row number too large")])
|
|
||||||
}
|
|
||||||
ShellError::IncompatiblePathAccess(name, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Data cannot be accessed with a cell path")
|
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
|
||||||
.with_message(format!("{} doesn't support cell paths", name))])
|
|
||||||
}
|
|
||||||
ShellError::CantFindColumn(span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
|
|
||||||
//FIXME: add "did you mean"
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("Cannot find column")
|
|
||||||
.with_labels(vec![
|
|
||||||
Label::primary(diag_file_id, diag_range).with_message("cannot find column")
|
|
||||||
])
|
|
||||||
}
|
|
||||||
ShellError::ExternalCommand(error, span) => {
|
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
|
||||||
|
|
||||||
Diagnostic::error()
|
|
||||||
.with_message("External command")
|
|
||||||
.with_labels(vec![
|
|
||||||
Label::primary(diag_file_id, diag_range).with_message(error.to_string())
|
|
||||||
])
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// println!("DIAG");
|
|
||||||
// println!("{:?}", diagnostic);
|
|
||||||
codespan_reporting::term::emit(&mut writer.lock(), &config, working_set, &diagnostic)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
@ -3,5 +3,5 @@ mod errors;
|
|||||||
mod syntax_highlight;
|
mod syntax_highlight;
|
||||||
|
|
||||||
pub use completions::NuCompleter;
|
pub use completions::NuCompleter;
|
||||||
pub use errors::{report_parsing_error, report_shell_error};
|
pub use errors::report_error;
|
||||||
pub use syntax_highlight::NuHighlighter;
|
pub use syntax_highlight::NuHighlighter;
|
||||||
|
@ -4,5 +4,6 @@ version = "0.1.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
codespan-reporting = "0.11.1"
|
miette = { version = "3.0.0-alpha.0" }
|
||||||
|
thiserror = "1.0.29"
|
||||||
nu-protocol = { path = "../nu-protocol"}
|
nu-protocol = { path = "../nu-protocol"}
|
@ -1,34 +1,150 @@
|
|||||||
|
use miette::Diagnostic;
|
||||||
use nu_protocol::{Span, Type};
|
use nu_protocol::{Span, Type};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug, Error, Diagnostic)]
|
||||||
pub enum ParseError {
|
pub enum ParseError {
|
||||||
ExtraTokens(Span),
|
/// The parser encountered unexpected tokens, when the code should have
|
||||||
ExtraPositional(Span),
|
/// finished. You should remove these or finish adding what you intended
|
||||||
UnexpectedEof(String, Span),
|
/// to add.
|
||||||
Unclosed(String, Span),
|
#[error("Extra tokens in code.")]
|
||||||
UnknownStatement(Span),
|
#[diagnostic(
|
||||||
Expected(String, Span),
|
code(nu::parser::extra_tokens),
|
||||||
Mismatch(String, String, Span), // expected, found, span
|
url(docsrs),
|
||||||
UnsupportedOperation(Span, Span, Type, Span, Type),
|
help("Try removing them.")
|
||||||
ExpectedKeyword(String, Span),
|
)]
|
||||||
MultipleRestParams(Span),
|
ExtraTokens(#[label = "extra tokens"] Span),
|
||||||
VariableNotFound(Span),
|
|
||||||
UnknownCommand(Span),
|
#[error("Extra positional argument.")]
|
||||||
NonUtf8(Span),
|
#[diagnostic(code(nu::parser::extra_positional), url(docsrs))]
|
||||||
UnknownFlag(Span),
|
ExtraPositional(#[label = "extra positional argument"] Span),
|
||||||
UnknownType(Span),
|
|
||||||
MissingFlagParam(Span),
|
#[error("Unexpected end of code.")]
|
||||||
ShortFlagBatchCantTakeArg(Span),
|
#[diagnostic(code(nu::parser::unexpected_eof), url(docsrs))]
|
||||||
MissingPositional(String, Span),
|
UnexpectedEof(String, #[label("expected {0}")] Span),
|
||||||
KeywordMissingArgument(String, Span),
|
|
||||||
MissingType(Span),
|
#[error("Unclosed delimiter.")]
|
||||||
TypeMismatch(Type, Type, Span), // expected, found, span
|
#[diagnostic(code(nu::parser::unclosed_delimiter), url(docsrs))]
|
||||||
MissingRequiredFlag(String, Span),
|
Unclosed(String, #[label("unclosed {0}")] Span),
|
||||||
IncompleteMathExpression(Span),
|
|
||||||
UnknownState(String, Span),
|
#[error("Unknown statement.")]
|
||||||
IncompleteParser(Span),
|
#[diagnostic(code(nu::parser::unknown_statement), url(docsrs))]
|
||||||
RestNeedsName(Span),
|
UnknownStatement(#[label("unknown statement")] Span),
|
||||||
ExtraColumns(usize, Span),
|
|
||||||
MissingColumns(usize, Span),
|
#[error("Parse mismatch during operation.")]
|
||||||
AssignmentMismatch(String, String, Span),
|
#[diagnostic(code(nu::parser::parse_mismatch), url(docsrs))]
|
||||||
|
Expected(String, #[label("expected {0}")] Span),
|
||||||
|
|
||||||
|
#[error("Type mismatch during operation.")]
|
||||||
|
#[diagnostic(code(nu::parser::type_mismatch), url(docsrs))]
|
||||||
|
Mismatch(String, String, #[label("expected {0}, found {1}")] Span), // expected, found, span
|
||||||
|
|
||||||
|
#[error("Unsupported operation.")]
|
||||||
|
#[diagnostic(
|
||||||
|
code(nu::parser::unsupported_operation),
|
||||||
|
url(docsrs),
|
||||||
|
help("Change {2} or {4} to be the right types and try again.")
|
||||||
|
)]
|
||||||
|
UnsupportedOperation(
|
||||||
|
#[label = "doesn't support these values."] Span,
|
||||||
|
#[label("{2}")] Span,
|
||||||
|
Type,
|
||||||
|
#[label("{4}")] Span,
|
||||||
|
Type,
|
||||||
|
),
|
||||||
|
|
||||||
|
#[error("Expected keyword.")]
|
||||||
|
#[diagnostic(code(nu::parser::expected_keyword), url(docsrs))]
|
||||||
|
ExpectedKeyword(String, #[label("expected {0}")] Span),
|
||||||
|
|
||||||
|
#[error("Multiple rest params.")]
|
||||||
|
#[diagnostic(code(nu::parser::multiple_rest_params), url(docsrs))]
|
||||||
|
MultipleRestParams(#[label = "multiple rest params"] Span),
|
||||||
|
|
||||||
|
#[error("Variable not found.")]
|
||||||
|
#[diagnostic(code(nu::parser::variable_not_found), url(docsrs))]
|
||||||
|
VariableNotFound(#[label = "variable not found"] Span),
|
||||||
|
|
||||||
|
#[error("Unknown command.")]
|
||||||
|
#[diagnostic(
|
||||||
|
code(nu::parser::unknown_command),
|
||||||
|
url(docsrs),
|
||||||
|
// TODO: actual suggestions
|
||||||
|
// help("Did you mean `foo`?")
|
||||||
|
)]
|
||||||
|
UnknownCommand(#[label = "unknown command"] Span),
|
||||||
|
|
||||||
|
#[error("Non-UTF8 code.")]
|
||||||
|
#[diagnostic(code(nu::parser::non_utf8), url(docsrs))]
|
||||||
|
NonUtf8(#[label = "non-UTF8 code"] Span),
|
||||||
|
|
||||||
|
#[error("Unknown flag.")]
|
||||||
|
#[diagnostic(code(nu::parser::unknown_flag), url(docsrs))]
|
||||||
|
UnknownFlag(#[label = "unknown flag"] Span),
|
||||||
|
|
||||||
|
#[error("Unknown type.")]
|
||||||
|
#[diagnostic(code(nu::parser::unknown_type), url(docsrs))]
|
||||||
|
UnknownType(#[label = "unknown type"] Span),
|
||||||
|
|
||||||
|
#[error("Missing flag param.")]
|
||||||
|
#[diagnostic(code(nu::parser::missing_flag_param), url(docsrs))]
|
||||||
|
MissingFlagParam(#[label = "flag missing param"] Span),
|
||||||
|
|
||||||
|
#[error("Batches of short flags can't take arguments.")]
|
||||||
|
#[diagnostic(code(nu::parser::short_flag_arg_cant_take_arg), url(docsrs))]
|
||||||
|
ShortFlagBatchCantTakeArg(#[label = "short flag batches can't take args"] Span),
|
||||||
|
|
||||||
|
#[error("Missing required positional argument.")]
|
||||||
|
#[diagnostic(code(nu::parser::missing_positional), url(docsrs))]
|
||||||
|
MissingPositional(String, #[label("missing {0}")] Span),
|
||||||
|
|
||||||
|
#[error("Missing argument to `{0}`.")]
|
||||||
|
#[diagnostic(code(nu::parser::keyword_missing_arg), url(docsrs))]
|
||||||
|
KeywordMissingArgument(String, #[label("missing value that follows {0}")] Span),
|
||||||
|
|
||||||
|
#[error("Missing type.")]
|
||||||
|
#[diagnostic(code(nu::parser::missing_type), url(docsrs))]
|
||||||
|
MissingType(#[label = "expected type"] Span),
|
||||||
|
|
||||||
|
#[error("Type mismatch.")]
|
||||||
|
#[diagnostic(code(nu::parser::type_mismatch), url(docsrs))]
|
||||||
|
TypeMismatch(Type, Type, #[label("expected {0:?}, found {1:?}")] Span), // expected, found, span
|
||||||
|
|
||||||
|
#[error("Missing required flag.")]
|
||||||
|
#[diagnostic(code(nu::parser::missing_required_flag), url(docsrs))]
|
||||||
|
MissingRequiredFlag(String, #[label("missing required flag {0}")] Span),
|
||||||
|
|
||||||
|
#[error("Incomplete math expression.")]
|
||||||
|
#[diagnostic(code(nu::parser::incomplete_math_expression), url(docsrs))]
|
||||||
|
IncompleteMathExpression(#[label = "incomplete math expression"] Span),
|
||||||
|
|
||||||
|
#[error("Unknown state.")]
|
||||||
|
#[diagnostic(code(nu::parser::unknown_state), url(docsrs))]
|
||||||
|
UnknownState(String, #[label("{0}")] Span),
|
||||||
|
|
||||||
|
#[error("Parser incomplete.")]
|
||||||
|
#[diagnostic(code(nu::parser::parser_incomplete), url(docsrs))]
|
||||||
|
IncompleteParser(#[label = "parser support missing for this expression"] Span),
|
||||||
|
|
||||||
|
#[error("Rest parameter needs a name.")]
|
||||||
|
#[diagnostic(code(nu::parser::rest_needs_name), url(docsrs))]
|
||||||
|
RestNeedsName(#[label = "needs a parameter name"] Span),
|
||||||
|
|
||||||
|
#[error("Extra columns.")]
|
||||||
|
#[diagnostic(code(nu::parser::extra_columns), url(docsrs))]
|
||||||
|
ExtraColumns(
|
||||||
|
usize,
|
||||||
|
#[label("expected {0} column{}", if *.0 == 1 { "" } else { "s" })] Span,
|
||||||
|
),
|
||||||
|
|
||||||
|
#[error("Missing columns.")]
|
||||||
|
#[diagnostic(code(nu::parser::missing_columns), url(docsrs))]
|
||||||
|
MissingColumns(
|
||||||
|
usize,
|
||||||
|
#[label("expected {0} column{}", if *.0 == 1 { "" } else { "s" })] Span,
|
||||||
|
),
|
||||||
|
|
||||||
|
#[error("{0}")]
|
||||||
|
#[diagnostic(code(nu::parser::assignment_mismatch), url(docsrs))]
|
||||||
|
AssignmentMismatch(String, String, #[label("{1}")] Span),
|
||||||
}
|
}
|
||||||
|
@ -6,4 +6,5 @@ edition = "2018"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
codespan-reporting = "0.11.1"
|
thiserror = "1.0.29"
|
||||||
|
miette = { version = "3.0.0-alpha.0" }
|
||||||
|
@ -2,7 +2,7 @@ use crate::{ast::Call, value::Value, BlockId, Example, ShellError, Signature};
|
|||||||
|
|
||||||
use super::EvaluationContext;
|
use super::EvaluationContext;
|
||||||
|
|
||||||
pub trait Command {
|
pub trait Command: Send + Sync {
|
||||||
fn name(&self) -> &str;
|
fn name(&self) -> &str;
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::Command;
|
use super::Command;
|
||||||
use crate::{ast::Block, BlockId, DeclId, Span, Type, VarId};
|
use crate::{ast::Block, BlockId, DeclId, Span, Type, VarId};
|
||||||
use core::panic;
|
use core::panic;
|
||||||
use std::{collections::HashMap, ops::Range, slice::Iter};
|
use std::{collections::HashMap, slice::Iter};
|
||||||
|
|
||||||
pub struct EngineState {
|
pub struct EngineState {
|
||||||
files: Vec<(String, usize, usize)>,
|
files: Vec<(String, usize, usize)>,
|
||||||
@ -549,95 +549,42 @@ impl<'a> StateWorkingSet<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> codespan_reporting::files::Files<'a> for StateWorkingSet<'a> {
|
impl<'a> miette::SourceCode for &StateWorkingSet<'a> {
|
||||||
type FileId = usize;
|
fn read_span<'b>(
|
||||||
|
&'b self,
|
||||||
type Name = String;
|
span: &miette::SourceSpan,
|
||||||
|
context_lines_before: usize,
|
||||||
type Source = String;
|
context_lines_after: usize,
|
||||||
|
) -> Result<Box<dyn miette::SpanContents + 'b>, miette::MietteError> {
|
||||||
fn name(&'a self, id: Self::FileId) -> Result<Self::Name, codespan_reporting::files::Error> {
|
for (filename, start, end) in self.files() {
|
||||||
Ok(self.get_filename(id))
|
if span.offset() >= *start && span.offset() + span.len() <= *end {
|
||||||
}
|
let our_span = Span {
|
||||||
|
start: *start,
|
||||||
fn source(
|
end: *end,
|
||||||
&'a self,
|
};
|
||||||
id: Self::FileId,
|
// We need to move to a local span because we're only reading
|
||||||
) -> Result<Self::Source, codespan_reporting::files::Error> {
|
// the specific file contents via self.get_span_contents.
|
||||||
Ok(self.get_file_source(id))
|
let local_span = (span.offset() - *start, span.len()).into();
|
||||||
}
|
let span_contents = self.get_span_contents(our_span);
|
||||||
|
let span_contents = span_contents.read_span(
|
||||||
fn line_index(
|
&local_span,
|
||||||
&'a self,
|
context_lines_before,
|
||||||
id: Self::FileId,
|
context_lines_after,
|
||||||
byte_index: usize,
|
)?;
|
||||||
) -> Result<usize, codespan_reporting::files::Error> {
|
let content_span = span_contents.span();
|
||||||
let source = self.get_file_source(id);
|
// Back to "global" indexing
|
||||||
|
let retranslated = (content_span.offset() + start, content_span.len()).into();
|
||||||
let mut count = 0;
|
return Ok(Box::new(miette::MietteSpanContents::new_named(
|
||||||
|
filename.clone(),
|
||||||
for byte in source.bytes().enumerate() {
|
span_contents.data(),
|
||||||
if byte.0 == byte_index {
|
retranslated,
|
||||||
// println!("count: {} for file: {} index: {}", count, id, byte_index);
|
span_contents.line(),
|
||||||
return Ok(count);
|
span_contents.column(),
|
||||||
}
|
span_contents.line_count(),
|
||||||
if byte.1 == b'\n' {
|
)));
|
||||||
count += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(miette::MietteError::OutOfBounds)
|
||||||
// println!("count: {} for file: {} index: {}", count, id, byte_index);
|
|
||||||
Ok(count)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn line_range(
|
|
||||||
&'a self,
|
|
||||||
id: Self::FileId,
|
|
||||||
line_index: usize,
|
|
||||||
) -> Result<Range<usize>, codespan_reporting::files::Error> {
|
|
||||||
let source = self.get_file_source(id);
|
|
||||||
|
|
||||||
let mut count = 0;
|
|
||||||
|
|
||||||
let mut start = Some(0);
|
|
||||||
let mut end = None;
|
|
||||||
|
|
||||||
for byte in source.bytes().enumerate() {
|
|
||||||
#[allow(clippy::comparison_chain)]
|
|
||||||
if count > line_index {
|
|
||||||
let start = start.expect("internal error: couldn't find line");
|
|
||||||
let end = end.expect("internal error: couldn't find line");
|
|
||||||
|
|
||||||
// println!(
|
|
||||||
// "Span: {}..{} for fileid: {} index: {}",
|
|
||||||
// start, end, id, line_index
|
|
||||||
// );
|
|
||||||
return Ok(start..end);
|
|
||||||
} else if count == line_index {
|
|
||||||
end = Some(byte.0 + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::comparison_chain)]
|
|
||||||
if byte.1 == b'\n' {
|
|
||||||
count += 1;
|
|
||||||
if count > line_index {
|
|
||||||
break;
|
|
||||||
} else if count == line_index {
|
|
||||||
start = Some(byte.0 + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match (start, end) {
|
|
||||||
(Some(start), Some(end)) => {
|
|
||||||
// println!(
|
|
||||||
// "Span: {}..{} for fileid: {} index: {}",
|
|
||||||
// start, end, id, line_index
|
|
||||||
// );
|
|
||||||
Ok(start..end)
|
|
||||||
}
|
|
||||||
_ => Err(codespan_reporting::files::Error::FileMissing),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,25 +1,72 @@
|
|||||||
|
use miette::Diagnostic;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{ast::Operator, Span, Type};
|
use crate::{ast::Operator, Span, Type};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Error, Diagnostic)]
|
||||||
pub enum ShellError {
|
pub enum ShellError {
|
||||||
|
#[error("Type mismatch during operation.")]
|
||||||
|
#[diagnostic(code(nu::shell::type_mismatch), url(docsrs))]
|
||||||
OperatorMismatch {
|
OperatorMismatch {
|
||||||
|
#[label = "type mismatch for operator"]
|
||||||
op_span: Span,
|
op_span: Span,
|
||||||
lhs_ty: Type,
|
lhs_ty: Type,
|
||||||
|
#[label("{lhs_ty}")]
|
||||||
lhs_span: Span,
|
lhs_span: Span,
|
||||||
rhs_ty: Type,
|
rhs_ty: Type,
|
||||||
|
#[label("{rhs_ty}")]
|
||||||
rhs_span: Span,
|
rhs_span: Span,
|
||||||
},
|
},
|
||||||
UnsupportedOperator(Operator, Span),
|
|
||||||
UnknownOperator(String, Span),
|
#[error("Unsupported operator: {0}.")]
|
||||||
ExternalNotSupported(Span),
|
#[diagnostic(code(nu::shell::unsupported_operator), url(docsrs))]
|
||||||
|
UnsupportedOperator(Operator, #[label = "unsupported operator"] Span),
|
||||||
|
|
||||||
|
#[error("Unsupported operator: {0}.")]
|
||||||
|
#[diagnostic(code(nu::shell::unknown_operator), url(docsrs))]
|
||||||
|
UnknownOperator(String, #[label = "unsupported operator"] Span),
|
||||||
|
|
||||||
|
#[error("External commands not yet supported")]
|
||||||
|
#[diagnostic(code(nu::shell::external_commands), url(docsrs))]
|
||||||
|
ExternalNotSupported(#[label = "external not supported"] Span),
|
||||||
|
|
||||||
|
#[error("Internal error: {0}.")]
|
||||||
|
#[diagnostic(code(nu::shell::internal_error), url(docsrs))]
|
||||||
InternalError(String),
|
InternalError(String),
|
||||||
VariableNotFoundAtRuntime(Span),
|
|
||||||
CantConvert(String, Span),
|
#[error("Variable not found")]
|
||||||
DivisionByZero(Span),
|
#[diagnostic(code(nu::shell::variable_not_found), url(docsrs))]
|
||||||
CannotCreateRange(Span),
|
VariableNotFoundAtRuntime(#[label = "variable not found"] Span),
|
||||||
AccessBeyondEnd(usize, Span),
|
|
||||||
AccessBeyondEndOfStream(Span),
|
#[error("Can't convert to {0}.")]
|
||||||
IncompatiblePathAccess(String, Span),
|
#[diagnostic(code(nu::shell::cant_convert), url(docsrs))]
|
||||||
CantFindColumn(Span),
|
CantConvert(String, #[label("can't convert to {0}")] Span),
|
||||||
ExternalCommand(String, Span),
|
|
||||||
|
#[error("Division by zero.")]
|
||||||
|
#[diagnostic(code(nu::shell::division_by_zero), url(docsrs))]
|
||||||
|
DivisionByZero(#[label("division by zero")] Span),
|
||||||
|
|
||||||
|
#[error("Can't convert range to countable values")]
|
||||||
|
#[diagnostic(code(nu::shell::range_to_countable), url(docsrs))]
|
||||||
|
CannotCreateRange(#[label = "can't convert to countable values"] Span),
|
||||||
|
|
||||||
|
#[error("Row number too large (max: {0}).")]
|
||||||
|
#[diagnostic(code(nu::shell::access_beyond_end), url(docsrs))]
|
||||||
|
AccessBeyondEnd(usize, #[label = "too large"] Span),
|
||||||
|
|
||||||
|
#[error("Row number too large.")]
|
||||||
|
#[diagnostic(code(nu::shell::access_beyond_end_of_stream), url(docsrs))]
|
||||||
|
AccessBeyondEndOfStream(#[label = "too large"] Span),
|
||||||
|
|
||||||
|
#[error("Data cannot be accessed with a cell path")]
|
||||||
|
#[diagnostic(code(nu::shell::incompatible_path_access), url(docsrs))]
|
||||||
|
IncompatiblePathAccess(String, #[label("{0} doesn't support cell paths")] Span),
|
||||||
|
|
||||||
|
#[error("Cannot find column")]
|
||||||
|
#[diagnostic(code(nu::shell::column_not_found), url(docsrs))]
|
||||||
|
CantFindColumn(#[label = "cannot find column"] Span),
|
||||||
|
|
||||||
|
#[error("External command")]
|
||||||
|
#[diagnostic(code(nu::shell::external_command), url(docsrs))]
|
||||||
|
ExternalCommand(String, #[label("{0}")] Span),
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,17 @@
|
|||||||
|
use miette::SourceSpan;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub struct Span {
|
pub struct Span {
|
||||||
pub start: usize,
|
pub start: usize,
|
||||||
pub end: usize,
|
pub end: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Span> for SourceSpan {
|
||||||
|
fn from(s: Span) -> Self {
|
||||||
|
Self::new(s.start.into(), (s.end - s.start).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Span {
|
impl Span {
|
||||||
pub fn new(start: usize, end: usize) -> Span {
|
pub fn new(start: usize, end: usize) -> Span {
|
||||||
Span { start, end }
|
Span { start, end }
|
||||||
|
28
src/main.rs
28
src/main.rs
@ -1,4 +1,5 @@
|
|||||||
use nu_cli::{report_parsing_error, report_shell_error, NuCompleter, NuHighlighter};
|
use miette::{IntoDiagnostic, Result};
|
||||||
|
use nu_cli::{report_error, NuCompleter, NuHighlighter};
|
||||||
use nu_command::create_default_context;
|
use nu_command::create_default_context;
|
||||||
use nu_engine::eval_block;
|
use nu_engine::eval_block;
|
||||||
use nu_parser::parse;
|
use nu_parser::parse;
|
||||||
@ -11,18 +12,18 @@ use reedline::DefaultCompletionActionHandler;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
fn main() -> std::io::Result<()> {
|
fn main() -> Result<()> {
|
||||||
let engine_state = create_default_context();
|
let engine_state = create_default_context();
|
||||||
|
|
||||||
if let Some(path) = std::env::args().nth(1) {
|
if let Some(path) = std::env::args().nth(1) {
|
||||||
let file = std::fs::read(&path)?;
|
let file = std::fs::read(&path).into_diagnostic()?;
|
||||||
|
|
||||||
let (block, delta) = {
|
let (block, delta) = {
|
||||||
let engine_state = engine_state.borrow();
|
let engine_state = engine_state.borrow();
|
||||||
let mut working_set = StateWorkingSet::new(&*engine_state);
|
let mut working_set = StateWorkingSet::new(&*engine_state);
|
||||||
let (output, err) = parse(&mut working_set, Some(&path), &file, false);
|
let (output, err) = parse(&mut working_set, Some(&path), &file, false);
|
||||||
if let Some(err) = err {
|
if let Some(err) = err {
|
||||||
let _ = report_parsing_error(&working_set, &err);
|
report_error(&working_set, &err);
|
||||||
|
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
@ -44,7 +45,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
let engine_state = engine_state.borrow();
|
let engine_state = engine_state.borrow();
|
||||||
let working_set = StateWorkingSet::new(&*engine_state);
|
let working_set = StateWorkingSet::new(&*engine_state);
|
||||||
|
|
||||||
let _ = report_shell_error(&working_set, &err);
|
report_error(&working_set, &err);
|
||||||
|
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
@ -56,11 +57,12 @@ fn main() -> std::io::Result<()> {
|
|||||||
|
|
||||||
let completer = NuCompleter::new(engine_state.clone());
|
let completer = NuCompleter::new(engine_state.clone());
|
||||||
|
|
||||||
let mut line_editor = Reedline::create()?
|
let mut line_editor = Reedline::create()
|
||||||
.with_history(Box::new(FileBackedHistory::with_file(
|
.into_diagnostic()?
|
||||||
1000,
|
.with_history(Box::new(
|
||||||
"history.txt".into(),
|
FileBackedHistory::with_file(1000, "history.txt".into()).into_diagnostic()?,
|
||||||
)?))?
|
))
|
||||||
|
.into_diagnostic()?
|
||||||
.with_highlighter(Box::new(NuHighlighter {
|
.with_highlighter(Box::new(NuHighlighter {
|
||||||
engine_state: engine_state.clone(),
|
engine_state: engine_state.clone(),
|
||||||
}))
|
}))
|
||||||
@ -102,7 +104,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
if let Some(err) = err {
|
if let Some(err) = err {
|
||||||
let _ = report_parsing_error(&working_set, &err);
|
report_error(&working_set, &err);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
(output, working_set.render())
|
(output, working_set.render())
|
||||||
@ -123,7 +125,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
let engine_state = engine_state.borrow();
|
let engine_state = engine_state.borrow();
|
||||||
let working_set = StateWorkingSet::new(&*engine_state);
|
let working_set = StateWorkingSet::new(&*engine_state);
|
||||||
|
|
||||||
let _ = report_shell_error(&working_set, &err);
|
report_error(&working_set, &err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,7 +136,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Ok(Signal::CtrlL) => {
|
Ok(Signal::CtrlL) => {
|
||||||
line_editor.clear_screen()?;
|
line_editor.clear_screen().into_diagnostic()?;
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let message = err.to_string();
|
let message = err.to_string();
|
||||||
|
@ -133,7 +133,7 @@ fn if_elseif4() -> TestResult {
|
|||||||
fn no_scope_leak1() -> TestResult {
|
fn no_scope_leak1() -> TestResult {
|
||||||
fail_test(
|
fail_test(
|
||||||
"if $false { let $x = 10 } else { let $x = 20 }; $x",
|
"if $false { let $x = 10 } else { let $x = 20 }; $x",
|
||||||
"variable not found",
|
"Variable not found",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user