From e4226def162012e7fafc3f74242cdf290ce19113 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 25 Nov 2019 18:30:48 -0800 Subject: [PATCH] Extract core stuff into own crates This commit extracts five new crates: - nu-source, which contains the core source-code handling logic in Nu, including Text, Span, and also the pretty.rs-based debug logic - nu-parser, which is the parser and expander logic - nu-protocol, which is the bulk of the types and basic conveniences used by plugins - nu-errors, which contains ShellError, ParseError and error handling conveniences - nu-textview, which is the textview plugin extracted into a crate One of the major consequences of this refactor is that it's no longer possible to `impl X for Spanned` outside of the `nu-source` crate, so a lot of types became more concrete (Value became a concrete type instead of Spanned, for example). This also turned a number of inherent methods in the main nu crate into plain functions (impl Value {} became a bunch of functions in the `value` namespace in `crate::data::value`). --- Cargo.lock | 169 ++++ Cargo.toml | 15 +- crates/nu-errors/Cargo.toml | 26 + src/errors.rs => crates/nu-errors/src/lib.rs | 38 +- crates/nu-parser/Cargo.toml | 37 + crates/nu-parser/src/commands.rs | 98 +++ crates/nu-parser/src/commands/classified.rs | 112 +++ {src/parser => crates/nu-parser/src}/debug.rs | 0 {src/parser => crates/nu-parser/src}/hir.rs | 74 +- .../nu-parser/src}/hir/baseline_parse.rs | 0 .../src}/hir/baseline_parse/tests.rs | 76 +- .../nu-parser/src}/hir/binary.rs | 7 +- .../src}/hir/expand_external_tokens.rs | 6 +- .../nu-parser/src}/hir/external_command.rs | 4 +- .../nu-parser/src}/hir/named.rs | 12 +- crates/nu-parser/src/hir/path.rs | 41 + .../nu-parser/src}/hir/syntax_shape.rs | 117 +-- .../nu-parser/src}/hir/syntax_shape/block.rs | 14 +- .../src}/hir/syntax_shape/expression.rs | 10 +- .../src}/hir/syntax_shape/expression/atom.rs | 14 +- .../hir/syntax_shape/expression/delimited.rs | 7 +- .../hir/syntax_shape/expression/file_path.rs | 10 +- .../src}/hir/syntax_shape/expression/list.rs | 6 +- .../hir/syntax_shape/expression/number.rs | 14 +- .../hir/syntax_shape/expression/pattern.rs | 13 +- .../hir/syntax_shape/expression/string.rs | 12 +- .../src}/hir/syntax_shape/expression/unit.rs | 15 +- .../syntax_shape/expression/variable_path.rs | 17 +- .../src}/hir/syntax_shape/flat_shape.rs | 5 +- .../nu-parser/src}/hir/tokens_iterator.rs | 11 +- .../src}/hir/tokens_iterator/debug.rs | 2 +- .../hir/tokens_iterator/debug/color_trace.rs | 7 +- .../hir/tokens_iterator/debug/expand_trace.rs | 7 +- .../src}/hir/tokens_iterator/tests.rs | 4 +- crates/nu-parser/src/lib.rs | 30 + {src/parser => crates/nu-parser/src}/parse.rs | 0 .../nu-parser/src}/parse/call_node.rs | 4 +- .../nu-parser/src}/parse/files.rs | 0 .../nu-parser/src}/parse/flag.rs | 5 +- .../nu-parser/src}/parse/operator.rs | 3 +- .../nu-parser/src}/parse/parser.rs | 45 +- .../nu-parser/src}/parse/pipeline.rs | 5 +- .../nu-parser/src}/parse/token_tree.rs | 12 +- .../src}/parse/token_tree_builder.rs | 18 +- .../nu-parser/src}/parse/tokens.rs | 12 +- .../nu-parser/src}/parse/unit.rs | 52 +- .../nu-parser/src}/parse/util.rs | 0 .../nu-parser/src}/parse_command.rs | 16 +- crates/nu-protocol/Cargo.toml | 35 + crates/nu-protocol/src/call_info.rs | 93 +++ crates/nu-protocol/src/lib.rs | 24 + crates/nu-protocol/src/macros.rs | 12 + crates/nu-protocol/src/maybe_owned.rs | 14 + {src => crates/nu-protocol/src}/plugin.rs | 7 +- crates/nu-protocol/src/return_value.rs | 76 ++ .../nu-protocol/src/signature.rs | 145 +--- crates/nu-protocol/src/syntax_shape.rs | 31 + .../nu-protocol/src/type_name.rs | 3 +- crates/nu-protocol/src/value.rs | 205 +++++ .../nu-protocol/src/value/column_path.rs | 42 +- crates/nu-protocol/src/value/convert.rs | 55 ++ .../nu-protocol/src/value}/debug.rs | 33 +- crates/nu-protocol/src/value/dict.rs | 140 ++++ crates/nu-protocol/src/value/evaluate.rs | 102 +++ crates/nu-protocol/src/value/primitive.rs | 65 ++ .../nu-protocol/src/value/serde_bigdecimal.rs | 24 + crates/nu-protocol/src/value/serde_bigint.rs | 23 + crates/nu-textview/Cargo.toml | 22 + .../nu-textview/src/main.rs | 9 +- src/cli.rs | 80 +- src/commands.rs | 1 - src/commands/append.rs | 5 +- src/commands/args.rs | 2 +- src/commands/autoview.rs | 28 +- src/commands/cd.rs | 3 +- src/commands/clip.rs | 5 +- src/commands/command.rs | 145 +--- src/commands/compact.rs | 6 +- src/commands/config.rs | 10 +- src/commands/count.rs | 9 +- src/commands/cp.rs | 6 +- src/commands/date.rs | 33 +- src/commands/debug.rs | 7 +- src/commands/default.rs | 5 +- src/commands/echo.rs | 9 +- src/commands/enter.rs | 19 +- src/commands/env.rs | 34 +- src/commands/evaluate_by.rs | 19 +- src/commands/exit.rs | 7 +- src/commands/fetch.rs | 30 +- src/commands/first.rs | 5 +- src/commands/from_bson.rs | 15 +- src/commands/from_csv.rs | 3 +- src/commands/from_delimited_data.rs | 4 +- src/commands/from_ini.rs | 4 +- src/commands/from_json.rs | 12 +- src/commands/from_sqlite.rs | 11 +- src/commands/from_ssv.rs | 4 +- src/commands/from_toml.rs | 10 +- src/commands/from_tsv.rs | 2 + src/commands/from_url.rs | 7 +- src/commands/from_xlsx.rs | 16 +- src/commands/from_xml.rs | 22 +- src/commands/from_yaml.rs | 10 +- src/commands/get.rs | 11 +- src/commands/group_by.rs | 24 +- src/commands/help.rs | 19 +- src/commands/histogram.rs | 13 +- src/commands/history.rs | 9 +- src/commands/last.rs | 5 +- src/commands/lines.rs | 4 +- src/commands/ls.rs | 3 +- src/commands/macros.rs | 12 +- src/commands/map_max_by.rs | 20 +- src/commands/mkdir.rs | 5 +- src/commands/mv.rs | 6 +- src/commands/next.rs | 4 +- src/commands/nth.rs | 5 +- src/commands/open.rs | 31 +- src/commands/pick.rs | 3 +- src/commands/pivot.rs | 17 +- src/commands/plugin.rs | 17 +- src/commands/post.rs | 38 +- src/commands/prepend.rs | 5 +- src/commands/prev.rs | 4 +- src/commands/pwd.rs | 4 +- src/commands/reduce_by.rs | 17 +- src/commands/reject.rs | 3 +- src/commands/reverse.rs | 5 +- src/commands/rm.rs | 6 +- src/commands/save.rs | 6 +- src/commands/shells.rs | 3 +- src/commands/size.rs | 15 +- src/commands/skip_while.rs | 8 +- src/commands/sort_by.rs | 10 +- src/commands/split_by.rs | 23 +- src/commands/split_column.rs | 5 +- src/commands/split_row.rs | 4 +- src/commands/t_sort_by.rs | 29 +- src/commands/table.rs | 8 +- src/commands/tags.rs | 11 +- src/commands/to_bson.rs | 12 +- src/commands/to_csv.rs | 3 +- src/commands/to_delimited_data.rs | 14 +- src/commands/to_json.rs | 4 +- src/commands/to_sqlite.rs | 7 +- src/commands/to_toml.rs | 7 +- src/commands/to_tsv.rs | 2 + src/commands/to_url.rs | 8 +- src/commands/to_yaml.rs | 8 +- src/commands/trim.rs | 5 +- src/commands/version.rs | 7 +- src/commands/what.rs | 9 +- src/commands/where_.rs | 12 +- src/commands/which_.rs | 8 +- src/context.rs | 25 +- src/data.rs | 6 +- src/data/base.rs | 696 ++-------------- src/data/base/property_get.rs | 742 ++++++++++-------- src/data/base/shape.rs | 49 +- src/data/command.rs | 16 +- src/data/config.rs | 4 +- src/data/dict.rs | 111 +-- src/data/files.rs | 24 +- src/data/into.rs | 13 - src/data/primitive.rs | 91 +++ src/data/process.rs | 12 +- src/data/types.rs | 27 +- src/data/value.rs | 152 ++++ src/{parser => }/deserializer.rs | 15 +- src/env/host.rs | 1 + src/evaluate/evaluate_args.rs | 58 ++ src/evaluate/evaluator.rs | 79 +- src/evaluate/mod.rs | 3 +- src/format.rs | 2 +- src/format/entries.rs | 5 +- src/format/generic.rs | 11 +- src/format/list.rs | 1 + src/format/table.rs | 19 +- src/lib.rs | 27 +- src/parser.rs | 32 - src/plugins/average.rs | 11 +- src/plugins/binaryview.rs | 6 +- src/plugins/docker.rs | 2 +- src/plugins/edit.rs | 8 +- src/plugins/embed.rs | 12 +- src/plugins/format.rs | 9 +- src/plugins/inc.rs | 45 +- src/plugins/insert.rs | 8 +- src/plugins/match.rs | 7 +- src/plugins/parse.rs | 12 +- src/plugins/ps.rs | 15 +- src/plugins/skip.rs | 7 +- src/plugins/str.rs | 60 +- src/plugins/sum.rs | 11 +- src/plugins/sys.rs | 91 +-- src/prelude.rs | 43 +- src/shell/filesystem_shell.rs | 2 + src/shell/help_shell.rs | 2 + src/shell/helper.rs | 8 +- src/shell/shell.rs | 2 +- src/shell/shell_manager.rs | 2 +- src/shell/value_shell.rs | 4 +- src/stream.rs | 1 + src/utils.rs | 39 +- 205 files changed, 3491 insertions(+), 2605 deletions(-) create mode 100644 crates/nu-errors/Cargo.toml rename src/errors.rs => crates/nu-errors/src/lib.rs (96%) create mode 100644 crates/nu-parser/Cargo.toml create mode 100644 crates/nu-parser/src/commands.rs create mode 100644 crates/nu-parser/src/commands/classified.rs rename {src/parser => crates/nu-parser/src}/debug.rs (100%) rename {src/parser => crates/nu-parser/src}/hir.rs (84%) rename {src/parser => crates/nu-parser/src}/hir/baseline_parse.rs (100%) rename {src/parser => crates/nu-parser/src}/hir/baseline_parse/tests.rs (62%) rename {src/parser => crates/nu-parser/src}/hir/binary.rs (84%) rename {src/parser => crates/nu-parser/src}/hir/expand_external_tokens.rs (99%) rename {src/parser => crates/nu-parser/src}/hir/external_command.rs (84%) rename {src/parser => crates/nu-parser/src}/hir/named.rs (89%) create mode 100644 crates/nu-parser/src/hir/path.rs rename {src/parser => crates/nu-parser/src}/hir/syntax_shape.rs (94%) rename {src/parser => crates/nu-parser/src}/hir/syntax_shape/block.rs (98%) rename {src/parser => crates/nu-parser/src}/hir/syntax_shape/expression.rs (98%) rename {src/parser => crates/nu-parser/src}/hir/syntax_shape/expression/atom.rs (98%) rename {src/parser => crates/nu-parser/src}/hir/syntax_shape/expression/delimited.rs (94%) rename {src/parser => crates/nu-parser/src}/hir/syntax_shape/expression/file_path.rs (94%) rename {src/parser => crates/nu-parser/src}/hir/syntax_shape/expression/list.rs (99%) rename {src/parser => crates/nu-parser/src}/hir/syntax_shape/expression/number.rs (96%) rename {src/parser => crates/nu-parser/src}/hir/syntax_shape/expression/pattern.rs (92%) rename {src/parser => crates/nu-parser/src}/hir/syntax_shape/expression/string.rs (91%) rename {src/parser => crates/nu-parser/src}/hir/syntax_shape/expression/unit.rs (89%) rename {src/parser => crates/nu-parser/src}/hir/syntax_shape/expression/variable_path.rs (98%) rename {src/parser => crates/nu-parser/src}/hir/syntax_shape/flat_shape.rs (95%) rename {src/parser => crates/nu-parser/src}/hir/tokens_iterator.rs (99%) rename {src/parser => crates/nu-parser/src}/hir/tokens_iterator/debug.rs (93%) rename {src/parser => crates/nu-parser/src}/hir/tokens_iterator/debug/color_trace.rs (98%) rename {src/parser => crates/nu-parser/src}/hir/tokens_iterator/debug/expand_trace.rs (98%) rename {src/parser => crates/nu-parser/src}/hir/tokens_iterator/tests.rs (79%) create mode 100644 crates/nu-parser/src/lib.rs rename {src/parser => crates/nu-parser/src}/parse.rs (100%) rename {src/parser => crates/nu-parser/src}/parse/call_node.rs (93%) rename {src/parser => crates/nu-parser/src}/parse/files.rs (100%) rename {src/parser => crates/nu-parser/src}/parse/flag.rs (87%) rename {src/parser => crates/nu-parser/src}/parse/operator.rs (97%) rename {src/parser => crates/nu-parser/src}/parse/parser.rs (96%) rename {src/parser => crates/nu-parser/src}/parse/pipeline.rs (93%) rename {src/parser => crates/nu-parser/src}/parse/token_tree.rs (97%) rename {src/parser => crates/nu-parser/src}/parse/token_tree_builder.rs (96%) rename {src/parser => crates/nu-parser/src}/parse/tokens.rs (95%) rename {src/parser => crates/nu-parser/src}/parse/unit.rs (56%) rename {src/parser => crates/nu-parser/src}/parse/util.rs (100%) rename {src/parser => crates/nu-parser/src}/parse_command.rs (98%) create mode 100644 crates/nu-protocol/Cargo.toml create mode 100644 crates/nu-protocol/src/call_info.rs create mode 100644 crates/nu-protocol/src/lib.rs create mode 100644 crates/nu-protocol/src/macros.rs create mode 100644 crates/nu-protocol/src/maybe_owned.rs rename {src => crates/nu-protocol/src}/plugin.rs (97%) create mode 100644 crates/nu-protocol/src/return_value.rs rename src/parser/registry.rs => crates/nu-protocol/src/signature.rs (55%) create mode 100644 crates/nu-protocol/src/syntax_shape.rs rename src/traits.rs => crates/nu-protocol/src/type_name.rs (90%) create mode 100644 crates/nu-protocol/src/value.rs rename src/parser/hir/path.rs => crates/nu-protocol/src/value/column_path.rs (73%) create mode 100644 crates/nu-protocol/src/value/convert.rs rename {src/data/base => crates/nu-protocol/src/value}/debug.rs (76%) create mode 100644 crates/nu-protocol/src/value/dict.rs create mode 100644 crates/nu-protocol/src/value/evaluate.rs create mode 100644 crates/nu-protocol/src/value/primitive.rs create mode 100644 crates/nu-protocol/src/value/serde_bigdecimal.rs create mode 100644 crates/nu-protocol/src/value/serde_bigint.rs create mode 100644 crates/nu-textview/Cargo.toml rename src/plugins/textview.rs => crates/nu-textview/src/main.rs (97%) delete mode 100644 src/data/into.rs create mode 100644 src/data/primitive.rs create mode 100644 src/data/value.rs rename src/{parser => }/deserializer.rs (97%) create mode 100644 src/evaluate/evaluate_args.rs delete mode 100644 src/parser.rs diff --git a/Cargo.lock b/Cargo.lock index 6241e14498..6ca3438be8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -770,6 +770,14 @@ dependencies = [ "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "erased-serde" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "failure" version = "0.1.6" @@ -972,6 +980,16 @@ dependencies = [ "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ghost" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "git2" version = "0.10.1" @@ -1254,6 +1272,26 @@ dependencies = [ "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "inventory" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "ghost 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "inventory-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "inventory-impl" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "iovec" version = "0.1.4" @@ -1704,6 +1742,9 @@ dependencies = [ "nom 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "nom-tracable 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "nom_locate 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nu-errors 0.1.0", + "nu-parser 0.1.0", + "nu-protocol 0.1.0", "nu-source 0.1.0", "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1715,6 +1756,7 @@ dependencies = [ "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "prettytable-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "ptree 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "query_interface 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "rawkey 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "roxmltree 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1741,12 +1783,92 @@ dependencies = [ "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "trash 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typetag 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "umask 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "which 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nu-errors" +version = "0.1.0" +dependencies = [ + "ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bigdecimal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "language-reporting 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nom 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nom_locate 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nu-source 0.1.0", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", + "subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nu-parser" +version = "0.1.0" +dependencies = [ + "ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bigdecimal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "getset 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "language-reporting 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "nom 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nom-tracable 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nom_locate 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nu-errors 0.1.0", + "nu-protocol 0.1.0", + "nu-source 0.1.0", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ptree 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "shellexpand 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nu-protocol" +version = "0.1.0" +dependencies = [ + "ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bigdecimal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "getset 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "language-reporting 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nom 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nom-tracable 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nom_locate 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nu-errors 0.1.0", + "nu-source 0.1.0", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "query_interface 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", + "subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "typetag 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "nu-source" version = "0.1.0" @@ -1761,6 +1883,19 @@ dependencies = [ "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nu-textview" +version = "0.1.0" +dependencies = [ + "ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossterm 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "nu 0.5.1", + "nu-protocol 0.1.0", + "nu-source 0.1.0", + "syntect 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-bigint" version = "0.2.3" @@ -2083,6 +2218,11 @@ dependencies = [ "tint 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "query_interface" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quick-error" version = "1.2.2" @@ -2852,6 +2992,28 @@ name = "typenum" version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "typetag" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "inventory 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "typetag-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "typetag-impl" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "umask" version = "0.1.8" @@ -3292,6 +3454,7 @@ dependencies = [ "checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" "checksum encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)" = "87240518927716f79692c2ed85bfe6e98196d18c6401ec75355760233a7e12e9" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" +"checksum erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3beee4bc16478a1b26f2e80ad819a52d24745e292f521a63c16eea5f74b7eb60" "checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" "checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" "checksum fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" @@ -3317,6 +3480,7 @@ dependencies = [ "checksum gethostname 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4ab273ca2a31eb6ca40b15837ccf1aa59a43c5db69ac10c542be342fae2e01d" "checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" "checksum getset 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5bb3f5b7d8d70c9bd23cf29b2b38094661418fb0ea79f1b0cc2019a11d6f5429" +"checksum ghost 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a36606a68532b5640dc86bb1f33c64b45c4682aad4c50f3937b317ea387f3d6" "checksum git2 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39f27186fbb5ec67ece9a56990292bc5aed3c3fc51b9b07b0b52446b1dfb4a82" "checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" @@ -3341,6 +3505,8 @@ dependencies = [ "checksum image 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4be8aaefbe7545dc42ae925afb55a0098f226a3fe5ef721872806f44f57826" "checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" "checksum inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" +"checksum inventory 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f4cece20baea71d9f3435e7bbe9adf4765f091c5fe404975f844006964a71299" +"checksum inventory-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2869bf972e998977b1cb87e60df70341d48e48dca0823f534feb91ea44adaf9" "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" "checksum isahc 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "17b77027f12e53ae59a379f7074259d32eb10867e6183388020e922832d9c3fb" "checksum isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e31a8281fc93ec9693494da65fbf28c0c2aa60a2eaec25dc58e2f31952e95edc" @@ -3428,6 +3594,7 @@ dependencies = [ "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" "checksum ptree 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0a3be00b19ee7bd33238c1c523a7ab4df697345f6b36f90827a7860ea938d4" +"checksum query_interface 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "78c0f0046284eebb86b68f93f9677d499034f88e15ca01021ceea32c4d3c3693" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quick-xml 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcdba8c8d71275493d966ef052a88726ac8590c15a09968b32158205c672ef" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" @@ -3514,6 +3681,8 @@ dependencies = [ "checksum trash 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f24d31505f49e989b1ee2c03c323251f6763d5907d471b71192dac92e323f8" "checksum typed-arena 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d" "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +"checksum typetag 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ebb2c484029d695fb68a06d80e1536c68d491b3e0cf874c66abed255e831cfe" +"checksum typetag-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b63fd4799e4d0ec5cf0b055ebb8e2c3a657bbf76a84f6edc77ca60780e000204" "checksum umask 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "d3ec2e5aeb4aadd510db9124513a7fec4a9c3a331b7f57aa519440dab3707067" "checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" diff --git a/Cargo.toml b/Cargo.toml index e81c4fdc40..ecdddda51a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,13 +13,18 @@ documentation = "https://book.nushell.sh" [workspace] -members = ["crates/nu-source"] +members = ["crates/nu-errors", "crates/nu-source", "crates/nu-textview", "crates/nu-protocol", "crates/nu-parser"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] nu-source = { path = "./crates/nu-source" } +nu-protocol = { path = "./crates/nu-protocol" } +nu-errors = { path = "./crates/nu-errors" } +nu-parser = { path = "./crates/nu-parser" } +query_interface = "0.3.5" +typetag = "0.1.4" rustyline = "5.0.4" chrono = { version = "0.4.9", features = ["serde"] } derive-new = "0.5.8" @@ -103,9 +108,8 @@ image = { version = "0.22.2", default_features = false, features = ["png_codec", starship = { version = "0.26.4", optional = true} [features] -default = ["textview", "sys", "ps"] +default = ["sys", "ps"] raw-key = ["rawkey", "neso"] -textview = ["syntect", "onig_sys", "crossterm"] binaryview = ["image", "crossterm"] sys = ["heim", "battery"] ps = ["heim"] @@ -191,11 +195,6 @@ name = "nu_plugin_binaryview" path = "src/plugins/binaryview.rs" required-features = ["binaryview"] -[[bin]] -name = "nu_plugin_textview" -path = "src/plugins/textview.rs" -required-features = ["textview"] - [[bin]] name = "nu_plugin_docker" path = "src/plugins/docker.rs" diff --git a/crates/nu-errors/Cargo.toml b/crates/nu-errors/Cargo.toml new file mode 100644 index 0000000000..4a512200e0 --- /dev/null +++ b/crates/nu-errors/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "nu-errors" +version = "0.1.0" +authors = ["Yehuda Katz "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +nu-source = { path = "../nu-source" } + +ansi_term = "0.12.1" +bigdecimal = { version = "0.1.0", features = ["serde"] } +derive-new = "0.5.8" +language-reporting = "0.4.0" +num-bigint = { version = "0.2.3", features = ["serde"] } +num-traits = "0.2.8" +serde = { version = "1.0.102", features = ["derive"] } +nom = "5.0.1" +nom_locate = "1.0.0" + +# implement conversions +subprocess = "0.1.18" +serde_yaml = "0.8" +toml = "0.5.5" +serde_json = "1.0.41" diff --git a/src/errors.rs b/crates/nu-errors/src/lib.rs similarity index 96% rename from src/errors.rs rename to crates/nu-errors/src/lib.rs index 036240a6a1..a7734bec54 100644 --- a/src/errors.rs +++ b/crates/nu-errors/src/lib.rs @@ -1,9 +1,10 @@ -use crate::prelude::*; - use ansi_term::Color; +use bigdecimal::BigDecimal; use derive_new::new; use language_reporting::{Diagnostic, Label, Severity}; -use nu_source::{Spanned, TracableContext}; +use nu_source::{b, DebugDocBuilder, PrettyDebug, Span, Spanned, SpannedItem, TracableContext}; +use num_bigint::BigInt; +use num_traits::ToPrimitive; use serde::{Deserialize, Serialize}; use std::fmt; use std::ops::Range; @@ -318,7 +319,7 @@ impl ShellError { .start() } - pub(crate) fn unexpected_eof(expected: impl Into, span: impl Into) -> ShellError { + pub fn unexpected_eof(expected: impl Into, span: impl Into) -> ShellError { ProximateShellError::UnexpectedEof { expected: expected.into(), span: span.into(), @@ -326,7 +327,7 @@ impl ShellError { .start() } - pub(crate) fn range_error( + pub fn range_error( expected: impl Into, actual: &Spanned, operation: impl Into, @@ -339,14 +340,14 @@ impl ShellError { .start() } - pub(crate) fn syntax_error(problem: Spanned>) -> ShellError { + pub fn syntax_error(problem: Spanned>) -> ShellError { ProximateShellError::SyntaxError { problem: problem.map(|p| p.into()), } .start() } - pub(crate) fn coerce_error( + pub fn coerce_error( left: Spanned>, right: Spanned>, ) -> ShellError { @@ -357,10 +358,7 @@ impl ShellError { .start() } - pub(crate) fn argument_error( - command: Spanned>, - kind: ArgumentError, - ) -> ShellError { + pub fn argument_error(command: Spanned>, kind: ArgumentError) -> ShellError { ProximateShellError::ArgumentError { command: command.map(|c| c.into()), error: kind, @@ -368,7 +366,7 @@ impl ShellError { .start() } - pub(crate) fn parse_error( + pub fn parse_error( error: nom::Err<( nom_locate::LocatedSpanEx<&str, TracableContext>, nom::error::ErrorKind, @@ -395,11 +393,11 @@ impl ShellError { } } - pub(crate) fn diagnostic(diagnostic: Diagnostic) -> ShellError { + pub fn diagnostic(diagnostic: Diagnostic) -> ShellError { ProximateShellError::Diagnostic(ShellDiagnostic { diagnostic }).start() } - pub(crate) fn to_diagnostic(self) -> Diagnostic { + pub fn to_diagnostic(self) -> Diagnostic { match self.error { ProximateShellError::MissingValue { span, reason } => { let mut d = Diagnostic::new( @@ -579,19 +577,11 @@ impl ShellError { ) } - // pub fn string(title: impl Into) -> ShellError { - // ProximateShellError::String(StringError::new(title.into(), String::new())).start() - // } - // - // pub(crate) fn unreachable(title: impl Into) -> ShellError { - // ShellError::untagged_runtime_error(&format!("BUG: Unreachable: {}", title.into())) - // } - - pub(crate) fn unimplemented(title: impl Into) -> ShellError { + pub fn unimplemented(title: impl Into) -> ShellError { ShellError::untagged_runtime_error(&format!("Unimplemented: {}", title.into())) } - pub(crate) fn unexpected(title: impl Into) -> ShellError { + pub fn unexpected(title: impl Into) -> ShellError { ShellError::untagged_runtime_error(&format!("Unexpected: {}", title.into())) } } diff --git a/crates/nu-parser/Cargo.toml b/crates/nu-parser/Cargo.toml new file mode 100644 index 0000000000..b375df22a9 --- /dev/null +++ b/crates/nu-parser/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "nu-parser" +version = "0.1.0" +authors = ["Yehuda Katz "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +nu-errors = { path = "../nu-errors" } +nu-source = { path = "../nu-source" } +nu-protocol = { path = "../nu-protocol" } + +pretty_env_logger = "0.3.1" +pretty = "0.5.2" +termcolor = "1.0.5" +log = "0.4.8" +indexmap = { version = "1.3.0", features = ["serde-1"] } +serde = { version = "1.0.102", features = ["derive"] } +nom = "5.0.1" +nom_locate = "1.0.0" +nom-tracable = "0.4.1" +num-traits = "0.2.8" +num-bigint = { version = "0.2.3", features = ["serde"] } +bigdecimal = { version = "0.1.0", features = ["serde"] } +derive-new = "0.5.8" +getset = "0.0.9" +cfg-if = "0.1" +itertools = "0.8.1" +shellexpand = "1.0.0" +ansi_term = "0.12.1" +ptree = {version = "0.2" } +language-reporting = "0.4.0" +unicode-xid = "0.2.0" + +[dev-dependencies] +pretty_assertions = "0.6.1" diff --git a/crates/nu-parser/src/commands.rs b/crates/nu-parser/src/commands.rs new file mode 100644 index 0000000000..3e94dd7c2f --- /dev/null +++ b/crates/nu-parser/src/commands.rs @@ -0,0 +1,98 @@ +pub mod classified; + +use crate::commands::classified::ClassifiedCommand; +use crate::hir::expand_external_tokens::ExternalTokensShape; +use crate::hir::syntax_shape::{expand_syntax, ExpandContext}; +use crate::hir::tokens_iterator::TokensIterator; +use nu_errors::ParseError; +use nu_source::{b, DebugDocBuilder, HasSpan, PrettyDebug, Span, Spanned, Tag, Tagged}; + +// Classify this command as an external command, which doesn't give special meaning +// to nu syntactic constructs, and passes all arguments to the external command as +// strings. +pub(crate) fn external_command( + tokens: &mut TokensIterator, + context: &ExpandContext, + name: Tagged<&str>, +) -> Result { + let Spanned { item, span } = expand_syntax(&ExternalTokensShape, tokens, context)?.tokens; + + Ok(ClassifiedCommand::External(ExternalCommand { + name: name.to_string(), + name_tag: name.tag(), + args: ExternalArgs { + list: item + .iter() + .map(|x| ExternalArg { + tag: x.span.into(), + arg: x.item.clone(), + }) + .collect(), + span, + }, + })) +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct ExternalArg { + pub arg: String, + pub tag: Tag, +} + +impl std::ops::Deref for ExternalArg { + type Target = str; + + fn deref(&self) -> &str { + &self.arg + } +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct ExternalArgs { + pub list: Vec, + pub span: Span, +} + +impl ExternalArgs { + pub fn iter(&self) -> impl Iterator { + self.list.iter() + } +} + +impl std::ops::Deref for ExternalArgs { + type Target = [ExternalArg]; + + fn deref(&self) -> &[ExternalArg] { + &self.list + } +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct ExternalCommand { + pub name: String, + + pub name_tag: Tag, + pub args: ExternalArgs, +} + +impl PrettyDebug for ExternalCommand { + fn pretty(&self) -> DebugDocBuilder { + b::typed( + "external command", + b::description(&self.name) + + b::preceded( + b::space(), + b::intersperse( + self.args.iter().map(|a| b::primitive(format!("{}", a.arg))), + b::space(), + ), + ), + ) + } +} + +impl HasSpan for ExternalCommand { + fn span(&self) -> Span { + self.name_tag.span.until(self.args.span) + } +} diff --git a/crates/nu-parser/src/commands/classified.rs b/crates/nu-parser/src/commands/classified.rs new file mode 100644 index 0000000000..3454ce5a75 --- /dev/null +++ b/crates/nu-parser/src/commands/classified.rs @@ -0,0 +1,112 @@ +use crate::commands::ExternalCommand; +use crate::hir; +use crate::parse::token_tree::TokenNode; +use derive_new::new; +use nu_source::{b, DebugDocBuilder, HasSpan, PrettyDebugWithSource, Span, Tag}; + +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum ClassifiedCommand { + #[allow(unused)] + Expr(TokenNode), + #[allow(unused)] + Dynamic(hir::Call), + Internal(InternalCommand), + External(ExternalCommand), +} + +impl PrettyDebugWithSource for ClassifiedCommand { + fn pretty_debug(&self, source: &str) -> DebugDocBuilder { + match self { + ClassifiedCommand::Expr(token) => b::typed("command", token.pretty_debug(source)), + ClassifiedCommand::Dynamic(call) => b::typed("command", call.pretty_debug(source)), + ClassifiedCommand::Internal(internal) => internal.pretty_debug(source), + ClassifiedCommand::External(external) => external.pretty_debug(source), + } + } +} + +impl HasSpan for ClassifiedCommand { + fn span(&self) -> Span { + match self { + ClassifiedCommand::Expr(node) => node.span(), + ClassifiedCommand::Internal(command) => command.span(), + ClassifiedCommand::Dynamic(call) => call.span, + ClassifiedCommand::External(command) => command.span(), + } + } +} + +#[derive(new, Debug, Clone, Eq, PartialEq)] +pub struct InternalCommand { + pub name: String, + pub name_tag: Tag, + pub args: hir::Call, +} + +impl PrettyDebugWithSource for InternalCommand { + fn pretty_debug(&self, source: &str) -> DebugDocBuilder { + b::typed( + "internal command", + b::description(&self.name) + b::space() + self.args.pretty_debug(source), + ) + } +} + +impl HasSpan for InternalCommand { + fn span(&self) -> Span { + let start = self.name_tag.span; + + start.until(self.args.span) + } +} + +#[derive(new, Debug, Eq, PartialEq)] +pub(crate) struct DynamicCommand { + pub(crate) args: hir::Call, +} + +#[derive(Debug, Clone)] +pub struct Commands { + pub list: Vec, + pub span: Span, +} + +impl std::ops::Deref for Commands { + type Target = [ClassifiedCommand]; + + fn deref(&self) -> &Self::Target { + &self.list + } +} + +#[derive(Debug, Clone)] +pub struct ClassifiedPipeline { + pub commands: Commands, +} + +impl ClassifiedPipeline { + pub fn commands(list: Vec, span: impl Into) -> ClassifiedPipeline { + ClassifiedPipeline { + commands: Commands { + list, + span: span.into(), + }, + } + } +} + +impl HasSpan for ClassifiedPipeline { + fn span(&self) -> Span { + self.commands.span + } +} + +impl PrettyDebugWithSource for ClassifiedPipeline { + fn pretty_debug(&self, source: &str) -> DebugDocBuilder { + b::intersperse( + self.commands.iter().map(|c| c.pretty_debug(source)), + b::operator(" | "), + ) + .or(b::delimit("<", b::description("empty pipeline"), ">")) + } +} diff --git a/src/parser/debug.rs b/crates/nu-parser/src/debug.rs similarity index 100% rename from src/parser/debug.rs rename to crates/nu-parser/src/debug.rs diff --git a/src/parser/hir.rs b/crates/nu-parser/src/hir.rs similarity index 84% rename from src/parser/hir.rs rename to crates/nu-parser/src/hir.rs index d5ec134f6a..b4c15e2905 100644 --- a/src/parser/hir.rs +++ b/crates/nu-parser/src/hir.rs @@ -4,30 +4,37 @@ pub(crate) mod expand_external_tokens; pub(crate) mod external_command; pub(crate) mod named; pub(crate) mod path; -pub(crate) mod syntax_shape; +pub mod syntax_shape; pub(crate) mod tokens_iterator; -use crate::parser::hir::path::PathMember; -use crate::parser::hir::syntax_shape::Member; -use crate::parser::{registry, Operator, Unit}; -use crate::prelude::*; +use crate::hir::syntax_shape::Member; +use crate::parse::operator::Operator; +use crate::parse::parser::Number; +use crate::parse::unit::Unit; use derive_new::new; use getset::Getters; -use nu_source::Spanned; +#[cfg(not(coloring_in_tokens))] +use nu_errors::ShellError; +#[cfg(not(coloring_in_tokens))] +use nu_protocol::{EvaluatedArgs, Scope}; +use nu_protocol::{PathMember, ShellTypeName}; +#[cfg(not(coloring_in_tokens))] +use nu_source::Text; +use nu_source::{ + b, DebugDocBuilder, HasSpan, PrettyDebug, PrettyDebugWithSource, Span, Spanned, SpannedItem, +}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; -use crate::evaluate::Scope; -use crate::parser::parse::tokens::RawNumber; +use crate::parse::tokens::RawNumber; pub(crate) use self::binary::Binary; -pub(crate) use self::external_command::ExternalCommand; -pub(crate) use self::named::NamedArguments; pub(crate) use self::path::Path; pub(crate) use self::syntax_shape::ExpandContext; pub(crate) use self::tokens_iterator::TokensIterator; -pub use self::syntax_shape::SyntaxShape; +pub use self::external_command::ExternalCommand; +pub use self::named::{NamedArguments, NamedValue}; #[derive(Debug, Clone, Eq, PartialEq, Getters, Serialize, Deserialize, new)] pub struct Call { @@ -60,17 +67,6 @@ impl PrettyDebugWithSource for Call { } } -impl Call { - pub fn evaluate( - &self, - registry: ®istry::CommandRegistry, - scope: &Scope, - source: &Text, - ) -> Result { - registry::evaluate_args(self, registry, scope, source) - } -} - #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] pub enum RawExpression { Literal(Literal), @@ -196,41 +192,37 @@ impl PrettyDebugWithSource for Expression { } impl Expression { - pub(crate) fn number(i: impl Into, span: impl Into) -> Expression { + pub fn number(i: impl Into, span: impl Into) -> Expression { let span = span.into(); RawExpression::Literal(RawLiteral::Number(i.into()).into_literal(span)).into_expr(span) } - pub(crate) fn size( - i: impl Into, - unit: impl Into, - span: impl Into, - ) -> Expression { + pub fn size(i: impl Into, unit: impl Into, span: impl Into) -> Expression { let span = span.into(); RawExpression::Literal(RawLiteral::Size(i.into(), unit.into()).into_literal(span)) .into_expr(span) } - pub(crate) fn synthetic_string(s: impl Into) -> Expression { + pub fn synthetic_string(s: impl Into) -> Expression { RawExpression::Synthetic(Synthetic::String(s.into())).into_unspanned_expr() } - pub(crate) fn string(inner: impl Into, outer: impl Into) -> Expression { + pub fn string(inner: impl Into, outer: impl Into) -> Expression { let outer = outer.into(); RawExpression::Literal(RawLiteral::String(inner.into()).into_literal(outer)) .into_expr(outer) } - pub(crate) fn column_path(members: Vec, span: impl Into) -> Expression { + pub fn column_path(members: Vec, span: impl Into) -> Expression { let span = span.into(); RawExpression::Literal(RawLiteral::ColumnPath(members).into_literal(span)).into_expr(span) } - pub(crate) fn path( + pub fn path( head: Expression, tail: Vec>, span: impl Into, @@ -239,7 +231,7 @@ impl Expression { RawExpression::Path(Box::new(Path::new(head, tail))).into_expr(span.into()) } - pub(crate) fn dot_member(head: Expression, next: impl Into) -> Expression { + pub fn dot_member(head: Expression, next: impl Into) -> Expression { let Expression { expr: item, span } = head; let next = next.into(); @@ -257,7 +249,7 @@ impl Expression { } } - pub(crate) fn infix( + pub fn infix( left: Expression, op: Spanned>, right: Expression, @@ -268,36 +260,36 @@ impl Expression { .into_expr(new_span) } - pub(crate) fn file_path(path: impl Into, outer: impl Into) -> Expression { + pub fn file_path(path: impl Into, outer: impl Into) -> Expression { RawExpression::FilePath(path.into()).into_expr(outer) } - pub(crate) fn list(list: Vec, span: impl Into) -> Expression { + pub fn list(list: Vec, span: impl Into) -> Expression { RawExpression::List(list).into_expr(span) } - pub(crate) fn bare(span: impl Into) -> Expression { + pub fn bare(span: impl Into) -> Expression { let span = span.into(); RawExpression::Literal(RawLiteral::Bare.into_literal(span)).into_expr(span) } - pub(crate) fn pattern(inner: impl Into, outer: impl Into) -> Expression { + pub fn pattern(inner: impl Into, outer: impl Into) -> Expression { let outer = outer.into(); RawExpression::Literal(RawLiteral::GlobPattern(inner.into()).into_literal(outer)) .into_expr(outer) } - pub(crate) fn variable(inner: impl Into, outer: impl Into) -> Expression { + pub fn variable(inner: impl Into, outer: impl Into) -> Expression { RawExpression::Variable(Variable::Other(inner.into())).into_expr(outer) } - pub(crate) fn external_command(inner: impl Into, outer: impl Into) -> Expression { + pub fn external_command(inner: impl Into, outer: impl Into) -> Expression { RawExpression::ExternalCommand(ExternalCommand::new(inner.into())).into_expr(outer) } - pub(crate) fn it_variable(inner: impl Into, outer: impl Into) -> Expression { + pub fn it_variable(inner: impl Into, outer: impl Into) -> Expression { RawExpression::Variable(Variable::It(inner.into())).into_expr(outer) } } diff --git a/src/parser/hir/baseline_parse.rs b/crates/nu-parser/src/hir/baseline_parse.rs similarity index 100% rename from src/parser/hir/baseline_parse.rs rename to crates/nu-parser/src/hir/baseline_parse.rs diff --git a/src/parser/hir/baseline_parse/tests.rs b/crates/nu-parser/src/hir/baseline_parse/tests.rs similarity index 62% rename from src/parser/hir/baseline_parse/tests.rs rename to crates/nu-parser/src/hir/baseline_parse/tests.rs index 16120a5507..216be656b8 100644 --- a/src/parser/hir/baseline_parse/tests.rs +++ b/crates/nu-parser/src/hir/baseline_parse/tests.rs @@ -1,13 +1,13 @@ -use crate::commands::classified::InternalCommand; -use crate::commands::ClassifiedCommand; -use crate::env::host::BasicHost; -use crate::parser::hir::TokensIterator; -use crate::parser::hir::{ - self, named::NamedValue, path::PathMember, syntax_shape::*, NamedArguments, -}; -use crate::parser::parse::token_tree_builder::{CurriedToken, TokenTreeBuilder as b}; -use crate::parser::TokenNode; +use crate::commands::classified::{ClassifiedCommand, InternalCommand}; +use crate::hir::TokensIterator; +use crate::hir::{self, named::NamedValue, syntax_shape::*, NamedArguments}; +use crate::parse::files::Files; +use crate::parse::token_tree_builder::{CurriedToken, TokenTreeBuilder as b}; +use crate::TokenNode; +use derive_new::new; use indexmap::IndexMap; +use nu_errors::ShellError; +use nu_protocol::{PathMember, Signature, SyntaxShape}; use nu_source::{HasSpan, Span, Tag, Text}; use pretty_assertions::assert_eq; use std::fmt::Debug; @@ -90,6 +90,43 @@ fn test_parse_command() { ); } +#[derive(new)] +struct TestRegistry { + #[new(default)] + signatures: indexmap::IndexMap, +} + +impl TestRegistry { + fn insert(&mut self, key: &str, value: Signature) { + self.signatures.insert(key.to_string(), value); + } +} + +impl SignatureRegistry for TestRegistry { + fn has(&self, name: &str) -> bool { + self.signatures.contains_key(name) + } + fn get(&self, name: &str) -> Option { + self.signatures.get(name).map(|sig| sig.clone()) + } +} + +fn with_empty_context(source: &Text, callback: impl FnOnce(ExpandContext)) { + let mut registry = TestRegistry::new(); + registry.insert( + "ls", + Signature::build("ls") + .optional( + "path", + SyntaxShape::Pattern, + "a path to get the directory contents from", + ) + .switch("full", "list all available columns for each entry"), + ); + + callback(ExpandContext::new(Box::new(registry), source, None)) +} + fn parse_tokens( shape: impl ExpandSyntax, tokens: Vec, @@ -99,7 +136,7 @@ fn parse_tokens( let (tokens, source) = b::build(tokens); let text = Text::from(source); - ExpandContext::with_empty(&text, |context| { + with_empty_context(&text, |context| { let tokens = tokens.expect_list(); let mut iterator = TokensIterator::all(tokens.item, text.clone(), tokens.span); @@ -108,7 +145,7 @@ fn parse_tokens( let expr = match expr { Ok(expr) => expr, Err(err) => { - crate::cli::print_err(err.into(), &BasicHost, context.source().clone()); + print_err(err.into(), context.source().clone()); panic!("Parse failed"); } }; @@ -120,3 +157,20 @@ fn parse_tokens( fn inner_string_span(span: Span) -> Span { Span::new(span.start() + 1, span.end() - 1) } + +pub fn print_err(err: ShellError, source: &Text) { + let diag = err.to_diagnostic(); + + let writer = termcolor::StandardStream::stderr(termcolor::ColorChoice::Auto); + let mut source = source.to_string(); + source.push_str(" "); + let files = Files::new(source); + let _ = std::panic::catch_unwind(move || { + let _ = language_reporting::emit( + &mut writer.lock(), + &files, + &diag, + &language_reporting::DefaultConfig, + ); + }); +} diff --git a/src/parser/hir/binary.rs b/crates/nu-parser/src/hir/binary.rs similarity index 84% rename from src/parser/hir/binary.rs rename to crates/nu-parser/src/hir/binary.rs index 4a119cb4f1..47148fa6d8 100644 --- a/src/parser/hir/binary.rs +++ b/crates/nu-parser/src/hir/binary.rs @@ -1,15 +1,14 @@ -use crate::parser::{hir::Expression, Operator}; -use crate::prelude::*; +use crate::{hir::Expression, Operator}; use derive_new::new; use getset::Getters; -use nu_source::Spanned; +use nu_source::{b, DebugDocBuilder, PrettyDebugWithSource, Spanned}; use serde::{Deserialize, Serialize}; #[derive( Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Getters, Serialize, Deserialize, new, )] -#[get = "pub(crate)"] +#[get = "pub"] pub struct Binary { left: Expression, op: Spanned, diff --git a/src/parser/hir/expand_external_tokens.rs b/crates/nu-parser/src/hir/expand_external_tokens.rs similarity index 99% rename from src/parser/hir/expand_external_tokens.rs rename to crates/nu-parser/src/hir/expand_external_tokens.rs index c0c3d8eaa7..99232bd9c6 100644 --- a/src/parser/hir/expand_external_tokens.rs +++ b/crates/nu-parser/src/hir/expand_external_tokens.rs @@ -1,7 +1,6 @@ -use crate::errors::ParseError; #[cfg(not(coloring_in_tokens))] -use crate::parser::hir::syntax_shape::FlatShape; -use crate::parser::{ +use crate::hir::syntax_shape::FlatShape; +use crate::{ hir::syntax_shape::{ color_syntax, expand_atom, expand_expr, expand_syntax, AtomicToken, ColorSyntax, ExpandContext, ExpandExpression, ExpandSyntax, ExpansionRule, MaybeSpaceShape, @@ -10,6 +9,7 @@ use crate::parser::{ hir::Expression, TokensIterator, }; +use nu_errors::ParseError; use nu_source::{b, DebugDocBuilder, HasSpan, PrettyDebug, Span, Spanned, SpannedItem}; #[derive(Debug, Clone)] diff --git a/src/parser/hir/external_command.rs b/crates/nu-parser/src/hir/external_command.rs similarity index 84% rename from src/parser/hir/external_command.rs rename to crates/nu-parser/src/hir/external_command.rs index 7174a12a73..a07257d063 100644 --- a/src/parser/hir/external_command.rs +++ b/crates/nu-parser/src/hir/external_command.rs @@ -1,12 +1,12 @@ -use crate::prelude::*; use derive_new::new; use getset::Getters; +use nu_source::Span; use serde::{Deserialize, Serialize}; #[derive( Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Getters, Serialize, Deserialize, new, )] -#[get = "pub(crate)"] +#[get = "pub"] pub struct ExternalCommand { pub(crate) name: Span, } diff --git a/src/parser/hir/named.rs b/crates/nu-parser/src/hir/named.rs similarity index 89% rename from src/parser/hir/named.rs rename to crates/nu-parser/src/hir/named.rs index 09e12e8723..a30fdac7ea 100644 --- a/src/parser/hir/named.rs +++ b/crates/nu-parser/src/hir/named.rs @@ -1,8 +1,8 @@ -use crate::parser::hir::Expression; -use crate::parser::Flag; -use crate::prelude::*; +use crate::hir::Expression; +use crate::Flag; use indexmap::IndexMap; use log::trace; +use nu_source::{b, DebugDocBuilder, PrettyDebugWithSource, Tag}; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] @@ -26,7 +26,7 @@ impl PrettyDebugWithSource for NamedValue { #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] pub struct NamedArguments { - pub(crate) named: IndexMap, + pub named: IndexMap, } impl NamedArguments { @@ -35,6 +35,10 @@ impl NamedArguments { named: IndexMap::new(), } } + + pub fn iter(&self) -> impl Iterator { + self.named.iter() + } } impl NamedArguments { diff --git a/crates/nu-parser/src/hir/path.rs b/crates/nu-parser/src/hir/path.rs new file mode 100644 index 0000000000..7930e0fb77 --- /dev/null +++ b/crates/nu-parser/src/hir/path.rs @@ -0,0 +1,41 @@ +use crate::hir::Expression; +use derive_new::new; +use getset::{Getters, MutGetters}; +use nu_protocol::PathMember; +use nu_source::{b, DebugDocBuilder, PrettyDebug, PrettyDebugWithSource}; +use serde::{Deserialize, Serialize}; + +#[derive( + Debug, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Hash, + Getters, + MutGetters, + Serialize, + Deserialize, + new, +)] +#[get = "pub"] +pub struct Path { + head: Expression, + #[get_mut = "pub(crate)"] + tail: Vec, +} + +impl PrettyDebugWithSource for Path { + fn pretty_debug(&self, source: &str) -> DebugDocBuilder { + self.head.pretty_debug(source) + + b::operator(".") + + b::intersperse(self.tail.iter().map(|m| m.pretty()), b::operator(".")) + } +} + +impl Path { + pub(crate) fn parts(self) -> (Expression, Vec) { + (self.head, self.tail) + } +} diff --git a/src/parser/hir/syntax_shape.rs b/crates/nu-parser/src/hir/syntax_shape.rs similarity index 94% rename from src/parser/hir/syntax_shape.rs rename to crates/nu-parser/src/hir/syntax_shape.rs index 8d78c87160..98483eb1ad 100644 --- a/src/parser/hir/syntax_shape.rs +++ b/crates/nu-parser/src/hir/syntax_shape.rs @@ -1,23 +1,25 @@ mod block; mod expression; -pub(crate) mod flat_shape; +pub mod flat_shape; -use crate::cli::external_command; -use crate::commands::{ - classified::{ClassifiedPipeline, InternalCommand}, - ClassifiedCommand, Command, -}; -use crate::parser::hir::expand_external_tokens::ExternalTokensShape; -use crate::parser::hir::syntax_shape::block::AnyBlockShape; -use crate::parser::hir::tokens_iterator::Peeked; -use crate::parser::parse::tokens::Token; -use crate::parser::parse_command::{parse_command_tail, CommandTailShape}; -use crate::parser::{hir, hir::TokensIterator, Operator, TokenNode, UnspannedToken}; -use crate::prelude::*; +use crate::commands::classified::{ClassifiedCommand, ClassifiedPipeline, InternalCommand}; +use crate::commands::external_command; +use crate::hir; +use crate::hir::expand_external_tokens::ExternalTokensShape; +use crate::hir::syntax_shape::block::AnyBlockShape; +use crate::hir::tokens_iterator::{Peeked, TokensIterator}; +use crate::parse::operator::Operator; +use crate::parse::token_tree::TokenNode; +use crate::parse::tokens::{Token, UnspannedToken}; +use crate::parse_command::{parse_command_tail, CommandTailShape}; use derive_new::new; use getset::Getters; -use nu_source::Spanned; -use serde::{Deserialize, Serialize}; +use nu_errors::{ParseError, ShellError}; +use nu_protocol::{ShellTypeName, Signature}; +use nu_source::{ + b, DebugDocBuilder, HasFallibleSpan, HasSpan, PrettyDebug, PrettyDebugWithSource, Span, + Spanned, SpannedItem, Tag, TaggedItem, Text, +}; use std::path::{Path, PathBuf}; pub(crate) use self::expression::atom::{ @@ -41,40 +43,12 @@ pub(crate) use self::expression::{continue_expression, AnyExpressionShape}; pub(crate) use self::flat_shape::FlatShape; #[cfg(not(coloring_in_tokens))] -use crate::parser::hir::tokens_iterator::debug::debug_tokens; +use crate::hir::tokens_iterator::debug::debug_tokens; #[cfg(not(coloring_in_tokens))] -use crate::parser::parse::pipeline::Pipeline; +use crate::parse::pipeline::Pipeline; #[cfg(not(coloring_in_tokens))] use log::{log_enabled, trace}; - -#[derive(Debug, Copy, Clone, Serialize, Deserialize)] -pub enum SyntaxShape { - Any, - String, - Member, - ColumnPath, - Number, - Int, - Path, - Pattern, - Block, -} - -impl PrettyDebug for SyntaxShape { - fn pretty(&self) -> DebugDocBuilder { - b::kind(match self { - SyntaxShape::Any => "any shape", - SyntaxShape::String => "string shape", - SyntaxShape::Member => "member shape", - SyntaxShape::ColumnPath => "column path shape", - SyntaxShape::Number => "number shape", - SyntaxShape::Int => "integer shape", - SyntaxShape::Path => "file path shape", - SyntaxShape::Pattern => "pattern shape", - SyntaxShape::Block => "block shape", - }) - } -} +use nu_protocol::SyntaxShape; #[cfg(not(coloring_in_tokens))] impl FallibleColorSyntax for SyntaxShape { @@ -200,10 +174,15 @@ impl ExpandExpression for SyntaxShape { } } +pub trait SignatureRegistry { + fn has(&self, name: &str) -> bool; + fn get(&self, name: &str) -> Option; +} + #[derive(Getters, new)] pub struct ExpandContext<'context> { #[get = "pub(crate)"] - registry: &'context CommandRegistry, + registry: Box, #[get = "pub(crate)"] source: &'context Text, homedir: Option, @@ -213,21 +192,6 @@ impl<'context> ExpandContext<'context> { pub(crate) fn homedir(&self) -> Option<&Path> { self.homedir.as_ref().map(|h| h.as_path()) } - - #[cfg(test)] - pub fn with_empty(source: &Text, callback: impl FnOnce(ExpandContext)) { - let mut registry = CommandRegistry::new(); - registry.insert( - "ls", - crate::commands::whole_stream_command(crate::commands::LS), - ); - - callback(ExpandContext { - registry: ®istry, - source, - homedir: None, - }) - } } pub trait TestSyntax: std::fmt::Debug + Copy { @@ -306,7 +270,7 @@ pub trait ColorSyntax: std::fmt::Debug + Copy { ) -> Self::Info; } -pub(crate) trait ExpandSyntax: std::fmt::Debug + Copy { +pub trait ExpandSyntax: std::fmt::Debug + Copy { type Output: HasFallibleSpan + Clone + std::fmt::Debug + 'static; fn name(&self) -> &'static str; @@ -318,7 +282,7 @@ pub(crate) trait ExpandSyntax: std::fmt::Debug + Copy { ) -> Result; } -pub(crate) fn expand_syntax<'a, 'b, T: ExpandSyntax>( +pub fn expand_syntax<'a, 'b, T: ExpandSyntax>( shape: &T, token_nodes: &'b mut TokensIterator<'a>, context: &ExpandContext, @@ -747,7 +711,7 @@ impl TestSyntax for BareShape { #[derive(Debug, Clone)] pub enum CommandSignature { - Internal(Spanned>), + Internal(Spanned), LiteralExternal { outer: Span, inner: Span }, External(Span), Expression(hir::Expression), @@ -757,7 +721,7 @@ impl PrettyDebugWithSource for CommandSignature { fn pretty_debug(&self, source: &str) -> DebugDocBuilder { match self { CommandSignature::Internal(internal) => { - b::typed("command", b::description(internal.name())) + b::typed("command", b::description(&internal.name)) } CommandSignature::LiteralExternal { outer, .. } => { b::typed("command", b::description(outer.slice(source))) @@ -1003,8 +967,8 @@ impl FallibleColorSyntax for CommandHeadShape { if context.registry.has(name) { // If the registry has the command, color it as an internal command shapes.push(FlatShape::InternalCommand.spanned(text)); - let command = context.registry.expect_command(name); - Ok(CommandHeadKind::Internal(command.signature())) + let signature = context.registry.get(name).unwrap(); + Ok(CommandHeadKind::Internal(signature)) } else { // Otherwise, color it as an external command shapes.push(FlatShape::ExternalCommand.spanned(text)); @@ -1060,8 +1024,8 @@ impl FallibleColorSyntax for CommandHeadShape { if context.registry.has(name) { // If the registry has the command, color it as an internal command token_nodes.color_shape(FlatShape::InternalCommand.spanned(text)); - let command = context.registry.expect_command(name); - Ok(CommandHeadKind::Internal(command.signature())) + let signature = context.registry.get(name).unwrap(); + Ok(CommandHeadKind::Internal(signature)) } else { // Otherwise, color it as an external command token_nodes.color_shape(FlatShape::ExternalCommand.spanned(text)); @@ -1100,8 +1064,8 @@ impl ExpandSyntax for CommandHeadShape { UnspannedToken::Bare => { let name = token_span.slice(context.source); if context.registry.has(name) { - let command = context.registry.expect_command(name); - CommandSignature::Internal(command.spanned(token_span)) + let signature = context.registry.get(name).unwrap(); + CommandSignature::Internal(signature.spanned(token_span)) } else { CommandSignature::External(token_span) } @@ -1162,9 +1126,8 @@ impl ExpandSyntax for ClassifiedCommandShape { external_command(iterator, context, name_str.tagged(outer)) } - CommandSignature::Internal(command) => { - let tail = - parse_command_tail(&command.signature(), &context, iterator, command.span)?; + CommandSignature::Internal(signature) => { + let tail = parse_command_tail(&signature.item, &context, iterator, signature.span)?; let (positional, named) = match tail { None => (None, None), @@ -1181,9 +1144,9 @@ impl ExpandSyntax for ClassifiedCommandShape { }; Ok(ClassifiedCommand::Internal(InternalCommand::new( - command.item.name().to_string(), + signature.item.name.clone(), Tag { - span: command.span, + span: signature.span, anchor: None, }, call, diff --git a/src/parser/hir/syntax_shape/block.rs b/crates/nu-parser/src/hir/syntax_shape/block.rs similarity index 98% rename from src/parser/hir/syntax_shape/block.rs rename to crates/nu-parser/src/hir/syntax_shape/block.rs index 927133ebad..4a8f0aa9ac 100644 --- a/src/parser/hir/syntax_shape/block.rs +++ b/crates/nu-parser/src/hir/syntax_shape/block.rs @@ -1,17 +1,17 @@ -use crate::errors::ShellError; #[cfg(not(coloring_in_tokens))] -use crate::parser::hir::syntax_shape::FlatShape; -use crate::parser::{ +use crate::hir::syntax_shape::FlatShape; +use crate::{ hir, hir::syntax_shape::{ color_fallible_syntax, color_syntax_with, continue_expression, expand_expr, expand_syntax, DelimitedShape, ExpandContext, ExpandExpression, ExpressionContinuationShape, - ExpressionListShape, FallibleColorSyntax, MemberShape, ParseError, PathTailShape, - PathTailSyntax, VariablePathShape, + ExpressionListShape, FallibleColorSyntax, MemberShape, PathTailShape, PathTailSyntax, + VariablePathShape, }, hir::tokens_iterator::TokensIterator, parse::token_tree::Delimiter, }; +use nu_errors::{ParseError, ShellError}; use nu_source::Span; #[cfg(not(coloring_in_tokens))] use nu_source::Spanned; @@ -388,8 +388,8 @@ impl FallibleColorSyntax for ShorthandHeadShape { _context: &ExpandContext, shapes: &mut Vec>, ) -> Result<(), ShellError> { - use crate::parser::parse::token_tree::TokenNode; - use crate::parser::parse::tokens::{Token, UnspannedToken}; + use crate::parse::token_tree::TokenNode; + use crate::parse::tokens::{Token, UnspannedToken}; use nu_source::SpannedItem; // A shorthand path must not be at EOF diff --git a/src/parser/hir/syntax_shape/expression.rs b/crates/nu-parser/src/hir/syntax_shape/expression.rs similarity index 98% rename from src/parser/hir/syntax_shape/expression.rs rename to crates/nu-parser/src/hir/syntax_shape/expression.rs index 65760e6e65..4c7dfd3db6 100644 --- a/src/parser/hir/syntax_shape/expression.rs +++ b/crates/nu-parser/src/hir/syntax_shape/expression.rs @@ -8,18 +8,18 @@ pub(crate) mod string; pub(crate) mod unit; pub(crate) mod variable_path; -use crate::parser::hir::syntax_shape::{ +use crate::hir::syntax_shape::{ color_delimited_square, color_fallible_syntax, color_fallible_syntax_with, expand_atom, expand_delimited_square, expand_expr, expand_syntax, BareShape, ColorableDotShape, DotShape, ExpandContext, ExpandExpression, ExpandSyntax, ExpansionRule, ExpressionContinuation, - ExpressionContinuationShape, FallibleColorSyntax, FlatShape, ParseError, UnspannedAtomicToken, + ExpressionContinuationShape, FallibleColorSyntax, FlatShape, UnspannedAtomicToken, }; -use crate::parser::{ +use crate::{ hir, hir::{Expression, TokensIterator}, }; -use crate::prelude::*; -use nu_source::Spanned; +use nu_errors::{ParseError, ShellError}; +use nu_source::{HasSpan, Span, Spanned, SpannedItem, Tag}; use std::path::PathBuf; #[derive(Debug, Copy, Clone)] diff --git a/src/parser/hir/syntax_shape/expression/atom.rs b/crates/nu-parser/src/hir/syntax_shape/expression/atom.rs similarity index 98% rename from src/parser/hir/syntax_shape/expression/atom.rs rename to crates/nu-parser/src/hir/syntax_shape/expression/atom.rs index 76b264b1ed..6fe8a992ac 100644 --- a/src/parser/hir/syntax_shape/expression/atom.rs +++ b/crates/nu-parser/src/hir/syntax_shape/expression/atom.rs @@ -1,15 +1,19 @@ -use crate::parser::hir::syntax_shape::{ +use crate::hir::syntax_shape::FlatShape; +use crate::hir::syntax_shape::{ expand_syntax, expression::expand_file_path, parse_single_node, BarePathShape, BarePatternShape, ExpandContext, UnitShape, UnitSyntax, }; -use crate::parser::{ +use crate::parse::token_tree::{DelimitedNode, Delimiter, TokenNode}; +use crate::parse::tokens::UnspannedToken; +use crate::parse::unit::Unit; +use crate::{ hir, hir::{Expression, RawNumber, TokensIterator}, parse::flag::{Flag, FlagKind}, - DelimitedNode, Delimiter, FlatShape, TokenNode, Unit, UnspannedToken, }; -use crate::prelude::*; -use nu_source::Spanned; +use nu_errors::{ParseError, ShellError}; +use nu_protocol::ShellTypeName; +use nu_source::{b, DebugDocBuilder, HasSpan, PrettyDebugWithSource, Span, Spanned, SpannedItem}; use std::ops::Deref; #[derive(Debug, Clone)] diff --git a/src/parser/hir/syntax_shape/expression/delimited.rs b/crates/nu-parser/src/hir/syntax_shape/expression/delimited.rs similarity index 94% rename from src/parser/hir/syntax_shape/expression/delimited.rs rename to crates/nu-parser/src/hir/syntax_shape/expression/delimited.rs index e92c179bd9..4d84e521e9 100644 --- a/src/parser/hir/syntax_shape/expression/delimited.rs +++ b/crates/nu-parser/src/hir/syntax_shape/expression/delimited.rs @@ -1,10 +1,11 @@ -use crate::parser::hir::syntax_shape::{ +use crate::hir::syntax_shape::{ color_syntax, expand_syntax, ColorSyntax, ExpandContext, ExpressionListShape, TokenNode, }; -use crate::parser::{hir, hir::TokensIterator, Delimiter, FlatShape}; -use crate::prelude::*; +use crate::{hir, hir::TokensIterator, Delimiter, FlatShape}; +use nu_errors::ParseError; #[cfg(not(coloring_in_tokens))] use nu_source::Spanned; +use nu_source::{Span, SpannedItem, Tag}; pub fn expand_delimited_square( children: &Vec, diff --git a/src/parser/hir/syntax_shape/expression/file_path.rs b/crates/nu-parser/src/hir/syntax_shape/expression/file_path.rs similarity index 94% rename from src/parser/hir/syntax_shape/expression/file_path.rs rename to crates/nu-parser/src/hir/syntax_shape/expression/file_path.rs index 337d2240ce..0fca4a6c2c 100644 --- a/src/parser/hir/syntax_shape/expression/file_path.rs +++ b/crates/nu-parser/src/hir/syntax_shape/expression/file_path.rs @@ -1,12 +1,12 @@ -use crate::parser::hir::syntax_shape::expression::atom::{ +use crate::hir::syntax_shape::expression::atom::{ expand_atom, ExpansionRule, UnspannedAtomicToken, }; -use crate::parser::hir::syntax_shape::{ +use crate::hir::syntax_shape::{ expression::expand_file_path, ExpandContext, ExpandExpression, FallibleColorSyntax, FlatShape, - ParseError, }; -use crate::parser::{hir, hir::TokensIterator}; -use crate::prelude::*; +use crate::{hir, hir::TokensIterator}; +use nu_errors::{ParseError, ShellError}; +use nu_source::SpannedItem; #[derive(Debug, Copy, Clone)] pub struct FilePathShape; diff --git a/src/parser/hir/syntax_shape/expression/list.rs b/crates/nu-parser/src/hir/syntax_shape/expression/list.rs similarity index 99% rename from src/parser/hir/syntax_shape/expression/list.rs rename to crates/nu-parser/src/hir/syntax_shape/expression/list.rs index 88c6f6e62f..d7066027a2 100644 --- a/src/parser/hir/syntax_shape/expression/list.rs +++ b/crates/nu-parser/src/hir/syntax_shape/expression/list.rs @@ -1,7 +1,6 @@ -use crate::errors::ParseError; #[cfg(not(coloring_in_tokens))] -use crate::parser::hir::syntax_shape::FlatShape; -use crate::parser::{ +use crate::hir::syntax_shape::FlatShape; +use crate::{ hir, hir::syntax_shape::{ color_fallible_syntax, color_syntax, expand_atom, expand_expr, maybe_spaced, spaced, @@ -10,6 +9,7 @@ use crate::parser::{ }, hir::TokensIterator, }; +use nu_errors::ParseError; use nu_source::{b, DebugDocBuilder, HasSpan, PrettyDebugWithSource, Span, Spanned, SpannedItem}; #[derive(Debug, Clone)] diff --git a/src/parser/hir/syntax_shape/expression/number.rs b/crates/nu-parser/src/hir/syntax_shape/expression/number.rs similarity index 96% rename from src/parser/hir/syntax_shape/expression/number.rs rename to crates/nu-parser/src/hir/syntax_shape/expression/number.rs index c4fce3a36a..ed95439ce2 100644 --- a/src/parser/hir/syntax_shape/expression/number.rs +++ b/crates/nu-parser/src/hir/syntax_shape/expression/number.rs @@ -1,15 +1,15 @@ -use crate::parser::hir::syntax_shape::{ +use crate::hir::syntax_shape::{ expand_atom, parse_single_node, ExpandContext, ExpandExpression, ExpansionRule, - FallibleColorSyntax, FlatShape, ParseError, TestSyntax, + FallibleColorSyntax, FlatShape, TestSyntax, }; -use crate::parser::hir::tokens_iterator::Peeked; -use crate::parser::{ +use crate::hir::tokens_iterator::Peeked; +use crate::parse::tokens::UnspannedToken; +use crate::{ hir, hir::{RawNumber, TokensIterator}, - UnspannedToken, }; -use crate::prelude::*; -use nu_source::Spanned; +use nu_errors::{ParseError, ShellError}; +use nu_source::{Spanned, SpannedItem}; #[derive(Debug, Copy, Clone)] pub struct NumberShape; diff --git a/src/parser/hir/syntax_shape/expression/pattern.rs b/crates/nu-parser/src/hir/syntax_shape/expression/pattern.rs similarity index 92% rename from src/parser/hir/syntax_shape/expression/pattern.rs rename to crates/nu-parser/src/hir/syntax_shape/expression/pattern.rs index 3d11f16652..02fa0ed687 100644 --- a/src/parser/hir/syntax_shape/expression/pattern.rs +++ b/crates/nu-parser/src/hir/syntax_shape/expression/pattern.rs @@ -1,12 +1,15 @@ -use crate::parser::hir::syntax_shape::{ +use crate::hir::syntax_shape::{ expand_atom, expand_bare, expression::expand_file_path, ExpandContext, ExpandExpression, - ExpandSyntax, ExpansionRule, FallibleColorSyntax, FlatShape, ParseError, UnspannedAtomicToken, + ExpandSyntax, ExpansionRule, FallibleColorSyntax, FlatShape, UnspannedAtomicToken, }; -use crate::parser::parse::tokens::Token; -use crate::parser::{hir, hir::TokensIterator, Operator, TokenNode, UnspannedToken}; -use crate::prelude::*; +use crate::parse::tokens::{Token, UnspannedToken}; +use crate::{hir, hir::TokensIterator, Operator, TokenNode}; +use nu_errors::{ParseError, ShellError}; +#[cfg(coloring_in_tokens)] +use nu_protocol::ShellTypeName; #[cfg(not(coloring_in_tokens))] use nu_source::Spanned; +use nu_source::{Span, SpannedItem}; #[derive(Debug, Copy, Clone)] pub struct PatternShape; diff --git a/src/parser/hir/syntax_shape/expression/string.rs b/crates/nu-parser/src/hir/syntax_shape/expression/string.rs similarity index 91% rename from src/parser/hir/syntax_shape/expression/string.rs rename to crates/nu-parser/src/hir/syntax_shape/expression/string.rs index b6dbb2769f..caf9b0abad 100644 --- a/src/parser/hir/syntax_shape/expression/string.rs +++ b/crates/nu-parser/src/hir/syntax_shape/expression/string.rs @@ -1,12 +1,14 @@ -use crate::parser::hir::syntax_shape::{ +use crate::hir::syntax_shape::{ expand_atom, expand_variable, parse_single_node, AtomicToken, ExpandContext, ExpandExpression, - ExpansionRule, FallibleColorSyntax, FlatShape, ParseError, TestSyntax, UnspannedAtomicToken, + ExpansionRule, FallibleColorSyntax, FlatShape, TestSyntax, UnspannedAtomicToken, }; -use crate::parser::hir::tokens_iterator::Peeked; -use crate::parser::{hir, hir::TokensIterator, UnspannedToken}; -use crate::prelude::*; +use crate::hir::tokens_iterator::Peeked; +use crate::parse::tokens::UnspannedToken; +use crate::{hir, hir::TokensIterator}; +use nu_errors::{ParseError, ShellError}; #[cfg(not(coloring_in_tokens))] use nu_source::Spanned; +use nu_source::SpannedItem; #[derive(Debug, Copy, Clone)] pub struct StringShape; diff --git a/src/parser/hir/syntax_shape/expression/unit.rs b/crates/nu-parser/src/hir/syntax_shape/expression/unit.rs similarity index 89% rename from src/parser/hir/syntax_shape/expression/unit.rs rename to crates/nu-parser/src/hir/syntax_shape/expression/unit.rs index 0c500583d8..44738f1075 100644 --- a/src/parser/hir/syntax_shape/expression/unit.rs +++ b/crates/nu-parser/src/hir/syntax_shape/expression/unit.rs @@ -1,15 +1,16 @@ -use crate::parser::hir::syntax_shape::{ExpandContext, ExpandSyntax, ParseError}; -use crate::parser::parse::tokens::RawNumber; -use crate::parser::parse::tokens::Token; -use crate::parser::parse::unit::Unit; -use crate::parser::{hir::TokensIterator, TokenNode, UnspannedToken}; -use crate::prelude::*; +use crate::hir::syntax_shape::{ExpandContext, ExpandSyntax}; +use crate::parse::tokens::RawNumber; +use crate::parse::tokens::Token; +use crate::parse::tokens::UnspannedToken; +use crate::parse::unit::Unit; +use crate::{hir::TokensIterator, TokenNode}; use nom::branch::alt; use nom::bytes::complete::tag; use nom::character::complete::digit1; use nom::combinator::{all_consuming, opt, value}; use nom::IResult; -use nu_source::{Span, Spanned}; +use nu_errors::ParseError; +use nu_source::{b, DebugDocBuilder, HasSpan, PrettyDebugWithSource, Span, Spanned, SpannedItem}; #[derive(Debug, Clone)] pub struct UnitSyntax { diff --git a/src/parser/hir/syntax_shape/expression/variable_path.rs b/crates/nu-parser/src/hir/syntax_shape/expression/variable_path.rs similarity index 98% rename from src/parser/hir/syntax_shape/expression/variable_path.rs rename to crates/nu-parser/src/hir/syntax_shape/expression/variable_path.rs index 52ef946402..2f075a9d6f 100644 --- a/src/parser/hir/syntax_shape/expression/variable_path.rs +++ b/crates/nu-parser/src/hir/syntax_shape/expression/variable_path.rs @@ -1,16 +1,19 @@ -use crate::parser::hir::path::PathMember; -use crate::parser::hir::syntax_shape::{ +use crate::hir::syntax_shape::{ color_fallible_syntax, color_fallible_syntax_with, expand_atom, expand_expr, expand_syntax, parse_single_node, AnyExpressionShape, BareShape, ExpandContext, ExpandExpression, ExpandSyntax, ExpansionRule, FallibleColorSyntax, FlatShape, ParseError, Peeked, SkipSyntax, StringShape, TestSyntax, UnspannedAtomicToken, WhitespaceShape, }; -use crate::parser::{ - hir, hir::Expression, hir::TokensIterator, Operator, RawNumber, UnspannedToken, +use crate::parse::tokens::{RawNumber, UnspannedToken}; +use crate::{hir, hir::Expression, hir::TokensIterator, Operator}; +use nu_errors::ShellError; +use nu_protocol::{PathMember, ShellTypeName}; +use nu_source::{ + b, DebugDocBuilder, HasSpan, PrettyDebug, PrettyDebugWithSource, Span, Spanned, SpannedItem, + Tag, Tagged, TaggedItem, Text, }; -use crate::prelude::*; -use nu_source::{Spanned, Tagged}; -use serde::Serialize; +use num_bigint::BigInt; +use serde::{Deserialize, Serialize}; use std::str::FromStr; #[derive(Debug, Copy, Clone)] diff --git a/src/parser/hir/syntax_shape/flat_shape.rs b/crates/nu-parser/src/hir/syntax_shape/flat_shape.rs similarity index 95% rename from src/parser/hir/syntax_shape/flat_shape.rs rename to crates/nu-parser/src/hir/syntax_shape/flat_shape.rs index af34524ce7..2f2c865652 100644 --- a/src/parser/hir/syntax_shape/flat_shape.rs +++ b/crates/nu-parser/src/hir/syntax_shape/flat_shape.rs @@ -1,4 +1,7 @@ -use crate::parser::{Delimiter, Flag, FlagKind, Operator, RawNumber, TokenNode, UnspannedToken}; +use crate::parse::flag::{Flag, FlagKind}; +use crate::parse::operator::Operator; +use crate::parse::token_tree::{Delimiter, TokenNode}; +use crate::parse::tokens::{RawNumber, UnspannedToken}; use nu_source::{HasSpan, Span, Spanned, SpannedItem, Text}; #[derive(Debug, Copy, Clone)] diff --git a/src/parser/hir/tokens_iterator.rs b/crates/nu-parser/src/hir/tokens_iterator.rs similarity index 99% rename from src/parser/hir/tokens_iterator.rs rename to crates/nu-parser/src/hir/tokens_iterator.rs index 9cee23647a..5b44fcf3e8 100644 --- a/src/parser/hir/tokens_iterator.rs +++ b/crates/nu-parser/src/hir/tokens_iterator.rs @@ -1,15 +1,14 @@ pub(crate) mod debug; use self::debug::{ColorTracer, ExpandTracer}; -use crate::errors::ShellError; #[cfg(coloring_in_tokens)] -use crate::parser::hir::syntax_shape::FlatShape; -use crate::parser::hir::Expression; -use crate::parser::TokenNode; -use crate::prelude::*; +use crate::hir::syntax_shape::FlatShape; +use crate::hir::Expression; +use crate::TokenNode; #[allow(unused)] use getset::{Getters, MutGetters}; -use nu_source::Spanned; +use nu_errors::{ParseError, ShellError}; +use nu_source::{HasFallibleSpan, Span, SpannedItem, Spanned, HasSpan, Tag, Text}; cfg_if::cfg_if! { if #[cfg(coloring_in_tokens)] { diff --git a/src/parser/hir/tokens_iterator/debug.rs b/crates/nu-parser/src/hir/tokens_iterator/debug.rs similarity index 93% rename from src/parser/hir/tokens_iterator/debug.rs rename to crates/nu-parser/src/hir/tokens_iterator/debug.rs index 14574ce631..67c6c1a3bf 100644 --- a/src/parser/hir/tokens_iterator/debug.rs +++ b/crates/nu-parser/src/hir/tokens_iterator/debug.rs @@ -6,7 +6,7 @@ pub(crate) mod expand_trace; pub(crate) use self::color_trace::*; pub(crate) use self::expand_trace::*; -use crate::parser::hir::tokens_iterator::TokensIteratorState; +use crate::hir::tokens_iterator::TokensIteratorState; use nu_source::{PrettyDebug, PrettyDebugWithSource, Text}; #[derive(Debug)] diff --git a/src/parser/hir/tokens_iterator/debug/color_trace.rs b/crates/nu-parser/src/hir/tokens_iterator/debug/color_trace.rs similarity index 98% rename from src/parser/hir/tokens_iterator/debug/color_trace.rs rename to crates/nu-parser/src/hir/tokens_iterator/debug/color_trace.rs index 3db7a06e5a..6cf2c131ef 100644 --- a/src/parser/hir/tokens_iterator/debug/color_trace.rs +++ b/crates/nu-parser/src/hir/tokens_iterator/debug/color_trace.rs @@ -1,9 +1,8 @@ -use crate::errors::ShellError; -use crate::parser::hir::syntax_shape::FlatShape; -use crate::prelude::*; +use crate::hir::syntax_shape::FlatShape; use ansi_term::Color; use log::trace; -use nu_source::Spanned; +use nu_errors::ShellError; +use nu_source::{Spanned, Text}; use ptree::*; use std::borrow::Cow; use std::io; diff --git a/src/parser/hir/tokens_iterator/debug/expand_trace.rs b/crates/nu-parser/src/hir/tokens_iterator/debug/expand_trace.rs similarity index 98% rename from src/parser/hir/tokens_iterator/debug/expand_trace.rs rename to crates/nu-parser/src/hir/tokens_iterator/debug/expand_trace.rs index d61d21703f..24d67d089b 100644 --- a/src/parser/hir/tokens_iterator/debug/expand_trace.rs +++ b/crates/nu-parser/src/hir/tokens_iterator/debug/expand_trace.rs @@ -1,8 +1,9 @@ -use crate::parser::hir::Expression; -use crate::prelude::*; +use crate::hir::Expression; use ansi_term::Color; use log::trace; -use nu_source::DebugDoc; +use nu_errors::ParseError; +use nu_protocol::ShellTypeName; +use nu_source::{DebugDoc, PrettyDebug, PrettyDebugWithSource, Text}; use ptree::*; use std::borrow::Cow; use std::io; diff --git a/src/parser/hir/tokens_iterator/tests.rs b/crates/nu-parser/src/hir/tokens_iterator/tests.rs similarity index 79% rename from src/parser/hir/tokens_iterator/tests.rs rename to crates/nu-parser/src/hir/tokens_iterator/tests.rs index 23f8889786..e3f44f7e05 100644 --- a/src/parser/hir/tokens_iterator/tests.rs +++ b/crates/nu-parser/src/hir/tokens_iterator/tests.rs @@ -1,5 +1,5 @@ -use crate::parser::hir::TokensIterator; -use crate::parser::parse::token_tree_builder::TokenTreeBuilder as b; +use crate::hir::TokensIterator; +use crate::parse::token_tree_builder::TokenTreeBuilder as b; use crate::Span; #[test] diff --git a/crates/nu-parser/src/lib.rs b/crates/nu-parser/src/lib.rs new file mode 100644 index 0000000000..e80df9b261 --- /dev/null +++ b/crates/nu-parser/src/lib.rs @@ -0,0 +1,30 @@ +pub mod commands; +pub mod debug; +pub mod hir; +pub mod parse; +pub mod parse_command; + +pub use crate::commands::classified::{ClassifiedCommand, ClassifiedPipeline, InternalCommand}; +pub use crate::commands::ExternalCommand; +pub use crate::hir::syntax_shape::flat_shape::FlatShape; +pub use crate::hir::syntax_shape::{expand_syntax, ExpandSyntax, PipelineShape, SignatureRegistry}; +pub use crate::hir::tokens_iterator::TokensIterator; +pub use crate::parse::files::Files; +pub use crate::parse::flag::Flag; +pub use crate::parse::operator::Operator; +pub use crate::parse::parser::pipeline; +pub use crate::parse::parser::Number; +pub use crate::parse::token_tree::{Delimiter, TokenNode}; +pub use crate::parse::token_tree_builder::TokenTreeBuilder; + +use nu_errors::ShellError; +use nu_source::nom_input; + +pub fn parse(input: &str) -> Result { + let _ = pretty_env_logger::try_init(); + + match pipeline(nom_input(input)) { + Ok((_rest, val)) => Ok(val), + Err(err) => Err(ShellError::parse_error(err)), + } +} diff --git a/src/parser/parse.rs b/crates/nu-parser/src/parse.rs similarity index 100% rename from src/parser/parse.rs rename to crates/nu-parser/src/parse.rs diff --git a/src/parser/parse/call_node.rs b/crates/nu-parser/src/parse/call_node.rs similarity index 93% rename from src/parser/parse/call_node.rs rename to crates/nu-parser/src/parse/call_node.rs index ef4298e425..b01d7f8945 100644 --- a/src/parser/parse/call_node.rs +++ b/crates/nu-parser/src/parse/call_node.rs @@ -1,6 +1,6 @@ -use crate::parser::TokenNode; -use crate::prelude::*; +use crate::TokenNode; use getset::Getters; +use nu_source::{b, DebugDocBuilder, PrettyDebugWithSource}; #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Getters)] pub struct CallNode { diff --git a/src/parser/parse/files.rs b/crates/nu-parser/src/parse/files.rs similarity index 100% rename from src/parser/parse/files.rs rename to crates/nu-parser/src/parse/files.rs diff --git a/src/parser/parse/flag.rs b/crates/nu-parser/src/parse/flag.rs similarity index 87% rename from src/parser/parse/flag.rs rename to crates/nu-parser/src/parse/flag.rs index 65f946ea31..ea3bd98578 100644 --- a/src/parser/parse/flag.rs +++ b/crates/nu-parser/src/parse/flag.rs @@ -1,8 +1,7 @@ -use crate::parser::hir::syntax_shape::flat_shape::FlatShape; -use crate::prelude::*; +use crate::hir::syntax_shape::flat_shape::FlatShape; use derive_new::new; use getset::Getters; -use nu_source::{Span, Spanned, SpannedItem}; +use nu_source::{Span, b, Spanned, SpannedItem, PrettyDebugWithSource, DebugDocBuilder}; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)] diff --git a/src/parser/parse/operator.rs b/crates/nu-parser/src/parse/operator.rs similarity index 97% rename from src/parser/parse/operator.rs rename to crates/nu-parser/src/parse/operator.rs index f98097f374..3a5df5b4ce 100644 --- a/src/parser/parse/operator.rs +++ b/crates/nu-parser/src/parse/operator.rs @@ -1,6 +1,5 @@ -#[allow(unused)] -use crate::prelude::*; use serde::{Deserialize, Serialize}; +use nu_source::{b, PrettyDebug, DebugDocBuilder}; use std::str::FromStr; diff --git a/src/parser/parse/parser.rs b/crates/nu-parser/src/parse/parser.rs similarity index 96% rename from src/parser/parse/parser.rs rename to crates/nu-parser/src/parse/parser.rs index 50cf4112bc..f63d505908 100644 --- a/src/parser/parse/parser.rs +++ b/crates/nu-parser/src/parse/parser.rs @@ -1,10 +1,9 @@ #![allow(unused)] -use crate::parser::parse::{ +use crate::parse::{ call_node::*, flag::*, operator::*, pipeline::*, token_tree::*, token_tree_builder::*, tokens::*, unit::*, }; -use crate::prelude::*; use nom; use nom::branch::*; use nom::bytes::complete::*; @@ -13,6 +12,7 @@ use nom::combinator::*; use nom::multi::*; use nom::sequence::*; +use bigdecimal::BigDecimal; use derive_new::new; use log::trace; use nom::dbg; @@ -20,7 +20,14 @@ use nom::*; use nom::{AsBytes, FindSubstring, IResult, InputLength, InputTake, Slice}; use nom_locate::{position, LocatedSpanEx}; use nom_tracable::{tracable_parser, HasTracableInfo, TracableInfo}; -use nu_source::{nom_input, NomSpan, Spanned}; +use nu_protocol::{Primitive, UntaggedValue}; +use nu_source::{ + b, nom_input, DebugDocBuilder, HasSpan, NomSpan, PrettyDebug, PrettyDebugWithSource, Span, + Spanned, SpannedItem, Tag, +}; +use num_bigint::BigInt; +use num_traits::identities::Zero; +use num_traits::FromPrimitive; use serde::{Deserialize, Serialize}; use std::fmt::Debug; use std::str::FromStr; @@ -63,6 +70,32 @@ impl Into for &Number { } } +impl Into for Number { + fn into(self) -> UntaggedValue { + match self { + Number::Int(i) => int(i), + Number::Decimal(d) => decimal(d), + } + } +} + +pub fn int(i: impl Into) -> UntaggedValue { + UntaggedValue::Primitive(Primitive::Int(i.into())) +} + +pub fn decimal(i: impl Into) -> UntaggedValue { + UntaggedValue::Primitive(Primitive::Decimal(i.into())) +} + +impl Into for &Number { + fn into(self) -> UntaggedValue { + match self { + Number::Int(i) => int(i.clone()), + Number::Decimal(d) => decimal(d.clone()), + } + } +} + impl PrettyDebug for Number { fn pretty(&self) -> DebugDocBuilder { match self { @@ -616,7 +649,7 @@ pub fn pipeline(input: NomSpan) -> IResult { )) } -fn int(frag: &str, neg: Option) -> i64 { +fn parse_int(frag: &str, neg: Option) -> i64 { let int = FromStr::from_str(frag).unwrap(); match neg { @@ -712,8 +745,8 @@ fn is_member_start(c: char) -> bool { #[cfg(test)] mod tests { use super::*; - use crate::parser::parse::token_tree_builder::TokenTreeBuilder as b; - use crate::parser::parse::token_tree_builder::{CurriedToken, TokenTreeBuilder}; + use crate::parse::token_tree_builder::TokenTreeBuilder as b; + use crate::parse::token_tree_builder::{CurriedToken, TokenTreeBuilder}; use pretty_assertions::assert_eq; pub type CurriedNode = Box T + 'static>; diff --git a/src/parser/parse/pipeline.rs b/crates/nu-parser/src/parse/pipeline.rs similarity index 93% rename from src/parser/parse/pipeline.rs rename to crates/nu-parser/src/parse/pipeline.rs index 883f714026..b2bfe99af3 100644 --- a/src/parser/parse/pipeline.rs +++ b/crates/nu-parser/src/parse/pipeline.rs @@ -1,8 +1,7 @@ -use crate::parser::TokenNode; -use crate::prelude::*; +use crate::TokenNode; use derive_new::new; use getset::Getters; -use nu_source::{DebugDocBuilder, PrettyDebugWithSource, Span, Spanned}; +use nu_source::{b, DebugDocBuilder, PrettyDebugWithSource, Span, Spanned, HasSpan}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Getters, new)] pub struct Pipeline { diff --git a/src/parser/parse/token_tree.rs b/crates/nu-parser/src/parse/token_tree.rs similarity index 97% rename from src/parser/parse/token_tree.rs rename to crates/nu-parser/src/parse/token_tree.rs index 116a672883..2869a4b7ae 100644 --- a/src/parser/parse/token_tree.rs +++ b/crates/nu-parser/src/parse/token_tree.rs @@ -1,10 +1,12 @@ -use crate::errors::{ParseError, ShellError}; -use crate::parser::parse::{call_node::*, flag::*, operator::*, pipeline::*, tokens::*}; -use crate::prelude::*; +use crate::parse::{call_node::*, flag::*, operator::*, pipeline::*, tokens::*}; use derive_new::new; use getset::Getters; -use nu_source::Spanned; -use nu_source::{Tagged, Text}; +use nu_errors::{ParseError, ShellError}; +use nu_protocol::ShellTypeName; +use nu_source::{ + b, DebugDocBuilder, HasSpan, PrettyDebugWithSource, Span, Spanned, SpannedItem, Tagged, + TaggedItem, Text, +}; use std::fmt; #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] diff --git a/src/parser/parse/token_tree_builder.rs b/crates/nu-parser/src/parse/token_tree_builder.rs similarity index 96% rename from src/parser/parse/token_tree_builder.rs rename to crates/nu-parser/src/parse/token_tree_builder.rs index 3b6929b11d..7b82cb4131 100644 --- a/src/parser/parse/token_tree_builder.rs +++ b/crates/nu-parser/src/parse/token_tree_builder.rs @@ -1,12 +1,12 @@ -use crate::prelude::*; - -use crate::parser::parse::flag::{Flag, FlagKind}; -use crate::parser::parse::operator::Operator; -use crate::parser::parse::pipeline::{Pipeline, PipelineElement}; -use crate::parser::parse::token_tree::{DelimitedNode, Delimiter, TokenNode}; -use crate::parser::parse::tokens::{RawNumber, UnspannedToken}; -use crate::parser::CallNode; -use nu_source::Spanned; +use crate::parse::call_node::CallNode; +use crate::parse::flag::{Flag, FlagKind}; +use crate::parse::operator::Operator; +use crate::parse::pipeline::{Pipeline, PipelineElement}; +use crate::parse::token_tree::{DelimitedNode, Delimiter, TokenNode}; +use crate::parse::tokens::{RawNumber, UnspannedToken}; +use bigdecimal::BigDecimal; +use nu_source::{Span, Spanned, SpannedItem}; +use num_bigint::BigInt; pub struct TokenTreeBuilder { pos: usize, diff --git a/src/parser/parse/tokens.rs b/crates/nu-parser/src/parse/tokens.rs similarity index 95% rename from src/parser/parse/tokens.rs rename to crates/nu-parser/src/parse/tokens.rs index 8b6bdf4574..8430725313 100644 --- a/src/parser/parse/tokens.rs +++ b/crates/nu-parser/src/parse/tokens.rs @@ -1,6 +1,12 @@ -use crate::parser::Operator; -use crate::prelude::*; -use nu_source::{Spanned, Text}; +use crate::parse::parser::Number; +use crate::Operator; +use bigdecimal::BigDecimal; +use nu_protocol::ShellTypeName; +use nu_source::{ + b, DebugDocBuilder, HasSpan, PrettyDebug, PrettyDebugWithSource, Span, Spanned, SpannedItem, + Text, +}; +use num_bigint::BigInt; use std::fmt; use std::str::FromStr; diff --git a/src/parser/parse/unit.rs b/crates/nu-parser/src/parse/unit.rs similarity index 56% rename from src/parser/parse/unit.rs rename to crates/nu-parser/src/parse/unit.rs index 5312ed7286..e51d6cf362 100644 --- a/src/parser/parse/unit.rs +++ b/crates/nu-parser/src/parse/unit.rs @@ -1,4 +1,7 @@ -use crate::prelude::*; +use crate::parse::parser::Number; +use nu_protocol::{Primitive, UntaggedValue}; +use nu_source::{b, DebugDocBuilder, PrettyDebug}; +use num_traits::ToPrimitive; use serde::{Deserialize, Serialize}; use std::str::FromStr; @@ -25,7 +28,7 @@ pub enum Unit { impl PrettyDebug for Unit { fn pretty(&self) -> DebugDocBuilder { - b::keyword(format!("{:?}", self)) + b::keyword(self.as_str()) } } @@ -55,31 +58,40 @@ impl Unit { } } - pub(crate) fn compute(&self, size: &Number) -> UntaggedValue { + pub fn compute(&self, size: &Number) -> UntaggedValue { let size = size.clone(); match &self { - Unit::Byte => UntaggedValue::number(size), - Unit::Kilobyte => UntaggedValue::number(size * 1024), - Unit::Megabyte => UntaggedValue::number(size * 1024 * 1024), - Unit::Gigabyte => UntaggedValue::number(size * 1024 * 1024 * 1024), - Unit::Terabyte => UntaggedValue::number(size * 1024 * 1024 * 1024 * 1024), - Unit::Petabyte => UntaggedValue::number(size * 1024 * 1024 * 1024 * 1024 * 1024), - Unit::Second => UntaggedValue::duration(convert_number_to_u64(&size)), - Unit::Minute => UntaggedValue::duration(60 * convert_number_to_u64(&size)), - Unit::Hour => UntaggedValue::duration(60 * 60 * convert_number_to_u64(&size)), - Unit::Day => UntaggedValue::duration(24 * 60 * 60 * convert_number_to_u64(&size)), - Unit::Week => UntaggedValue::duration(7 * 24 * 60 * 60 * convert_number_to_u64(&size)), - Unit::Month => { - UntaggedValue::duration(30 * 24 * 60 * 60 * convert_number_to_u64(&size)) - } - Unit::Year => { - UntaggedValue::duration(365 * 24 * 60 * 60 * convert_number_to_u64(&size)) - } + Unit::Byte => number(size), + Unit::Kilobyte => number(size * 1024), + Unit::Megabyte => number(size * 1024 * 1024), + Unit::Gigabyte => number(size * 1024 * 1024 * 1024), + Unit::Terabyte => number(size * 1024 * 1024 * 1024 * 1024), + Unit::Petabyte => number(size * 1024 * 1024 * 1024 * 1024 * 1024), + Unit::Second => duration(convert_number_to_u64(&size)), + Unit::Minute => duration(60 * convert_number_to_u64(&size)), + Unit::Hour => duration(60 * 60 * convert_number_to_u64(&size)), + Unit::Day => duration(24 * 60 * 60 * convert_number_to_u64(&size)), + Unit::Week => duration(7 * 24 * 60 * 60 * convert_number_to_u64(&size)), + Unit::Month => duration(30 * 24 * 60 * 60 * convert_number_to_u64(&size)), + Unit::Year => duration(365 * 24 * 60 * 60 * convert_number_to_u64(&size)), } } } +fn number(number: impl Into) -> UntaggedValue { + let number = number.into(); + + match number { + Number::Int(int) => UntaggedValue::Primitive(Primitive::Int(int)), + Number::Decimal(decimal) => UntaggedValue::Primitive(Primitive::Decimal(decimal)), + } +} + +pub fn duration(secs: u64) -> UntaggedValue { + UntaggedValue::Primitive(Primitive::Duration(secs)) +} + impl FromStr for Unit { type Err = (); fn from_str(input: &str) -> Result::Err> { diff --git a/src/parser/parse/util.rs b/crates/nu-parser/src/parse/util.rs similarity index 100% rename from src/parser/parse/util.rs rename to crates/nu-parser/src/parse/util.rs diff --git a/src/parser/parse_command.rs b/crates/nu-parser/src/parse_command.rs similarity index 98% rename from src/parser/parse_command.rs rename to crates/nu-parser/src/parse_command.rs index 41aff543f8..5edc93fd45 100644 --- a/src/parser/parse_command.rs +++ b/crates/nu-parser/src/parse_command.rs @@ -1,17 +1,17 @@ -use crate::errors::{ArgumentError, ParseError}; -use crate::parser::hir::syntax_shape::{ +use crate::hir::syntax_shape::{ color_fallible_syntax, color_syntax, expand_expr, flat_shape::FlatShape, spaced, BackoffColoringMode, ColorSyntax, MaybeSpaceShape, }; -use crate::parser::registry::{NamedType, PositionalType, Signature}; -use crate::parser::TokensIterator; -use crate::parser::{ +use crate::TokensIterator; +use crate::{ hir::{self, ExpandContext, NamedArguments}, Flag, }; use log::trace; -use nu_source::{PrettyDebugWithSource, Text}; -use nu_source::{Span, Spanned, SpannedItem}; +use nu_source::{PrettyDebugWithSource, Span, Spanned, SpannedItem, Text}; + +use nu_errors::{ArgumentError, ParseError}; +use nu_protocol::{NamedType, PositionalType, Signature}; pub fn parse_command_tail( config: &Signature, @@ -389,7 +389,7 @@ impl ColorSyntax for CommandTailShape { token_nodes: &'b mut TokensIterator<'a>, context: &ExpandContext, ) -> Self::Info { - use crate::parser::hir::syntax_shape::SyntaxShape; + use nu_protocol::SyntaxShape; let mut args = ColoringArgs::new(token_nodes.len()); trace_remaining("nodes", &token_nodes, context.source()); diff --git a/crates/nu-protocol/Cargo.toml b/crates/nu-protocol/Cargo.toml new file mode 100644 index 0000000000..79169e7bc2 --- /dev/null +++ b/crates/nu-protocol/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "nu-protocol" +version = "0.1.0" +authors = ["Yehuda Katz "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +nu-source = { path = "../nu-source" } +nu-errors = { path = "../nu-errors" } + +serde = { version = "1.0.102", features = ["derive"] } +indexmap = { version = "1.3.0", features = ["serde-1"] } +num-bigint = { version = "0.2.3", features = ["serde"] } +bigdecimal = { version = "0.1.0", features = ["serde"] } +chrono = { version = "0.4.9", features = ["serde"] } +num-traits = "0.2.8" +serde_bytes = "0.11.2" +getset = "0.0.9" +derive-new = "0.5.8" +ansi_term = "0.12.1" +language-reporting = "0.4.0" +nom = "5.0.1" +nom_locate = "1.0.0" +nom-tracable = "0.4.1" +typetag = "0.1.4" +query_interface = "0.3.5" + +# implement conversions +subprocess = "0.1.18" +serde_yaml = "0.8" +toml = "0.5.5" +serde_json = "1.0.41" + diff --git a/crates/nu-protocol/src/call_info.rs b/crates/nu-protocol/src/call_info.rs new file mode 100644 index 0000000000..333890cc20 --- /dev/null +++ b/crates/nu-protocol/src/call_info.rs @@ -0,0 +1,93 @@ +use nu_errors::ShellError; +use crate::value::Value; +use derive_new::new; +use indexmap::IndexMap; +use nu_source::Tag; +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize, Debug, Clone)] +pub struct CallInfo { + pub args: EvaluatedArgs, + pub name_tag: Tag, +} + +#[derive(Debug, Default, new, Serialize, Deserialize, Clone)] +pub struct EvaluatedArgs { + pub positional: Option>, + pub named: Option>, +} + +impl EvaluatedArgs { + pub fn slice_from(&self, from: usize) -> Vec { + let positional = &self.positional; + + match positional { + None => vec![], + Some(list) => list[from..].to_vec(), + } + } + + pub fn nth(&self, pos: usize) -> Option<&Value> { + match &self.positional { + None => None, + Some(array) => array.iter().nth(pos), + } + } + + pub fn expect_nth(&self, pos: usize) -> Result<&Value, ShellError> { + match &self.positional { + None => Err(ShellError::unimplemented("Better error: expect_nth")), + Some(array) => match array.iter().nth(pos) { + None => Err(ShellError::unimplemented("Better error: expect_nth")), + Some(item) => Ok(item), + }, + } + } + + pub fn len(&self) -> usize { + match &self.positional { + None => 0, + Some(array) => array.len(), + } + } + + pub fn has(&self, name: &str) -> bool { + match &self.named { + None => false, + Some(named) => named.contains_key(name), + } + } + + pub fn get(&self, name: &str) -> Option<&Value> { + match &self.named { + None => None, + Some(named) => named.get(name), + } + } + + pub fn positional_iter(&self) -> PositionalIter<'_> { + match &self.positional { + None => PositionalIter::Empty, + Some(v) => { + let iter = v.iter(); + PositionalIter::Array(iter) + } + } + } +} + +pub enum PositionalIter<'a> { + Empty, + Array(std::slice::Iter<'a, Value>), +} + +impl<'a> Iterator for PositionalIter<'a> { + type Item = &'a Value; + + fn next(&mut self) -> Option { + match self { + PositionalIter::Empty => None, + PositionalIter::Array(iter) => iter.next(), + } + } +} diff --git a/crates/nu-protocol/src/lib.rs b/crates/nu-protocol/src/lib.rs new file mode 100644 index 0000000000..8aa60ea695 --- /dev/null +++ b/crates/nu-protocol/src/lib.rs @@ -0,0 +1,24 @@ +#[macro_use] +mod macros; + +mod call_info; +mod maybe_owned; +mod plugin; +mod return_value; +mod signature; +mod syntax_shape; +mod type_name; +mod value; + +pub use crate::call_info::{CallInfo, EvaluatedArgs}; +pub use crate::maybe_owned::MaybeOwned; +pub use crate::plugin::{serve_plugin, Plugin}; +pub use crate::return_value::{CommandAction, ReturnSuccess, ReturnValue}; +pub use crate::signature::{NamedType, PositionalType, Signature}; +pub use crate::syntax_shape::SyntaxShape; +pub use crate::type_name::{PrettyType, ShellTypeName, SpannedTypeName}; +pub use crate::value::column_path::{ColumnPath, PathMember, UnspannedPathMember}; +pub use crate::value::dict::Dictionary; +pub use crate::value::evaluate::{Evaluate, EvaluateTrait, Scope}; +pub use crate::value::primitive::Primitive; +pub use crate::value::{UntaggedValue, Value}; diff --git a/crates/nu-protocol/src/macros.rs b/crates/nu-protocol/src/macros.rs new file mode 100644 index 0000000000..66e7ab13b6 --- /dev/null +++ b/crates/nu-protocol/src/macros.rs @@ -0,0 +1,12 @@ +// These macros exist to differentiate between intentional writing to stdout +// and stray printlns left by accident + +#[macro_export] +macro_rules! outln { + ($($tokens:tt)*) => { println!($($tokens)*) } +} + +#[macro_export] +macro_rules! errln { + ($($tokens:tt)*) => { eprintln!($($tokens)*) } +} diff --git a/crates/nu-protocol/src/maybe_owned.rs b/crates/nu-protocol/src/maybe_owned.rs new file mode 100644 index 0000000000..c654057cab --- /dev/null +++ b/crates/nu-protocol/src/maybe_owned.rs @@ -0,0 +1,14 @@ +#[derive(Debug)] +pub enum MaybeOwned<'a, T> { + Owned(T), + Borrowed(&'a T), +} + +impl MaybeOwned<'_, T> { + pub fn borrow(&self) -> &T { + match self { + MaybeOwned::Owned(v) => v, + MaybeOwned::Borrowed(v) => v, + } + } +} diff --git a/src/plugin.rs b/crates/nu-protocol/src/plugin.rs similarity index 97% rename from src/plugin.rs rename to crates/nu-protocol/src/plugin.rs index cc9ee411b8..4fc56e0af9 100644 --- a/src/plugin.rs +++ b/crates/nu-protocol/src/plugin.rs @@ -1,5 +1,8 @@ -use crate::Signature; -use crate::{CallInfo, ReturnValue, ShellError, Value}; +use crate::call_info::CallInfo; +use crate::return_value::ReturnValue; +use crate::signature::Signature; +use crate::value::Value; +use nu_errors::ShellError; use serde::{Deserialize, Serialize}; use std::io; diff --git a/crates/nu-protocol/src/return_value.rs b/crates/nu-protocol/src/return_value.rs new file mode 100644 index 0000000000..e79b495446 --- /dev/null +++ b/crates/nu-protocol/src/return_value.rs @@ -0,0 +1,76 @@ +use nu_errors::ShellError; +use crate::value::Value; +use nu_source::{b, DebugDocBuilder, PrettyDebug}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum CommandAction { + ChangePath(String), + Exit, + Error(ShellError), + EnterShell(String), + EnterValueShell(Value), + EnterHelpShell(Value), + PreviousShell, + NextShell, + LeaveShell, +} + +impl PrettyDebug for CommandAction { + fn pretty(&self) -> DebugDocBuilder { + match self { + CommandAction::ChangePath(path) => b::typed("change path", b::description(path)), + CommandAction::Exit => b::description("exit"), + CommandAction::Error(_) => b::error("error"), + CommandAction::EnterShell(s) => b::typed("enter shell", b::description(s)), + CommandAction::EnterValueShell(v) => b::typed("enter value shell", v.pretty()), + CommandAction::EnterHelpShell(v) => b::typed("enter help shell", v.pretty()), + CommandAction::PreviousShell => b::description("previous shell"), + CommandAction::NextShell => b::description("next shell"), + CommandAction::LeaveShell => b::description("leave shell"), + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum ReturnSuccess { + Value(Value), + DebugValue(Value), + Action(CommandAction), +} + +impl PrettyDebug for ReturnSuccess { + fn pretty(&self) -> DebugDocBuilder { + match self { + ReturnSuccess::Value(value) => b::typed("value", value.pretty()), + ReturnSuccess::DebugValue(value) => b::typed("debug value", value.pretty()), + ReturnSuccess::Action(action) => b::typed("action", action.pretty()), + } + } +} + +pub type ReturnValue = Result; + +impl Into for Value { + fn into(self) -> ReturnValue { + Ok(ReturnSuccess::Value(self)) + } +} + +impl ReturnSuccess { + pub fn change_cwd(path: String) -> ReturnValue { + Ok(ReturnSuccess::Action(CommandAction::ChangePath(path))) + } + + pub fn value(input: impl Into) -> ReturnValue { + Ok(ReturnSuccess::Value(input.into())) + } + + pub fn debug_value(input: impl Into) -> ReturnValue { + Ok(ReturnSuccess::DebugValue(input.into())) + } + + pub fn action(input: CommandAction) -> ReturnValue { + Ok(ReturnSuccess::Action(input)) + } +} diff --git a/src/parser/registry.rs b/crates/nu-protocol/src/signature.rs similarity index 55% rename from src/parser/registry.rs rename to crates/nu-protocol/src/signature.rs index 98d8a0375c..591ec4d727 100644 --- a/src/parser/registry.rs +++ b/crates/nu-protocol/src/signature.rs @@ -1,11 +1,6 @@ -// TODO: Temporary redirect -pub(crate) use crate::context::CommandRegistry; -use crate::evaluate::{evaluate_baseline_expr, Scope}; -use crate::parser::{hir, hir::SyntaxShape}; -use crate::prelude::*; -use derive_new::new; +use crate::syntax_shape::SyntaxShape; use indexmap::IndexMap; - +use nu_source::{b, DebugDocBuilder, PrettyDebug, PrettyDebugWithSource}; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize, Clone)] @@ -57,14 +52,14 @@ impl PositionalType { PositionalType::Optional(name.to_string(), SyntaxShape::Any) } - pub(crate) fn name(&self) -> &str { + pub fn name(&self) -> &str { match self { PositionalType::Mandatory(s, _) => s, PositionalType::Optional(s, _) => s, } } - pub(crate) fn syntax_type(&self) -> SyntaxShape { + pub fn syntax_type(&self) -> SyntaxShape { match *self { PositionalType::Mandatory(_, t) => t, PositionalType::Optional(_, t) => t, @@ -192,135 +187,3 @@ impl Signature { self } } - -#[derive(Debug, Default, new, Serialize, Deserialize, Clone)] -pub struct EvaluatedArgs { - pub positional: Option>, - pub named: Option>, -} - -impl EvaluatedArgs { - pub fn slice_from(&self, from: usize) -> Vec { - let positional = &self.positional; - - match positional { - None => vec![], - Some(list) => list[from..].to_vec(), - } - } -} - -impl EvaluatedArgs { - pub fn nth(&self, pos: usize) -> Option<&Value> { - match &self.positional { - None => None, - Some(array) => array.iter().nth(pos), - } - } - - pub fn expect_nth(&self, pos: usize) -> Result<&Value, ShellError> { - match &self.positional { - None => Err(ShellError::unimplemented("Better error: expect_nth")), - Some(array) => match array.iter().nth(pos) { - None => Err(ShellError::unimplemented("Better error: expect_nth")), - Some(item) => Ok(item), - }, - } - } - - pub fn len(&self) -> usize { - match &self.positional { - None => 0, - Some(array) => array.len(), - } - } - - pub fn has(&self, name: &str) -> bool { - match &self.named { - None => false, - Some(named) => named.contains_key(name), - } - } - - pub fn get(&self, name: &str) -> Option<&Value> { - match &self.named { - None => None, - Some(named) => named.get(name), - } - } - - pub fn positional_iter(&self) -> PositionalIter<'_> { - match &self.positional { - None => PositionalIter::Empty, - Some(v) => { - let iter = v.iter(); - PositionalIter::Array(iter) - } - } - } -} - -pub enum PositionalIter<'a> { - Empty, - Array(std::slice::Iter<'a, Value>), -} - -impl<'a> Iterator for PositionalIter<'a> { - type Item = &'a Value; - - fn next(&mut self) -> Option { - match self { - PositionalIter::Empty => None, - PositionalIter::Array(iter) => iter.next(), - } - } -} - -pub(crate) fn evaluate_args( - call: &hir::Call, - registry: &CommandRegistry, - scope: &Scope, - source: &Text, -) -> Result { - let positional: Result>, _> = call - .positional() - .as_ref() - .map(|p| { - p.iter() - .map(|e| evaluate_baseline_expr(e, registry, scope, source)) - .collect() - }) - .transpose(); - - let positional = positional?; - - let named: Result>, ShellError> = call - .named() - .as_ref() - .map(|n| { - let mut results = IndexMap::new(); - - for (name, value) in n.named.iter() { - match value { - hir::named::NamedValue::PresentSwitch(tag) => { - results.insert(name.clone(), UntaggedValue::boolean(true).into_value(tag)); - } - hir::named::NamedValue::Value(expr) => { - results.insert( - name.clone(), - evaluate_baseline_expr(expr, registry, scope, source)?, - ); - } - - _ => {} - }; - } - - Ok(results) - }) - .transpose(); - - let named = named?; - - Ok(EvaluatedArgs::new(positional, named)) -} diff --git a/crates/nu-protocol/src/syntax_shape.rs b/crates/nu-protocol/src/syntax_shape.rs new file mode 100644 index 0000000000..7f6d486bfd --- /dev/null +++ b/crates/nu-protocol/src/syntax_shape.rs @@ -0,0 +1,31 @@ +use nu_source::{b, DebugDocBuilder, PrettyDebug}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +pub enum SyntaxShape { + Any, + String, + Member, + ColumnPath, + Number, + Int, + Path, + Pattern, + Block, +} + +impl PrettyDebug for SyntaxShape { + fn pretty(&self) -> DebugDocBuilder { + b::kind(match self { + SyntaxShape::Any => "any shape", + SyntaxShape::String => "string shape", + SyntaxShape::Member => "member shape", + SyntaxShape::ColumnPath => "column path shape", + SyntaxShape::Number => "number shape", + SyntaxShape::Int => "integer shape", + SyntaxShape::Path => "file path shape", + SyntaxShape::Pattern => "pattern shape", + SyntaxShape::Block => "block shape", + }) + } +} diff --git a/src/traits.rs b/crates/nu-protocol/src/type_name.rs similarity index 90% rename from src/traits.rs rename to crates/nu-protocol/src/type_name.rs index 94d09b67c3..b9d6344c0e 100644 --- a/src/traits.rs +++ b/crates/nu-protocol/src/type_name.rs @@ -1,5 +1,4 @@ -use crate::prelude::*; -use nu_source::{DebugDocBuilder, Spanned, SpannedItem, Tagged}; +use nu_source::{DebugDocBuilder, HasSpan, Spanned, SpannedItem, Tagged}; pub trait ShellTypeName { fn type_name(&self) -> &'static str; diff --git a/crates/nu-protocol/src/value.rs b/crates/nu-protocol/src/value.rs new file mode 100644 index 0000000000..72b4bf7dda --- /dev/null +++ b/crates/nu-protocol/src/value.rs @@ -0,0 +1,205 @@ +pub mod column_path; +mod convert; +mod debug; +pub mod dict; +pub mod evaluate; +pub mod primitive; +mod serde_bigdecimal; +mod serde_bigint; + +use crate::type_name::{ShellTypeName, SpannedTypeName}; +use crate::value::dict::Dictionary; +use crate::value::evaluate::Evaluate; +use crate::value::primitive::Primitive; +use nu_errors::ShellError; +use nu_source::{AnchorLocation, HasSpan, Span, Tag}; +use serde::{Deserialize, Serialize}; +use std::path::PathBuf; + +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)] +pub enum UntaggedValue { + Primitive(Primitive), + Row(Dictionary), + Table(Vec), + + // Errors are a type of value too + Error(ShellError), + + Block(Evaluate), +} + +impl UntaggedValue { + pub fn retag(self, tag: impl Into) -> Value { + Value { + value: self, + tag: tag.into(), + } + } + + pub fn data_descriptors(&self) -> Vec { + match self { + UntaggedValue::Primitive(_) => vec![], + UntaggedValue::Row(columns) => columns + .entries + .keys() + .into_iter() + .map(|x| x.to_string()) + .collect(), + UntaggedValue::Block(_) => vec![], + UntaggedValue::Table(_) => vec![], + UntaggedValue::Error(_) => vec![], + } + } + + pub fn into_value(self, tag: impl Into) -> Value { + Value { + value: self, + tag: tag.into(), + } + } + + pub fn into_untagged_value(self) -> Value { + Value { + value: self, + tag: Tag::unknown(), + } + } + + pub fn is_true(&self) -> bool { + match self { + UntaggedValue::Primitive(Primitive::Boolean(true)) => true, + _ => false, + } + } + + pub fn is_some(&self) -> bool { + !self.is_none() + } + + pub fn is_none(&self) -> bool { + match self { + UntaggedValue::Primitive(Primitive::Nothing) => true, + _ => false, + } + } + + pub fn is_error(&self) -> bool { + match self { + UntaggedValue::Error(_err) => true, + _ => false, + } + } + + pub fn expect_error(&self) -> ShellError { + match self { + UntaggedValue::Error(err) => err.clone(), + _ => panic!("Don't call expect_error without first calling is_error"), + } + } + + pub fn expect_string(&self) -> &str { + match self { + UntaggedValue::Primitive(Primitive::String(string)) => &string[..], + _ => panic!("expect_string assumes that the value must be a string"), + } + } +} + +#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq, Serialize, Deserialize)] +pub struct Value { + pub value: UntaggedValue, + pub tag: Tag, +} + +impl std::ops::Deref for Value { + type Target = UntaggedValue; + + fn deref(&self) -> &Self::Target { + &self.value + } +} + +impl Value { + pub fn anchor(&self) -> Option { + self.tag.anchor() + } + + pub fn anchor_name(&self) -> Option { + self.tag.anchor_name() + } + + pub fn tag(&self) -> Tag { + self.tag.clone() + } + + pub fn as_string(&self) -> Result<&str, ShellError> { + match &self.value { + UntaggedValue::Primitive(Primitive::String(string)) => Ok(&string[..]), + _ => Err(ShellError::type_error("string", self.spanned_type_name())), + } + } + + pub fn as_path(&self) -> Result { + match &self.value { + UntaggedValue::Primitive(Primitive::Path(path)) => Ok(path.clone()), + UntaggedValue::Primitive(Primitive::String(path_str)) => { + Ok(PathBuf::from(&path_str).clone()) + } + _ => Err(ShellError::type_error("Path", self.spanned_type_name())), + } + } +} + +impl Into for &str { + fn into(self) -> UntaggedValue { + UntaggedValue::Primitive(Primitive::String(self.to_string())) + } +} + +impl Into for Value { + fn into(self) -> UntaggedValue { + self.value + } +} + +impl<'a> Into<&'a UntaggedValue> for &'a Value { + fn into(self) -> &'a UntaggedValue { + &self.value + } +} + +impl HasSpan for Value { + fn span(&self) -> Span { + self.tag.span + } +} + +impl ShellTypeName for Value { + fn type_name(&self) -> &'static str { + ShellTypeName::type_name(&self.value) + } +} + +impl ShellTypeName for UntaggedValue { + fn type_name(&self) -> &'static str { + match &self { + UntaggedValue::Primitive(p) => p.type_name(), + UntaggedValue::Row(_) => "row", + UntaggedValue::Table(_) => "table", + UntaggedValue::Error(_) => "error", + UntaggedValue::Block(_) => "block", + } + } +} + +impl From for UntaggedValue { + fn from(input: Primitive) -> UntaggedValue { + UntaggedValue::Primitive(input) + } +} + +impl From for UntaggedValue { + fn from(input: String) -> UntaggedValue { + UntaggedValue::Primitive(Primitive::String(input)) + } +} diff --git a/src/parser/hir/path.rs b/crates/nu-protocol/src/value/column_path.rs similarity index 73% rename from src/parser/hir/path.rs rename to crates/nu-protocol/src/value/column_path.rs index 2e2e6f4248..5695b59572 100644 --- a/src/parser/hir/path.rs +++ b/crates/nu-protocol/src/value/column_path.rs @@ -1,8 +1,7 @@ -use crate::parser::hir::Expression; -use crate::prelude::*; use derive_new::new; -use getset::{Getters, MutGetters}; -use nu_source::{b, span_for_spanned_list, PrettyDebug}; +use getset::Getters; +use nu_source::{b, span_for_spanned_list, DebugDocBuilder, HasFallibleSpan, PrettyDebug, Span}; +use num_bigint::BigInt; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] @@ -86,38 +85,3 @@ impl PathMember { UnspannedPathMember::Int(int.into()).into_path_member(span) } } - -#[derive( - Debug, - Clone, - Eq, - PartialEq, - Ord, - PartialOrd, - Hash, - Getters, - MutGetters, - Serialize, - Deserialize, - new, -)] -#[get = "pub(crate)"] -pub struct Path { - head: Expression, - #[get_mut = "pub(crate)"] - tail: Vec, -} - -impl PrettyDebugWithSource for Path { - fn pretty_debug(&self, source: &str) -> DebugDocBuilder { - self.head.pretty_debug(source) - + b::operator(".") - + b::intersperse(self.tail.iter().map(|m| m.pretty()), b::operator(".")) - } -} - -impl Path { - pub(crate) fn parts(self) -> (Expression, Vec) { - (self.head, self.tail) - } -} diff --git a/crates/nu-protocol/src/value/convert.rs b/crates/nu-protocol/src/value/convert.rs new file mode 100644 index 0000000000..75dd3d0ad9 --- /dev/null +++ b/crates/nu-protocol/src/value/convert.rs @@ -0,0 +1,55 @@ +use nu_errors::{CoerceInto, ShellError}; +use crate::type_name::SpannedTypeName; +use crate::value::dict::Dictionary; +use crate::value::primitive::Primitive; +use crate::value::{UntaggedValue, Value}; +use nu_source::TaggedItem; + +impl std::convert::TryFrom<&Value> for i64 { + type Error = ShellError; + + fn try_from(value: &Value) -> Result { + match &value.value { + UntaggedValue::Primitive(Primitive::Int(int)) => { + int.tagged(&value.tag).coerce_into("converting to i64") + } + _ => Err(ShellError::type_error("Integer", value.spanned_type_name())), + } + } +} + +impl std::convert::TryFrom<&Value> for String { + type Error = ShellError; + + fn try_from(value: &Value) -> Result { + match &value.value { + UntaggedValue::Primitive(Primitive::String(s)) => Ok(s.clone()), + _ => Err(ShellError::type_error("String", value.spanned_type_name())), + } + } +} + +impl std::convert::TryFrom<&Value> for Vec { + type Error = ShellError; + + fn try_from(value: &Value) -> Result, ShellError> { + match &value.value { + UntaggedValue::Primitive(Primitive::Binary(b)) => Ok(b.clone()), + _ => Err(ShellError::type_error("Binary", value.spanned_type_name())), + } + } +} + +impl<'a> std::convert::TryFrom<&'a Value> for &'a Dictionary { + type Error = ShellError; + + fn try_from(value: &'a Value) -> Result<&'a Dictionary, ShellError> { + match &value.value { + UntaggedValue::Row(d) => Ok(d), + _ => Err(ShellError::type_error( + "Dictionary", + value.spanned_type_name(), + )), + } + } +} diff --git a/src/data/base/debug.rs b/crates/nu-protocol/src/value/debug.rs similarity index 76% rename from src/data/base/debug.rs rename to crates/nu-protocol/src/value/debug.rs index 05b8b911bd..c24789340d 100644 --- a/src/data/base/debug.rs +++ b/crates/nu-protocol/src/value/debug.rs @@ -1,7 +1,28 @@ -use crate::data::base::Primitive; -use crate::traits::PrettyType; +use crate::type_name::PrettyType; +use crate::value::primitive::Primitive; +use crate::value::{UntaggedValue, Value}; use nu_source::{b, DebugDocBuilder, PrettyDebug}; +impl PrettyDebug for &Value { + fn pretty(&self) -> DebugDocBuilder { + PrettyDebug::pretty(*self) + } +} + +impl PrettyDebug for Value { + fn pretty(&self) -> DebugDocBuilder { + match &self.value { + UntaggedValue::Primitive(p) => p.pretty(), + UntaggedValue::Row(row) => row.pretty_builder().nest(1).group().into(), + UntaggedValue::Table(table) => { + b::delimit("[", b::intersperse(table, b::space()), "]").nest() + } + UntaggedValue::Error(_) => b::error("error"), + UntaggedValue::Block(_) => b::opaque("block"), + } + } +} + impl PrettyType for Primitive { fn pretty_type(&self) -> DebugDocBuilder { match self { @@ -51,10 +72,10 @@ fn prim(name: impl std::fmt::Debug) -> DebugDocBuilder { b::primitive(format!("{:?}", name)) } -fn ty(name: impl std::fmt::Debug) -> DebugDocBuilder { - b::kind(format!("{:?}", name)) -} - fn primitive_doc(name: impl std::fmt::Debug, ty: impl Into) -> DebugDocBuilder { b::primitive(format!("{:?}", name)) + b::delimit("(", b::kind(ty.into()), ")") } + +fn ty(name: impl std::fmt::Debug) -> DebugDocBuilder { + b::kind(format!("{:?}", name)) +} diff --git a/crates/nu-protocol/src/value/dict.rs b/crates/nu-protocol/src/value/dict.rs new file mode 100644 index 0000000000..d8c588803d --- /dev/null +++ b/crates/nu-protocol/src/value/dict.rs @@ -0,0 +1,140 @@ +use crate::maybe_owned::MaybeOwned; +use crate::value::primitive::Primitive; +use crate::value::{UntaggedValue, Value}; +use derive_new::new; +use getset::Getters; +use indexmap::IndexMap; +use nu_source::{b, DebugDocBuilder, PrettyDebug, Spanned, Tag}; +use serde::{Deserialize, Serialize}; +use std::cmp::{Ord, Ordering, PartialOrd}; + +#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone, Getters, new)] +pub struct Dictionary { + #[get = "pub"] + pub entries: IndexMap, +} + +impl PartialOrd for Dictionary { + fn partial_cmp(&self, other: &Dictionary) -> Option { + let this: Vec<&String> = self.entries.keys().collect(); + let that: Vec<&String> = other.entries.keys().collect(); + + if this != that { + return this.partial_cmp(&that); + } + + let this: Vec<&Value> = self.entries.values().collect(); + let that: Vec<&Value> = self.entries.values().collect(); + + this.partial_cmp(&that) + } +} + +impl Ord for Dictionary { + fn cmp(&self, other: &Dictionary) -> Ordering { + let this: Vec<&String> = self.entries.keys().collect(); + let that: Vec<&String> = other.entries.keys().collect(); + + if this != that { + return this.cmp(&that); + } + + let this: Vec<&Value> = self.entries.values().collect(); + let that: Vec<&Value> = self.entries.values().collect(); + + this.cmp(&that) + } +} + +impl PartialEq for Dictionary { + fn eq(&self, other: &Value) -> bool { + match &other.value { + UntaggedValue::Row(d) => self == d, + _ => false, + } + } +} + +#[derive(Debug, new)] +struct DebugEntry<'a> { + key: &'a str, + value: &'a Value, +} + +impl<'a> PrettyDebug for DebugEntry<'a> { + fn pretty(&self) -> DebugDocBuilder { + (b::key(self.key.to_string()) + b::equals() + self.value.pretty().as_value()).group() + } +} + +impl PrettyDebug for Dictionary { + fn pretty(&self) -> DebugDocBuilder { + b::delimit( + "(", + b::intersperse( + self.entries() + .iter() + .map(|(key, value)| DebugEntry::new(key, value)), + b::space(), + ), + ")", + ) + } +} + +impl From> for Dictionary { + fn from(input: IndexMap) -> Dictionary { + let mut out = IndexMap::default(); + + for (key, value) in input { + out.insert(key, value); + } + + Dictionary::new(out) + } +} + +impl Dictionary { + pub fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value> { + match self.entries.get(desc) { + Some(v) => MaybeOwned::Borrowed(v), + None => MaybeOwned::Owned( + UntaggedValue::Primitive(Primitive::Nothing).into_untagged_value(), + ), + } + } + + pub fn keys(&self) -> impl Iterator { + self.entries.keys() + } + + pub fn get_data_by_key(&self, name: Spanned<&str>) -> Option { + let result = self + .entries + .iter() + .find(|(desc_name, _)| *desc_name == name.item)? + .1; + + Some( + result + .value + .clone() + .into_value(Tag::new(result.tag.anchor(), name.span)), + ) + } + + pub fn get_mut_data_by_key(&mut self, name: &str) -> Option<&mut Value> { + match self + .entries + .iter_mut() + .find(|(desc_name, _)| *desc_name == name) + { + Some((_, v)) => Some(v), + None => None, + } + } + + pub fn insert_data_at_key(&mut self, name: &str, value: Value) { + self.entries.insert(name.to_string(), value); + } +} diff --git a/crates/nu-protocol/src/value/evaluate.rs b/crates/nu-protocol/src/value/evaluate.rs new file mode 100644 index 0000000000..9dea813809 --- /dev/null +++ b/crates/nu-protocol/src/value/evaluate.rs @@ -0,0 +1,102 @@ +use crate::value::{Primitive, UntaggedValue, Value}; +use indexmap::IndexMap; +use nu_errors::ShellError; +use query_interface::{interfaces, vtable_for, Object, ObjectHash}; +use serde::{Deserialize, Serialize}; +use std::cmp::{Ord, Ordering, PartialOrd}; +use std::fmt::Debug; + +#[derive(Debug)] +pub struct Scope { + pub it: Value, + pub vars: IndexMap, +} + +impl Scope { + pub fn new(it: Value) -> Scope { + Scope { + it, + vars: IndexMap::new(), + } + } +} + +impl Scope { + pub fn empty() -> Scope { + Scope { + it: UntaggedValue::Primitive(Primitive::Nothing).into_untagged_value(), + vars: IndexMap::new(), + } + } + + pub fn it_value(value: Value) -> Scope { + Scope { + it: value, + vars: IndexMap::new(), + } + } +} + +#[typetag::serde(tag = "type")] +pub trait EvaluateTrait: Debug + Send + Sync + Object + ObjectHash + 'static { + fn invoke(&self, scope: &Scope) -> Result; + fn clone_box(&self) -> Evaluate; +} + +interfaces!(Evaluate: dyn ObjectHash); + +#[typetag::serde] +impl EvaluateTrait for Evaluate { + fn invoke(&self, scope: &Scope) -> Result { + self.expr.invoke(scope) + } + + fn clone_box(&self) -> Evaluate { + self.expr.clone_box() + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Evaluate { + expr: Box, +} + +impl Evaluate { + pub fn new(evaluate: impl EvaluateTrait) -> Evaluate { + Evaluate { + expr: Box::new(evaluate), + } + } +} + +impl std::hash::Hash for Evaluate { + fn hash(&self, state: &mut H) { + self.expr.obj_hash(state) + } +} + +impl Clone for Evaluate { + fn clone(&self) -> Evaluate { + self.expr.clone_box() + } +} + +impl Ord for Evaluate { + fn cmp(&self, _: &Self) -> Ordering { + Ordering::Equal + } +} + +impl PartialOrd for Evaluate { + fn partial_cmp(&self, _: &Evaluate) -> Option { + Some(Ordering::Equal) + } +} + +impl PartialEq for Evaluate { + fn eq(&self, _: &Evaluate) -> bool { + true + } +} + +impl Eq for Evaluate {} diff --git a/crates/nu-protocol/src/value/primitive.rs b/crates/nu-protocol/src/value/primitive.rs new file mode 100644 index 0000000000..34bacb69ca --- /dev/null +++ b/crates/nu-protocol/src/value/primitive.rs @@ -0,0 +1,65 @@ +use crate::type_name::ShellTypeName; +use crate::value::column_path::ColumnPath; +use crate::value::{serde_bigdecimal, serde_bigint}; +use bigdecimal::BigDecimal; +use chrono::{DateTime, Utc}; +use num_bigint::BigInt; +use num_traits::cast::FromPrimitive; +use serde::{Deserialize, Serialize}; +use std::path::PathBuf; + +#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Deserialize, Serialize)] +pub enum Primitive { + Nothing, + #[serde(with = "serde_bigint")] + Int(BigInt), + #[serde(with = "serde_bigdecimal")] + Decimal(BigDecimal), + Bytes(u64), + String(String), + ColumnPath(ColumnPath), + Pattern(String), + Boolean(bool), + Date(DateTime), + Duration(u64), // Duration in seconds + Path(PathBuf), + #[serde(with = "serde_bytes")] + Binary(Vec), + + // Stream markers (used as bookend markers rather than actual values) + BeginningOfStream, + EndOfStream, +} + +impl From for Primitive { + fn from(decimal: BigDecimal) -> Primitive { + Primitive::Decimal(decimal) + } +} + +impl From for Primitive { + fn from(float: f64) -> Primitive { + Primitive::Decimal(BigDecimal::from_f64(float).unwrap()) + } +} + +impl ShellTypeName for Primitive { + fn type_name(&self) -> &'static str { + match self { + Primitive::Nothing => "nothing", + Primitive::Int(_) => "integer", + Primitive::Decimal(_) => "decimal", + Primitive::Bytes(_) => "bytes", + Primitive::String(_) => "string", + Primitive::ColumnPath(_) => "column path", + Primitive::Pattern(_) => "pattern", + Primitive::Boolean(_) => "boolean", + Primitive::Date(_) => "date", + Primitive::Duration(_) => "duration", + Primitive::Path(_) => "file path", + Primitive::Binary(_) => "binary", + Primitive::BeginningOfStream => "marker", + Primitive::EndOfStream => "marker", + } + } +} diff --git a/crates/nu-protocol/src/value/serde_bigdecimal.rs b/crates/nu-protocol/src/value/serde_bigdecimal.rs new file mode 100644 index 0000000000..423826887c --- /dev/null +++ b/crates/nu-protocol/src/value/serde_bigdecimal.rs @@ -0,0 +1,24 @@ +use bigdecimal::BigDecimal; +use num_traits::cast::FromPrimitive; +use num_traits::cast::ToPrimitive; + +pub fn serialize(big_decimal: &BigDecimal, serializer: S) -> Result +where + S: serde::Serializer, +{ + serde::Serialize::serialize( + &big_decimal + .to_f64() + .ok_or(serde::ser::Error::custom("expected a f64-sized bignum"))?, + serializer, + ) +} + +pub fn deserialize<'de, D>(deserializer: D) -> Result +where + D: serde::Deserializer<'de>, +{ + let x: f64 = serde::Deserialize::deserialize(deserializer)?; + Ok(BigDecimal::from_f64(x) + .ok_or(serde::de::Error::custom("expected a f64-sized bigdecimal"))?) +} diff --git a/crates/nu-protocol/src/value/serde_bigint.rs b/crates/nu-protocol/src/value/serde_bigint.rs new file mode 100644 index 0000000000..2ab4ec4dfe --- /dev/null +++ b/crates/nu-protocol/src/value/serde_bigint.rs @@ -0,0 +1,23 @@ +use num_bigint::BigInt; +use num_traits::cast::FromPrimitive; +use num_traits::cast::ToPrimitive; + +pub fn serialize(big_int: &BigInt, serializer: S) -> Result +where + S: serde::Serializer, +{ + serde::Serialize::serialize( + &big_int + .to_i64() + .ok_or(serde::ser::Error::custom("expected a i64-sized bignum"))?, + serializer, + ) +} + +pub fn deserialize<'de, D>(deserializer: D) -> Result +where + D: serde::Deserializer<'de>, +{ + let x: i64 = serde::Deserialize::deserialize(deserializer)?; + Ok(BigInt::from_i64(x).ok_or(serde::de::Error::custom("expected a i64-sized bignum"))?) +} diff --git a/crates/nu-textview/Cargo.toml b/crates/nu-textview/Cargo.toml new file mode 100644 index 0000000000..3baaf708f2 --- /dev/null +++ b/crates/nu-textview/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "nu-textview" +version = "0.1.0" +authors = ["Yehuda Katz "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[[bin]] +name = "nu_plugin_textview" +path = "src/main.rs" +required-features = ["textview"] + +[dependencies] + +syntect = { version = "3.2.0" } +ansi_term = "0.12.1" +crossterm = { version = "0.10.2" } +nu = { path = "../.." } +nu-protocol = { path = "../nu-protocol" } +nu-source = { path = "../nu-source" } +url = "2.1.0" diff --git a/src/plugins/textview.rs b/crates/nu-textview/src/main.rs similarity index 97% rename from src/plugins/textview.rs rename to crates/nu-textview/src/main.rs index dd6d3da341..208eaae810 100644 --- a/src/plugins/textview.rs +++ b/crates/nu-textview/src/main.rs @@ -1,8 +1,7 @@ use crossterm::{cursor, terminal, RawScreen}; use crossterm::{InputEvent, KeyEvent}; -use nu::{ - outln, serve_plugin, CallInfo, Plugin, Primitive, ShellError, Signature, UntaggedValue, Value, -}; +use nu::{CallInfo, Plugin, Primitive, ShellError, Signature, UntaggedValue, Value}; +use nu_protocol::{outln, serve_plugin}; use nu_source::AnchorLocation; use syntect::easy::HighlightLines; @@ -252,12 +251,12 @@ fn view_text_value(value: &Value) { Some(extension) => { // Load these once at the start of your program let ps: SyntaxSet = syntect::dumps::from_binary(include_bytes!( - "../../assets/syntaxes.bin" + "../../../assets/syntaxes.bin" )); if let Some(syntax) = ps.find_syntax_by_extension(&extension) { let ts: ThemeSet = syntect::dumps::from_binary(include_bytes!( - "../../assets/themes.bin" + "../../../assets/themes.bin" )); let mut h = HighlightLines::new(syntax, &ts.themes["OneHalfDark"]); diff --git a/src/cli.rs b/src/cli.rs index 4554b6bdcd..493c61dc8c 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,27 +1,20 @@ use crate::commands::classified::{ - ClassifiedCommand, ClassifiedInputStream, ClassifiedPipeline, ExternalArg, ExternalArgs, - ExternalCommand, InternalCommand, StreamNext, + run_external_command, run_internal_command, ClassifiedInputStream, StreamNext, }; use crate::commands::plugin::JsonRpc; use crate::commands::plugin::{PluginCommand, PluginSink}; use crate::commands::whole_stream_command; use crate::context::Context; -use crate::data::{ - base::{UntaggedValue, Value}, - config, -}; -pub(crate) use crate::errors::ShellError; +use crate::data::config; #[cfg(not(feature = "starship-prompt"))] use crate::git::current_branch; -use crate::parser::registry::Signature; -use crate::parser::{ - hir, - hir::syntax_shape::{expand_syntax, ExpandContext, PipelineShape}, - hir::{expand_external_tokens::ExternalTokensShape, tokens_iterator::TokensIterator}, - TokenNode, -}; use crate::prelude::*; -use nu_source::{Spanned, Tagged}; +use nu_errors::ShellError; +use nu_parser::{ + expand_syntax, hir, ClassifiedCommand, ClassifiedPipeline, InternalCommand, PipelineShape, + TokenNode, TokensIterator, +}; +use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value}; use log::{debug, log_enabled, trace}; use rustyline::error::ReadlineError; @@ -32,21 +25,6 @@ use std::iter::Iterator; use std::path::PathBuf; use std::sync::atomic::Ordering; -#[derive(Debug)] -pub enum MaybeOwned<'a, T> { - Owned(T), - Borrowed(&'a T), -} - -impl MaybeOwned<'_, T> { - pub fn borrow(&self) -> &T { - match self { - MaybeOwned::Owned(v) => v, - MaybeOwned::Borrowed(v) => v, - } - } -} - fn load_plugin(path: &std::path::Path, context: &mut Context) -> Result<(), ShellError> { let mut child = std::process::Command::new(path) .stdin(std::process::Stdio::piped()) @@ -570,7 +548,7 @@ async fn process_line(readline: Result, ctx: &mut Context Ok(line) => { let line = chomp_newline(line); - let result = match crate::parser::parse(&line) { + let result = match nu_parser::parse(&line) { Err(err) => { return LineResult::Error(line.to_string(), err); } @@ -642,20 +620,20 @@ async fn process_line(readline: Result, ctx: &mut Context ( Some(ClassifiedCommand::Internal(left)), Some(ClassifiedCommand::External(_)), - ) => match left.run(ctx, input, Text::from(line)) { + ) => match run_internal_command(left, ctx, input, Text::from(line)).await { Ok(val) => ClassifiedInputStream::from_input_stream(val), Err(err) => return LineResult::Error(line.to_string(), err), }, (Some(ClassifiedCommand::Internal(left)), Some(_)) => { - match left.run(ctx, input, Text::from(line)) { + match run_internal_command(left, ctx, input, Text::from(line)).await { Ok(val) => ClassifiedInputStream::from_input_stream(val), Err(err) => return LineResult::Error(line.to_string(), err), } } (Some(ClassifiedCommand::Internal(left)), None) => { - match left.run(ctx, input, Text::from(line)) { + match run_internal_command(left, ctx, input, Text::from(line)).await { Ok(val) => { use futures::stream::TryStreamExt; @@ -688,20 +666,20 @@ async fn process_line(readline: Result, ctx: &mut Context ( Some(ClassifiedCommand::External(left)), Some(ClassifiedCommand::External(_)), - ) => match left.run(ctx, input, StreamNext::External).await { + ) => match run_external_command(left, ctx, input, StreamNext::External).await { Ok(val) => val, Err(err) => return LineResult::Error(line.to_string(), err), }, (Some(ClassifiedCommand::External(left)), Some(_)) => { - match left.run(ctx, input, StreamNext::Internal).await { + match run_external_command(left, ctx, input, StreamNext::Internal).await { Ok(val) => val, Err(err) => return LineResult::Error(line.to_string(), err), } } (Some(ClassifiedCommand::External(left)), None) => { - match left.run(ctx, input, StreamNext::Last).await { + match run_external_command(left, ctx, input, StreamNext::Last).await { Ok(val) => val, Err(err) => return LineResult::Error(line.to_string(), err), } @@ -744,39 +722,13 @@ fn classify_pipeline( result } -// Classify this command as an external command, which doesn't give special meaning -// to nu syntactic constructs, and passes all arguments to the external command as -// strings. -pub(crate) fn external_command( - tokens: &mut TokensIterator, - context: &ExpandContext, - name: Tagged<&str>, -) -> Result { - let Spanned { item, span } = expand_syntax(&ExternalTokensShape, tokens, context)?.tokens; - - Ok(ClassifiedCommand::External(ExternalCommand { - name: name.to_string(), - name_tag: name.tag(), - args: ExternalArgs { - list: item - .iter() - .map(|x| ExternalArg { - tag: x.span.into(), - arg: x.item.clone(), - }) - .collect(), - span, - }, - })) -} - pub fn print_err(err: ShellError, host: &dyn Host, source: &Text) { let diag = err.to_diagnostic(); let writer = host.err_termcolor(); let mut source = source.to_string(); source.push_str(" "); - let files = crate::parser::Files::new(source); + let files = nu_parser::Files::new(source); let _ = std::panic::catch_unwind(move || { let _ = language_reporting::emit( &mut writer.lock(), diff --git a/src/commands.rs b/src/commands.rs index 705deb1d56..f2e6ef477b 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -99,7 +99,6 @@ pub(crate) use command::{ }; pub(crate) use append::Append; -pub(crate) use classified::ClassifiedCommand; pub(crate) use compact::Compact; pub(crate) use config::Config; pub(crate) use count::Count; diff --git a/src/commands/append.rs b/src/commands/append.rs index a41e3e4a23..9866e05f95 100644 --- a/src/commands/append.rs +++ b/src/commands/append.rs @@ -1,7 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; -use crate::parser::CommandRegistry; +use crate::context::CommandRegistry; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Signature, SyntaxShape, Value}; #[derive(Deserialize)] struct AppendArgs { diff --git a/src/commands/args.rs b/src/commands/args.rs index 85329af5a1..2e6961888c 100644 --- a/src/commands/args.rs +++ b/src/commands/args.rs @@ -1,4 +1,4 @@ -use crate::data::Value; +use nu_protocol::Value; #[derive(Debug)] pub enum LogLevel {} diff --git a/src/commands/autoview.rs b/src/commands/autoview.rs index 26e9532697..c515a3f506 100644 --- a/src/commands/autoview.rs +++ b/src/commands/autoview.rs @@ -1,9 +1,11 @@ use crate::commands::{RawCommandArgs, WholeStreamCommand}; -use crate::errors::ShellError; -use crate::parser::hir::{Expression, NamedArguments}; +use crate::data::value; +use nu_parser::hir::{Expression, NamedArguments}; use crate::prelude::*; use futures::stream::TryStreamExt; +use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; use std::sync::atomic::Ordering; +use nu_errors::{ShellError}; pub struct Autoview; @@ -137,7 +139,7 @@ pub fn autoview( } if anchor.is_some() => { if let Some(text) = text { let mut stream = VecDeque::new(); - stream.push_back(UntaggedValue::string(s).into_value(Tag { anchor, span })); + stream.push_back(value::string(s).into_value(Tag { anchor, span })); let result = text.run(raw.with_input(stream.into()), &context.commands); result.collect::>().await; } else { @@ -150,6 +152,24 @@ pub fn autoview( } => { outln!("{}", s); } + Value { + value: UntaggedValue::Primitive(Primitive::Path(s)), + .. + } => { + outln!("{}", s.display()); + } + Value { + value: UntaggedValue::Primitive(Primitive::Int(n)), + .. + } => { + outln!("{}", n); + } + Value { + value: UntaggedValue::Primitive(Primitive::Decimal(n)), + .. + } => { + outln!("{}", n); + } Value { value: UntaggedValue::Primitive(Primitive::Binary(ref b)), .. } => { if let Some(binary) = binary { @@ -188,7 +208,7 @@ pub fn autoview( // Needed for async_stream to type check if false { - yield ReturnSuccess::value(UntaggedValue::nothing().into_untagged_value()); + yield ReturnSuccess::value(value::nothing().into_untagged_value()); } })) } diff --git a/src/commands/cd.rs b/src/commands/cd.rs index 65cc45231d..fe5381f27b 100644 --- a/src/commands/cd.rs +++ b/src/commands/cd.rs @@ -1,6 +1,7 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; use crate::prelude::*; +use nu_protocol::{SyntaxShape, Signature}; +use nu_errors::ShellError; pub struct CD; diff --git a/src/commands/clip.rs b/src/commands/clip.rs index 3b59d9eed6..de10ffca14 100644 --- a/src/commands/clip.rs +++ b/src/commands/clip.rs @@ -2,9 +2,10 @@ pub mod clipboard { use crate::commands::WholeStreamCommand; use crate::context::CommandRegistry; - use crate::errors::ShellError; use crate::prelude::*; use futures::stream::StreamExt; + use nu_errors::ShellError; + use nu_protocol::{ReturnValue, Signature, Value}; use clipboard::{ClipboardContext, ClipboardProvider}; @@ -67,7 +68,7 @@ pub mod clipboard { } let string: String = match i.as_string() { - Ok(string) => string, + Ok(string) => string.to_string(), Err(_) => { return OutputStream::one(Err(ShellError::labeled_error( "Given non-string data", diff --git a/src/commands/command.rs b/src/commands/command.rs index 97c4fa373a..9be654ce0e 100644 --- a/src/commands/command.rs +++ b/src/commands/command.rs @@ -1,14 +1,14 @@ -use crate::data::Value; -use crate::errors::ShellError; -use crate::evaluate::Scope; -use crate::parser::hir; -use crate::parser::{registry, ConfigDeserializer}; +use crate::context::CommandRegistry; +use crate::deserializer::ConfigDeserializer; +use crate::evaluate::evaluate_args::evaluate_args; use crate::prelude::*; use derive_new::new; use getset::Getters; +use nu_errors::ShellError; +use nu_parser::hir; +use nu_protocol::{CallInfo, EvaluatedArgs, ReturnValue, Scope, Signature, Value}; use serde::{Deserialize, Serialize}; use std::ops::Deref; -use std::path::PathBuf; use std::sync::atomic::AtomicBool; #[derive(Deserialize, Serialize, Debug, Clone)] @@ -21,10 +21,10 @@ pub struct UnevaluatedCallInfo { impl UnevaluatedCallInfo { pub fn evaluate( self, - registry: ®istry::CommandRegistry, + registry: &CommandRegistry, scope: &Scope, ) -> Result { - let args = self.args.evaluate(registry, scope, &self.source)?; + let args = evaluate_args(&self.args, registry, scope, &self.source)?; Ok(CallInfo { args, @@ -33,14 +33,16 @@ impl UnevaluatedCallInfo { } } -#[derive(Deserialize, Serialize, Debug, Clone)] -pub struct CallInfo { - pub args: registry::EvaluatedArgs, - pub name_tag: Tag, +pub trait CallInfoExt { + fn process<'de, T: Deserialize<'de>>( + &self, + shell_manager: &ShellManager, + callback: fn(T, &RunnablePerItemContext) -> Result, + ) -> Result, ShellError>; } -impl CallInfo { - pub fn process<'de, T: Deserialize<'de>>( +impl CallInfoExt for CallInfo { + fn process<'de, T: Deserialize<'de>>( &self, shell_manager: &ShellManager, callback: fn(T, &RunnablePerItemContext) -> Result, @@ -87,10 +89,6 @@ impl RawCommandArgs { input: input.into(), } } - - pub fn source(&self) -> Text { - self.call_info.source.clone() - } } impl std::fmt::Debug for CommandArgs { @@ -102,7 +100,7 @@ impl std::fmt::Debug for CommandArgs { impl CommandArgs { pub fn evaluate_once( self, - registry: ®istry::CommandRegistry, + registry: &CommandRegistry, ) -> Result { let host = self.host.clone(); let ctrl_c = self.ctrl_c.clone(); @@ -198,12 +196,6 @@ pub struct RunnablePerItemContext { pub name: Tag, } -impl RunnablePerItemContext { - pub fn cwd(&self) -> PathBuf { - PathBuf::from(self.shell_manager.path()) - } -} - pub struct RunnableContext { pub input: InputStream, pub shell_manager: ShellManager, @@ -295,7 +287,7 @@ impl EvaluatedWholeStreamCommandArgs { self.args.call_info.name_tag.clone() } - pub fn parts(self) -> (InputStream, registry::EvaluatedArgs) { + pub fn parts(self) -> (InputStream, EvaluatedArgs) { let EvaluatedWholeStreamCommandArgs { args, input } = self; (input, args.call_info.args) @@ -349,112 +341,19 @@ pub struct EvaluatedCommandArgs { } impl EvaluatedCommandArgs { - pub fn call_args(&self) -> ®istry::EvaluatedArgs { - &self.call_info.args - } - pub fn nth(&self, pos: usize) -> Option<&Value> { self.call_info.args.nth(pos) } - pub fn expect_nth(&self, pos: usize) -> Result<&Value, ShellError> { - self.call_info.args.expect_nth(pos) - } - - pub fn len(&self) -> usize { - self.call_info.args.len() - } - pub fn get(&self, name: &str) -> Option<&Value> { self.call_info.args.get(name) } - pub fn slice_from(&self, from: usize) -> Vec { - let positional = &self.call_info.args.positional; - - match positional { - None => vec![], - Some(list) => list[from..].to_vec(), - } - } - pub fn has(&self, name: &str) -> bool { self.call_info.args.has(name) } } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum CommandAction { - ChangePath(String), - Exit, - Error(ShellError), - EnterShell(String), - EnterValueShell(Value), - EnterHelpShell(Value), - PreviousShell, - NextShell, - LeaveShell, -} - -impl PrettyDebug for CommandAction { - fn pretty(&self) -> DebugDocBuilder { - match self { - CommandAction::ChangePath(path) => b::typed("change path", b::description(path)), - CommandAction::Exit => b::description("exit"), - CommandAction::Error(_) => b::error("error"), - CommandAction::EnterShell(s) => b::typed("enter shell", b::description(s)), - CommandAction::EnterValueShell(v) => b::typed("enter value shell", v.pretty()), - CommandAction::EnterHelpShell(v) => b::typed("enter help shell", v.pretty()), - CommandAction::PreviousShell => b::description("previous shell"), - CommandAction::NextShell => b::description("next shell"), - CommandAction::LeaveShell => b::description("leave shell"), - } - } -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum ReturnSuccess { - Value(Value), - DebugValue(Value), - Action(CommandAction), -} - -impl PrettyDebug for ReturnSuccess { - fn pretty(&self) -> DebugDocBuilder { - match self { - ReturnSuccess::Value(value) => b::typed("value", value.pretty()), - ReturnSuccess::DebugValue(value) => b::typed("debug value", value.pretty()), - ReturnSuccess::Action(action) => b::typed("action", action.pretty()), - } - } -} - -pub type ReturnValue = Result; - -impl From for ReturnValue { - fn from(input: Value) -> ReturnValue { - Ok(ReturnSuccess::Value(input)) - } -} - -impl ReturnSuccess { - pub fn change_cwd(path: String) -> ReturnValue { - Ok(ReturnSuccess::Action(CommandAction::ChangePath(path))) - } - - pub fn value(input: impl Into) -> ReturnValue { - Ok(ReturnSuccess::Value(input.into())) - } - - pub fn debug_value(input: impl Into) -> ReturnValue { - Ok(ReturnSuccess::DebugValue(input.into())) - } - - pub fn action(input: CommandAction) -> ReturnValue { - Ok(ReturnSuccess::Action(input)) - } -} - pub trait WholeStreamCommand: Send + Sync { fn name(&self) -> &str; @@ -474,7 +373,7 @@ pub trait WholeStreamCommand: Send + Sync { fn run( &self, args: CommandArgs, - registry: ®istry::CommandRegistry, + registry: &CommandRegistry, ) -> Result; fn is_binary(&self) -> bool { @@ -570,7 +469,7 @@ impl Command { } } - pub fn run(&self, args: CommandArgs, registry: ®istry::CommandRegistry) -> OutputStream { + pub fn run(&self, args: CommandArgs, registry: &CommandRegistry) -> OutputStream { match self { Command::WholeStream(command) => match command.run(args, registry) { Ok(stream) => stream, @@ -637,7 +536,7 @@ impl WholeStreamCommand for FnFilterCommand { fn run( &self, args: CommandArgs, - registry: ®istry::CommandRegistry, + registry: &CommandRegistry, ) -> Result { let CommandArgs { host, @@ -649,7 +548,7 @@ impl WholeStreamCommand for FnFilterCommand { let host: Arc> = host.clone(); let shell_manager = shell_manager.clone(); - let registry: registry::CommandRegistry = registry.clone(); + let registry: CommandRegistry = registry.clone(); let func = self.func; let result = input.values.map(move |it| { diff --git a/src/commands/compact.rs b/src/commands/compact.rs index b2bd01b29d..94ee9dc4f7 100644 --- a/src/commands/compact.rs +++ b/src/commands/compact.rs @@ -1,9 +1,9 @@ use crate::commands::WholeStreamCommand; -use crate::data::base::UntaggedValue; -use crate::errors::ShellError; -use crate::parser::registry::{CommandRegistry, Signature}; +use crate::context::CommandRegistry; use crate::prelude::*; use futures::stream::StreamExt; +use nu_errors::ShellError; +use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; use nu_source::Tagged; pub struct Compact; diff --git a/src/commands/config.rs b/src/commands/config.rs index 1cabfd2c57..eaa7dbab0b 100644 --- a/src/commands/config.rs +++ b/src/commands/config.rs @@ -1,9 +1,9 @@ use crate::commands::WholeStreamCommand; -use crate::data::{config, Value}; -use crate::errors::ShellError; -use crate::parser::hir::SyntaxShape; -use crate::parser::registry::{self}; +use crate::context::CommandRegistry; +use crate::data::config; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_source::Tagged; use std::path::PathBuf; @@ -55,7 +55,7 @@ impl WholeStreamCommand for Config { fn run( &self, args: CommandArgs, - registry: ®istry::CommandRegistry, + registry: &CommandRegistry, ) -> Result { args.process(registry, config)?.run() } diff --git a/src/commands/count.rs b/src/commands/count.rs index 1bfa746f6a..f6b7b78cb4 100644 --- a/src/commands/count.rs +++ b/src/commands/count.rs @@ -1,9 +1,10 @@ use crate::commands::WholeStreamCommand; -use crate::data::Value; -use crate::errors::ShellError; -use crate::parser::CommandRegistry; +use crate::context::CommandRegistry; +use crate::data::value; use crate::prelude::*; use futures::stream::StreamExt; +use nu_errors::ShellError; +use nu_protocol::{ReturnSuccess, Signature, Value}; pub struct Count; @@ -39,7 +40,7 @@ pub fn count( let stream = async_stream! { let rows: Vec = input.values.collect().await; - yield ReturnSuccess::value(UntaggedValue::int(rows.len()).into_value(name)) + yield ReturnSuccess::value(value::int(rows.len()).into_value(name)) }; Ok(stream.to_output_stream()) diff --git a/src/commands/cp.rs b/src/commands/cp.rs index 2ef0af269b..4919dc3758 100644 --- a/src/commands/cp.rs +++ b/src/commands/cp.rs @@ -1,8 +1,8 @@ use crate::commands::command::RunnablePerItemContext; -use crate::errors::ShellError; -use crate::parser::hir::SyntaxShape; -use crate::parser::registry::{CommandRegistry, Signature}; +use crate::context::CommandRegistry; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{CallInfo, Signature, SyntaxShape, Value}; use nu_source::Tagged; use std::path::PathBuf; diff --git a/src/commands/date.rs b/src/commands/date.rs index d4c094819f..438939daca 100644 --- a/src/commands/date.rs +++ b/src/commands/date.rs @@ -1,13 +1,14 @@ -use crate::data::{Dictionary, Value}; -use crate::errors::ShellError; use crate::prelude::*; use chrono::{DateTime, Local, Utc}; +use nu_errors::ShellError; +use nu_protocol::{Dictionary, Value}; use crate::commands::WholeStreamCommand; -use crate::parser::registry::Signature; +use crate::data::value; use chrono::{Datelike, TimeZone, Timelike}; use core::fmt::Display; use indexmap::IndexMap; +use nu_protocol::{Signature, UntaggedValue}; pub struct Date; @@ -41,35 +42,23 @@ where { let mut indexmap = IndexMap::new(); - indexmap.insert( - "year".to_string(), - UntaggedValue::int(dt.year()).into_value(&tag), - ); - indexmap.insert( - "month".to_string(), - UntaggedValue::int(dt.month()).into_value(&tag), - ); - indexmap.insert( - "day".to_string(), - UntaggedValue::int(dt.day()).into_value(&tag), - ); - indexmap.insert( - "hour".to_string(), - UntaggedValue::int(dt.hour()).into_value(&tag), - ); + indexmap.insert("year".to_string(), value::int(dt.year()).into_value(&tag)); + indexmap.insert("month".to_string(), value::int(dt.month()).into_value(&tag)); + indexmap.insert("day".to_string(), value::int(dt.day()).into_value(&tag)); + indexmap.insert("hour".to_string(), value::int(dt.hour()).into_value(&tag)); indexmap.insert( "minute".to_string(), - UntaggedValue::int(dt.minute()).into_value(&tag), + value::int(dt.minute()).into_value(&tag), ); indexmap.insert( "second".to_string(), - UntaggedValue::int(dt.second()).into_value(&tag), + value::int(dt.second()).into_value(&tag), ); let tz = dt.offset(); indexmap.insert( "timezone".to_string(), - UntaggedValue::string(format!("{}", tz)).into_value(&tag), + value::string(format!("{}", tz)).into_value(&tag), ); UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag) diff --git a/src/commands/debug.rs b/src/commands/debug.rs index 63662fece5..e19995e6b1 100644 --- a/src/commands/debug.rs +++ b/src/commands/debug.rs @@ -1,5 +1,8 @@ use crate::commands::WholeStreamCommand; +use crate::data::value; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{ReturnSuccess, Signature}; pub struct Debug; @@ -34,8 +37,6 @@ fn debug_value( ) -> Result { Ok(input .values - .map(|v| { - ReturnSuccess::value(UntaggedValue::string(format!("{:?}", v)).into_untagged_value()) - }) + .map(|v| ReturnSuccess::value(value::string(format!("{:?}", v)).into_untagged_value())) .to_output_stream()) } diff --git a/src/commands/default.rs b/src/commands/default.rs index 9107eb9d0d..c423f06b2b 100644 --- a/src/commands/default.rs +++ b/src/commands/default.rs @@ -1,7 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; -use crate::parser::CommandRegistry; +use crate::context::CommandRegistry; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_source::Tagged; #[derive(Deserialize)] diff --git a/src/commands/echo.rs b/src/commands/echo.rs index 45b6daf479..50a995ae9d 100644 --- a/src/commands/echo.rs +++ b/src/commands/echo.rs @@ -1,8 +1,7 @@ -use crate::data::Value; -use crate::errors::ShellError; +use crate::data::value; use crate::prelude::*; - -use crate::parser::registry::Signature; +use nu_errors::ShellError; +use nu_protocol::{CallInfo, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; pub struct Echo; @@ -42,7 +41,7 @@ fn run( match i.as_string() { Ok(s) => { output.push(Ok(ReturnSuccess::Value( - UntaggedValue::string(s).into_value(i.tag.clone()), + value::string(s).into_value(i.tag.clone()), ))); } _ => match i { diff --git a/src/commands/enter.rs b/src/commands/enter.rs index 66d5c0c86e..26e55291ff 100644 --- a/src/commands/enter.rs +++ b/src/commands/enter.rs @@ -1,9 +1,12 @@ -use crate::commands::command::CommandAction; use crate::commands::PerItemCommand; use crate::commands::UnevaluatedCallInfo; -use crate::errors::ShellError; -use crate::parser::registry; +use crate::context::CommandRegistry; +use crate::data::value; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{ + CallInfo, CommandAction, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, +}; use std::path::PathBuf; pub struct Enter; @@ -13,7 +16,7 @@ impl PerItemCommand for Enter { "enter" } - fn signature(&self) -> registry::Signature { + fn signature(&self) -> Signature { Signature::build("enter").required( "location", SyntaxShape::Path, @@ -28,7 +31,7 @@ impl PerItemCommand for Enter { fn run( &self, call_info: &CallInfo, - registry: ®istry::CommandRegistry, + registry: &CommandRegistry, raw_args: &RawCommandArgs, _input: Value, ) -> Result { @@ -51,12 +54,12 @@ impl PerItemCommand for Enter { if registry.has(command) { Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell( - UntaggedValue::string(command).into_value(Tag::unknown()), + value::string(command).into_value(Tag::unknown()), )))] .into()) } else { Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell( - UntaggedValue::nothing().into_value(Tag::unknown()), + value::nothing().into_value(Tag::unknown()), )))] .into()) } @@ -93,7 +96,7 @@ impl PerItemCommand for Enter { ctrl_c: raw_args.ctrl_c, shell_manager: raw_args.shell_manager, call_info: UnevaluatedCallInfo { - args: crate::parser::hir::Call { + args: nu_parser::hir::Call { head: raw_args.call_info.args.head, positional: None, named: None, diff --git a/src/commands/env.rs b/src/commands/env.rs index add9df82ff..e7385c3202 100644 --- a/src/commands/env.rs +++ b/src/commands/env.rs @@ -1,12 +1,11 @@ use crate::cli::History; -use crate::data::config; -use crate::data::{Dictionary, Value}; -use crate::errors::ShellError; +use crate::data::{config, value}; use crate::prelude::*; use crate::TaggedDictBuilder; +use nu_errors::ShellError; +use nu_protocol::{Dictionary, Signature, UntaggedValue, Value}; use crate::commands::WholeStreamCommand; -use crate::parser::registry::Signature; use indexmap::IndexMap; pub struct Env; @@ -37,39 +36,24 @@ pub fn get_environment(tag: Tag) -> Result> { let mut indexmap = IndexMap::new(); let path = std::env::current_dir()?; - indexmap.insert( - "cwd".to_string(), - UntaggedValue::path(path).into_value(&tag), - ); + indexmap.insert("cwd".to_string(), value::path(path).into_value(&tag)); if let Some(home) = dirs::home_dir() { - indexmap.insert( - "home".to_string(), - UntaggedValue::path(home).into_value(&tag), - ); + indexmap.insert("home".to_string(), value::path(home).into_value(&tag)); } let config = config::default_path()?; - indexmap.insert( - "config".to_string(), - UntaggedValue::path(config).into_value(&tag), - ); + indexmap.insert("config".to_string(), value::path(config).into_value(&tag)); let history = History::path(); - indexmap.insert( - "history".to_string(), - UntaggedValue::path(history).into_value(&tag), - ); + indexmap.insert("history".to_string(), value::path(history).into_value(&tag)); let temp = std::env::temp_dir(); - indexmap.insert( - "temp".to_string(), - UntaggedValue::path(temp).into_value(&tag), - ); + indexmap.insert("temp".to_string(), value::path(temp).into_value(&tag)); let mut dict = TaggedDictBuilder::new(&tag); for v in std::env::vars() { - dict.insert_untagged(v.0, UntaggedValue::string(v.1)); + dict.insert_untagged(v.0, value::string(v.1)); } if !dict.is_empty() { indexmap.insert("vars".to_string(), dict.into_value()); diff --git a/src/commands/evaluate_by.rs b/src/commands/evaluate_by.rs index d0d568f9aa..08559758e0 100644 --- a/src/commands/evaluate_by.rs +++ b/src/commands/evaluate_by.rs @@ -1,6 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::parser::hir::SyntaxShape; +use crate::data::value; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_source::{SpannedItem, Tagged}; pub struct EvaluateBy; @@ -71,7 +73,7 @@ pub fn evaluate_by( fn fetch(key: Option) -> Box Option + 'static> { Box::new(move |value: Value, tag| match &key { Some(key_given) => value.get_data_by_key(key_given[..].spanned(tag.span)), - None => Some(UntaggedValue::int(1).into_value(tag)), + None => Some(value::int(1).into_value(tag)), }) } @@ -136,25 +138,26 @@ mod tests { use crate::commands::evaluate_by::{evaluate, fetch}; use crate::commands::group_by::group; use crate::commands::t_sort_by::t_sort; + use crate::data::value; use crate::prelude::*; - use crate::Value; use indexmap::IndexMap; + use nu_protocol::{UntaggedValue, Value}; use nu_source::TaggedItem; fn int(s: impl Into) -> Value { - UntaggedValue::int(s).into_untagged_value() + value::int(s).into_untagged_value() } fn string(input: impl Into) -> Value { - UntaggedValue::string(input.into()).into_untagged_value() + value::string(input.into()).into_untagged_value() } fn row(entries: IndexMap) -> Value { - UntaggedValue::row(entries).into_untagged_value() + value::row(entries).into_untagged_value() } fn table(list: &Vec) -> Value { - UntaggedValue::table(list).into_untagged_value() + value::table(list).into_untagged_value() } fn nu_releases_sorted_by_date() -> Value { @@ -222,7 +225,7 @@ mod tests { assert_eq!( evaluator(subject, Tag::unknown()), - Some(UntaggedValue::int(1).into_untagged_value()) + Some(value::int(1).into_untagged_value()) ); } diff --git a/src/commands/exit.rs b/src/commands/exit.rs index b7db7cc340..fc22502ebc 100644 --- a/src/commands/exit.rs +++ b/src/commands/exit.rs @@ -1,7 +1,8 @@ -use crate::commands::command::{CommandAction, WholeStreamCommand}; -use crate::errors::ShellError; -use crate::parser::registry::{CommandRegistry, Signature}; +use crate::commands::command::WholeStreamCommand; +use crate::context::CommandRegistry; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{CommandAction, ReturnSuccess, Signature}; pub struct Exit; diff --git a/src/commands/fetch.rs b/src/commands/fetch.rs index 0432f917e1..451a5085e0 100644 --- a/src/commands/fetch.rs +++ b/src/commands/fetch.rs @@ -1,10 +1,9 @@ use crate::commands::UnevaluatedCallInfo; -use crate::data::base::Value; -use crate::errors::ShellError; -use crate::parser::hir::SyntaxShape; -use crate::parser::registry::Signature; +use crate::data::value; use crate::prelude::*; use mime::Mime; +use nu_errors::ShellError; +use nu_protocol::{CallInfo, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_source::{AnchorLocation, Span}; use std::path::PathBuf; use std::str::FromStr; @@ -91,7 +90,7 @@ fn run( ctrl_c: raw_args.ctrl_c, shell_manager: raw_args.shell_manager, call_info: UnevaluatedCallInfo { - args: crate::parser::hir::Call { + args: nu_parser::hir::Call { head: raw_args.call_info.args.head, positional: None, named: None, @@ -147,7 +146,7 @@ pub async fn fetch( match (content_type.type_(), content_type.subtype()) { (mime::APPLICATION, mime::XML) => Ok(( Some("xml".to_string()), - UntaggedValue::string(r.body_string().await.map_err(|_| { + value::string(r.body_string().await.map_err(|_| { ShellError::labeled_error( "Could not load text from remote url", "could not load", @@ -161,7 +160,7 @@ pub async fn fetch( )), (mime::APPLICATION, mime::JSON) => Ok(( Some("json".to_string()), - UntaggedValue::string(r.body_string().await.map_err(|_| { + value::string(r.body_string().await.map_err(|_| { ShellError::labeled_error( "Could not load text from remote url", "could not load", @@ -183,7 +182,7 @@ pub async fn fetch( })?; Ok(( None, - UntaggedValue::binary(buf), + value::binary(buf), Tag { span, anchor: Some(AnchorLocation::Url(location.to_string())), @@ -192,7 +191,7 @@ pub async fn fetch( } (mime::IMAGE, mime::SVG) => Ok(( Some("svg".to_string()), - UntaggedValue::string(r.body_string().await.map_err(|_| { + value::string(r.body_string().await.map_err(|_| { ShellError::labeled_error( "Could not load svg from remote url", "could not load", @@ -214,7 +213,7 @@ pub async fn fetch( })?; Ok(( Some(image_ty.to_string()), - UntaggedValue::binary(buf), + value::binary(buf), Tag { span, anchor: Some(AnchorLocation::Url(location.to_string())), @@ -223,7 +222,7 @@ pub async fn fetch( } (mime::TEXT, mime::HTML) => Ok(( Some("html".to_string()), - UntaggedValue::string(r.body_string().await.map_err(|_| { + value::string(r.body_string().await.map_err(|_| { ShellError::labeled_error( "Could not load text from remote url", "could not load", @@ -249,7 +248,7 @@ pub async fn fetch( Ok(( path_extension, - UntaggedValue::string(r.body_string().await.map_err(|_| { + value::string(r.body_string().await.map_err(|_| { ShellError::labeled_error( "Could not load text from remote url", "could not load", @@ -264,10 +263,7 @@ pub async fn fetch( } (ty, sub_ty) => Ok(( None, - UntaggedValue::string(format!( - "Not yet supported MIME type: {} {}", - ty, sub_ty - )), + value::string(format!("Not yet supported MIME type: {} {}", ty, sub_ty)), Tag { span, anchor: Some(AnchorLocation::Url(location.to_string())), @@ -277,7 +273,7 @@ pub async fn fetch( } None => Ok(( None, - UntaggedValue::string(format!("No content type found")), + value::string(format!("No content type found")), Tag { span, anchor: Some(AnchorLocation::Url(location.to_string())), diff --git a/src/commands/first.rs b/src/commands/first.rs index 1113691bf1..eaf74b83fe 100644 --- a/src/commands/first.rs +++ b/src/commands/first.rs @@ -1,7 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; -use crate::parser::CommandRegistry; +use crate::context::CommandRegistry; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Signature, SyntaxShape}; use nu_source::Tagged; pub struct First; diff --git a/src/commands/from_bson.rs b/src/commands/from_bson.rs index e6a41907ad..e0de2dfeab 100644 --- a/src/commands/from_bson.rs +++ b/src/commands/from_bson.rs @@ -1,8 +1,10 @@ use crate::commands::WholeStreamCommand; +use crate::data::value; use crate::data::TaggedDictBuilder; -use crate::errors::ExpectedRange; use crate::prelude::*; use bson::{decode_document, spec::BinarySubtype, Bson}; +use nu_errors::{ExpectedRange, ShellError}; +use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; use nu_source::SpannedItem; use std::str::FromStr; @@ -72,8 +74,8 @@ fn convert_bson_value_to_nu_value(v: &Bson, tag: impl Into) -> Result UntaggedValue::number(n).into_value(&tag), - Bson::I64(n) => UntaggedValue::number(n).into_value(&tag), + Bson::I32(n) => value::number(n).into_value(&tag), + Bson::I64(n) => value::number(n).into_value(&tag), Bson::Decimal128(n) => { // TODO: this really isn't great, and we should update this to do a higher // fidelity translation @@ -108,10 +110,7 @@ fn convert_bson_value_to_nu_value(v: &Bson, tag: impl Into) -> Result { let mut collected = TaggedDictBuilder::new(tag.clone()); - collected.insert_value( - "$timestamp".to_string(), - UntaggedValue::number(ts).into_value(&tag), - ); + collected.insert_value("$timestamp".to_string(), value::number(ts).into_value(&tag)); collected.into_value() } Bson::Binary(bst, bytes) => { @@ -119,7 +118,7 @@ fn convert_bson_value_to_nu_value(v: &Bson, tag: impl Into) -> Result UntaggedValue::number(u), + BinarySubtype::UserDefined(u) => value::number(u), _ => { UntaggedValue::Primitive(Primitive::String(binary_subtype_to_string(*bst))) } diff --git a/src/commands/from_csv.rs b/src/commands/from_csv.rs index 663b2fd255..fb821d7363 100644 --- a/src/commands/from_csv.rs +++ b/src/commands/from_csv.rs @@ -1,7 +1,8 @@ use crate::commands::from_delimited_data::from_delimited_data; use crate::commands::WholeStreamCommand; -use crate::data::{Primitive, Value}; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value}; pub struct FromCSV; diff --git a/src/commands/from_delimited_data.rs b/src/commands/from_delimited_data.rs index 805f187eb3..99db232f80 100644 --- a/src/commands/from_delimited_data.rs +++ b/src/commands/from_delimited_data.rs @@ -1,6 +1,8 @@ -use crate::data::{Primitive, TaggedDictBuilder, Value}; +use crate::data::TaggedDictBuilder; use crate::prelude::*; use csv::ReaderBuilder; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, UntaggedValue, Value}; fn from_delimited_string_to_value( s: String, diff --git a/src/commands/from_ini.rs b/src/commands/from_ini.rs index bd2282ea4c..63383ba18d 100644 --- a/src/commands/from_ini.rs +++ b/src/commands/from_ini.rs @@ -1,6 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::data::{Primitive, TaggedDictBuilder, Value}; +use crate::data::TaggedDictBuilder; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; use std::collections::HashMap; pub struct FromINI; diff --git a/src/commands/from_json.rs b/src/commands/from_json.rs index 0eff08daa6..9a9ea1ecbd 100644 --- a/src/commands/from_json.rs +++ b/src/commands/from_json.rs @@ -1,6 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::data::{Primitive, TaggedDictBuilder, Value}; +use crate::data::{value, TaggedDictBuilder}; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; pub struct FromJSON; @@ -36,10 +38,10 @@ fn convert_json_value_to_nu_value(v: &serde_hjson::Value, tag: impl Into) - match v { serde_hjson::Value::Null => UntaggedValue::Primitive(Primitive::Nothing).into_value(&tag), - serde_hjson::Value::Bool(b) => UntaggedValue::boolean(*b).into_value(&tag), - serde_hjson::Value::F64(n) => UntaggedValue::number(n).into_value(&tag), - serde_hjson::Value::U64(n) => UntaggedValue::number(n).into_value(&tag), - serde_hjson::Value::I64(n) => UntaggedValue::number(n).into_value(&tag), + serde_hjson::Value::Bool(b) => value::boolean(*b).into_value(&tag), + serde_hjson::Value::F64(n) => value::number(n).into_value(&tag), + serde_hjson::Value::U64(n) => value::number(n).into_value(&tag), + serde_hjson::Value::I64(n) => value::number(n).into_value(&tag), serde_hjson::Value::String(s) => { UntaggedValue::Primitive(Primitive::String(String::from(s))).into_value(&tag) } diff --git a/src/commands/from_sqlite.rs b/src/commands/from_sqlite.rs index 15bfbb6cab..5c65e4ccc4 100644 --- a/src/commands/from_sqlite.rs +++ b/src/commands/from_sqlite.rs @@ -1,7 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::data::{Primitive, TaggedDictBuilder, Value}; -use crate::errors::ShellError; +use crate::data::{value, TaggedDictBuilder}; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; use rusqlite::{types::ValueRef, Connection, Row, NO_PARAMS}; use std::io::Write; use std::path::Path; @@ -105,14 +106,14 @@ fn convert_sqlite_value_to_nu_value(value: ValueRef, tag: impl Into + Clone ValueRef::Null => { UntaggedValue::Primitive(Primitive::String(String::from(""))).into_value(tag) } - ValueRef::Integer(i) => UntaggedValue::number(i).into_value(tag), - ValueRef::Real(f) => UntaggedValue::number(f).into_value(tag), + ValueRef::Integer(i) => value::number(i).into_value(tag), + ValueRef::Real(f) => value::number(f).into_value(tag), t @ ValueRef::Text(_) => { // this unwrap is safe because we know the ValueRef is Text. UntaggedValue::Primitive(Primitive::String(t.as_str().unwrap().to_string())) .into_value(tag) } - ValueRef::Blob(u) => UntaggedValue::binary(u.to_owned()).into_value(tag), + ValueRef::Blob(u) => value::binary(u.to_owned()).into_value(tag), } } diff --git a/src/commands/from_ssv.rs b/src/commands/from_ssv.rs index a77ecf4f50..24caae107e 100644 --- a/src/commands/from_ssv.rs +++ b/src/commands/from_ssv.rs @@ -1,6 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::data::{Primitive, TaggedDictBuilder, Value}; +use crate::data::TaggedDictBuilder; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_source::Tagged; pub struct FromSSV; diff --git a/src/commands/from_toml.rs b/src/commands/from_toml.rs index 70ddde6b7d..eabaa2392c 100644 --- a/src/commands/from_toml.rs +++ b/src/commands/from_toml.rs @@ -1,6 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::data::{Primitive, TaggedDictBuilder, Value}; +use crate::data::{value, TaggedDictBuilder}; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; pub struct FromTOML; @@ -30,9 +32,9 @@ pub fn convert_toml_value_to_nu_value(v: &toml::Value, tag: impl Into) -> V let tag = tag.into(); match v { - toml::Value::Boolean(b) => UntaggedValue::boolean(*b).into_value(tag), - toml::Value::Integer(n) => UntaggedValue::number(n).into_value(tag), - toml::Value::Float(n) => UntaggedValue::number(n).into_value(tag), + toml::Value::Boolean(b) => value::boolean(*b).into_value(tag), + toml::Value::Integer(n) => value::number(n).into_value(tag), + toml::Value::Float(n) => value::number(n).into_value(tag), toml::Value::String(s) => { UntaggedValue::Primitive(Primitive::String(String::from(s))).into_value(tag) } diff --git a/src/commands/from_tsv.rs b/src/commands/from_tsv.rs index 38af5e4333..c4807dd912 100644 --- a/src/commands/from_tsv.rs +++ b/src/commands/from_tsv.rs @@ -1,6 +1,8 @@ use crate::commands::from_delimited_data::from_delimited_data; use crate::commands::WholeStreamCommand; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::Signature; pub struct FromTSV; diff --git a/src/commands/from_url.rs b/src/commands/from_url.rs index e3b6694ad3..cafcb6cd1f 100644 --- a/src/commands/from_url.rs +++ b/src/commands/from_url.rs @@ -1,6 +1,9 @@ use crate::commands::WholeStreamCommand; -use crate::data::{Primitive, TaggedDictBuilder, Value}; +use crate::data::value; +use crate::data::TaggedDictBuilder; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; pub struct FromURL; @@ -63,7 +66,7 @@ fn from_url(args: CommandArgs, registry: &CommandRegistry) -> Result UntaggedValue::nothing(), - DataType::String(s) => UntaggedValue::string(s), - DataType::Float(f) => UntaggedValue::decimal(*f), - DataType::Int(i) => UntaggedValue::int(*i), - DataType::Bool(b) => UntaggedValue::boolean(*b), - _ => UntaggedValue::nothing(), + DataType::Empty => value::nothing(), + DataType::String(s) => value::string(s), + DataType::Float(f) => value::decimal(*f), + DataType::Int(i) => value::int(*i), + DataType::Bool(b) => value::boolean(*b), + _ => value::nothing(), }; row_output.insert_untagged(&format!("Column{}", i), value); diff --git a/src/commands/from_xml.rs b/src/commands/from_xml.rs index 1b97646980..db2d173604 100644 --- a/src/commands/from_xml.rs +++ b/src/commands/from_xml.rs @@ -1,7 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::data::base::{Primitive, UntaggedValue, Value}; -use crate::data::TaggedDictBuilder; +use crate::data::{value, TaggedDictBuilder}; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; pub struct FromXML; @@ -60,13 +61,13 @@ fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>, tag: impl Into) collected.into_value() } else if n.is_comment() { - UntaggedValue::string("").into_value(tag) + value::string("").into_value(tag) } else if n.is_pi() { - UntaggedValue::string("").into_value(tag) + value::string("").into_value(tag) } else if n.is_text() { - UntaggedValue::string(n.text().unwrap()).into_value(tag) + value::string(n.text().unwrap()).into_value(tag) } else { - UntaggedValue::string("").into_value(tag) + value::string("").into_value(tag) } } @@ -139,20 +140,21 @@ fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result) -> Value { - UntaggedValue::string(input.into()).into_untagged_value() + value::string(input.into()).into_untagged_value() } fn row(entries: IndexMap) -> Value { - UntaggedValue::row(entries).into_untagged_value() + value::row(entries).into_untagged_value() } fn table(list: &Vec) -> Value { - UntaggedValue::table(list).into_untagged_value() + value::table(list).into_untagged_value() } fn parse(xml: &str) -> Value { diff --git a/src/commands/from_yaml.rs b/src/commands/from_yaml.rs index 6377efd77f..3beea333c9 100644 --- a/src/commands/from_yaml.rs +++ b/src/commands/from_yaml.rs @@ -1,6 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::data::{Primitive, TaggedDictBuilder, Value}; +use crate::data::{value, TaggedDictBuilder}; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; pub struct FromYAML; @@ -54,14 +56,14 @@ fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, tag: impl Into) -> let tag = tag.into(); match v { - serde_yaml::Value::Bool(b) => UntaggedValue::boolean(*b).into_value(tag), + serde_yaml::Value::Bool(b) => value::boolean(*b).into_value(tag), serde_yaml::Value::Number(n) if n.is_i64() => { - UntaggedValue::number(n.as_i64().unwrap()).into_value(tag) + value::number(n.as_i64().unwrap()).into_value(tag) } serde_yaml::Value::Number(n) if n.is_f64() => { UntaggedValue::Primitive(Primitive::from(n.as_f64().unwrap())).into_value(tag) } - serde_yaml::Value::String(s) => UntaggedValue::string(s).into_value(tag), + serde_yaml::Value::String(s) => value::string(s).into_value(tag), serde_yaml::Value::Sequence(a) => UntaggedValue::Table( a.iter() .map(|x| convert_yaml_value_to_nu_value(x, &tag)) diff --git a/src/commands/get.rs b/src/commands/get.rs index fe39287620..8de42c339a 100644 --- a/src/commands/get.rs +++ b/src/commands/get.rs @@ -1,12 +1,14 @@ use crate::commands::WholeStreamCommand; +use crate::data::base::property_get::get_data_by_column_path; use crate::data::base::shape::Shapes; -use crate::data::Value; -use crate::errors::ShellError; use crate::prelude::*; use crate::utils::did_you_mean; -use crate::ColumnPath; use futures_util::pin_mut; use log::trace; +use nu_errors::ShellError; +use nu_protocol::{ + ColumnPath, ReturnSuccess, ReturnValue, Signature, SyntaxShape, UntaggedValue, Value, +}; use nu_source::{span_for_spanned_list, PrettyDebug}; pub struct Get; @@ -44,7 +46,8 @@ impl WholeStreamCommand for Get { pub fn get_column_path(path: &ColumnPath, obj: &Value) -> Result { let fields = path.clone(); - obj.get_data_by_column_path( + get_data_by_column_path( + obj, path, Box::new(move |(obj_source, column_path_tried, error)| { match &obj_source.value { diff --git a/src/commands/group_by.rs b/src/commands/group_by.rs index 066950db72..71e0d2e2e6 100644 --- a/src/commands/group_by.rs +++ b/src/commands/group_by.rs @@ -1,8 +1,9 @@ use crate::commands::WholeStreamCommand; -use crate::data::base::UntaggedValue; -use crate::data::TaggedDictBuilder; -use crate::errors::ShellError; +use crate::data::base::property_get::get_data_by_key; +use crate::data::{value, TaggedDictBuilder}; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, Value}; use nu_source::Tagged; pub struct GroupBy; @@ -69,10 +70,10 @@ pub fn group( ) -> Result { let tag = tag.into(); - let mut groups = indexmap::IndexMap::new(); + let mut groups: indexmap::IndexMap> = indexmap::IndexMap::new(); for value in values { - let group_key = value.get_data_by_key(column_name.borrow_spanned()); + let group_key = get_data_by_key(&value, column_name.borrow_spanned()); if group_key.is_none() { let possibilities = value.data_descriptors(); @@ -99,7 +100,7 @@ pub fn group( } } - let group_key = group_key.unwrap().as_string()?; + let group_key = group_key.unwrap().as_string()?.to_string(); let group = groups.entry(group_key).or_insert(vec![]); group.push(value); } @@ -107,7 +108,7 @@ pub fn group( let mut out = TaggedDictBuilder::new(&tag); for (k, v) in groups.iter() { - out.insert_untagged(k, UntaggedValue::table(v)); + out.insert_untagged(k, value::table(v)); } Ok(out.into_value()) @@ -116,20 +117,21 @@ pub fn group( #[cfg(test)] mod tests { use crate::commands::group_by::group; - use crate::data::base::{UntaggedValue, Value}; + use crate::data::value; use indexmap::IndexMap; + use nu_protocol::Value; use nu_source::*; fn string(input: impl Into) -> Value { - UntaggedValue::string(input.into()).into_untagged_value() + value::string(input.into()).into_untagged_value() } fn row(entries: IndexMap) -> Value { - UntaggedValue::row(entries).into_untagged_value() + value::row(entries).into_untagged_value() } fn table(list: &Vec) -> Value { - UntaggedValue::table(list).into_untagged_value() + value::table(list).into_untagged_value() } fn nu_releases_commiters() -> Vec { diff --git a/src/commands/help.rs b/src/commands/help.rs index 3958f558b4..cc44442d97 100644 --- a/src/commands/help.rs +++ b/src/commands/help.rs @@ -1,8 +1,12 @@ use crate::commands::PerItemCommand; +use crate::data::base::property_get::get_data_by_key; use crate::data::{command_dict, TaggedDictBuilder}; -use crate::errors::ShellError; -use crate::parser::registry::{self, NamedType, PositionalType}; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{ + CallInfo, NamedType, PositionalType, Primitive, ReturnSuccess, Signature, SyntaxShape, + UntaggedValue, Value, +}; use nu_source::SpannedItem; pub struct Help; @@ -12,7 +16,7 @@ impl PerItemCommand for Help { "help" } - fn signature(&self) -> registry::Signature { + fn signature(&self) -> Signature { Signature::build("help").rest(SyntaxShape::Any, "the name of command(s) to get help on") } @@ -45,8 +49,7 @@ impl PerItemCommand for Help { short_desc.insert_untagged("name", cmd); short_desc.insert_untagged( "description", - value - .get_data_by_key("usage".spanned_unknown()) + get_data_by_key(&value, "usage".spanned_unknown()) .unwrap() .as_string() .unwrap(), @@ -149,7 +152,7 @@ impl PerItemCommand for Help { } help.push_back(ReturnSuccess::value( - UntaggedValue::string(long_desc).into_value(tag.clone()), + value::string(long_desc).into_value(tag.clone()), )); } } @@ -167,9 +170,7 @@ You can also learn more at https://book.nushell.sh"#; let mut output_stream = VecDeque::new(); - output_stream.push_back(ReturnSuccess::value( - UntaggedValue::string(msg).into_value(tag), - )); + output_stream.push_back(ReturnSuccess::value(value::string(msg).into_value(tag))); Ok(output_stream.to_output_stream()) } diff --git a/src/commands/histogram.rs b/src/commands/histogram.rs index 533126ccf8..7e97b5dd27 100644 --- a/src/commands/histogram.rs +++ b/src/commands/histogram.rs @@ -5,9 +5,10 @@ use crate::commands::reduce_by::reduce; use crate::commands::t_sort_by::columns_sorted; use crate::commands::t_sort_by::t_sort; use crate::commands::WholeStreamCommand; -use crate::data::TaggedDictBuilder; -use crate::errors::ShellError; +use crate::data::{value, TaggedDictBuilder}; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_source::Tagged; use num_traits::cast::ToPrimitive; @@ -90,11 +91,11 @@ pub fn histogram( let mut fact = TaggedDictBuilder::new(&name); let value: Tagged = group_labels.get(idx).unwrap().clone(); - fact.insert_value(&column, UntaggedValue::string(value.item).into_value(value.tag)); + fact.insert_value(&column, value::string(value.item).into_value(value.tag)); if let Value { value: UntaggedValue::Primitive(Primitive::Int(ref num)), .. } = percentage.clone() { let string = std::iter::repeat("*").take(num.to_i32().unwrap() as usize).collect::(); - fact.insert_untagged(&frequency_column_name, UntaggedValue::string(string)); + fact.insert_untagged(&frequency_column_name, value::string(string)); } idx = idx + 1; @@ -145,9 +146,9 @@ fn percentages(values: &Value, max: Value, tag: impl Into) -> Result UntaggedValue::number(0).into_value(&tag), + _ => value::number(0).into_value(&tag), }) .collect::>(); UntaggedValue::Table(data).into_value(&tag) diff --git a/src/commands/history.rs b/src/commands/history.rs index 9c4fc7e80c..11b7896582 100644 --- a/src/commands/history.rs +++ b/src/commands/history.rs @@ -1,8 +1,9 @@ use crate::cli::History as HistoryFile; use crate::commands::PerItemCommand; -use crate::errors::ShellError; -use crate::parser::registry::{self}; +use crate::data::value; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{CallInfo, ReturnSuccess, Signature, Value}; use std::fs::File; use std::io::{BufRead, BufReader}; @@ -13,7 +14,7 @@ impl PerItemCommand for History { "history" } - fn signature(&self) -> registry::Signature { + fn signature(&self) -> Signature { Signature::build("history") } @@ -37,7 +38,7 @@ impl PerItemCommand for History { let reader = BufReader::new(file); for line in reader.lines() { if let Ok(line) = line { - yield ReturnSuccess::value(UntaggedValue::string(line).into_value(tag.clone())); + yield ReturnSuccess::value(value::string(line).into_value(tag.clone())); } } } else { diff --git a/src/commands/last.rs b/src/commands/last.rs index 35d84de861..dc74116069 100644 --- a/src/commands/last.rs +++ b/src/commands/last.rs @@ -1,7 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; -use crate::parser::CommandRegistry; +use crate::context::CommandRegistry; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, Value}; use nu_source::Tagged; pub struct Last; diff --git a/src/commands/lines.rs b/src/commands/lines.rs index 0338d91e94..32f0523044 100644 --- a/src/commands/lines.rs +++ b/src/commands/lines.rs @@ -1,8 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::data::Primitive; -use crate::errors::ShellError; use crate::prelude::*; use log::trace; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue}; pub struct Lines; diff --git a/src/commands/ls.rs b/src/commands/ls.rs index ddb58ebaf4..0bd7a465b7 100644 --- a/src/commands/ls.rs +++ b/src/commands/ls.rs @@ -1,6 +1,7 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Signature, SyntaxShape}; use nu_source::Tagged; use std::path::PathBuf; diff --git a/src/commands/macros.rs b/src/commands/macros.rs index 4a83f5e069..eb2368c050 100644 --- a/src/commands/macros.rs +++ b/src/commands/macros.rs @@ -45,8 +45,8 @@ macro_rules! command { stringify!($config_name) } - fn config(&self) -> $crate::parser::registry::Signature { - $crate::parser::registry::Signature { + fn config(&self) -> $nu_parser::registry::Signature { + $nu_parser::registry::Signature { name: self.name().to_string(), positional: vec![$($mandatory_positional)*], rest_positional: false, @@ -54,13 +54,13 @@ macro_rules! command { is_sink: false, named: { - use $crate::parser::registry::NamedType; + use $nu_parser::registry::NamedType; #[allow(unused_mut)] let mut named: indexmap::IndexMap = indexmap::IndexMap::new(); $( - named.insert(stringify!($named_param).to_string(), $crate::parser::registry::NamedType::$named_kind); + named.insert(stringify!($named_param).to_string(), $nu_parser::registry::NamedType::$named_kind); )* named @@ -250,7 +250,7 @@ macro_rules! command { Rest { $($rest)* } Signature { name: $config_name, - mandatory_positional: vec![ $($mandatory_positional)* $crate::parser::registry::PositionalType::mandatory_block( + mandatory_positional: vec![ $($mandatory_positional)* $nu_parser::registry::PositionalType::mandatory_block( stringify!($param_name) ), ], optional_positional: vec![ $($optional_positional)* ], @@ -305,7 +305,7 @@ macro_rules! command { Rest { $($rest)* } Signature { name: $config_name, - mandatory_positional: vec![ $($mandatory_positional)* $crate::parser::registry::PositionalType::mandatory( + mandatory_positional: vec![ $($mandatory_positional)* $nu_parser::registry::PositionalType::mandatory( stringify!($param_name), <$param_kind>::syntax_type() ), ], optional_positional: vec![ $($optional_positional)* ], diff --git a/src/commands/map_max_by.rs b/src/commands/map_max_by.rs index 7b34f05432..416d5f56e4 100644 --- a/src/commands/map_max_by.rs +++ b/src/commands/map_max_by.rs @@ -1,6 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::parser::hir::SyntaxShape; +use crate::data::value; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_source::Tagged; use num_traits::cast::ToPrimitive; @@ -101,9 +103,9 @@ pub fn map_max( } _ => acc, }); - UntaggedValue::number(data).into_value(&tag) + value::number(data).into_value(&tag) } - _ => UntaggedValue::number(0).into_value(&tag), + _ => value::number(0).into_value(&tag), }) .collect(); @@ -120,9 +122,9 @@ pub fn map_max( } _ => max, }); - UntaggedValue::number(datasets).into_value(&tag) + value::number(datasets).into_value(&tag) } - _ => UntaggedValue::number(-1).into_value(&tag), + _ => value::number(-1).into_value(&tag), }; Ok(results) @@ -137,20 +139,20 @@ mod tests { use crate::commands::reduce_by::reduce; use crate::commands::t_sort_by::t_sort; use crate::prelude::*; - use crate::Value; use indexmap::IndexMap; + use nu_protocol::{UntaggedValue, Value}; use nu_source::*; fn int(s: impl Into) -> Value { - UntaggedValue::int(s).into_untagged_value() + value::int(s).into_untagged_value() } fn string(input: impl Into) -> Value { - UntaggedValue::string(input.into()).into_untagged_value() + value::string(input.into()).into_untagged_value() } fn row(entries: IndexMap) -> Value { - UntaggedValue::row(entries).into_untagged_value() + value::row(entries).into_untagged_value() } fn nu_releases_evaluated_by_default_one() -> Value { diff --git a/src/commands/mkdir.rs b/src/commands/mkdir.rs index 561f5c4c96..befce8ad24 100644 --- a/src/commands/mkdir.rs +++ b/src/commands/mkdir.rs @@ -1,7 +1,8 @@ use crate::commands::command::RunnablePerItemContext; -use crate::errors::ShellError; -use crate::parser::registry::{CommandRegistry, Signature}; +use crate::context::CommandRegistry; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{CallInfo, Signature, SyntaxShape, Value}; use nu_source::Tagged; use std::path::PathBuf; diff --git a/src/commands/mv.rs b/src/commands/mv.rs index 6e90d1087f..91f395e6f2 100644 --- a/src/commands/mv.rs +++ b/src/commands/mv.rs @@ -1,8 +1,8 @@ use crate::commands::command::RunnablePerItemContext; -use crate::errors::ShellError; -use crate::parser::hir::SyntaxShape; -use crate::parser::registry::{CommandRegistry, Signature}; +use crate::context::CommandRegistry; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{CallInfo, Signature, SyntaxShape, Value}; use nu_source::Tagged; use std::path::PathBuf; diff --git a/src/commands/next.rs b/src/commands/next.rs index 359f262312..d815a3d8f3 100644 --- a/src/commands/next.rs +++ b/src/commands/next.rs @@ -1,7 +1,7 @@ -use crate::commands::command::CommandAction; use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; use crate::prelude::*; +use nu_protocol::{CommandAction, ReturnSuccess, Signature}; +use nu_errors::ShellError; pub struct Next; diff --git a/src/commands/nth.rs b/src/commands/nth.rs index b57b7a413f..e740960fec 100644 --- a/src/commands/nth.rs +++ b/src/commands/nth.rs @@ -1,7 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; -use crate::parser::CommandRegistry; +use crate::context::CommandRegistry; use crate::prelude::*; +use nu_protocol::{Signature, SyntaxShape}; +use nu_errors::ShellError; use nu_source::Tagged; #[derive(Deserialize)] diff --git a/src/commands/open.rs b/src/commands/open.rs index 47fc2ecc8b..8642d08c24 100644 --- a/src/commands/open.rs +++ b/src/commands/open.rs @@ -1,12 +1,13 @@ use crate::commands::UnevaluatedCallInfo; -use crate::data::Value; -use crate::errors::ShellError; -use crate::parser::hir::SyntaxShape; -use crate::parser::registry::Signature; +use crate::data::value; use crate::prelude::*; -use nu_source::AnchorLocation; -use nu_source::Span; +use nu_protocol::{ + CallInfo, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, +}; +use nu_errors::ShellError; +use nu_source::{AnchorLocation, Span}; use std::path::{Path, PathBuf}; + pub struct Open; impl PerItemCommand for Open { @@ -91,7 +92,7 @@ fn run( ctrl_c: raw_args.ctrl_c, shell_manager: raw_args.shell_manager, call_info: UnevaluatedCallInfo { - args: crate::parser::hir::Call { + args: nu_parser::hir::Call { head: raw_args.call_info.args.head, positional: None, named: None, @@ -141,7 +142,7 @@ pub async fn fetch( Ok(s) => Ok(( cwd.extension() .map(|name| name.to_string_lossy().to_string()), - UntaggedValue::string(s), + value::string(s), Tag { span, anchor: Some(AnchorLocation::File(cwd.to_string_lossy().to_string())), @@ -159,7 +160,7 @@ pub async fn fetch( Ok(s) => Ok(( cwd.extension() .map(|name| name.to_string_lossy().to_string()), - UntaggedValue::string(s), + value::string(s), Tag { span, anchor: Some(AnchorLocation::File( @@ -169,7 +170,7 @@ pub async fn fetch( )), Err(_) => Ok(( None, - UntaggedValue::binary(bytes), + value::binary(bytes), Tag { span, anchor: Some(AnchorLocation::File( @@ -181,7 +182,7 @@ pub async fn fetch( } else { Ok(( None, - UntaggedValue::binary(bytes), + value::binary(bytes), Tag { span, anchor: Some(AnchorLocation::File( @@ -200,7 +201,7 @@ pub async fn fetch( Ok(s) => Ok(( cwd.extension() .map(|name| name.to_string_lossy().to_string()), - UntaggedValue::string(s), + value::string(s), Tag { span, anchor: Some(AnchorLocation::File( @@ -210,7 +211,7 @@ pub async fn fetch( )), Err(_) => Ok(( None, - UntaggedValue::binary(bytes), + value::binary(bytes), Tag { span, anchor: Some(AnchorLocation::File( @@ -222,7 +223,7 @@ pub async fn fetch( } else { Ok(( None, - UntaggedValue::binary(bytes), + value::binary(bytes), Tag { span, anchor: Some(AnchorLocation::File( @@ -234,7 +235,7 @@ pub async fn fetch( } _ => Ok(( None, - UntaggedValue::binary(bytes), + value::binary(bytes), Tag { span, anchor: Some(AnchorLocation::File( diff --git a/src/commands/pick.rs b/src/commands/pick.rs index a6cdbf040a..a8d075830a 100644 --- a/src/commands/pick.rs +++ b/src/commands/pick.rs @@ -1,8 +1,9 @@ use crate::commands::WholeStreamCommand; use crate::context::CommandRegistry; use crate::data::base::select_fields; -use crate::errors::ShellError; use crate::prelude::*; +use nu_protocol::{Signature, SyntaxShape}; +use nu_errors::ShellError; use nu_source::Tagged; #[derive(Deserialize)] diff --git a/src/commands/pivot.rs b/src/commands/pivot.rs index 86d25c4d4b..5ab8c04f50 100644 --- a/src/commands/pivot.rs +++ b/src/commands/pivot.rs @@ -1,7 +1,10 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; +use crate::data::base::property_get::get_data_by_key; +use crate::data::value; use crate::prelude::*; use crate::TaggedDictBuilder; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, Value}; +use nu_errors::ShellError; use nu_source::{SpannedItem, Tagged}; pub struct Pivot; @@ -61,7 +64,7 @@ pub fn pivot(args: PivotArgs, context: RunnableContext) -> Result = vec![]; if args.rest.len() > 0 && args.header_row { yield Err(ShellError::labeled_error("Can not provide header names and use header row", "using header row", context.name)); @@ -71,10 +74,10 @@ pub fn pivot(args: PivotArgs, context: RunnableContext) -> Result { if let Ok(s) = x.as_string() { - headers.push(s); + headers.push(s.to_string()); } else { yield Err(ShellError::labeled_error("Header row needs string headers", "used non-string headers", context.name)); return; @@ -111,17 +114,17 @@ pub fn pivot(args: PivotArgs, context: RunnableContext) -> Result { dict.insert_value(headers[column_num].clone(), x.clone()); } _ => { - dict.insert_untagged(headers[column_num].clone(), UntaggedValue::nothing()); + dict.insert_untagged(headers[column_num].clone(), value::nothing()); } } column_num += 1; diff --git a/src/commands/plugin.rs b/src/commands/plugin.rs index c7dc318717..b1bd267725 100644 --- a/src/commands/plugin.rs +++ b/src/commands/plugin.rs @@ -1,9 +1,12 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; -use crate::parser::registry; +use crate::data::value; use crate::prelude::*; use derive_new::new; use log::trace; +use nu_protocol::{ + Primitive, ReturnSuccess, ReturnValue, Signature, UntaggedValue, Value, +}; +use nu_errors::ShellError; use serde::{self, Deserialize, Serialize}; use std::io::prelude::*; use std::io::BufReader; @@ -39,7 +42,7 @@ pub enum NuResult { pub struct PluginCommand { name: String, path: String, - config: registry::Signature, + config: Signature, } impl WholeStreamCommand for PluginCommand { @@ -47,7 +50,7 @@ impl WholeStreamCommand for PluginCommand { &self.name } - fn signature(&self) -> registry::Signature { + fn signature(&self) -> Signature { self.config.clone() } @@ -264,7 +267,7 @@ pub fn filter_plugin( pub struct PluginSink { name: String, path: String, - config: registry::Signature, + config: Signature, } impl WholeStreamCommand for PluginSink { @@ -272,7 +275,7 @@ impl WholeStreamCommand for PluginSink { &self.name } - fn signature(&self) -> registry::Signature { + fn signature(&self) -> Signature { self.config.clone() } @@ -315,7 +318,7 @@ pub fn sink_plugin( // Needed for async_stream to type check if false { - yield ReturnSuccess::value(UntaggedValue::nothing().into_untagged_value()); + yield ReturnSuccess::value(value::nothing().into_untagged_value()); } }; Ok(OutputStream::new(stream)) diff --git a/src/commands/post.rs b/src/commands/post.rs index 1d4d1e7856..288f9c76be 100644 --- a/src/commands/post.rs +++ b/src/commands/post.rs @@ -1,11 +1,12 @@ use crate::commands::UnevaluatedCallInfo; -use crate::data::base::{UntaggedValue, Value}; -use crate::errors::ShellError; -use crate::parser::hir::SyntaxShape; -use crate::parser::registry::Signature; +use crate::data::value; use crate::prelude::*; use base64::encode; use mime::Mime; +use nu_protocol::{ + CallInfo, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, +}; +use nu_errors::ShellError; use nu_source::AnchorLocation; use std::path::PathBuf; use std::str::FromStr; @@ -81,13 +82,16 @@ fn run( })? { file => file.clone(), }; - let path_str = path.as_string()?; + let path_str = path.as_string()?.to_string(); let has_raw = call_info.args.has("raw"); - let user = call_info.args.get("user").map(|x| x.as_string().unwrap()); + let user = call_info + .args + .get("user") + .map(|x| x.as_string().unwrap().to_string()); let password = call_info .args .get("password") - .map(|x| x.as_string().unwrap()); + .map(|x| x.as_string().unwrap().to_string()); let registry = registry.clone(); let raw_args = raw_args.clone(); @@ -115,7 +119,7 @@ fn run( ctrl_c: raw_args.ctrl_c, shell_manager: raw_args.shell_manager, call_info: UnevaluatedCallInfo { - args: crate::parser::hir::Call { + args: nu_parser::hir::Call { head: raw_args.call_info.args.head, positional: None, named: None, @@ -259,7 +263,7 @@ pub async fn post( ctrl_c: raw_args.ctrl_c, shell_manager: raw_args.shell_manager, call_info: UnevaluatedCallInfo { - args: crate::parser::hir::Call { + args: nu_parser::hir::Call { head: raw_args.call_info.args.head, positional: None, named: None, @@ -316,7 +320,7 @@ pub async fn post( match (content_type.type_(), content_type.subtype()) { (mime::APPLICATION, mime::XML) => Ok(( Some("xml".to_string()), - UntaggedValue::string(r.body_string().await.map_err(|_| { + value::string(r.body_string().await.map_err(|_| { ShellError::labeled_error( "Could not load text from remote url", "could not load", @@ -330,7 +334,7 @@ pub async fn post( )), (mime::APPLICATION, mime::JSON) => Ok(( Some("json".to_string()), - UntaggedValue::string(r.body_string().await.map_err(|_| { + value::string(r.body_string().await.map_err(|_| { ShellError::labeled_error( "Could not load text from remote url", "could not load", @@ -352,7 +356,7 @@ pub async fn post( })?; Ok(( None, - UntaggedValue::binary(buf), + value::binary(buf), Tag { anchor: Some(AnchorLocation::Url(location.to_string())), span: tag.span, @@ -369,7 +373,7 @@ pub async fn post( })?; Ok(( Some(image_ty.to_string()), - UntaggedValue::binary(buf), + value::binary(buf), Tag { anchor: Some(AnchorLocation::Url(location.to_string())), span: tag.span, @@ -378,7 +382,7 @@ pub async fn post( } (mime::TEXT, mime::HTML) => Ok(( Some("html".to_string()), - UntaggedValue::string(r.body_string().await.map_err(|_| { + value::string(r.body_string().await.map_err(|_| { ShellError::labeled_error( "Could not load text from remote url", "could not load", @@ -404,7 +408,7 @@ pub async fn post( Ok(( path_extension, - UntaggedValue::string(r.body_string().await.map_err(|_| { + value::string(r.body_string().await.map_err(|_| { ShellError::labeled_error( "Could not load text from remote url", "could not load", @@ -419,7 +423,7 @@ pub async fn post( } (ty, sub_ty) => Ok(( None, - UntaggedValue::string(format!( + value::string(format!( "Not yet supported MIME type: {} {}", ty, sub_ty )), @@ -432,7 +436,7 @@ pub async fn post( } None => Ok(( None, - UntaggedValue::string(format!("No content type found")), + value::string(format!("No content type found")), Tag { anchor: Some(AnchorLocation::Url(location.to_string())), span: tag.span, diff --git a/src/commands/prepend.rs b/src/commands/prepend.rs index de2cc499f1..6adb7c7ec5 100644 --- a/src/commands/prepend.rs +++ b/src/commands/prepend.rs @@ -1,7 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; -use crate::parser::CommandRegistry; +use crate::context::CommandRegistry; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Signature, SyntaxShape, Value}; #[derive(Deserialize)] struct PrependArgs { diff --git a/src/commands/prev.rs b/src/commands/prev.rs index 970cce3436..79a8de4963 100644 --- a/src/commands/prev.rs +++ b/src/commands/prev.rs @@ -1,6 +1,6 @@ -use crate::commands::command::CommandAction; -use crate::errors::ShellError; use crate::prelude::*; +use nu_protocol::{CommandAction, ReturnSuccess, Signature}; +use nu_errors::ShellError; use crate::commands::WholeStreamCommand; diff --git a/src/commands/pwd.rs b/src/commands/pwd.rs index 37e2668bdb..390ed2dd6b 100644 --- a/src/commands/pwd.rs +++ b/src/commands/pwd.rs @@ -1,7 +1,7 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; -use crate::parser::registry::Signature; use crate::prelude::*; +use nu_protocol::{Signature}; +use nu_errors::ShellError; pub struct PWD; diff --git a/src/commands/reduce_by.rs b/src/commands/reduce_by.rs index 24ad5950e9..3992276e12 100644 --- a/src/commands/reduce_by.rs +++ b/src/commands/reduce_by.rs @@ -1,6 +1,7 @@ use crate::commands::WholeStreamCommand; -use crate::parser::hir::SyntaxShape; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_source::Tagged; use num_traits::cast::ToPrimitive; @@ -134,9 +135,9 @@ pub fn reduce( } = d { acc = reduce_with(acc, x.clone()); - UntaggedValue::number(acc).into_value(&tag) + value::number(acc).into_value(&tag) } else { - UntaggedValue::number(0).into_value(&tag) + value::number(0).into_value(&tag) } }) .collect::>(); @@ -163,24 +164,24 @@ mod tests { use crate::commands::reduce_by::{reduce, reducer_for, Reduce}; use crate::commands::t_sort_by::t_sort; use crate::prelude::*; - use crate::Value; use indexmap::IndexMap; + use nu_protocol::{UntaggedValue, Value}; use nu_source::*; fn int(s: impl Into) -> Value { - UntaggedValue::int(s).into_untagged_value() + value::int(s).into_untagged_value() } fn string(input: impl Into) -> Value { - UntaggedValue::string(input.into()).into_untagged_value() + value::string(input.into()).into_untagged_value() } fn row(entries: IndexMap) -> Value { - UntaggedValue::row(entries).into_untagged_value() + value::row(entries).into_untagged_value() } fn table(list: &Vec) -> Value { - UntaggedValue::table(list).into_untagged_value() + value::table(list).into_untagged_value() } fn nu_releases_sorted_by_date() -> Value { diff --git a/src/commands/reject.rs b/src/commands/reject.rs index 8df4cfcd37..519a0d371d 100644 --- a/src/commands/reject.rs +++ b/src/commands/reject.rs @@ -1,7 +1,8 @@ use crate::commands::WholeStreamCommand; use crate::data::base::reject_fields; -use crate::errors::ShellError; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Signature, SyntaxShape}; use nu_source::Tagged; #[derive(Deserialize)] diff --git a/src/commands/reverse.rs b/src/commands/reverse.rs index 8b81297249..fd70090d02 100644 --- a/src/commands/reverse.rs +++ b/src/commands/reverse.rs @@ -1,7 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; -use crate::parser::CommandRegistry; +use crate::context::CommandRegistry; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::Signature; pub struct Reverse; diff --git a/src/commands/rm.rs b/src/commands/rm.rs index c1f4104137..9b8f67ffe3 100644 --- a/src/commands/rm.rs +++ b/src/commands/rm.rs @@ -1,8 +1,8 @@ use crate::commands::command::RunnablePerItemContext; -use crate::errors::ShellError; -use crate::parser::hir::SyntaxShape; -use crate::parser::registry::{CommandRegistry, Signature}; +use crate::context::CommandRegistry; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{CallInfo, Signature, SyntaxShape, Value}; use nu_source::Tagged; use std::path::PathBuf; diff --git a/src/commands/save.rs b/src/commands/save.rs index 9c065dadd8..3bb87029cd 100644 --- a/src/commands/save.rs +++ b/src/commands/save.rs @@ -1,7 +1,7 @@ use crate::commands::{UnevaluatedCallInfo, WholeStreamCommand}; -use crate::data::Value; -use crate::errors::ShellError; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_source::Tagged; use std::path::{Path, PathBuf}; @@ -185,7 +185,7 @@ fn save( ctrl_c, shell_manager, call_info: UnevaluatedCallInfo { - args: crate::parser::hir::Call { + args: nu_parser::hir::Call { head: raw_args.call_info.args.head, positional: None, named: None, diff --git a/src/commands/shells.rs b/src/commands/shells.rs index aac5f8e7d7..7112237f0e 100644 --- a/src/commands/shells.rs +++ b/src/commands/shells.rs @@ -1,7 +1,8 @@ use crate::commands::WholeStreamCommand; use crate::data::TaggedDictBuilder; -use crate::errors::ShellError; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::Signature; use std::sync::atomic::Ordering; pub struct Shells; diff --git a/src/commands/size.rs b/src/commands/size.rs index 80dcdbd082..5a637ea94c 100644 --- a/src/commands/size.rs +++ b/src/commands/size.rs @@ -1,7 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::data::{TaggedDictBuilder, Value}; -use crate::errors::ShellError; +use crate::data::{value, TaggedDictBuilder}; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; pub struct Size; @@ -76,11 +77,11 @@ fn count(contents: &str, tag: impl Into) -> Value { let mut dict = TaggedDictBuilder::new(tag); //TODO: add back in name when we have it in the tag - //dict.insert("name", UntaggedValue::string(name)); - dict.insert_untagged("lines", UntaggedValue::int(lines)); - dict.insert_untagged("words", UntaggedValue::int(words)); - dict.insert_untagged("chars", UntaggedValue::int(chars)); - dict.insert_untagged("max length", UntaggedValue::int(bytes)); + //dict.insert("name", value::string(name)); + dict.insert_untagged("lines", value::int(lines)); + dict.insert_untagged("words", value::int(words)); + dict.insert_untagged("chars", value::int(chars)); + dict.insert_untagged("max length", value::int(bytes)); dict.into_value() } diff --git a/src/commands/skip_while.rs b/src/commands/skip_while.rs index 9e1cfe14c5..2407ffe5a6 100644 --- a/src/commands/skip_while.rs +++ b/src/commands/skip_while.rs @@ -1,14 +1,14 @@ use crate::commands::WholeStreamCommand; -use crate::data::base::Block; -use crate::errors::ShellError; use crate::prelude::*; use log::trace; +use nu_errors::ShellError; +use nu_protocol::{Evaluate, Scope, Signature, SyntaxShape}; pub struct SkipWhile; #[derive(Deserialize)] pub struct SkipWhileArgs { - condition: Block, + condition: Evaluate, } impl WholeStreamCommand for SkipWhile { @@ -45,7 +45,7 @@ pub fn skip_while( ) -> Result { let objects = input.values.skip_while(move |item| { trace!("ITEM = {:?}", item); - let result = condition.invoke(&item); + let result = condition.invoke(&Scope::new(item.clone())); trace!("RESULT = {:?}", result); let return_value = match result { diff --git a/src/commands/sort_by.rs b/src/commands/sort_by.rs index 8d6378a8c4..ed4180ef30 100644 --- a/src/commands/sort_by.rs +++ b/src/commands/sort_by.rs @@ -1,6 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; +use crate::data::base::property_get::get_data_by_key; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Signature, SyntaxShape, Value}; use nu_source::Tagged; pub struct SortBy; @@ -39,10 +41,10 @@ fn sort_by( Ok(OutputStream::new(async_stream! { let mut vec = context.input.drain_vec().await; - let calc_key = |item: &crate::data::base::Value| { + let calc_key = |item: &Value| { rest.iter() - .map(|f| item.get_data_by_key(f.borrow_spanned()).map(|i| i.clone())) - .collect::>>() + .map(|f| get_data_by_key(item, f.borrow_spanned()).map(|i| i.clone())) + .collect::>>() }; vec.sort_by_cached_key(calc_key); diff --git a/src/commands/split_by.rs b/src/commands/split_by.rs index 7821d3cfcb..e7a9540e58 100644 --- a/src/commands/split_by.rs +++ b/src/commands/split_by.rs @@ -1,8 +1,10 @@ use crate::commands::WholeStreamCommand; -use crate::data::base::UntaggedValue; use crate::data::TaggedDictBuilder; -use crate::errors::ShellError; use crate::prelude::*; +use nu_protocol::{ + ReturnSuccess, Signature, SpannedTypeName, SyntaxShape, UntaggedValue, Value, +}; +use nu_errors::ShellError; use nu_source::Tagged; pub struct SplitBy; @@ -104,7 +106,7 @@ pub fn split( .or_insert(indexmap::IndexMap::new()); s.insert( group_key.clone(), - UntaggedValue::table(&subset).into_value(tag), + value::table(&subset).into_value(tag), ); } other => { @@ -144,7 +146,7 @@ pub fn split( let mut out = TaggedDictBuilder::new(&origin_tag); for (k, v) in splits.into_iter() { - out.insert_untagged(k, UntaggedValue::row(v)); + out.insert_untagged(k, value::row(v)); } Ok(out.into_value()) @@ -154,20 +156,21 @@ mod tests { use crate::commands::group_by::group; use crate::commands::split_by::split; - use crate::data::base::{UntaggedValue, Value}; + use crate::data::value; use indexmap::IndexMap; + use nu_protocol::Value; use nu_source::*; fn string(input: impl Into) -> Value { - UntaggedValue::string(input.into()).into_untagged_value() + value::string(input.into()).into_untagged_value() } fn row(entries: IndexMap) -> Value { - UntaggedValue::row(entries).into_untagged_value() + value::row(entries).into_untagged_value() } fn table(list: &Vec) -> Value { - UntaggedValue::table(list).into_untagged_value() + value::table(list).into_untagged_value() } fn nu_releases_grouped_by_date() -> Value { @@ -213,7 +216,7 @@ mod tests { assert_eq!( split(&for_key, &nu_releases_grouped_by_date(), Tag::unknown()).unwrap(), - UntaggedValue::row(indexmap! { + value::row(indexmap! { "EC".into() => row(indexmap! { "August 23-2019".into() => table(&vec![ row(indexmap!{"name".into() => string("AR"), "country".into() => string("EC"), "date".into() => string("August 23-2019")}) @@ -260,7 +263,7 @@ mod tests { row(indexmap!{"name".into() => string("AR"), "country".into() => string("EC"), "date".into() => string("August 23-2019")}) ]), "Sept 24-2019".into() => table(&vec![ - row(indexmap!{"name".into() => UntaggedValue::string("JT").into_value(Tag::from(Span::new(5,10))), "date".into() => string("Sept 24-2019")}) + row(indexmap!{"name".into() => value::string("JT").into_value(Tag::from(Span::new(5,10))), "date".into() => string("Sept 24-2019")}) ]), "October 10-2019".into() => table(&vec![ row(indexmap!{"name".into() => string("YK"), "country".into() => string("US"), "date".into() => string("October 10-2019")}) diff --git a/src/commands/split_column.rs b/src/commands/split_column.rs index 874c6ebb66..110f9b2a28 100644 --- a/src/commands/split_column.rs +++ b/src/commands/split_column.rs @@ -1,8 +1,9 @@ use crate::commands::WholeStreamCommand; -use crate::data::{Primitive, TaggedDictBuilder}; -use crate::errors::ShellError; +use crate::data::TaggedDictBuilder; use crate::prelude::*; use log::trace; +use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue}; +use nu_errors::ShellError; use nu_source::Tagged; #[derive(Deserialize)] diff --git a/src/commands/split_row.rs b/src/commands/split_row.rs index 209e25c578..0e6b702b6b 100644 --- a/src/commands/split_row.rs +++ b/src/commands/split_row.rs @@ -1,8 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::data::Primitive; -use crate::errors::ShellError; use crate::prelude::*; use log::trace; +use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue}; +use nu_errors::ShellError; use nu_source::Tagged; #[derive(Deserialize)] diff --git a/src/commands/t_sort_by.rs b/src/commands/t_sort_by.rs index e0e639108a..222a545467 100644 --- a/src/commands/t_sort_by.rs +++ b/src/commands/t_sort_by.rs @@ -1,8 +1,12 @@ use crate::commands::WholeStreamCommand; -use crate::data::{TaggedDictBuilder, TaggedListBuilder}; -use crate::errors::ShellError; +use crate::data::base::property_get::get_data_by_key; +use crate::data::{value, TaggedDictBuilder, TaggedListBuilder}; use crate::prelude::*; use chrono::{DateTime, NaiveDate, Utc}; +use nu_protocol::{ + Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, +}; +use nu_errors::ShellError; use nu_source::Tagged; pub struct TSortBy; @@ -68,7 +72,7 @@ fn t_sort_by( if show_columns { for label in columns_sorted(column_grouped_by_name, &values[0], &name).into_iter() { - yield ReturnSuccess::value(UntaggedValue::string(label.item).into_value(label.tag)); + yield ReturnSuccess::value(value::string(label.item).into_value(label.tag)); } } else { match t_sort(column_grouped_by_name, None, &values[0], name) { @@ -102,7 +106,7 @@ pub fn columns_sorted( Ok(parsed) => UntaggedValue::Primitive(Primitive::Date( DateTime::::from_utc(parsed.and_hms(12, 34, 56), Utc), )), - Err(_) => UntaggedValue::string(k), + Err(_) => value::string(k), }; date.into_untagged_value() @@ -118,7 +122,7 @@ pub fn columns_sorted( value: UntaggedValue::Primitive(Primitive::Date(d)), .. } => format!("{}", d.format("%B %d-%Y")), - _ => k.as_string().unwrap(), + _ => k.as_string().unwrap().to_string(), }) .collect(); @@ -168,7 +172,7 @@ pub fn t_sort( let results: Vec> = split_labels .iter() .map(|split| { - let groups = dataset.get_data_by_key(split.borrow_spanned()); + let groups = get_data_by_key(&dataset, split.borrow_spanned()); sorted_labels .clone() @@ -195,10 +199,10 @@ pub fn t_sort( return Ok(UntaggedValue::Table(outer.list).into_value(&origin_tag)); } - Some(_) => return Ok(UntaggedValue::nothing().into_value(&origin_tag)), + Some(_) => return Ok(value::nothing().into_value(&origin_tag)), } } - None => return Ok(UntaggedValue::nothing().into_value(&origin_tag)), + None => return Ok(value::nothing().into_value(&origin_tag)), } } #[cfg(test)] @@ -206,20 +210,21 @@ mod tests { use crate::commands::group_by::group; use crate::commands::t_sort_by::{columns_sorted, t_sort}; - use crate::data::base::{UntaggedValue, Value}; + use crate::data::value; use indexmap::IndexMap; + use nu_protocol::{UntaggedValue, Value}; use nu_source::*; fn string(input: impl Into) -> Value { - UntaggedValue::string(input.into()).into_untagged_value() + value::string(input.into()).into_untagged_value() } fn row(entries: IndexMap) -> Value { - UntaggedValue::row(entries).into_untagged_value() + value::row(entries).into_untagged_value() } fn table(list: &Vec) -> Value { - UntaggedValue::table(list).into_untagged_value() + value::table(list).into_untagged_value() } fn nu_releases_grouped_by_date() -> Value { diff --git a/src/commands/table.rs b/src/commands/table.rs index 71ee30c824..1292b9419b 100644 --- a/src/commands/table.rs +++ b/src/commands/table.rs @@ -1,7 +1,11 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; +use crate::data::value; use crate::format::TableView; use crate::prelude::*; +use nu_protocol::{ + Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, +}; +use nu_errors::ShellError; pub struct Table; @@ -56,7 +60,7 @@ fn table(args: CommandArgs, registry: &CommandRegistry) -> Result Result { - tags.insert_untagged("anchor", UntaggedValue::string(source)); + tags.insert_untagged("anchor", value::string(source)); } Some(AnchorLocation::Url(source)) => { - tags.insert_untagged("anchor", UntaggedValue::string(source)); + tags.insert_untagged("anchor", value::string(source)); } _ => {} } diff --git a/src/commands/to_bson.rs b/src/commands/to_bson.rs index 9156532b7e..9fab91a9d1 100644 --- a/src/commands/to_bson.rs +++ b/src/commands/to_bson.rs @@ -1,8 +1,12 @@ use crate::commands::WholeStreamCommand; -use crate::data::{Dictionary, Primitive, Value}; +use crate::data::value; use crate::prelude::*; -use crate::UnspannedPathMember; use bson::{encode_document, oid::ObjectId, spec::BinarySubtype, Bson, Document}; +use nu_errors::{CoerceInto, ShellError}; +use nu_protocol::{ + Dictionary, Primitive, ReturnSuccess, Signature, SpannedTypeName, UnspannedPathMember, + UntaggedValue, Value, +}; use std::convert::TryInto; pub struct ToBSON; @@ -190,7 +194,7 @@ fn get_binary_subtype<'a>(tagged_value: &'a Value) -> Result Err(ShellError::type_error( "bson binary", - tagged_value.type_name().spanned(tagged_value.span()), + tagged_value.spanned_type_name(), )), } } @@ -269,7 +273,7 @@ fn to_bson(args: CommandArgs, registry: &CommandRegistry) -> Result yield ReturnSuccess::value( - UntaggedValue::binary(x).into_value(&name_tag), + value::binary(x).into_value(&name_tag), ), _ => yield Err(ShellError::labeled_error_with_secondary( "Expected a table with BSON-compatible structure.tag() from pipeline", diff --git a/src/commands/to_csv.rs b/src/commands/to_csv.rs index 03643cc691..2ce9b9d6e4 100644 --- a/src/commands/to_csv.rs +++ b/src/commands/to_csv.rs @@ -1,7 +1,8 @@ use crate::commands::to_delimited_data::to_delimited_data; use crate::commands::WholeStreamCommand; -use crate::data::{Primitive, Value}; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Primitive, Signature, UntaggedValue, Value}; pub struct ToCSV; diff --git a/src/commands/to_delimited_data.rs b/src/commands/to_delimited_data.rs index 8494ce5377..ceadfef803 100644 --- a/src/commands/to_delimited_data.rs +++ b/src/commands/to_delimited_data.rs @@ -1,7 +1,9 @@ -use crate::data::{Primitive, Value}; +use crate::data::base::property_get::get_data_by_key; use crate::prelude::*; use csv::WriterBuilder; use indexmap::{indexset, IndexSet}; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, UntaggedValue, Value}; use nu_source::Spanned; fn from_value_to_delimited_string( @@ -55,7 +57,7 @@ fn from_value_to_delimited_string( for l in list { let mut row = vec![]; for desc in &merged_descriptors { - match l.get_data_by_key(desc.borrow_spanned()) { + match get_data_by_key(l, desc.borrow_spanned()) { Some(s) => { row.push(to_string_tagged_value(&s)?); } @@ -129,10 +131,10 @@ fn to_string_tagged_value(v: &Value) -> Result { let tmp = format!("{}", b); Ok(tmp) } - UntaggedValue::Primitive(Primitive::Boolean(_)) => Ok(v.as_string()?), - UntaggedValue::Primitive(Primitive::Decimal(_)) => Ok(v.as_string()?), - UntaggedValue::Primitive(Primitive::Int(_)) => Ok(v.as_string()?), - UntaggedValue::Primitive(Primitive::Path(_)) => Ok(v.as_string()?), + UntaggedValue::Primitive(Primitive::Boolean(_)) => Ok(v.as_string()?.to_string()), + UntaggedValue::Primitive(Primitive::Decimal(_)) => Ok(v.as_string()?.to_string()), + UntaggedValue::Primitive(Primitive::Int(_)) => Ok(v.as_string()?.to_string()), + UntaggedValue::Primitive(Primitive::Path(_)) => Ok(v.as_string()?.to_string()), UntaggedValue::Table(_) => return Ok(String::from("[Table]")), UntaggedValue::Row(_) => return Ok(String::from("[Row]")), UntaggedValue::Primitive(Primitive::String(s)) => return Ok(s.to_string()), diff --git a/src/commands/to_json.rs b/src/commands/to_json.rs index b1dba6910b..10244a2260 100644 --- a/src/commands/to_json.rs +++ b/src/commands/to_json.rs @@ -1,7 +1,7 @@ use crate::commands::WholeStreamCommand; -use crate::data::base::{Primitive, UntaggedValue, Value}; use crate::prelude::*; -use crate::UnspannedPathMember; +use nu_errors::{CoerceInto, ShellError}; +use nu_protocol::{Primitive, ReturnSuccess, Signature, UnspannedPathMember, UntaggedValue, Value}; pub struct ToJSON; diff --git a/src/commands/to_sqlite.rs b/src/commands/to_sqlite.rs index b8a278e74a..5f395aa0d0 100644 --- a/src/commands/to_sqlite.rs +++ b/src/commands/to_sqlite.rs @@ -1,7 +1,10 @@ use crate::commands::WholeStreamCommand; -use crate::data::{Dictionary, Primitive, Value}; use crate::prelude::*; use hex::encode; +use nu_protocol::{ + Dictionary, Primitive, ReturnSuccess, Signature, UntaggedValue, Value, +}; +use nu_errors::ShellError; use rusqlite::{Connection, NO_PARAMS}; use std::io::Read; @@ -195,7 +198,7 @@ fn sqlite_input_stream_to_bytes(values: Vec) -> Result Result { diff --git a/src/commands/to_toml.rs b/src/commands/to_toml.rs index 71ff12ebee..76b03aa89c 100644 --- a/src/commands/to_toml.rs +++ b/src/commands/to_toml.rs @@ -1,7 +1,10 @@ use crate::commands::WholeStreamCommand; -use crate::data::{Primitive, Value}; use crate::prelude::*; -use crate::UnspannedPathMember; +use nu_protocol::{ + Primitive, ReturnSuccess, Signature, UnspannedPathMember, UntaggedValue, Value, +}; +use nu_errors::{ShellError, CoerceInto}; + pub struct ToTOML; diff --git a/src/commands/to_tsv.rs b/src/commands/to_tsv.rs index f567215e59..3177e1dca9 100644 --- a/src/commands/to_tsv.rs +++ b/src/commands/to_tsv.rs @@ -1,6 +1,8 @@ use crate::commands::to_delimited_data::to_delimited_data; use crate::commands::WholeStreamCommand; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::Signature; pub struct ToTSV; diff --git a/src/commands/to_url.rs b/src/commands/to_url.rs index 3cb12ac045..1326561681 100644 --- a/src/commands/to_url.rs +++ b/src/commands/to_url.rs @@ -1,6 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::data::Value; +use crate::data::value; use crate::prelude::*; +use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value}; +use nu_errors::ShellError; pub struct ToURL; @@ -41,7 +43,7 @@ fn to_url(args: CommandArgs, registry: &CommandRegistry) -> Result { - row_vec.push((k.clone(), s)); + row_vec.push((k.clone(), s.to_string())); } _ => { yield Err(ShellError::labeled_error_with_secondary( @@ -57,7 +59,7 @@ fn to_url(args: CommandArgs, registry: &CommandRegistry) -> Result { - yield ReturnSuccess::value(UntaggedValue::string(s).into_value(&tag)); + yield ReturnSuccess::value(value::string(s).into_value(&tag)); } _ => { yield Err(ShellError::labeled_error( diff --git a/src/commands/to_yaml.rs b/src/commands/to_yaml.rs index 3b3556726b..20ad7be45c 100644 --- a/src/commands/to_yaml.rs +++ b/src/commands/to_yaml.rs @@ -1,7 +1,11 @@ use crate::commands::WholeStreamCommand; -use crate::data::{Primitive, Value}; use crate::prelude::*; -use crate::UnspannedPathMember; +use nu_protocol::{ + Primitive, ReturnSuccess, Signature, UnspannedPathMember, + UntaggedValue, Value, +}; +use nu_errors::{ShellError, CoerceInto}; + pub struct ToYAML; diff --git a/src/commands/trim.rs b/src/commands/trim.rs index de10249dcf..264b8c68e0 100644 --- a/src/commands/trim.rs +++ b/src/commands/trim.rs @@ -1,7 +1,8 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; use crate::prelude::*; +use nu_protocol::{ReturnSuccess, Signature}; +use nu_errors::ShellError; pub struct Trim; @@ -34,7 +35,7 @@ fn trim(args: CommandArgs, _registry: &CommandRegistry) -> Result Result registry::Signature { + fn signature(&self) -> Signature { Signature::build("where").required( "condition", SyntaxShape::Block, @@ -26,7 +26,7 @@ impl PerItemCommand for Where { fn run( &self, call_info: &CallInfo, - _registry: ®istry::CommandRegistry, + _registry: &CommandRegistry, _raw_args: &RawCommandArgs, input: Value, ) -> Result { @@ -37,7 +37,7 @@ impl PerItemCommand for Where { value: UntaggedValue::Block(block), .. } => { - let result = block.invoke(&input_clone); + let result = block.invoke(&Scope::new(input_clone.clone())); match result { Ok(v) => { if v.is_true() { diff --git a/src/commands/which_.rs b/src/commands/which_.rs index cc68adf59a..e1459d2da2 100644 --- a/src/commands/which_.rs +++ b/src/commands/which_.rs @@ -1,9 +1,7 @@ -use crate::data::Value; -use crate::errors::ShellError; -use crate::prelude::*; - use crate::commands::WholeStreamCommand; -use crate::parser::registry::Signature; +use crate::prelude::*; +use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value}; +use nu_errors::ShellError; pub struct Which; diff --git a/src/context.rs b/src/context.rs index 5535e9c1d4..0753d00f56 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,12 +1,12 @@ use crate::commands::{command::CommandArgs, Command, UnevaluatedCallInfo}; use crate::env::host::Host; -use crate::errors::ShellError; -use crate::parser::{hir, hir::syntax_shape::ExpandContext}; +use nu_parser::{hir, hir::syntax_shape::ExpandContext, hir::syntax_shape::SignatureRegistry}; use crate::shell::shell_manager::ShellManager; use crate::stream::{InputStream, OutputStream}; use indexmap::IndexMap; -use nu_source::Tag; -use nu_source::Text; +use nu_errors::ShellError; +use nu_protocol::{errln, Signature}; +use nu_source::{Tag, Text}; use std::error::Error; use std::sync::atomic::AtomicBool; use std::sync::{Arc, Mutex}; @@ -16,6 +16,17 @@ pub struct CommandRegistry { registry: Arc>>>, } +impl SignatureRegistry for CommandRegistry { + fn has(&self, name: &str) -> bool { + let registry = self.registry.lock().unwrap(); + registry.contains_key(name) + } + fn get(&self, name: &str) -> Option { + let registry = self.registry.lock().unwrap(); + registry.get(name).map(|command| command.signature()) + } +} + impl CommandRegistry { pub fn new() -> CommandRegistry { CommandRegistry { @@ -76,7 +87,11 @@ impl Context { &'context self, source: &'context Text, ) -> ExpandContext<'context> { - ExpandContext::new(&self.registry, source, self.shell_manager.homedir()) + ExpandContext::new( + Box::new(self.registry.clone()), + source, + self.shell_manager.homedir(), + ) } pub(crate) fn basic() -> Result> { diff --git a/src/data.rs b/src/data.rs index a0968e3085..80518ee6b6 100644 --- a/src/data.rs +++ b/src/data.rs @@ -3,10 +3,10 @@ pub(crate) mod command; pub(crate) mod config; pub(crate) mod dict; pub(crate) mod files; -pub(crate) mod into; +pub mod primitive; pub(crate) mod types; +pub mod value; -pub(crate) use base::{Primitive, Value}; pub(crate) use command::command_dict; -pub(crate) use dict::{Dictionary, TaggedDictBuilder, TaggedListBuilder}; +pub(crate) use dict::{TaggedDictBuilder, TaggedListBuilder}; pub(crate) use files::dir_entry_dict; diff --git a/src/data/base.rs b/src/data/base.rs index 605e2fc216..70549b48e0 100644 --- a/src/data/base.rs +++ b/src/data/base.rs @@ -1,222 +1,26 @@ -mod debug; -mod property_get; +pub(crate) mod property_get; pub(crate) mod shape; use crate::context::CommandRegistry; -use crate::data::base::shape::{Column, InlineShape, TypeShape}; -use crate::data::TaggedDictBuilder; -use crate::errors::ShellError; -use crate::evaluate::{evaluate_baseline_expr, Scope}; -use crate::parser::hir::path::{ColumnPath, PathMember}; -use crate::parser::{hir, Operator}; -use crate::prelude::*; +use crate::data::base::property_get::ValueExt; +use crate::data::{value, TaggedDictBuilder}; +use crate::evaluate::evaluate_baseline_expr; +use bigdecimal::BigDecimal; use chrono::{DateTime, Utc}; -use chrono_humanize::Humanize; use derive_new::new; -use indexmap::IndexMap; use log::trace; -use nu_source::{AnchorLocation, PrettyDebug, SpannedItem, Tagged, TaggedItem, Text}; +use nu_errors::ShellError; +use nu_parser::{hir, Operator}; +use nu_protocol::{ + Evaluate, EvaluateTrait, Primitive, Scope, ShellTypeName, SpannedTypeName, UntaggedValue, Value, +}; +use nu_source::{Tag, Text}; +use num_bigint::BigInt; +use num_traits::Zero; +use query_interface::{interfaces, vtable_for, ObjectHash}; use serde::{Deserialize, Serialize}; -use std::path::PathBuf; use std::time::SystemTime; -mod serde_bigint { - use num_traits::cast::FromPrimitive; - use num_traits::cast::ToPrimitive; - - pub fn serialize(big_int: &super::BigInt, serializer: S) -> Result - where - S: serde::Serializer, - { - serde::Serialize::serialize( - &big_int - .to_i64() - .ok_or(serde::ser::Error::custom("expected a i64-sized bignum"))?, - serializer, - ) - } - - pub fn deserialize<'de, D>(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let x: i64 = serde::Deserialize::deserialize(deserializer)?; - Ok(super::BigInt::from_i64(x) - .ok_or(serde::de::Error::custom("expected a i64-sized bignum"))?) - } -} - -mod serde_bigdecimal { - use num_traits::cast::FromPrimitive; - use num_traits::cast::ToPrimitive; - - pub fn serialize(big_decimal: &super::BigDecimal, serializer: S) -> Result - where - S: serde::Serializer, - { - serde::Serialize::serialize( - &big_decimal - .to_f64() - .ok_or(serde::ser::Error::custom("expected a f64-sized bignum"))?, - serializer, - ) - } - - pub fn deserialize<'de, D>(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let x: f64 = serde::Deserialize::deserialize(deserializer)?; - Ok(super::BigDecimal::from_f64(x) - .ok_or(serde::de::Error::custom("expected a f64-sized bigdecimal"))?) - } -} - -#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Deserialize, Serialize)] -pub enum Primitive { - Nothing, - #[serde(with = "serde_bigint")] - Int(BigInt), - #[serde(with = "serde_bigdecimal")] - Decimal(BigDecimal), - Bytes(u64), - String(String), - ColumnPath(ColumnPath), - Pattern(String), - Boolean(bool), - Date(DateTime), - Duration(u64), // Duration in seconds - Path(PathBuf), - #[serde(with = "serde_bytes")] - Binary(Vec), - - // Stream markers (used as bookend markers rather than actual values) - BeginningOfStream, - EndOfStream, -} - -impl ShellTypeName for Primitive { - fn type_name(&self) -> &'static str { - match self { - Primitive::Nothing => "nothing", - Primitive::Int(_) => "integer", - Primitive::Decimal(_) => "decimal", - Primitive::Bytes(_) => "bytes", - Primitive::String(_) => "string", - Primitive::ColumnPath(_) => "column path", - Primitive::Pattern(_) => "pattern", - Primitive::Boolean(_) => "boolean", - Primitive::Date(_) => "date", - Primitive::Duration(_) => "duration", - Primitive::Path(_) => "file path", - Primitive::Binary(_) => "binary", - Primitive::BeginningOfStream => "marker", - Primitive::EndOfStream => "marker", - } - } -} - -impl From for Primitive { - fn from(decimal: BigDecimal) -> Primitive { - Primitive::Decimal(decimal) - } -} - -impl From for Primitive { - fn from(float: f64) -> Primitive { - Primitive::Decimal(BigDecimal::from_f64(float).unwrap()) - } -} - -impl Primitive { - pub fn number(number: impl Into) -> Primitive { - let number = number.into(); - - match number { - Number::Int(int) => Primitive::Int(int), - Number::Decimal(decimal) => Primitive::Decimal(decimal), - } - } - - pub fn format(&self, field_name: Option<&String>) -> String { - match self { - Primitive::Nothing => String::new(), - Primitive::BeginningOfStream => String::new(), - Primitive::EndOfStream => String::new(), - Primitive::Path(p) => format!("{}", p.display()), - Primitive::Bytes(b) => { - let byte = byte_unit::Byte::from_bytes(*b as u128); - - if byte.get_bytes() == 0u128 { - return "—".to_string(); - } - - let byte = byte.get_appropriate_unit(false); - - match byte.get_unit() { - byte_unit::ByteUnit::B => format!("{} B ", byte.get_value()), - _ => format!("{}", byte.format(1)), - } - } - Primitive::Duration(sec) => format_duration(*sec), - Primitive::Int(i) => format!("{}", i), - Primitive::Decimal(decimal) => format!("{}", decimal), - Primitive::Pattern(s) => format!("{}", s), - Primitive::String(s) => format!("{}", s), - Primitive::ColumnPath(p) => { - let mut members = p.iter(); - let mut f = String::new(); - - f.push_str( - &members - .next() - .expect("BUG: column path with zero members") - .display(), - ); - - for member in members { - f.push_str("."); - f.push_str(&member.display()) - } - - f - } - Primitive::Boolean(b) => match (b, field_name) { - (true, None) => format!("Yes"), - (false, None) => format!("No"), - (true, Some(s)) if !s.is_empty() => format!("{}", s), - (false, Some(s)) if !s.is_empty() => format!(""), - (true, Some(_)) => format!("Yes"), - (false, Some(_)) => format!("No"), - }, - Primitive::Binary(_) => format!(""), - Primitive::Date(d) => format!("{}", d.humanize()), - } - } - - pub fn style(&self) -> &'static str { - match self { - Primitive::Bytes(0) => "c", // centre 'missing' indicator - Primitive::Int(_) | Primitive::Bytes(_) | Primitive::Decimal(_) => "r", - _ => "", - } - } -} - -fn format_duration(sec: u64) -> String { - let (minutes, seconds) = (sec / 60, sec % 60); - let (hours, minutes) = (minutes / 60, minutes % 60); - let (days, hours) = (hours / 24, hours % 24); - - match (days, hours, minutes, seconds) { - (0, 0, 0, 1) => format!("1 sec"), - (0, 0, 0, s) => format!("{} secs", s), - (0, 0, m, s) => format!("{}:{:02}", m, s), - (0, h, m, s) => format!("{}:{:02}:{:02}", h, m, s), - (d, h, m, s) => format!("{}:{:02}:{:02}:{:02}", d, h, m, s), - } -} - #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, new, Serialize)] pub struct Operation { pub(crate) left: Value, @@ -231,12 +35,13 @@ pub struct Block { pub(crate) tag: Tag, } -impl Block { - pub fn invoke(&self, value: &Value) -> Result { - let scope = Scope::new(value.clone()); +interfaces!(Block: dyn ObjectHash); +#[typetag::serde] +impl EvaluateTrait for Block { + fn invoke(&self, scope: &Scope) -> Result { if self.expressions.len() == 0 { - return Ok(UntaggedValue::nothing().into_value(&self.tag)); + return Ok(value::nothing().into_value(&self.tag)); } let mut last = None; @@ -260,231 +65,10 @@ impl Block { Ok(last.unwrap()) } -} -#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Serialize, Deserialize)] -pub enum UntaggedValue { - Primitive(Primitive), - Row(crate::data::Dictionary), - Table(Vec), - - // Errors are a type of value too - Error(ShellError), - - Block(Block), -} - -#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] -pub struct Value { - pub value: UntaggedValue, - pub tag: Tag, -} - -impl std::ops::Deref for Value { - type Target = UntaggedValue; - - fn deref(&self) -> &Self::Target { - &self.value - } -} - -impl Into for Value { - fn into(self) -> UntaggedValue { - self.value - } -} - -impl<'a> Into<&'a UntaggedValue> for &'a Value { - fn into(self) -> &'a UntaggedValue { - &self.value - } -} - -impl HasSpan for Value { - fn span(&self) -> Span { - self.tag.span - } -} - -impl ShellTypeName for Value { - fn type_name(&self) -> &'static str { - ShellTypeName::type_name(&self.value) - } -} - -impl ShellTypeName for UntaggedValue { - fn type_name(&self) -> &'static str { - match &self { - UntaggedValue::Primitive(p) => p.type_name(), - UntaggedValue::Row(_) => "row", - UntaggedValue::Table(_) => "table", - UntaggedValue::Error(_) => "error", - UntaggedValue::Block(_) => "block", - } - } -} - -impl Into for Number { - fn into(self) -> UntaggedValue { - match self { - Number::Int(int) => UntaggedValue::int(int), - Number::Decimal(decimal) => UntaggedValue::decimal(decimal), - } - } -} - -impl Into for &Number { - fn into(self) -> UntaggedValue { - match self { - Number::Int(int) => UntaggedValue::int(int.clone()), - Number::Decimal(decimal) => UntaggedValue::decimal(decimal.clone()), - } - } -} - -impl Value { - pub fn anchor(&self) -> Option { - self.tag.anchor() - } - - pub fn anchor_name(&self) -> Option { - self.tag.anchor_name() - } - - pub fn tag(&self) -> Tag { - self.tag.clone() - } - - pub fn into_parts(self) -> (UntaggedValue, Tag) { - (self.value, self.tag) - } - - pub(crate) fn as_path(&self) -> Result { - match &self.value { - UntaggedValue::Primitive(Primitive::Path(path)) => Ok(path.clone()), - UntaggedValue::Primitive(Primitive::String(path_str)) => { - Ok(PathBuf::from(&path_str).clone()) - } - _ => Err(ShellError::type_error("Path", self.spanned_type_name())), - } - } - - pub fn tagged_type_name(&self) -> Tagged { - let name = self.type_name().to_string(); - name.tagged(self.tag.clone()) - } - - pub(crate) fn compare( - &self, - operator: &Operator, - other: &Value, - ) -> Result { - match operator { - _ => { - let coerced = coerce_compare(self, other)?; - let ordering = coerced.compare(); - - use std::cmp::Ordering; - - let result = match (operator, ordering) { - (Operator::Equal, Ordering::Equal) => true, - (Operator::NotEqual, Ordering::Less) - | (Operator::NotEqual, Ordering::Greater) => true, - (Operator::LessThan, Ordering::Less) => true, - (Operator::GreaterThan, Ordering::Greater) => true, - (Operator::GreaterThanOrEqual, Ordering::Greater) - | (Operator::GreaterThanOrEqual, Ordering::Equal) => true, - (Operator::LessThanOrEqual, Ordering::Less) - | (Operator::LessThanOrEqual, Ordering::Equal) => true, - _ => false, - }; - - Ok(result) - } - } - } -} - -impl PrettyDebug for &Value { - fn pretty(&self) -> DebugDocBuilder { - PrettyDebug::pretty(*self) - } -} - -impl PrettyDebug for Value { - fn pretty(&self) -> DebugDocBuilder { - match &self.value { - UntaggedValue::Primitive(p) => p.pretty(), - UntaggedValue::Row(row) => row.pretty_builder().nest(1).group().into(), - UntaggedValue::Table(table) => { - b::delimit("[", b::intersperse(table, b::space()), "]").nest() - } - UntaggedValue::Error(_) => b::error("error"), - UntaggedValue::Block(_) => b::opaque("block"), - } - } -} - -impl std::convert::TryFrom<&Value> for Block { - type Error = ShellError; - - fn try_from(value: &Value) -> Result { - match &value.value { - UntaggedValue::Block(block) => Ok(block.clone()), - _ => Err(ShellError::type_error( - "Block", - value.type_name().spanned(value.tag.span), - )), - } - } -} - -impl std::convert::TryFrom<&Value> for i64 { - type Error = ShellError; - - fn try_from(value: &Value) -> Result { - match &value.value { - UntaggedValue::Primitive(Primitive::Int(int)) => { - int.tagged(&value.tag).coerce_into("converting to i64") - } - _ => Err(ShellError::type_error("Integer", value.spanned_type_name())), - } - } -} - -impl std::convert::TryFrom<&Value> for String { - type Error = ShellError; - - fn try_from(value: &Value) -> Result { - match &value.value { - UntaggedValue::Primitive(Primitive::String(s)) => Ok(s.clone()), - _ => Err(ShellError::type_error("String", value.spanned_type_name())), - } - } -} - -impl std::convert::TryFrom<&Value> for Vec { - type Error = ShellError; - - fn try_from(value: &Value) -> Result, ShellError> { - match &value.value { - UntaggedValue::Primitive(Primitive::Binary(b)) => Ok(b.clone()), - _ => Err(ShellError::type_error("Binary", value.spanned_type_name())), - } - } -} - -impl<'a> std::convert::TryFrom<&'a Value> for &'a crate::data::Dictionary { - type Error = ShellError; - - fn try_from(value: &'a Value) -> Result<&'a crate::data::Dictionary, ShellError> { - match &value.value { - UntaggedValue::Row(d) => Ok(d), - _ => Err(ShellError::type_error( - "Dictionary", - value.spanned_type_name(), - )), - } + fn clone_box(&self) -> Evaluate { + let block = self.clone(); + Evaluate::new(block) } } @@ -508,188 +92,6 @@ impl std::convert::TryFrom> for Switch { } } -impl UntaggedValue { - pub fn into_value(self, tag: impl Into) -> Value { - Value { - value: self, - tag: tag.into(), - } - } - - pub fn into_untagged_value(self) -> Value { - Value { - value: self, - tag: Tag::unknown(), - } - } - - pub fn retag(self, tag: impl Into) -> Value { - Value { - value: self, - tag: tag.into(), - } - } - - pub fn data_descriptors(&self) -> Vec { - match self { - UntaggedValue::Primitive(_) => vec![], - UntaggedValue::Row(columns) => columns - .entries - .keys() - .into_iter() - .map(|x| x.to_string()) - .collect(), - UntaggedValue::Block(_) => vec![], - UntaggedValue::Table(_) => vec![], - UntaggedValue::Error(_) => vec![], - } - } - - #[allow(unused)] - pub(crate) fn format_type(&self, width: usize) -> String { - TypeShape::from_value(self).colored_string(width) - } - - pub(crate) fn format_leaf(&self) -> DebugDocBuilder { - InlineShape::from_value(self).format().pretty() - } - - #[allow(unused)] - pub(crate) fn format_for_column(&self, column: impl Into) -> DebugDocBuilder { - InlineShape::from_value(self) - .format_for_column(column) - .pretty() - } - - pub(crate) fn style_leaf(&self) -> &'static str { - match self { - UntaggedValue::Primitive(p) => p.style(), - _ => "", - } - } - - pub(crate) fn is_true(&self) -> bool { - match self { - UntaggedValue::Primitive(Primitive::Boolean(true)) => true, - _ => false, - } - } - - pub(crate) fn is_some(&self) -> bool { - !self.is_none() - } - - pub(crate) fn is_none(&self) -> bool { - match self { - UntaggedValue::Primitive(Primitive::Nothing) => true, - _ => false, - } - } - - pub(crate) fn is_error(&self) -> bool { - match self { - UntaggedValue::Error(_err) => true, - _ => false, - } - } - - pub(crate) fn expect_error(&self) -> ShellError { - match self { - UntaggedValue::Error(err) => err.clone(), - _ => panic!("Don't call expect_error without first calling is_error"), - } - } - - pub fn expect_string(&self) -> &str { - match self { - UntaggedValue::Primitive(Primitive::String(string)) => &string[..], - _ => panic!("expect_string assumes that the value must be a string"), - } - } - - #[allow(unused)] - pub fn row(entries: IndexMap) -> UntaggedValue { - UntaggedValue::Row(entries.into()) - } - - pub fn table(list: &Vec) -> UntaggedValue { - UntaggedValue::Table(list.to_vec()) - } - - pub fn string(s: impl Into) -> UntaggedValue { - UntaggedValue::Primitive(Primitive::String(s.into())) - } - - pub fn column_path(s: Vec>) -> UntaggedValue { - UntaggedValue::Primitive(Primitive::ColumnPath(ColumnPath::new( - s.into_iter().map(|p| p.into()).collect(), - ))) - } - - pub fn int(i: impl Into) -> UntaggedValue { - UntaggedValue::Primitive(Primitive::Int(i.into())) - } - - pub fn pattern(s: impl Into) -> UntaggedValue { - UntaggedValue::Primitive(Primitive::String(s.into())) - } - - pub fn path(s: impl Into) -> UntaggedValue { - UntaggedValue::Primitive(Primitive::Path(s.into())) - } - - pub fn bytes(s: impl Into) -> UntaggedValue { - UntaggedValue::Primitive(Primitive::Bytes(s.into())) - } - - pub fn decimal(s: impl Into) -> UntaggedValue { - UntaggedValue::Primitive(Primitive::Decimal(s.into())) - } - - pub fn binary(binary: Vec) -> UntaggedValue { - UntaggedValue::Primitive(Primitive::Binary(binary)) - } - - pub fn number(s: impl Into) -> UntaggedValue { - let num = s.into(); - - match num { - Number::Int(int) => UntaggedValue::int(int), - Number::Decimal(decimal) => UntaggedValue::decimal(decimal), - } - } - - pub fn boolean(s: impl Into) -> UntaggedValue { - UntaggedValue::Primitive(Primitive::Boolean(s.into())) - } - - pub fn duration(secs: u64) -> UntaggedValue { - UntaggedValue::Primitive(Primitive::Duration(secs)) - } - - pub fn system_date(s: SystemTime) -> UntaggedValue { - UntaggedValue::Primitive(Primitive::Date(s.into())) - } - - pub fn date_from_str(s: Tagged<&str>) -> Result { - let date = DateTime::parse_from_rfc3339(s.item).map_err(|err| { - ShellError::labeled_error( - &format!("Date parse error: {}", err), - "original value", - s.tag, - ) - })?; - - let date = date.with_timezone(&chrono::offset::Utc); - - Ok(UntaggedValue::Primitive(Primitive::Date(date))) - } - - pub fn nothing() -> UntaggedValue { - UntaggedValue::Primitive(Primitive::Nothing) - } -} - pub(crate) fn select_fields(obj: &Value, fields: &[String], tag: impl Into) -> Value { let mut out = TaggedDictBuilder::new(tag); @@ -697,7 +99,7 @@ pub(crate) fn select_fields(obj: &Value, fields: &[String], tag: impl Into) for field in fields { match descs.iter().find(|d| *d == field) { - None => out.insert_untagged(field, UntaggedValue::nothing()), + None => out.insert_untagged(field, value::nothing()), Some(desc) => out.insert_value(desc.clone(), obj.get_data(desc).borrow().clone()), } } @@ -721,7 +123,7 @@ pub(crate) fn reject_fields(obj: &Value, fields: &[String], tag: impl Into) out.into_value() } -enum CompareValues { +pub(crate) enum CompareValues { Ints(BigInt, BigInt), Decimals(BigDecimal, BigDecimal), String(String, String), @@ -730,7 +132,7 @@ enum CompareValues { } impl CompareValues { - fn compare(&self) -> std::cmp::Ordering { + pub fn compare(&self) -> std::cmp::Ordering { match self { CompareValues::Ints(left, right) => left.cmp(right), CompareValues::Decimals(left, right) => left.cmp(right), @@ -747,7 +149,7 @@ impl CompareValues { } } -fn coerce_compare( +pub(crate) fn coerce_compare( left: &Value, right: &Value, ) -> Result { @@ -791,30 +193,28 @@ fn coerce_compare_primitive( } #[cfg(test)] mod tests { - - use super::UntaggedValue; - use crate::parser::hir::path::PathMember; - use crate::ColumnPath as ColumnPathValue; - use crate::ShellError; - use crate::Value; + use super::value; + use crate::data::base::property_get::{as_column_path, ValueExt}; use indexmap::IndexMap; + use nu_errors::ShellError; + use nu_protocol::{ColumnPath as ColumnPathValue, PathMember, Value}; use nu_source::*; use num_bigint::BigInt; fn string(input: impl Into) -> Value { - UntaggedValue::string(input.into()).into_untagged_value() + value::string(input.into()).into_untagged_value() } fn int(input: impl Into) -> Value { - UntaggedValue::int(input.into()).into_untagged_value() + value::int(input.into()).into_untagged_value() } fn row(entries: IndexMap) -> Value { - UntaggedValue::row(entries).into_untagged_value() + value::row(entries).into_untagged_value() } fn table(list: &Vec) -> Value { - UntaggedValue::table(list).into_untagged_value() + value::table(list).into_untagged_value() } fn error_callback( @@ -824,14 +224,12 @@ mod tests { } fn column_path(paths: &Vec) -> Tagged { - table(&paths.iter().cloned().collect()) - .as_column_path() - .unwrap() + as_column_path(&table(&paths.iter().cloned().collect())).unwrap() } #[test] fn gets_matching_field_from_a_row() { - let row = UntaggedValue::row(indexmap! { + let row = value::row(indexmap! { "amigos".into() => table(&vec![string("andres"),string("jonathan"),string("yehuda")]) }) .into_untagged_value(); @@ -852,7 +250,7 @@ mod tests { let (version, tag) = string("0.4.0").into_parts(); - let value = UntaggedValue::row(indexmap! { + let value = value::row(indexmap! { "package".into() => row(indexmap! { "name".into() => string("nu"), @@ -875,7 +273,7 @@ mod tests { let (_, tag) = string("Andrés N. Robalino").into_parts(); - let value = UntaggedValue::row(indexmap! { + let value = value::row(indexmap! { "package".into() => row(indexmap! { "name".into() => string("nu"), "version".into() => string("0.4.0"), @@ -909,7 +307,7 @@ mod tests { let (_, tag) = string("Andrés N. Robalino").into_parts(); - let value = UntaggedValue::row(indexmap! { + let value = value::row(indexmap! { "package".into() => row(indexmap! { "name".into() => string("nu"), "version".into() => string("0.4.0"), @@ -926,7 +324,7 @@ mod tests { .into_value(tag) .get_data_by_column_path(&field_path, Box::new(error_callback("package.authors.0"))) .unwrap(), - UntaggedValue::row(indexmap! { + value::row(indexmap! { "name".into() => string("Andrés N. Robalino") }) ); @@ -938,7 +336,7 @@ mod tests { let (_, tag) = string("Andrés N. Robalino").into_parts(); - let value = UntaggedValue::row(indexmap! { + let value = value::row(indexmap! { "package".into() => row(indexmap! { "name".into() => string("nu"), "version".into() => string("0.4.0"), @@ -958,7 +356,7 @@ mod tests { Box::new(error_callback("package.authors.\"0\"")) ) .unwrap(), - UntaggedValue::row(indexmap! { + value::row(indexmap! { "name".into() => string("Andrés N. Robalino") }) ); @@ -968,7 +366,7 @@ mod tests { fn replaces_matching_field_from_a_row() { let field_path = column_path(&vec![string("amigos")]); - let sample = UntaggedValue::row(indexmap! { + let sample = value::row(indexmap! { "amigos".into() => table(&vec![ string("andres"), string("jonathan"), @@ -994,7 +392,7 @@ mod tests { string("los.3.caballeros"), ]); - let sample = UntaggedValue::row(indexmap! { + let sample = value::row(indexmap! { "package".into() => row(indexmap! { "authors".into() => row(indexmap! { "los.3.mosqueteros".into() => table(&vec![string("andres::yehuda::jonathan")]), @@ -1014,7 +412,7 @@ mod tests { assert_eq!( actual, - UntaggedValue::row(indexmap! { + value::row(indexmap! { "package".into() => row(indexmap! { "authors".into() => row(indexmap! { "los.3.mosqueteros".into() => table(&vec![string("andres::yehuda::jonathan")]), @@ -1031,7 +429,7 @@ mod tests { string("nu.version.arepa"), ]); - let sample = UntaggedValue::row(indexmap! { + let sample = value::row(indexmap! { "shell_policy".into() => row(indexmap! { "releases".into() => table(&vec![ row(indexmap! { @@ -1066,7 +464,7 @@ mod tests { assert_eq!( actual, - UntaggedValue::row(indexmap! { + value::row(indexmap! { "shell_policy".into() => row(indexmap! { "releases".into() => table(&vec![ row(indexmap! { diff --git a/src/data/base/property_get.rs b/src/data/base/property_get.rs index 81589a11b3..9189f62b38 100644 --- a/src/data/base/property_get.rs +++ b/src/data/base/property_get.rs @@ -1,311 +1,408 @@ -use crate::errors::ExpectedRange; -use crate::parser::hir::path::{PathMember, UnspannedPathMember}; +use crate::data::value; use crate::prelude::*; -use crate::ColumnPath; -use crate::SpannedTypeName; +use nu_errors::{ExpectedRange, ShellError}; +use nu_protocol::{ + ColumnPath, PathMember, Primitive, ShellTypeName, SpannedTypeName, UnspannedPathMember, + UntaggedValue, Value, +}; use nu_source::{Spanned, SpannedItem, Tagged}; -impl Value { - pub(crate) fn get_data_by_member(&self, name: &PathMember) -> Result { - match &self.value { - // If the value is a row, the member is a column name - UntaggedValue::Row(o) => match &name.unspanned { - // If the member is a string, get the data - UnspannedPathMember::String(string) => o - .get_data_by_key(string[..].spanned(name.span)) - .ok_or_else(|| { - ShellError::missing_property( - "row".spanned(self.tag.span), - string.spanned(name.span), - ) - }), +pub trait ValueExt { + fn into_parts(self) -> (UntaggedValue, Tag); + fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value>; + fn get_data_by_key(&self, name: Spanned<&str>) -> Option; + fn get_data_by_member(&self, name: &PathMember) -> Result; + fn get_data_by_column_path( + &self, + path: &ColumnPath, + callback: Box ShellError>, + ) -> Result; + fn insert_data_at_path(&self, path: &str, new_value: Value) -> Option; + fn insert_data_at_member( + &mut self, + member: &PathMember, + new_value: Value, + ) -> Result<(), ShellError>; + fn insert_data_at_column_path( + &self, + split_path: &ColumnPath, + new_value: Value, + ) -> Result; + fn replace_data_at_column_path( + &self, + split_path: &ColumnPath, + replaced_value: Value, + ) -> Option; + fn as_column_path(&self) -> Result, ShellError>; + fn as_path_member(&self) -> Result; + fn as_string(&self) -> Result; +} - // If the member is a number, it's an error - UnspannedPathMember::Int(_) => Err(ShellError::invalid_integer_index( - "row".spanned(self.tag.span), - name.span, - )), - }, - - // If the value is a table - UntaggedValue::Table(l) => { - match &name.unspanned { - // If the member is a string, map over the member - UnspannedPathMember::String(string) => { - let mut out = vec![]; - - for item in l { - match item { - Value { - value: UntaggedValue::Row(o), - .. - } => match o.get_data_by_key(string[..].spanned(name.span)) { - Some(v) => out.push(v), - None => {} - }, - _ => {} - } - } - - if out.len() == 0 { - Err(ShellError::missing_property( - "table".spanned(self.tag.span), - string.spanned(name.span), - )) - } else { - Ok(UntaggedValue::Table(out) - .into_value(Tag::new(self.anchor(), name.span))) - } - } - UnspannedPathMember::Int(int) => { - let index = int.to_usize().ok_or_else(|| { - ShellError::range_error( - ExpectedRange::Usize, - &"massive integer".spanned(name.span), - "indexing", - ) - })?; - - match self.get_data_by_index(index.spanned(self.tag.span)) { - Some(v) => Ok(v.clone()), - None => Err(ShellError::range_error( - 0..(l.len()), - &int.spanned(name.span), - "indexing", - )), - } - } - } - } - other => Err(ShellError::type_error( - "row or table", - other.type_name().spanned(self.tag.span), - )), - } +impl ValueExt for Value { + fn into_parts(self) -> (UntaggedValue, Tag) { + (self.value, self.tag) } - pub fn get_data_by_column_path( + fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value> { + get_data(self, desc) + } + + fn get_data_by_key(&self, name: Spanned<&str>) -> Option { + get_data_by_key(self, name) + } + + fn get_data_by_member(&self, name: &PathMember) -> Result { + get_data_by_member(self, name) + } + + fn get_data_by_column_path( &self, path: &ColumnPath, callback: Box ShellError>, ) -> Result { - let mut current = self.clone(); - - for p in path.iter() { - let value = current.get_data_by_member(p); - - match value { - Ok(v) => current = v.clone(), - Err(e) => return Err(callback((¤t.clone(), &p.clone(), e))), - } - } - - Ok(current) + get_data_by_column_path(self, path, callback) } - pub fn insert_data_at_path(&self, path: &str, new_value: Value) -> Option { - let mut new_obj = self.clone(); - - let split_path: Vec<_> = path.split(".").collect(); - - if let UntaggedValue::Row(ref mut o) = new_obj.value { - let mut current = o; - - if split_path.len() == 1 { - // Special case for inserting at the top level - current.entries.insert( - path.to_string(), - new_value.value.clone().into_value(&self.tag), - ); - return Some(new_obj); - } - - for idx in 0..split_path.len() { - match current.entries.get_mut(split_path[idx]) { - Some(next) => { - if idx == (split_path.len() - 2) { - match &mut next.value { - UntaggedValue::Row(o) => { - o.entries.insert( - split_path[idx + 1].to_string(), - new_value.value.clone().into_value(&self.tag), - ); - } - _ => {} - } - - return Some(new_obj.clone()); - } else { - match next.value { - UntaggedValue::Row(ref mut o) => { - current = o; - } - _ => return None, - } - } - } - _ => return None, - } - } - } - - None + fn insert_data_at_path(&self, path: &str, new_value: Value) -> Option { + insert_data_at_path(self, path, new_value) } - pub fn insert_data_at_member( + fn insert_data_at_member( &mut self, member: &PathMember, new_value: Value, ) -> Result<(), ShellError> { - match &mut self.value { - UntaggedValue::Row(dict) => match &member.unspanned { - UnspannedPathMember::String(key) => Ok({ - dict.insert_data_at_key(key, new_value); - }), - UnspannedPathMember::Int(_) => Err(ShellError::type_error( - "column name", - "integer".spanned(member.span), - )), - }, - UntaggedValue::Table(array) => match &member.unspanned { - UnspannedPathMember::String(_) => Err(ShellError::type_error( - "list index", - "string".spanned(member.span), - )), - UnspannedPathMember::Int(int) => Ok({ - let int = int.to_usize().ok_or_else(|| { - ShellError::range_error( - ExpectedRange::Usize, - &"bigger number".spanned(member.span), - "inserting into a list", - ) - })?; - - insert_data_at_index(array, int.tagged(member.span), new_value.clone())?; - }), - }, - other => match &member.unspanned { - UnspannedPathMember::String(_) => Err(ShellError::type_error( - "row", - other.type_name().spanned(self.span()), - )), - UnspannedPathMember::Int(_) => Err(ShellError::type_error( - "table", - other.type_name().spanned(self.span()), - )), - }, - } + insert_data_at_member(self, member, new_value) } - pub fn insert_data_at_column_path( + fn insert_data_at_column_path( &self, split_path: &ColumnPath, new_value: Value, ) -> Result { - let (last, front) = split_path.split_last(); - let mut original = self.clone(); - - let mut current: &mut Value = &mut original; - - for member in front { - let type_name = current.spanned_type_name(); - - current = current.get_mut_data_by_member(&member).ok_or_else(|| { - ShellError::missing_property( - member.plain_string(std::usize::MAX).spanned(member.span), - type_name, - ) - })? - } - - current.insert_data_at_member(&last, new_value)?; - - Ok(original) + insert_data_at_column_path(self, split_path, new_value) } - pub fn replace_data_at_column_path( + fn replace_data_at_column_path( &self, split_path: &ColumnPath, replaced_value: Value, ) -> Option { - let mut new_obj: Value = self.clone(); - let mut current = &mut new_obj; - let split_path = split_path.members(); + replace_data_at_column_path(self, split_path, replaced_value) + } - for idx in 0..split_path.len() { - match current.get_mut_data_by_member(&split_path[idx]) { - Some(next) => { - if idx == (split_path.len() - 1) { - *next = replaced_value.value.into_value(&self.tag); - return Some(new_obj); + fn as_column_path(&self) -> Result, ShellError> { + as_column_path(self) + } + + fn as_path_member(&self) -> Result { + as_path_member(self) + } + + fn as_string(&self) -> Result { + as_string(self) + } +} + +pub(crate) fn get_data_by_member(value: &Value, name: &PathMember) -> Result { + match &value.value { + // If the value is a row, the member is a column name + UntaggedValue::Row(o) => match &name.unspanned { + // If the member is a string, get the data + UnspannedPathMember::String(string) => o + .get_data_by_key(string[..].spanned(name.span)) + .ok_or_else(|| { + ShellError::missing_property( + "row".spanned(value.tag.span), + string.spanned(name.span), + ) + }), + + // If the member is a number, it's an error + UnspannedPathMember::Int(_) => Err(ShellError::invalid_integer_index( + "row".spanned(value.tag.span), + name.span, + )), + }, + + // If the value is a table + UntaggedValue::Table(l) => { + match &name.unspanned { + // If the member is a string, map over the member + UnspannedPathMember::String(string) => { + let mut out = vec![]; + + for item in l { + match item { + Value { + value: UntaggedValue::Row(o), + .. + } => match o.get_data_by_key(string[..].spanned(name.span)) { + Some(v) => out.push(v), + None => {} + }, + _ => {} + } + } + + if out.len() == 0 { + Err(ShellError::missing_property( + "table".spanned(value.tag.span), + string.spanned(name.span), + )) } else { - current = next; + Ok(UntaggedValue::Table(out) + .into_value(Tag::new(value.anchor(), name.span))) } } - None => { - return None; + UnspannedPathMember::Int(int) => { + let index = int.to_usize().ok_or_else(|| { + ShellError::range_error( + ExpectedRange::Usize, + &"massive integer".spanned(name.span), + "indexing", + ) + })?; + + match get_data_by_index(value, index.spanned(value.tag.span)) { + Some(v) => Ok(v.clone()), + None => Err(ShellError::range_error( + 0..(l.len()), + &int.spanned(name.span), + "indexing", + )), + } } } } + other => Err(ShellError::type_error( + "row or table", + other.type_name().spanned(value.tag.span), + )), + } +} - None +pub fn get_data_by_column_path( + value: &Value, + path: &ColumnPath, + callback: Box ShellError>, +) -> Result { + let mut current = value.clone(); + + for p in path.iter() { + let value = get_data_by_member(¤t, p); + + match value { + Ok(v) => current = v.clone(), + Err(e) => return Err(callback((¤t.clone(), &p.clone(), e))), + } } - pub fn as_column_path(&self) -> Result, ShellError> { - match &self.value { - UntaggedValue::Table(table) => { - let mut out: Vec = vec![]; + Ok(current) +} - for item in table { - out.push(item.as_path_member()?); +pub fn insert_data_at_path(value: &Value, path: &str, new_value: Value) -> Option { + let mut new_obj = value.clone(); + + let split_path: Vec<_> = path.split(".").collect(); + + if let UntaggedValue::Row(ref mut o) = new_obj.value { + let mut current = o; + + if split_path.len() == 1 { + // Special case for inserting at the top level + current.entries.insert( + path.to_string(), + new_value.value.clone().into_value(&value.tag), + ); + return Some(new_obj); + } + + for idx in 0..split_path.len() { + match current.entries.get_mut(split_path[idx]) { + Some(next) => { + if idx == (split_path.len() - 2) { + match &mut next.value { + UntaggedValue::Row(o) => { + o.entries.insert( + split_path[idx + 1].to_string(), + new_value.value.clone().into_value(&value.tag), + ); + } + _ => {} + } + + return Some(new_obj.clone()); + } else { + match next.value { + UntaggedValue::Row(ref mut o) => { + current = o; + } + _ => return None, + } + } } - - Ok(ColumnPath::new(out).tagged(&self.tag)) + _ => return None, } + } + } - UntaggedValue::Primitive(Primitive::ColumnPath(path)) => { - Ok(path.clone().tagged(self.tag.clone())) - } + None +} - other => Err(ShellError::type_error( - "column path", - other.type_name().spanned(self.span()), +pub fn insert_data_at_member( + value: &mut Value, + member: &PathMember, + new_value: Value, +) -> Result<(), ShellError> { + match &mut value.value { + UntaggedValue::Row(dict) => match &member.unspanned { + UnspannedPathMember::String(key) => Ok({ + dict.insert_data_at_key(key, new_value); + }), + UnspannedPathMember::Int(_) => Err(ShellError::type_error( + "column name", + "integer".spanned(member.span), )), + }, + UntaggedValue::Table(array) => match &member.unspanned { + UnspannedPathMember::String(_) => Err(ShellError::type_error( + "list index", + "string".spanned(member.span), + )), + UnspannedPathMember::Int(int) => Ok({ + let int = int.to_usize().ok_or_else(|| { + ShellError::range_error( + ExpectedRange::Usize, + &"bigger number".spanned(member.span), + "inserting into a list", + ) + })?; + + insert_data_at_index(array, int.tagged(member.span), new_value.clone())?; + }), + }, + other => match &member.unspanned { + UnspannedPathMember::String(_) => Err(ShellError::type_error( + "row", + other.type_name().spanned(value.span()), + )), + UnspannedPathMember::Int(_) => Err(ShellError::type_error( + "table", + other.type_name().spanned(value.span()), + )), + }, + } +} + +pub fn insert_data_at_column_path( + value: &Value, + split_path: &ColumnPath, + new_value: Value, +) -> Result { + let (last, front) = split_path.split_last(); + let mut original = value.clone(); + + let mut current: &mut Value = &mut original; + + for member in front { + let type_name = current.spanned_type_name(); + + current = get_mut_data_by_member(current, &member).ok_or_else(|| { + ShellError::missing_property( + member.plain_string(std::usize::MAX).spanned(member.span), + type_name, + ) + })? + } + + insert_data_at_member(current, &last, new_value)?; + + Ok(original) +} + +pub fn replace_data_at_column_path( + value: &Value, + split_path: &ColumnPath, + replaced_value: Value, +) -> Option { + let mut new_obj: Value = value.clone(); + let mut current = &mut new_obj; + let split_path = split_path.members(); + + for idx in 0..split_path.len() { + match get_mut_data_by_member(current, &split_path[idx]) { + Some(next) => { + if idx == (split_path.len() - 1) { + *next = replaced_value.value.into_value(&value.tag); + return Some(new_obj); + } else { + current = next; + } + } + None => { + return None; + } } } - pub fn as_path_member(&self) -> Result { - match &self.value { - UntaggedValue::Primitive(primitive) => match primitive { - Primitive::Int(int) => Ok(PathMember::int(int.clone(), self.tag.span)), - Primitive::String(string) => Ok(PathMember::string(string, self.tag.span)), - other => Err(ShellError::type_error( - "path member", - other.type_name().spanned(self.span()), - )), - }, + None +} + +pub fn as_column_path(value: &Value) -> Result, ShellError> { + match &value.value { + UntaggedValue::Table(table) => { + let mut out: Vec = vec![]; + + for item in table { + out.push(as_path_member(item)?); + } + + Ok(ColumnPath::new(out).tagged(&value.tag)) + } + + UntaggedValue::Primitive(Primitive::ColumnPath(path)) => { + Ok(path.clone().tagged(value.tag.clone())) + } + + other => Err(ShellError::type_error( + "column path", + other.type_name().spanned(value.span()), + )), + } +} + +pub fn as_path_member(value: &Value) -> Result { + match &value.value { + UntaggedValue::Primitive(primitive) => match primitive { + Primitive::Int(int) => Ok(PathMember::int(int.clone(), value.tag.span)), + Primitive::String(string) => Ok(PathMember::string(string, value.tag.span)), other => Err(ShellError::type_error( "path member", - other.type_name().spanned(self.span()), + other.type_name().spanned(value.span()), )), - } + }, + other => Err(ShellError::type_error( + "path member", + other.type_name().spanned(value.span()), + )), } +} - pub fn as_string(&self) -> Result { - match &self.value { - UntaggedValue::Primitive(Primitive::String(s)) => Ok(s.clone()), - UntaggedValue::Primitive(Primitive::Boolean(x)) => Ok(format!("{}", x)), - UntaggedValue::Primitive(Primitive::Decimal(x)) => Ok(format!("{}", x)), - UntaggedValue::Primitive(Primitive::Int(x)) => Ok(format!("{}", x)), - UntaggedValue::Primitive(Primitive::Bytes(x)) => Ok(format!("{}", x)), - UntaggedValue::Primitive(Primitive::Path(x)) => Ok(format!("{}", x.display())), - // TODO: this should definitely be more general with better errors - other => Err(ShellError::labeled_error( - "Expected string", - other.type_name(), - &self.tag, - )), - } +pub fn as_string(value: &Value) -> Result { + match &value.value { + UntaggedValue::Primitive(Primitive::String(s)) => Ok(s.clone()), + UntaggedValue::Primitive(Primitive::Boolean(x)) => Ok(format!("{}", x)), + UntaggedValue::Primitive(Primitive::Decimal(x)) => Ok(format!("{}", x)), + UntaggedValue::Primitive(Primitive::Int(x)) => Ok(format!("{}", x)), + UntaggedValue::Primitive(Primitive::Bytes(x)) => Ok(format!("{}", x)), + UntaggedValue::Primitive(Primitive::Path(x)) => Ok(format!("{}", x.display())), + // TODO: this should definitely be more general with better errors + other => Err(ShellError::labeled_error( + "Expected string", + other.type_name(), + &value.tag, + )), } } @@ -326,88 +423,89 @@ fn insert_data_at_index( } } -impl Value { - pub fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value> { - match &self.value { - UntaggedValue::Primitive(_) => MaybeOwned::Borrowed(self), - UntaggedValue::Row(o) => o.get_data(desc), - UntaggedValue::Block(_) | UntaggedValue::Table(_) | UntaggedValue::Error(_) => { - MaybeOwned::Owned(UntaggedValue::nothing().into_untagged_value()) - } +pub fn get_data<'value>(value: &'value Value, desc: &String) -> MaybeOwned<'value, Value> { + match &value.value { + UntaggedValue::Primitive(_) => MaybeOwned::Borrowed(value), + UntaggedValue::Row(o) => o.get_data(desc), + UntaggedValue::Block(_) | UntaggedValue::Table(_) | UntaggedValue::Error(_) => { + MaybeOwned::Owned(value::nothing().into_untagged_value()) } } +} - pub(crate) fn get_data_by_index(&self, idx: Spanned) -> Option { - match &self.value { - UntaggedValue::Table(value_set) => { - let value = value_set.get(idx.item)?; - Some( - value - .value - .clone() - .into_value(Tag::new(value.anchor(), idx.span)), - ) - } - _ => None, +pub(crate) fn get_data_by_index(value: &Value, idx: Spanned) -> Option { + match &value.value { + UntaggedValue::Table(value_set) => { + let value = value_set.get(idx.item)?; + Some( + value + .value + .clone() + .into_value(Tag::new(value.anchor(), idx.span)), + ) } + _ => None, } +} - pub(crate) fn get_data_by_key(&self, name: Spanned<&str>) -> Option { - match &self.value { - UntaggedValue::Row(o) => o.get_data_by_key(name), - UntaggedValue::Table(l) => { - let mut out = vec![]; +pub(crate) fn get_data_by_key(value: &Value, name: Spanned<&str>) -> Option { + match &value.value { + UntaggedValue::Row(o) => o.get_data_by_key(name), + UntaggedValue::Table(l) => { + let mut out = vec![]; + for item in l { + match item { + Value { + value: UntaggedValue::Row(o), + .. + } => match o.get_data_by_key(name) { + Some(v) => out.push(v), + None => out.push(value::nothing().into_untagged_value()), + }, + _ => out.push(value::nothing().into_untagged_value()), + } + } + + if out.len() > 0 { + Some(UntaggedValue::Table(out).into_value(name.span)) + } else { + None + } + } + _ => None, + } +} + +pub(crate) fn get_mut_data_by_member<'value>( + value: &'value mut Value, + name: &PathMember, +) -> Option<&'value mut Value> { + match &mut value.value { + UntaggedValue::Row(o) => match &name.unspanned { + UnspannedPathMember::String(string) => o.get_mut_data_by_key(&string), + UnspannedPathMember::Int(_) => None, + }, + UntaggedValue::Table(l) => match &name.unspanned { + UnspannedPathMember::String(string) => { for item in l { match item { Value { value: UntaggedValue::Row(o), .. - } => match o.get_data_by_key(name) { - Some(v) => out.push(v), - None => out.push(UntaggedValue::nothing().into_untagged_value()), + } => match o.get_mut_data_by_key(&string) { + Some(v) => return Some(v), + None => {} }, - _ => out.push(UntaggedValue::nothing().into_untagged_value()), + _ => {} } } - - if out.len() > 0 { - Some(UntaggedValue::Table(out).into_value(name.span)) - } else { - None - } + None } - _ => None, - } - } - - pub(crate) fn get_mut_data_by_member(&mut self, name: &PathMember) -> Option<&mut Value> { - match &mut self.value { - UntaggedValue::Row(o) => match &name.unspanned { - UnspannedPathMember::String(string) => o.get_mut_data_by_key(&string), - UnspannedPathMember::Int(_) => None, - }, - UntaggedValue::Table(l) => match &name.unspanned { - UnspannedPathMember::String(string) => { - for item in l { - match item { - Value { - value: UntaggedValue::Row(o), - .. - } => match o.get_mut_data_by_key(&string) { - Some(v) => return Some(v), - None => {} - }, - _ => {} - } - } - None - } - UnspannedPathMember::Int(int) => { - let index = int.to_usize()?; - l.get_mut(index) - } - }, - _ => None, - } + UnspannedPathMember::Int(int) => { + let index = int.to_usize()?; + l.get_mut(index) + } + }, + _ => None, } } diff --git a/src/data/base/shape.rs b/src/data/base/shape.rs index 74c53407ed..8a95513022 100644 --- a/src/data/base/shape.rs +++ b/src/data/base/shape.rs @@ -1,12 +1,13 @@ -use crate::data::base::{Block, ColumnPath}; -use crate::data::dict::Dictionary; use crate::prelude::*; use chrono::{DateTime, Utc}; use chrono_humanize::Humanize; use derive_new::new; use indexmap::IndexMap; -use nu_source::DebugDoc; -use nu_source::{b, PrettyDebug}; +use nu_protocol::{ + ColumnPath, Dictionary, Evaluate, Primitive, ShellTypeName, UntaggedValue, Value, +}; +use nu_errors::ShellError; +use nu_source::{b, DebugDoc, PrettyDebug}; use std::collections::BTreeMap; use std::fmt::Debug; use std::hash::Hash; @@ -475,13 +476,7 @@ pub enum Shape { Row(Vec), Table { from: usize, to: usize }, Error(ShellError), - Block(Block), -} - -impl Value { - pub fn shape(&self) -> Shape { - Shape::for_value(self) - } + Block(Evaluate), } impl Shape { @@ -502,32 +497,6 @@ impl Shape { Shape::Row(dict.keys().map(|key| Column::String(key.clone())).collect()) } - pub fn kind(&self) -> String { - match self { - Shape::Primitive(primitive) => primitive, - Shape::Row(row) => { - return row - .iter() - .map(|c| match c { - Column::String(s) => s.clone(), - Column::Value => format!(""), - }) - .join(", ") - } - Shape::Table { .. } => "table", - Shape::Error(_) => "error", - Shape::Block(_) => "block", - } - .to_string() - } - - pub fn describe_str(&self) -> String { - let mut v = vec![]; - self.describe(&mut v) - .expect("it isn't possible to fail to write into a memory buffer"); - String::from_utf8_lossy(&v[..]).to_string() - } - pub fn describe(&self, w: &mut impl Write) -> Result<(), std::io::Error> { match self { Shape::Primitive(desc) => write!(w, "[{}]", desc), @@ -559,7 +528,7 @@ impl Shape { .expect("Writing into a Vec can't fail"); let string = String::from_utf8_lossy(&out); - UntaggedValue::string(string).into_untagged_value() + value::string(string).into_untagged_value() } } @@ -589,7 +558,7 @@ impl Shapes { vec![dict! { "type" => shape.to_value(), - "rows" => UntaggedValue::string("all") + "rows" => value::string("all") }] } else { self.shapes @@ -599,7 +568,7 @@ impl Shapes { dict! { "type" => shape.to_value(), - "rows" => UntaggedValue::string(format!("[ {} ]", rows)) + "rows" => value::string(format!("[ {} ]", rows)) } }) .collect() diff --git a/src/data/command.rs b/src/data/command.rs index d47bc26e4c..3eb504a422 100644 --- a/src/data/command.rs +++ b/src/data/command.rs @@ -1,7 +1,7 @@ use crate::commands::command::Command; -use crate::data::{TaggedDictBuilder, TaggedListBuilder, Value}; -use crate::parser::registry::{NamedType, PositionalType, Signature}; +use crate::data::{TaggedDictBuilder, TaggedListBuilder}; use crate::prelude::*; +use nu_protocol::{NamedType, PositionalType, Signature, Value}; use std::ops::Deref; pub(crate) fn command_dict(command: Arc, tag: impl Into) -> Value { @@ -9,18 +9,18 @@ pub(crate) fn command_dict(command: Arc, tag: impl Into) -> Value let mut cmd_dict = TaggedDictBuilder::new(&tag); - cmd_dict.insert_untagged("name", UntaggedValue::string(command.name())); + cmd_dict.insert_untagged("name", value::string(command.name())); cmd_dict.insert_untagged( "type", - UntaggedValue::string(match command.deref() { + value::string(match command.deref() { Command::WholeStream(_) => "Command", Command::PerItem(_) => "Filter", }), ); cmd_dict.insert_value("signature", signature_dict(command.signature(), tag)); - cmd_dict.insert_untagged("usage", UntaggedValue::string(command.usage())); + cmd_dict.insert_untagged("usage", value::string(command.usage())); cmd_dict.into_value() } @@ -30,11 +30,11 @@ fn for_spec(name: &str, ty: &str, required: bool, tag: impl Into) -> Value let mut spec = TaggedDictBuilder::new(tag); - spec.insert_untagged("name", UntaggedValue::string(name)); - spec.insert_untagged("type", UntaggedValue::string(ty)); + spec.insert_untagged("name", value::string(name)); + spec.insert_untagged("type", value::string(ty)); spec.insert_untagged( "required", - UntaggedValue::string(if required { "yes" } else { "no" }), + value::string(if required { "yes" } else { "no" }), ); spec.into_value() diff --git a/src/data/config.rs b/src/data/config.rs index 8f74e7ff21..7caa2b8826 100644 --- a/src/data/config.rs +++ b/src/data/config.rs @@ -1,11 +1,11 @@ use crate::commands::from_toml::convert_toml_value_to_nu_value; use crate::commands::to_toml::value_to_toml_value; -use crate::data::{Dictionary, Value}; -use crate::errors::ShellError; use crate::prelude::*; use app_dirs::*; use indexmap::IndexMap; use log::trace; +use nu_protocol::{Dictionary, ShellTypeName, UntaggedValue, Value}; +use nu_errors::ShellError; use serde::{Deserialize, Serialize}; use std::fs::{self, OpenOptions}; use std::io; diff --git a/src/data/dict.rs b/src/data/dict.rs index 5f48a9a4b7..bbdcf5bd19 100644 --- a/src/data/dict.rs +++ b/src/data/dict.rs @@ -1,19 +1,8 @@ -use crate::data::base::{Primitive, UntaggedValue, Value}; use crate::prelude::*; use derive_new::new; -use getset::Getters; use indexmap::IndexMap; -use nu_source::Spanned; -use nu_source::{b, PrettyDebug}; -use pretty::{BoxAllocator, DocAllocator}; -use serde::{Deserialize, Serialize}; -use std::cmp::{Ordering, PartialOrd}; - -#[derive(Debug, Default, Eq, PartialEq, Serialize, Deserialize, Clone, Getters, new)] -pub struct Dictionary { - #[get = "pub"] - pub entries: IndexMap, -} +use nu_protocol::{Dictionary, Primitive, UntaggedValue, Value}; +use nu_source::{b, PrettyDebug, Spanned}; #[derive(Debug, new)] struct DebugEntry<'a> { @@ -27,87 +16,17 @@ impl<'a> PrettyDebug for DebugEntry<'a> { } } -impl PrettyDebug for Dictionary { - fn pretty(&self) -> DebugDocBuilder { - BoxAllocator - .text("(") - .append( - BoxAllocator - .intersperse( - self.entries() - .iter() - .map(|(key, value)| DebugEntry::new(key, value).to_doc()), - BoxAllocator.space(), - ) - .nest(1) - .group(), - ) - .append(BoxAllocator.text(")")) - .into() - } +pub trait DictionaryExt { + fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value>; + + fn keys(&self) -> indexmap::map::Keys; + fn get_data_by_key(&self, name: Spanned<&str>) -> Option; + fn get_mut_data_by_key(&mut self, name: &str) -> Option<&mut Value>; + fn insert_data_at_key(&mut self, name: &str, value: Value); } -impl PartialOrd for Dictionary { - fn partial_cmp(&self, other: &Dictionary) -> Option { - let this: Vec<&String> = self.entries.keys().collect(); - let that: Vec<&String> = other.entries.keys().collect(); - - if this != that { - return this.partial_cmp(&that); - } - - let this: Vec<&Value> = self.entries.values().collect(); - let that: Vec<&Value> = self.entries.values().collect(); - - this.partial_cmp(&that) - } -} - -impl From> for Dictionary { - fn from(input: IndexMap) -> Dictionary { - let mut out = IndexMap::default(); - - for (key, value) in input { - out.insert(key, value); - } - - Dictionary::new(out) - } -} - -impl Ord for Dictionary { - fn cmp(&self, other: &Dictionary) -> Ordering { - let this: Vec<&String> = self.entries.keys().collect(); - let that: Vec<&String> = other.entries.keys().collect(); - - if this != that { - return this.cmp(&that); - } - - let this: Vec<&Value> = self.entries.values().collect(); - let that: Vec<&Value> = self.entries.values().collect(); - - this.cmp(&that) - } -} - -impl PartialOrd for Dictionary { - fn partial_cmp(&self, _other: &Value) -> Option { - Some(Ordering::Less) - } -} - -impl PartialEq for Dictionary { - fn eq(&self, other: &Value) -> bool { - match &other.value { - UntaggedValue::Row(d) => self == d, - _ => false, - } - } -} - -impl Dictionary { - pub fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value> { +impl DictionaryExt for Dictionary { + fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value> { match self.entries.get(desc) { Some(v) => MaybeOwned::Borrowed(v), None => MaybeOwned::Owned( @@ -116,11 +35,11 @@ impl Dictionary { } } - pub fn keys(&self) -> impl Iterator { + fn keys(&self) -> indexmap::map::Keys { self.entries.keys() } - pub(crate) fn get_data_by_key(&self, name: Spanned<&str>) -> Option { + fn get_data_by_key(&self, name: Spanned<&str>) -> Option { let result = self .entries .iter() @@ -135,7 +54,7 @@ impl Dictionary { ) } - pub(crate) fn get_mut_data_by_key(&mut self, name: &str) -> Option<&mut Value> { + fn get_mut_data_by_key(&mut self, name: &str) -> Option<&mut Value> { match self .entries .iter_mut() @@ -146,7 +65,7 @@ impl Dictionary { } } - pub(crate) fn insert_data_at_key(&mut self, name: &str, value: Value) { + fn insert_data_at_key(&mut self, name: &str, value: Value) { self.entries.insert(name.to_string(), value); } } diff --git a/src/data/files.rs b/src/data/files.rs index 3a2a99ee31..b7cde60cc1 100644 --- a/src/data/files.rs +++ b/src/data/files.rs @@ -1,6 +1,7 @@ -use crate::data::{TaggedDictBuilder, Value}; -use crate::errors::ShellError; +use crate::data::TaggedDictBuilder; use crate::prelude::*; +use nu_protocol::{Value}; +use nu_errors::ShellError; #[derive(Debug)] pub enum FileType { @@ -16,7 +17,7 @@ pub(crate) fn dir_entry_dict( full: bool, ) -> Result { let mut dict = TaggedDictBuilder::new(tag); - dict.insert_untagged("name", UntaggedValue::string(filename.to_string_lossy())); + dict.insert_untagged("name", value::string(filename.to_string_lossy())); let kind = if metadata.is_dir() { FileType::Directory @@ -26,39 +27,36 @@ pub(crate) fn dir_entry_dict( FileType::Symlink }; - dict.insert_untagged("type", UntaggedValue::string(format!("{:?}", kind))); + dict.insert_untagged("type", value::string(format!("{:?}", kind))); if full { dict.insert_untagged( "readonly", - UntaggedValue::boolean(metadata.permissions().readonly()), + value::boolean(metadata.permissions().readonly()), ); #[cfg(unix)] { use std::os::unix::fs::PermissionsExt; let mode = metadata.permissions().mode(); - dict.insert_untagged( - "mode", - UntaggedValue::string(umask::Mode::from(mode).to_string()), - ); + dict.insert_untagged("mode", value::string(umask::Mode::from(mode).to_string())); } } - dict.insert_untagged("size", UntaggedValue::bytes(metadata.len() as u64)); + dict.insert_untagged("size", value::bytes(metadata.len() as u64)); match metadata.created() { - Ok(c) => dict.insert_untagged("created", UntaggedValue::system_date(c)), + Ok(c) => dict.insert_untagged("created", value::system_date(c)), Err(_) => {} } match metadata.accessed() { - Ok(a) => dict.insert_untagged("accessed", UntaggedValue::system_date(a)), + Ok(a) => dict.insert_untagged("accessed", value::system_date(a)), Err(_) => {} } match metadata.modified() { - Ok(m) => dict.insert_untagged("modified", UntaggedValue::system_date(m)), + Ok(m) => dict.insert_untagged("modified", value::system_date(m)), Err(_) => {} } diff --git a/src/data/into.rs b/src/data/into.rs deleted file mode 100644 index 1fe6c52cfd..0000000000 --- a/src/data/into.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::data::base::{Primitive, UntaggedValue}; - -impl From for UntaggedValue { - fn from(input: Primitive) -> UntaggedValue { - UntaggedValue::Primitive(input) - } -} - -impl From for UntaggedValue { - fn from(input: String) -> UntaggedValue { - UntaggedValue::Primitive(Primitive::String(input)) - } -} diff --git a/src/data/primitive.rs b/src/data/primitive.rs new file mode 100644 index 0000000000..2123e9e946 --- /dev/null +++ b/src/data/primitive.rs @@ -0,0 +1,91 @@ +use chrono_humanize::Humanize; +use nu_parser::Number; +use nu_protocol::Primitive; +use nu_source::PrettyDebug; + +pub fn number(number: impl Into) -> Primitive { + let number = number.into(); + + match number { + Number::Int(int) => Primitive::Int(int), + Number::Decimal(decimal) => Primitive::Decimal(decimal), + } +} + +pub fn format_primitive(primitive: &Primitive, field_name: Option<&String>) -> String { + match primitive { + Primitive::Nothing => String::new(), + Primitive::BeginningOfStream => String::new(), + Primitive::EndOfStream => String::new(), + Primitive::Path(p) => format!("{}", p.display()), + Primitive::Bytes(b) => { + let byte = byte_unit::Byte::from_bytes(*b as u128); + + if byte.get_bytes() == 0u128 { + return "—".to_string(); + } + + let byte = byte.get_appropriate_unit(false); + + match byte.get_unit() { + byte_unit::ByteUnit::B => format!("{} B ", byte.get_value()), + _ => format!("{}", byte.format(1)), + } + } + Primitive::Duration(sec) => format_duration(*sec), + Primitive::Int(i) => format!("{}", i), + Primitive::Decimal(decimal) => format!("{}", decimal), + Primitive::Pattern(s) => format!("{}", s), + Primitive::String(s) => format!("{}", s), + Primitive::ColumnPath(p) => { + let mut members = p.iter(); + let mut f = String::new(); + + f.push_str( + &members + .next() + .expect("BUG: column path with zero members") + .display(), + ); + + for member in members { + f.push_str("."); + f.push_str(&member.display()) + } + + f + } + Primitive::Boolean(b) => match (b, field_name) { + (true, None) => format!("Yes"), + (false, None) => format!("No"), + (true, Some(s)) if !s.is_empty() => format!("{}", s), + (false, Some(s)) if !s.is_empty() => format!(""), + (true, Some(_)) => format!("Yes"), + (false, Some(_)) => format!("No"), + }, + Primitive::Binary(_) => format!(""), + Primitive::Date(d) => format!("{}", d.humanize()), + } +} + +pub fn style_primitive(primitive: &Primitive) -> &'static str { + match primitive { + Primitive::Bytes(0) => "c", // centre 'missing' indicator + Primitive::Int(_) | Primitive::Bytes(_) | Primitive::Decimal(_) => "r", + _ => "", + } +} + +fn format_duration(sec: u64) -> String { + let (minutes, seconds) = (sec / 60, sec % 60); + let (hours, minutes) = (minutes / 60, minutes % 60); + let (days, hours) = (hours / 24, hours % 24); + + match (days, hours, minutes, seconds) { + (0, 0, 0, 1) => format!("1 sec"), + (0, 0, 0, s) => format!("{} secs", s), + (0, 0, m, s) => format!("{}:{:02}", m, s), + (0, h, m, s) => format!("{}:{:02}:{:02}", h, m, s), + (d, h, m, s) => format!("{}:{:02}:{:02}:{:02}", d, h, m, s), + } +} diff --git a/src/data/process.rs b/src/data/process.rs index 0e166d2f90..8772beba44 100644 --- a/src/data/process.rs +++ b/src/data/process.rs @@ -9,18 +9,18 @@ pub(crate) fn process_dict(proc: &sysinfo::Process, tag: impl Into) -> Valu let cmd = proc.cmd(); let cmd_value = if cmd.len() == 0 { - UntaggedValue::nothing() + value::nothing() } else { - UntaggedValue::string(join(cmd, "")) + value::string(join(cmd, "")) }; - dict.insert("pid", UntaggedValue::int(proc.pid() as i64)); - dict.insert("status", UntaggedValue::string(proc.status().to_string())); - dict.insert("cpu", UntaggedValue::number(proc.cpu_usage())); + dict.insert("pid", value::int(proc.pid() as i64)); + dict.insert("status", value::string(proc.status().to_string())); + dict.insert("cpu", value::number(proc.cpu_usage())); match cmd_value { UntaggedValue::Primitive(Primitive::Nothing) => { - dict.insert("name", UntaggedValue::string(proc.name())); + dict.insert("name", value::string(proc.name())); } _ => dict.insert("name", cmd_value), } diff --git a/src/data/types.rs b/src/data/types.rs index ce5684d4eb..23ddb638b0 100644 --- a/src/data/types.rs +++ b/src/data/types.rs @@ -1,5 +1,7 @@ use crate::prelude::*; use log::trace; +use nu_protocol::{Primitive, SpannedTypeName, UntaggedValue, Value}; +use nu_errors::{ShellError, CoerceInto}; use nu_source::Tagged; pub trait ExtractType: Sized { @@ -28,10 +30,7 @@ impl ExtractType for bool { value: UntaggedValue::Primitive(Primitive::Nothing), .. } => Ok(false), - other => Err(ShellError::type_error( - "Boolean", - other.type_name().spanned(other.span()), - )), + other => Err(ShellError::type_error("Boolean", other.spanned_type_name())), } } } @@ -45,10 +44,7 @@ impl ExtractType for std::path::PathBuf { value: UntaggedValue::Primitive(Primitive::Path(p)), .. } => Ok(p.clone()), - other => Err(ShellError::type_error( - "Path", - other.type_name().spanned(other.span()), - )), + other => Err(ShellError::type_error("Path", other.spanned_type_name())), } } } @@ -62,10 +58,7 @@ impl ExtractType for i64 { value: UntaggedValue::Primitive(Primitive::Int(int)), .. } => Ok(int.tagged(&value.tag).coerce_into("converting to i64")?), - other => Err(ShellError::type_error( - "Integer", - other.type_name().spanned(other.span()), - )), + other => Err(ShellError::type_error("Integer", other.spanned_type_name())), } } } @@ -79,10 +72,7 @@ impl ExtractType for u64 { value: UntaggedValue::Primitive(Primitive::Int(int)), .. } => Ok(int.tagged(&value.tag).coerce_into("converting to u64")?), - other => Err(ShellError::type_error( - "Integer", - other.type_name().spanned(other.span()), - )), + other => Err(ShellError::type_error("Integer", other.spanned_type_name())), } } } @@ -96,10 +86,7 @@ impl ExtractType for String { value: UntaggedValue::Primitive(Primitive::String(string)), .. } => Ok(string.clone()), - other => Err(ShellError::type_error( - "String", - other.type_name().spanned(other.span()), - )), + other => Err(ShellError::type_error("String", other.spanned_type_name())), } } } diff --git a/src/data/value.rs b/src/data/value.rs new file mode 100644 index 0000000000..17d78c4597 --- /dev/null +++ b/src/data/value.rs @@ -0,0 +1,152 @@ +use crate::data::base::coerce_compare; +use crate::data::base::shape::{Column, InlineShape, TypeShape}; +use crate::data::primitive::style_primitive; +use crate::data::value; +use bigdecimal::BigDecimal; +use chrono::DateTime; +use indexmap::IndexMap; +use nu_errors::ShellError; +use nu_parser::Number; +use nu_parser::Operator; +use nu_protocol::{ColumnPath, PathMember, Primitive, UntaggedValue, Value}; +use nu_source::{DebugDocBuilder, PrettyDebug, Tagged}; +use num_bigint::BigInt; +use std::path::PathBuf; +use std::time::SystemTime; + +#[allow(unused)] +pub fn row(entries: IndexMap) -> UntaggedValue { + UntaggedValue::Row(entries.into()) +} + +pub fn table(list: &Vec) -> UntaggedValue { + UntaggedValue::Table(list.to_vec()) +} + +pub fn string(s: impl Into) -> UntaggedValue { + UntaggedValue::Primitive(Primitive::String(s.into())) +} + +pub fn column_path(s: Vec>) -> UntaggedValue { + UntaggedValue::Primitive(Primitive::ColumnPath(ColumnPath::new( + s.into_iter().map(|p| p.into()).collect(), + ))) +} + +pub fn int(i: impl Into) -> UntaggedValue { + UntaggedValue::Primitive(Primitive::Int(i.into())) +} + +pub fn pattern(s: impl Into) -> UntaggedValue { + UntaggedValue::Primitive(Primitive::String(s.into())) +} + +pub fn path(s: impl Into) -> UntaggedValue { + UntaggedValue::Primitive(Primitive::Path(s.into())) +} + +pub fn bytes(s: impl Into) -> UntaggedValue { + UntaggedValue::Primitive(Primitive::Bytes(s.into())) +} + +pub fn decimal(s: impl Into) -> UntaggedValue { + UntaggedValue::Primitive(Primitive::Decimal(s.into())) +} + +pub fn binary(binary: Vec) -> UntaggedValue { + UntaggedValue::Primitive(Primitive::Binary(binary)) +} + +pub fn number(s: impl Into) -> UntaggedValue { + let num = s.into(); + + match num { + Number::Int(int) => value::int(int), + Number::Decimal(decimal) => value::decimal(decimal), + } +} + +pub fn boolean(s: impl Into) -> UntaggedValue { + UntaggedValue::Primitive(Primitive::Boolean(s.into())) +} + +pub fn duration(secs: u64) -> UntaggedValue { + UntaggedValue::Primitive(Primitive::Duration(secs)) +} + +pub fn system_date(s: SystemTime) -> UntaggedValue { + UntaggedValue::Primitive(Primitive::Date(s.into())) +} + +pub fn date_from_str(s: Tagged<&str>) -> Result { + let date = DateTime::parse_from_rfc3339(s.item).map_err(|err| { + ShellError::labeled_error( + &format!("Date parse error: {}", err), + "original value", + s.tag, + ) + })?; + + let date = date.with_timezone(&chrono::offset::Utc); + + Ok(UntaggedValue::Primitive(Primitive::Date(date))) +} + +pub fn nothing() -> UntaggedValue { + UntaggedValue::Primitive(Primitive::Nothing) +} + +pub fn compare_values( + operator: &Operator, + left: &Value, + right: &Value, +) -> Result { + match operator { + _ => { + let coerced = coerce_compare(left, right)?; + let ordering = coerced.compare(); + + use std::cmp::Ordering; + + let result = match (operator, ordering) { + (Operator::Equal, Ordering::Equal) => true, + (Operator::NotEqual, Ordering::Less) | (Operator::NotEqual, Ordering::Greater) => { + true + } + (Operator::LessThan, Ordering::Less) => true, + (Operator::GreaterThan, Ordering::Greater) => true, + (Operator::GreaterThanOrEqual, Ordering::Greater) + | (Operator::GreaterThanOrEqual, Ordering::Equal) => true, + (Operator::LessThanOrEqual, Ordering::Less) + | (Operator::LessThanOrEqual, Ordering::Equal) => true, + _ => false, + }; + + Ok(result) + } + } +} + +pub fn format_type<'a>(value: impl Into<&'a UntaggedValue>, width: usize) -> String { + TypeShape::from_value(value.into()).colored_string(width) +} + +pub fn format_leaf<'a>(value: impl Into<&'a UntaggedValue>) -> DebugDocBuilder { + InlineShape::from_value(value.into()).format().pretty() +} + +pub fn style_leaf<'a>(value: impl Into<&'a UntaggedValue>) -> &'static str { + match value.into() { + UntaggedValue::Primitive(p) => style_primitive(p), + _ => "", + } +} + +pub fn format_for_column<'a>( + value: impl Into<&'a UntaggedValue>, + column: impl Into, +) -> DebugDocBuilder { + InlineShape::from_value(value.into()) + .format_for_column(column) + .pretty() +} diff --git a/src/parser/deserializer.rs b/src/deserializer.rs similarity index 97% rename from src/parser/deserializer.rs rename to src/deserializer.rs index 5121e08d70..12db815e12 100644 --- a/src/parser/deserializer.rs +++ b/src/deserializer.rs @@ -1,8 +1,9 @@ -use crate::data::base::Block; -use crate::prelude::*; -use crate::ColumnPath; +use crate::data::base::property_get::ValueExt; +use crate::data::value; use log::trace; -use nu_source::Tagged; +use nu_errors::{CoerceInto, ShellError}; +use nu_protocol::{CallInfo, ColumnPath, Evaluate, Primitive, ShellTypeName, UntaggedValue, Value}; +use nu_source::{HasSpan, SpannedItem, Tagged, TaggedItem}; use serde::de; use std::path::PathBuf; @@ -55,7 +56,7 @@ impl<'de> ConfigDeserializer<'de> { self.stack.push(DeserializerItem { key_struct_field: Some((name.to_string(), name)), - val: value.unwrap_or_else(|| UntaggedValue::nothing().into_value(&self.call.name_tag)), + val: value.unwrap_or_else(|| value::nothing().into_value(&self.call.name_tag)), }); Ok(()) @@ -348,7 +349,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut ConfigDeserializer<'de> { return visit::(value.val, name, fields, visitor); } - if name == "Block" { + if name == "Evaluate" { let block = match value.val { Value { value: UntaggedValue::Block(block), @@ -361,7 +362,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut ConfigDeserializer<'de> { )) } }; - return visit::(block, name, fields, visitor); + return visit::(block, name, fields, visitor); } if name == "ColumnPath" { diff --git a/src/env/host.rs b/src/env/host.rs index bd3bd17d53..b8fd61d26b 100644 --- a/src/env/host.rs +++ b/src/env/host.rs @@ -1,5 +1,6 @@ use crate::prelude::*; use language_reporting::termcolor; +use nu_errors::ShellError; use std::fmt::Debug; pub trait Host: Debug + Send { diff --git a/src/evaluate/evaluate_args.rs b/src/evaluate/evaluate_args.rs new file mode 100644 index 0000000000..0ba59d5bd0 --- /dev/null +++ b/src/evaluate/evaluate_args.rs @@ -0,0 +1,58 @@ +// TODO: Temporary redirect +use crate::context::CommandRegistry; +use crate::data::value; +use crate::evaluate::evaluate_baseline_expr; +use indexmap::IndexMap; +use nu_errors::ShellError; +use nu_parser::hir; +use nu_protocol::{EvaluatedArgs, Scope, Value}; +use nu_source::Text; + +pub(crate) fn evaluate_args( + call: &hir::Call, + registry: &CommandRegistry, + scope: &Scope, + source: &Text, +) -> Result { + let positional: Result>, _> = call + .positional + .as_ref() + .map(|p| { + p.iter() + .map(|e| evaluate_baseline_expr(e, registry, scope, source)) + .collect() + }) + .transpose(); + + let positional = positional?; + + let named: Result>, ShellError> = call + .named + .as_ref() + .map(|n| { + let mut results = IndexMap::new(); + + for (name, value) in n.named.iter() { + match value { + hir::NamedValue::PresentSwitch(tag) => { + results.insert(name.clone(), value::boolean(true).into_value(tag)); + } + hir::NamedValue::Value(expr) => { + results.insert( + name.clone(), + evaluate_baseline_expr(expr, registry, scope, source)?, + ); + } + + _ => {} + }; + } + + Ok(results) + }) + .transpose(); + + let named = named?; + + Ok(EvaluatedArgs::new(positional, named)) +} diff --git a/src/evaluate/evaluator.rs b/src/evaluate/evaluator.rs index 3700ce50f3..19d87ea308 100644 --- a/src/evaluate/evaluator.rs +++ b/src/evaluate/evaluator.rs @@ -1,4 +1,6 @@ +use crate::context::CommandRegistry; use crate::data::base::Block; +use crate::data::value; use crate::errors::ArgumentError; use crate::evaluate::operator::apply_operator; use crate::parser::hir::path::{ColumnPath, UnspannedPathMember}; @@ -8,41 +10,14 @@ use crate::parser::{ }; use crate::prelude::*; use crate::TaggedDictBuilder; -use indexmap::IndexMap; use log::trace; +use nu_errors::{ArgumentError, ShellError}; +use nu_parser::hir::{self, Expression, RawExpression}; +use nu_protocol::{ + ColumnPath, Evaluate, Primitive, Scope, UnspannedPathMember, UntaggedValue, Value, +}; use nu_source::Text; -#[derive(Debug)] -pub struct Scope { - it: Value, - vars: IndexMap, -} - -impl Scope { - pub fn new(it: Value) -> Scope { - Scope { - it, - vars: IndexMap::new(), - } - } -} - -impl Scope { - pub(crate) fn empty() -> Scope { - Scope { - it: UntaggedValue::nothing().into_untagged_value(), - vars: IndexMap::new(), - } - } - - pub(crate) fn it_value(value: Value) -> Scope { - Scope { - it: value, - vars: IndexMap::new(), - } - } -} - pub(crate) fn evaluate_baseline_expr( expr: &Expression, registry: &CommandRegistry, @@ -59,9 +34,9 @@ pub(crate) fn evaluate_baseline_expr( "Invalid external word".spanned(tag.span), ArgumentError::InvalidExternalWord, )), - RawExpression::FilePath(path) => Ok(UntaggedValue::path(path.clone()).into_value(tag)), + RawExpression::FilePath(path) => Ok(value::path(path.clone()).into_value(tag)), RawExpression::Synthetic(hir::Synthetic::String(s)) => { - Ok(UntaggedValue::string(s).into_untagged_value()) + Ok(value::string(s).into_untagged_value()) } RawExpression::Variable(var) => evaluate_reference(var, scope, source, tag), RawExpression::Command(_) => evaluate_command(tag, scope, source), @@ -90,12 +65,12 @@ pub(crate) fn evaluate_baseline_expr( Ok(UntaggedValue::Table(exprs).into_value(tag)) } - RawExpression::Block(block) => { - Ok( - UntaggedValue::Block(Block::new(block.clone(), source.clone(), tag.clone())) - .into_value(&tag), - ) - } + RawExpression::Block(block) => Ok(UntaggedValue::Block(Evaluate::new(Block::new( + block.clone(), + source.clone(), + tag.clone(), + ))) + .into_value(&tag)), RawExpression::Path(path) => { let value = evaluate_baseline_expr(path.head(), registry, scope, source)?; let mut item = value; @@ -149,17 +124,11 @@ fn evaluate_literal(literal: &hir::Literal, source: &Text) -> Value { UntaggedValue::Primitive(Primitive::ColumnPath(ColumnPath::new(members))) .into_value(&literal.span) } - hir::RawLiteral::Number(int) => UntaggedValue::number(int.clone()).into_value(literal.span), + hir::RawLiteral::Number(int) => value::number(int.clone()).into_value(literal.span), hir::RawLiteral::Size(int, unit) => unit.compute(&int).into_value(literal.span), - hir::RawLiteral::String(tag) => { - UntaggedValue::string(tag.slice(source)).into_value(literal.span) - } - hir::RawLiteral::GlobPattern(pattern) => { - UntaggedValue::pattern(pattern).into_value(literal.span) - } - hir::RawLiteral::Bare => { - UntaggedValue::string(literal.span.slice(source)).into_value(literal.span) - } + hir::RawLiteral::String(tag) => value::string(tag.slice(source)).into_value(literal.span), + hir::RawLiteral::GlobPattern(pattern) => value::pattern(pattern).into_value(literal.span), + hir::RawLiteral::Bare => value::string(literal.span.slice(source)).into_value(literal.span), } } @@ -177,32 +146,32 @@ fn evaluate_reference( let mut dict = TaggedDictBuilder::new(&tag); for v in std::env::vars() { if v.0 != "PATH" && v.0 != "Path" { - dict.insert_untagged(v.0, UntaggedValue::string(v.1)); + dict.insert_untagged(v.0, value::string(v.1)); } } Ok(dict.into_value()) } x if x == "nu:config" => { let config = crate::data::config::read(tag.clone(), &None)?; - Ok(UntaggedValue::row(config).into_value(tag)) + Ok(value::row(config).into_value(tag)) } x if x == "nu:path" => { let mut table = vec![]; match std::env::var_os("PATH") { Some(paths) => { for path in std::env::split_paths(&paths) { - table.push(UntaggedValue::path(path).into_value(&tag)); + table.push(value::path(path).into_value(&tag)); } } _ => {} } - Ok(UntaggedValue::table(&table).into_value(tag)) + Ok(value::table(&table).into_value(tag)) } x => Ok(scope .vars .get(x) .map(|v| v.clone()) - .unwrap_or_else(|| UntaggedValue::nothing().into_value(tag))), + .unwrap_or_else(|| value::nothing().into_value(tag))), }, } } diff --git a/src/evaluate/mod.rs b/src/evaluate/mod.rs index f8133808e0..a94d84372f 100644 --- a/src/evaluate/mod.rs +++ b/src/evaluate/mod.rs @@ -1,4 +1,5 @@ +pub(crate) mod evaluate_args; pub(crate) mod evaluator; pub(crate) mod operator; -pub(crate) use evaluator::{evaluate_baseline_expr, Scope}; +pub(crate) use evaluator::evaluate_baseline_expr; diff --git a/src/format.rs b/src/format.rs index 6cdd5b256e..bc464a0de6 100644 --- a/src/format.rs +++ b/src/format.rs @@ -4,9 +4,9 @@ pub(crate) mod list; pub(crate) mod table; use crate::prelude::*; +use nu_errors::ShellError; pub(crate) use entries::EntriesView; - pub(crate) use table::TableView; pub(crate) trait RenderView { diff --git a/src/format/entries.rs b/src/format/entries.rs index 7dd891bd97..0584ce4695 100644 --- a/src/format/entries.rs +++ b/src/format/entries.rs @@ -1,5 +1,8 @@ +use crate::data::value; use crate::format::RenderView; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::Value; use derive_new::new; @@ -21,7 +24,7 @@ impl EntriesView { for desc in descs { let value = value.get_data(&desc); - let formatted_value = value.borrow().format_leaf().plain_string(75); + let formatted_value = value::format_leaf(value.borrow()).plain_string(75); entries.push((desc.clone(), formatted_value)) } diff --git a/src/format/generic.rs b/src/format/generic.rs index 3379325113..f0860c7933 100644 --- a/src/format/generic.rs +++ b/src/format/generic.rs @@ -1,7 +1,10 @@ -use crate::data::Value; +use crate::data::primitive::format_primitive; +use crate::data::value::format_leaf; use crate::format::{EntriesView, RenderView, TableView}; use crate::prelude::*; use derive_new::new; +use nu_errors::ShellError; +use nu_protocol::{UntaggedValue, Value}; // A list is printed one line at a time with an optional separator between groups #[derive(new)] @@ -13,7 +16,7 @@ impl RenderView for GenericView<'_> { fn render_view(&self, host: &mut dyn Host) -> Result<(), ShellError> { let tag = &self.value.tag; match &self.value.value { - UntaggedValue::Primitive(p) => Ok(host.stdout(&p.format(None))), + UntaggedValue::Primitive(p) => Ok(host.stdout(&format_primitive(p, None))), UntaggedValue::Table(l) => { let view = TableView::from_list(l, 0); @@ -31,8 +34,8 @@ impl RenderView for GenericView<'_> { } b @ UntaggedValue::Block(_) => { - let printed = b.format_leaf().plain_string(host.width()); - let view = EntriesView::from_value(&UntaggedValue::string(printed).into_value(tag)); + let printed = format_leaf(b).plain_string(host.width()); + let view = EntriesView::from_value(&value::string(printed).into_value(tag)); view.render_view(host)?; Ok(()) } diff --git a/src/format/list.rs b/src/format/list.rs index 6b945e1fd9..073940adff 100644 --- a/src/format/list.rs +++ b/src/format/list.rs @@ -1,6 +1,7 @@ use crate::format::RenderView; use crate::prelude::*; use derive_new::new; +use nu_errors::ShellError; // A list is printed one line at a time with an optional separator between groups diff --git a/src/format/table.rs b/src/format/table.rs index e956f171ec..7bb496bd77 100644 --- a/src/format/table.rs +++ b/src/format/table.rs @@ -1,8 +1,9 @@ -use crate::data::Value; +use crate::data::value::{format_leaf, style_leaf}; use crate::format::RenderView; use crate::prelude::*; use derive_new::new; -use nu_source::PrettyDebug; +use nu_errors::ShellError; +use nu_protocol::{UntaggedValue, Value}; use textwrap::fill; use prettytable::format::{FormatBuilder, LinePosition, LineSeparator}; @@ -67,10 +68,10 @@ impl TableView { value: UntaggedValue::Row(..), .. } => ( - UntaggedValue::nothing().format_leaf().plain_string(100000), - UntaggedValue::nothing().style_leaf(), + format_leaf(&value::nothing()).plain_string(100000), + style_leaf(&value::nothing()), ), - _ => (value.format_leaf().plain_string(100000), value.style_leaf()), + _ => (format_leaf(value).plain_string(100000), style_leaf(value)), } } else { match value { @@ -80,13 +81,13 @@ impl TableView { } => { let data = value.get_data(d); ( - data.borrow().format_leaf().plain_string(100000), - data.borrow().style_leaf(), + format_leaf(data.borrow()).plain_string(100000), + style_leaf(data.borrow()), ) } _ => ( - UntaggedValue::nothing().format_leaf().plain_string(100000), - UntaggedValue::nothing().style_leaf(), + format_leaf(&value::nothing()).plain_string(100000), + style_leaf(&value::nothing()), ), } } diff --git a/src/lib.rs b/src/lib.rs index 6da0736934..6f86ad8b84 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,30 +11,25 @@ mod cli; mod commands; mod context; mod data; +mod deserializer; mod env; -mod errors; mod evaluate; mod format; mod git; -mod parser; -mod plugin; mod shell; mod stream; -mod traits; mod utils; -pub use crate::commands::command::{CallInfo, ReturnSuccess, ReturnValue}; +pub use crate::cli::cli; +pub use crate::data::base::property_get::ValueExt; +pub use crate::data::config::{config_path, APP_INFO}; +pub use crate::data::dict::{TaggedDictBuilder, TaggedListBuilder}; +pub use crate::data::primitive; +pub use crate::data::value; pub use crate::env::host::BasicHost; -pub use crate::parser::hir::path::{ColumnPath, PathMember, UnspannedPathMember}; -pub use crate::parser::hir::SyntaxShape; -pub use crate::parser::parse::token_tree_builder::TokenTreeBuilder; -pub use crate::plugin::{serve_plugin, Plugin}; -pub use crate::traits::{ShellTypeName, SpannedTypeName}; pub use crate::utils::{did_you_mean, AbsoluteFile, AbsolutePath, RelativePath}; -pub use cli::cli; -pub use data::base::{Primitive, UntaggedValue, Value}; -pub use data::config::{config_path, APP_INFO}; -pub use data::dict::{Dictionary, TaggedDictBuilder, TaggedListBuilder}; -pub use errors::{CoerceInto, ShellError}; +pub use nu_parser::TokenTreeBuilder; pub use num_traits::cast::ToPrimitive; -pub use parser::registry::{EvaluatedArgs, NamedType, PositionalType, Signature}; + +// TODO: Temporary redirect +pub use nu_protocol::{serve_plugin, Plugin}; diff --git a/src/parser.rs b/src/parser.rs deleted file mode 100644 index 597c069a1c..0000000000 --- a/src/parser.rs +++ /dev/null @@ -1,32 +0,0 @@ -pub(crate) mod debug; -pub(crate) mod deserializer; -pub(crate) mod hir; -pub(crate) mod parse; -pub(crate) mod parse_command; -pub(crate) mod registry; - -use crate::errors::ShellError; - -pub(crate) use deserializer::ConfigDeserializer; -pub(crate) use hir::syntax_shape::flat_shape::FlatShape; -pub(crate) use hir::TokensIterator; -pub(crate) use parse::call_node::CallNode; -pub(crate) use parse::files::Files; -pub(crate) use parse::flag::{Flag, FlagKind}; -pub(crate) use parse::operator::Operator; -pub(crate) use parse::parser::pipeline; -pub(crate) use parse::token_tree::{DelimitedNode, Delimiter, TokenNode}; -pub(crate) use parse::tokens::{RawNumber, UnspannedToken}; -pub(crate) use parse::unit::Unit; -pub(crate) use registry::CommandRegistry; - -use nu_source::nom_input; - -pub fn parse(input: &str) -> Result { - let _ = pretty_env_logger::try_init(); - - match pipeline(nom_input(input)) { - Ok((_rest, val)) => Ok(val), - Err(err) => Err(ShellError::parse_error(err)), - } -} diff --git a/src/plugins/average.rs b/src/plugins/average.rs index 8f852110b3..560aa6562c 100644 --- a/src/plugins/average.rs +++ b/src/plugins/average.rs @@ -1,6 +1,7 @@ -use nu::{ - serve_plugin, CallInfo, CoerceInto, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, - Signature, UntaggedValue, Value, +use nu::{serve_plugin, value, Plugin}; +use nu_errors::{CoerceInto, ShellError}; +use nu_protocol::{ + CallInfo, Primitive, ReturnSuccess, ReturnValue, Signature, UntaggedValue, Value, }; use nu_source::TaggedItem; @@ -26,7 +27,7 @@ impl Average { value: UntaggedValue::Primitive(Primitive::Int(j)), tag, }) => { - self.total = Some(UntaggedValue::int(i + j).into_value(tag)); + self.total = Some(value::int(i + j).into_value(tag)); self.count += 1; Ok(()) } @@ -46,7 +47,7 @@ impl Average { value: UntaggedValue::Primitive(Primitive::Bytes(j)), tag, }) => { - self.total = Some(UntaggedValue::bytes(b + j).into_value(tag)); + self.total = Some(value::bytes(b + j).into_value(tag)); self.count += 1; Ok(()) } diff --git a/src/plugins/binaryview.rs b/src/plugins/binaryview.rs index db00d89aab..07ea73e5e3 100644 --- a/src/plugins/binaryview.rs +++ b/src/plugins/binaryview.rs @@ -1,7 +1,7 @@ use crossterm::{cursor, terminal, Attribute, RawScreen}; -use nu::{ - outln, serve_plugin, CallInfo, Plugin, Primitive, ShellError, Signature, UntaggedValue, Value, -}; +use nu::{serve_plugin, Plugin}; +use nu_errors::ShellError; +use nu_protocol::{outln, CallInfo, Primitive, Signature, UntaggedValue, Value}; use nu_source::AnchorLocation; use pretty_hex::*; diff --git a/src/plugins/docker.rs b/src/plugins/docker.rs index 51936c3c6a..fc483a5ecf 100644 --- a/src/plugins/docker.rs +++ b/src/plugins/docker.rs @@ -50,7 +50,7 @@ fn process_docker_output(cmd_output: &str, tag: Tag) -> Result, Shell for (i, v) in values.iter().enumerate() { dict.insert( header[i].to_string(), - UntaggedValue::string(v.trim().to_string()), + value::string(v.trim().to_string()), ); } diff --git a/src/plugins/edit.rs b/src/plugins/edit.rs index 14e5c17e88..91e6ee5437 100644 --- a/src/plugins/edit.rs +++ b/src/plugins/edit.rs @@ -1,6 +1,8 @@ -use nu::{ - serve_plugin, CallInfo, ColumnPath, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, - Signature, SpannedTypeName, SyntaxShape, UntaggedValue, Value, +use nu::{serve_plugin, Plugin, ValueExt}; +use nu_errors::ShellError; +use nu_protocol::{ + CallInfo, ColumnPath, Primitive, ReturnSuccess, ReturnValue, Signature, SpannedTypeName, + SyntaxShape, UntaggedValue, Value, }; use nu_source::Tagged; diff --git a/src/plugins/embed.rs b/src/plugins/embed.rs index 53f0eaebdb..cce9698679 100644 --- a/src/plugins/embed.rs +++ b/src/plugins/embed.rs @@ -1,9 +1,11 @@ #[macro_use] extern crate indexmap; -use nu::{ - serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, - SpannedTypeName, SyntaxShape, UntaggedValue, Value, +use nu::{serve_plugin, value, Plugin}; +use nu_errors::ShellError; +use nu_protocol::{ + CallInfo, Primitive, ReturnSuccess, ReturnValue, Signature, SpannedTypeName, SyntaxShape, + UntaggedValue, Value, }; use nu_source::Tag; @@ -56,11 +58,11 @@ impl Plugin for Embed { } fn end_filter(&mut self) -> Result, ShellError> { - let row = UntaggedValue::row(indexmap! { + let row = value::row(indexmap! { match &self.field { Some(key) => key.clone(), None => "root".into(), - } => UntaggedValue::table(&self.values).into_value(Tag::unknown()), + } => value::table(&self.values).into_value(Tag::unknown()), }) .into_untagged_value(); diff --git a/src/plugins/format.rs b/src/plugins/format.rs index dda875ab86..d6b352c762 100644 --- a/src/plugins/format.rs +++ b/src/plugins/format.rs @@ -1,6 +1,7 @@ -use nu::{ - serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, - SyntaxShape, UntaggedValue, Value, +use nu::{serve_plugin, value, Plugin}; +use nu_errors::ShellError; +use nu_protocol::{ + CallInfo, Primitive, ReturnSuccess, ReturnValue, Signature, SyntaxShape, UntaggedValue, Value, }; use nom::{ @@ -114,7 +115,7 @@ impl Plugin for Format { } return Ok(vec![ReturnSuccess::value( - UntaggedValue::string(output).into_untagged_value(), + value::string(output).into_untagged_value(), )]); } _ => {} diff --git a/src/plugins/inc.rs b/src/plugins/inc.rs index dc0f3acd31..08887cfee5 100644 --- a/src/plugins/inc.rs +++ b/src/plugins/inc.rs @@ -1,6 +1,8 @@ -use nu::{ - did_you_mean, serve_plugin, CallInfo, ColumnPath, Plugin, Primitive, ReturnSuccess, - ReturnValue, ShellError, ShellTypeName, Signature, SyntaxShape, UntaggedValue, Value, +use nu::{did_you_mean, serve_plugin, value, Plugin, ValueExt}; +use nu_errors::ShellError; +use nu_protocol::{ + CallInfo, ColumnPath, Primitive, ReturnSuccess, ReturnValue, ShellTypeName, Signature, + SyntaxShape, UntaggedValue, Value, }; use nu_source::{span_for_spanned_list, HasSpan, SpannedItem, Tagged}; @@ -35,7 +37,7 @@ impl Inc { Some(Action::SemVerAction(act_on)) => { let mut ver = match semver::Version::parse(&input) { Ok(parsed_ver) => parsed_ver, - Err(_) => return Ok(UntaggedValue::string(input.to_string())), + Err(_) => return Ok(value::string(input.to_string())), }; match act_on { @@ -44,11 +46,11 @@ impl Inc { SemVerAction::Patch => ver.increment_patch(), } - UntaggedValue::string(ver.to_string()) + value::string(ver.to_string()) } Some(Action::Default) | None => match input.parse::() { - Ok(v) => UntaggedValue::string(format!("{}", v + 1)), - Err(_) => UntaggedValue::string(input), + Ok(v) => value::string(format!("{}", v + 1)), + Err(_) => value::string(input), }, }; @@ -78,10 +80,10 @@ impl Inc { fn inc(&self, value: Value) -> Result { match &value.value { UntaggedValue::Primitive(Primitive::Int(i)) => { - Ok(UntaggedValue::int(i + 1).into_value(value.tag())) + Ok(value::int(i + 1).into_value(value.tag())) } UntaggedValue::Primitive(Primitive::Bytes(b)) => { - Ok(UntaggedValue::bytes(b + 1 as u64).into_value(value.tag())) + Ok(value::bytes(b + 1 as u64).into_value(value.tag())) } UntaggedValue::Primitive(Primitive::String(ref s)) => { Ok(self.apply(&s)?.into_value(value.tag())) @@ -224,9 +226,10 @@ mod tests { use super::{Inc, SemVerAction}; use indexmap::IndexMap; - use nu::{ - CallInfo, EvaluatedArgs, PathMember, Plugin, ReturnSuccess, TaggedDictBuilder, - UnspannedPathMember, UntaggedValue, Value, + use nu::{value, Plugin, TaggedDictBuilder}; + use nu_protocol::{ + CallInfo, EvaluatedArgs, PathMember, ReturnSuccess, UnspannedPathMember, UntaggedValue, + Value, }; use nu_source::{Span, Tag}; @@ -246,7 +249,7 @@ mod tests { fn with_long_flag(&mut self, name: &str) -> &mut Self { self.flags.insert( name.to_string(), - UntaggedValue::boolean(true).into_value(Tag::unknown()), + value::boolean(true).into_value(Tag::unknown()), ); self } @@ -260,7 +263,7 @@ mod tests { .collect(); self.positionals - .push(UntaggedValue::column_path(fields).into_untagged_value()); + .push(value::column_path(fields).into_untagged_value()); self } @@ -274,7 +277,7 @@ mod tests { fn cargo_sample_record(with_version: &str) -> Value { let mut package = TaggedDictBuilder::new(Tag::unknown()); - package.insert_untagged("version", UntaggedValue::string(with_version)); + package.insert_untagged("version", value::string(with_version)); package.into_value() } @@ -357,21 +360,21 @@ mod tests { fn incs_major() { let mut inc = Inc::new(); inc.for_semver(SemVerAction::Major); - assert_eq!(inc.apply("0.1.3").unwrap(), UntaggedValue::string("1.0.0")); + assert_eq!(inc.apply("0.1.3").unwrap(), value::string("1.0.0")); } #[test] fn incs_minor() { let mut inc = Inc::new(); inc.for_semver(SemVerAction::Minor); - assert_eq!(inc.apply("0.1.3").unwrap(), UntaggedValue::string("0.2.0")); + assert_eq!(inc.apply("0.1.3").unwrap(), value::string("0.2.0")); } #[test] fn incs_patch() { let mut inc = Inc::new(); inc.for_semver(SemVerAction::Patch); - assert_eq!(inc.apply("0.1.3").unwrap(), UntaggedValue::string("0.1.4")); + assert_eq!(inc.apply("0.1.3").unwrap(), value::string("0.1.4")); } #[test] @@ -396,7 +399,7 @@ mod tests { .. }) => assert_eq!( *o.get_data(&String::from("version")).borrow(), - UntaggedValue::string(String::from("1.0.0")).into_untagged_value() + value::string(String::from("1.0.0")).into_untagged_value() ), _ => {} } @@ -424,7 +427,7 @@ mod tests { .. }) => assert_eq!( *o.get_data(&String::from("version")).borrow(), - UntaggedValue::string(String::from("0.2.0")).into_untagged_value() + value::string(String::from("0.2.0")).into_untagged_value() ), _ => {} } @@ -453,7 +456,7 @@ mod tests { .. }) => assert_eq!( *o.get_data(&field).borrow(), - UntaggedValue::string(String::from("0.1.4")).into_untagged_value() + value::string(String::from("0.1.4")).into_untagged_value() ), _ => {} } diff --git a/src/plugins/insert.rs b/src/plugins/insert.rs index 20eacbd993..9f99bcfb15 100644 --- a/src/plugins/insert.rs +++ b/src/plugins/insert.rs @@ -1,6 +1,8 @@ -use nu::{ - serve_plugin, CallInfo, ColumnPath, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, - ShellTypeName, Signature, SpannedTypeName, SyntaxShape, UntaggedValue, Value, +use nu::{serve_plugin, Plugin, ValueExt}; +use nu_errors::ShellError; +use nu_protocol::{ + CallInfo, ColumnPath, Primitive, ReturnSuccess, ReturnValue, ShellTypeName, Signature, + SpannedTypeName, SyntaxShape, UntaggedValue, Value, }; use nu_source::SpannedItem; diff --git a/src/plugins/match.rs b/src/plugins/match.rs index 271425aa8e..b513073eaf 100644 --- a/src/plugins/match.rs +++ b/src/plugins/match.rs @@ -1,6 +1,7 @@ -use nu::{ - serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, - SyntaxShape, UntaggedValue, Value, +use nu::{serve_plugin, Plugin}; +use nu_errors::ShellError; +use nu_protocol::{ + CallInfo, Primitive, ReturnSuccess, ReturnValue, Signature, SyntaxShape, UntaggedValue, Value, }; use regex::Regex; diff --git a/src/plugins/parse.rs b/src/plugins/parse.rs index 5e45c2d561..8354cafb10 100644 --- a/src/plugins/parse.rs +++ b/src/plugins/parse.rs @@ -1,6 +1,7 @@ -use nu::{ - serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, - SyntaxShape, TaggedDictBuilder, UntaggedValue, Value, +use nu::{serve_plugin, value, Plugin, TaggedDictBuilder}; +use nu_errors::ShellError; +use nu_protocol::{ + CallInfo, Primitive, ReturnSuccess, ReturnValue, Signature, SyntaxShape, UntaggedValue, Value, }; use nom::{ @@ -139,10 +140,7 @@ impl Plugin for Parse { let mut dict = TaggedDictBuilder::new(tag); for (idx, column_name) in self.column_names.iter().enumerate() { - dict.insert_untagged( - column_name, - UntaggedValue::string(&cap[idx + 1].to_string()), - ); + dict.insert_untagged(column_name, value::string(&cap[idx + 1].to_string())); } results.push(ReturnSuccess::value(dict.into_value())); diff --git a/src/plugins/ps.rs b/src/plugins/ps.rs index 49098702d9..3c3d7f4644 100644 --- a/src/plugins/ps.rs +++ b/src/plugins/ps.rs @@ -5,10 +5,9 @@ use heim::process::{self as process, Process, ProcessResult}; use heim::units::{ratio, Ratio}; use std::usize; -use nu::{ - serve_plugin, CallInfo, Plugin, ReturnSuccess, ReturnValue, ShellError, Signature, - TaggedDictBuilder, UntaggedValue, Value, -}; +use nu::{serve_plugin, value, Plugin, TaggedDictBuilder}; +use nu_errors::ShellError; +use nu_protocol::{CallInfo, ReturnSuccess, ReturnValue, Signature, Value}; use nu_source::Tag; use std::time::Duration; @@ -43,14 +42,14 @@ async fn ps(tag: Tag) -> Vec { while let Some(res) = processes.next().await { if let Ok((process, usage)) = res { let mut dict = TaggedDictBuilder::new(&tag); - dict.insert_untagged("pid", UntaggedValue::int(process.pid())); + dict.insert_untagged("pid", value::int(process.pid())); if let Ok(name) = process.name().await { - dict.insert_untagged("name", UntaggedValue::string(name)); + dict.insert_untagged("name", value::string(name)); } if let Ok(status) = process.status().await { - dict.insert_untagged("status", UntaggedValue::string(format!("{:?}", status))); + dict.insert_untagged("status", value::string(format!("{:?}", status))); } - dict.insert_untagged("cpu", UntaggedValue::number(usage.get::())); + dict.insert_untagged("cpu", value::number(usage.get::())); output.push(dict.into_value()); } } diff --git a/src/plugins/skip.rs b/src/plugins/skip.rs index 9b64e3dfc0..1bf0982125 100644 --- a/src/plugins/skip.rs +++ b/src/plugins/skip.rs @@ -1,6 +1,7 @@ -use nu::{ - serve_plugin, CallInfo, CoerceInto, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, - Signature, SyntaxShape, UntaggedValue, Value, +use nu::{serve_plugin, Plugin}; +use nu_errors::{CoerceInto, ShellError}; +use nu_protocol::{ + CallInfo, Primitive, ReturnSuccess, ReturnValue, Signature, SyntaxShape, UntaggedValue, Value, }; use nu_source::TaggedItem; diff --git a/src/plugins/str.rs b/src/plugins/str.rs index 38b69d6826..b31828d4a0 100644 --- a/src/plugins/str.rs +++ b/src/plugins/str.rs @@ -1,6 +1,8 @@ -use nu::{ - did_you_mean, serve_plugin, CallInfo, ColumnPath, Plugin, Primitive, ReturnSuccess, - ReturnValue, ShellError, ShellTypeName, Signature, SyntaxShape, UntaggedValue, Value, +use nu::{did_you_mean, serve_plugin, value, Plugin, ValueExt}; +use nu_errors::ShellError; +use nu_protocol::{ + CallInfo, ColumnPath, Primitive, ReturnSuccess, ReturnValue, ShellTypeName, Signature, + SyntaxShape, UntaggedValue, Value, }; use nu_source::{span_for_spanned_list, Tagged}; @@ -33,15 +35,15 @@ impl Str { fn apply(&self, input: &str) -> Result { let applied = match self.action.as_ref() { - Some(Action::Downcase) => UntaggedValue::string(input.to_ascii_lowercase()), - Some(Action::Upcase) => UntaggedValue::string(input.to_ascii_uppercase()), + Some(Action::Downcase) => value::string(input.to_ascii_lowercase()), + Some(Action::Upcase) => value::string(input.to_ascii_uppercase()), Some(Action::Substring(s, e)) => { let end: usize = cmp::min(*e, input.len()); let start: usize = *s; if start > input.len() - 1 { - UntaggedValue::string("") + value::string("") } else { - UntaggedValue::string( + value::string( &input .chars() .skip(start) @@ -52,11 +54,11 @@ impl Str { } Some(Action::ToInteger) => match input.trim() { other => match other.parse::() { - Ok(v) => UntaggedValue::int(v), - Err(_) => UntaggedValue::string(input), + Ok(v) => value::int(v), + Err(_) => value::string(input), }, }, - None => UntaggedValue::string(input), + None => value::string(input), }; Ok(applied) @@ -267,9 +269,10 @@ fn main() { mod tests { use super::{Action, Str}; use indexmap::IndexMap; - use nu::{ - CallInfo, EvaluatedArgs, Plugin, Primitive, ReturnSuccess, TaggedDictBuilder, - UnspannedPathMember, UntaggedValue, Value, + use nu::{value, Plugin, TaggedDictBuilder}; + use nu_protocol::{ + CallInfo, EvaluatedArgs, Primitive, ReturnSuccess, UnspannedPathMember, UntaggedValue, + Value, }; use nu_source::Tag; use num_bigint::BigInt; @@ -290,7 +293,7 @@ mod tests { fn with_named_parameter(&mut self, name: &str, value: &str) -> &mut Self { self.flags.insert( name.to_string(), - UntaggedValue::string(value).into_value(Tag::unknown()), + value::string(value).into_value(Tag::unknown()), ); self } @@ -298,7 +301,7 @@ mod tests { fn with_long_flag(&mut self, name: &str) -> &mut Self { self.flags.insert( name.to_string(), - UntaggedValue::boolean(true).into_value(Tag::unknown()), + value::boolean(true).into_value(Tag::unknown()), ); self } @@ -306,7 +309,7 @@ mod tests { fn with_parameter(&mut self, name: &str) -> &mut Self { let fields: Vec = name .split(".") - .map(|s| UntaggedValue::string(s.to_string()).into_value(Tag::unknown())) + .map(|s| value::string(s.to_string()).into_value(Tag::unknown())) .collect(); self.positionals @@ -324,12 +327,12 @@ mod tests { fn structured_sample_record(key: &str, value: &str) -> Value { let mut record = TaggedDictBuilder::new(Tag::unknown()); - record.insert_untagged(key.clone(), UntaggedValue::string(value)); + record.insert_untagged(key.clone(), value::string(value)); record.into_value() } fn unstructured_sample_record(value: &str) -> Value { - UntaggedValue::string(value).into_value(Tag::unknown()) + value::string(value).into_value(Tag::unknown()) } #[test] @@ -416,30 +419,21 @@ mod tests { fn str_downcases() { let mut strutils = Str::new(); strutils.for_downcase(); - assert_eq!( - strutils.apply("ANDRES").unwrap(), - UntaggedValue::string("andres") - ); + assert_eq!(strutils.apply("ANDRES").unwrap(), value::string("andres")); } #[test] fn str_upcases() { let mut strutils = Str::new(); strutils.for_upcase(); - assert_eq!( - strutils.apply("andres").unwrap(), - UntaggedValue::string("ANDRES") - ); + assert_eq!(strutils.apply("andres").unwrap(), value::string("ANDRES")); } #[test] fn str_to_int() { let mut strutils = Str::new(); strutils.for_to_int(); - assert_eq!( - strutils.apply("9999").unwrap(), - UntaggedValue::int(9999 as i64) - ); + assert_eq!(strutils.apply("9999").unwrap(), value::int(9999 as i64)); } #[test] @@ -464,7 +458,7 @@ mod tests { .. }) => assert_eq!( *o.get_data(&String::from("name")).borrow(), - UntaggedValue::string(String::from("JOTANDREHUDA")).into_untagged_value() + value::string(String::from("JOTANDREHUDA")).into_untagged_value() ), _ => {} } @@ -512,7 +506,7 @@ mod tests { .. }) => assert_eq!( *o.get_data(&String::from("name")).borrow(), - UntaggedValue::string(String::from("jotandrehuda")).into_untagged_value() + value::string(String::from("jotandrehuda")).into_untagged_value() ), _ => {} } @@ -560,7 +554,7 @@ mod tests { .. }) => assert_eq!( *o.get_data(&String::from("Nu_birthday")).borrow(), - UntaggedValue::int(10).into_untagged_value() + value::int(10).into_untagged_value() ), _ => {} } diff --git a/src/plugins/sum.rs b/src/plugins/sum.rs index 733b86926e..32e9dff2e5 100644 --- a/src/plugins/sum.rs +++ b/src/plugins/sum.rs @@ -1,6 +1,7 @@ -use nu::{ - serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, - UntaggedValue, Value, +use nu::{serve_plugin, value, Plugin}; +use nu_errors::ShellError; +use nu_protocol::{ + CallInfo, Primitive, ReturnSuccess, ReturnValue, Signature, UntaggedValue, Value, }; struct Sum { @@ -21,7 +22,7 @@ impl Sum { tag, }) => { //TODO: handle overflow - self.total = Some(UntaggedValue::int(i + j).into_value(tag)); + self.total = Some(value::int(i + j).into_value(tag)); Ok(()) } None => { @@ -42,7 +43,7 @@ impl Sum { tag, }) => { //TODO: handle overflow - self.total = Some(UntaggedValue::bytes(b + j).into_value(tag)); + self.total = Some(value::bytes(b + j).into_value(tag)); Ok(()) } None => { diff --git a/src/plugins/sys.rs b/src/plugins/sys.rs index 3226916015..c4816e6adc 100644 --- a/src/plugins/sys.rs +++ b/src/plugins/sys.rs @@ -4,10 +4,9 @@ use futures::executor::block_on; use futures::stream::StreamExt; use heim::units::{frequency, information, thermodynamic_temperature, time}; use heim::{disk, host, memory, net, sensors}; -use nu::{ - serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, - TaggedDictBuilder, UntaggedValue, Value, -}; +use nu::{primitive, serve_plugin, value, Plugin, TaggedDictBuilder}; +use nu_errors::ShellError; +use nu_protocol::{CallInfo, ReturnSuccess, ReturnValue, Signature, UntaggedValue, Value}; use nu_source::Tag; struct Sys; @@ -21,26 +20,26 @@ async fn cpu(tag: Tag) -> Option { match futures::future::try_join(heim::cpu::logical_count(), heim::cpu::frequency()).await { Ok((num_cpu, cpu_speed)) => { let mut cpu_idx = TaggedDictBuilder::with_capacity(tag, 4); - cpu_idx.insert_untagged("cores", Primitive::number(num_cpu)); + cpu_idx.insert_untagged("cores", primitive::number(num_cpu)); let current_speed = (cpu_speed.current().get::() as f64 / 1_000_000_000.0 * 100.0) .round() / 100.0; - cpu_idx.insert_untagged("current ghz", Primitive::number(current_speed)); + cpu_idx.insert_untagged("current ghz", primitive::number(current_speed)); if let Some(min_speed) = cpu_speed.min() { let min_speed = (min_speed.get::() as f64 / 1_000_000_000.0 * 100.0).round() / 100.0; - cpu_idx.insert_untagged("min ghz", Primitive::number(min_speed)); + cpu_idx.insert_untagged("min ghz", primitive::number(min_speed)); } if let Some(max_speed) = cpu_speed.max() { let max_speed = (max_speed.get::() as f64 / 1_000_000_000.0 * 100.0).round() / 100.0; - cpu_idx.insert_untagged("max ghz", Primitive::number(max_speed)); + cpu_idx.insert_untagged("max ghz", primitive::number(max_speed)); } Some(cpu_idx.into_value()) @@ -58,22 +57,22 @@ async fn mem(tag: Tag) -> Value { if let Ok(memory) = memory_result { dict.insert_untagged( "total", - UntaggedValue::bytes(memory.total().get::()), + value::bytes(memory.total().get::()), ); dict.insert_untagged( "free", - UntaggedValue::bytes(memory.free().get::()), + value::bytes(memory.free().get::()), ); } if let Ok(swap) = swap_result { dict.insert_untagged( "swap total", - UntaggedValue::bytes(swap.total().get::()), + value::bytes(swap.total().get::()), ); dict.insert_untagged( "swap free", - UntaggedValue::bytes(swap.free().get::()), + value::bytes(swap.free().get::()), ); } @@ -88,13 +87,10 @@ async fn host(tag: Tag) -> Value { // OS if let Ok(platform) = platform_result { - dict.insert_untagged("name", UntaggedValue::string(platform.system())); - dict.insert_untagged("release", UntaggedValue::string(platform.release())); - dict.insert_untagged("hostname", UntaggedValue::string(platform.hostname())); - dict.insert_untagged( - "arch", - UntaggedValue::string(platform.architecture().as_str()), - ); + dict.insert_untagged("name", value::string(platform.system())); + dict.insert_untagged("release", value::string(platform.release())); + dict.insert_untagged("hostname", value::string(platform.hostname())); + dict.insert_untagged("arch", value::string(platform.architecture().as_str())); } // Uptime @@ -107,10 +103,10 @@ async fn host(tag: Tag) -> Value { let minutes = (uptime - days * 60 * 60 * 24 - hours * 60 * 60) / 60; let seconds = uptime % 60; - uptime_dict.insert_untagged("days", UntaggedValue::int(days)); - uptime_dict.insert_untagged("hours", UntaggedValue::int(hours)); - uptime_dict.insert_untagged("mins", UntaggedValue::int(minutes)); - uptime_dict.insert_untagged("secs", UntaggedValue::int(seconds)); + uptime_dict.insert_untagged("days", value::int(days)); + uptime_dict.insert_untagged("hours", value::int(hours)); + uptime_dict.insert_untagged("mins", value::int(minutes)); + uptime_dict.insert_untagged("secs", value::int(seconds)); dict.insert_value("uptime", uptime_dict); } @@ -121,7 +117,7 @@ async fn host(tag: Tag) -> Value { while let Some(user) = users.next().await { if let Ok(user) = user { user_vec.push(Value { - value: UntaggedValue::string(user.username()), + value: value::string(user.username()), tag: tag.clone(), }); } @@ -140,31 +136,28 @@ async fn disks(tag: Tag) -> Option { let mut dict = TaggedDictBuilder::with_capacity(&tag, 6); dict.insert_untagged( "device", - UntaggedValue::string( + value::string( part.device() .unwrap_or_else(|| OsStr::new("N/A")) .to_string_lossy(), ), ); - dict.insert_untagged("type", UntaggedValue::string(part.file_system().as_str())); - dict.insert_untagged( - "mount", - UntaggedValue::string(part.mount_point().to_string_lossy()), - ); + dict.insert_untagged("type", value::string(part.file_system().as_str())); + dict.insert_untagged("mount", value::string(part.mount_point().to_string_lossy())); if let Ok(usage) = disk::usage(part.mount_point().to_path_buf()).await { dict.insert_untagged( "total", - UntaggedValue::bytes(usage.total().get::()), + value::bytes(usage.total().get::()), ); dict.insert_untagged( "used", - UntaggedValue::bytes(usage.used().get::()), + value::bytes(usage.used().get::()), ); dict.insert_untagged( "free", - UntaggedValue::bytes(usage.free().get::()), + value::bytes(usage.free().get::()), ); } @@ -188,28 +181,24 @@ async fn battery(tag: Tag) -> Option { if let Ok(battery) = battery { let mut dict = TaggedDictBuilder::new(&tag); if let Some(vendor) = battery.vendor() { - dict.insert_untagged("vendor", UntaggedValue::string(vendor)); + dict.insert_untagged("vendor", value::string(vendor)); } if let Some(model) = battery.model() { - dict.insert_untagged("model", UntaggedValue::string(model)); + dict.insert_untagged("model", value::string(model)); } if let Some(cycles) = battery.cycle_count() { - dict.insert_untagged("cycles", UntaggedValue::int(cycles)); + dict.insert_untagged("cycles", value::int(cycles)); } if let Some(time_to_full) = battery.time_to_full() { dict.insert_untagged( "mins to full", - UntaggedValue::number( - time_to_full.get::(), - ), + value::number(time_to_full.get::()), ); } if let Some(time_to_empty) = battery.time_to_empty() { dict.insert_untagged( "mins to empty", - UntaggedValue::number( - time_to_empty.get::(), - ), + value::number(time_to_empty.get::()), ); } output.push(dict.into_value()); @@ -232,13 +221,13 @@ async fn temp(tag: Tag) -> Option { while let Some(sensor) = sensors.next().await { if let Ok(sensor) = sensor { let mut dict = TaggedDictBuilder::new(&tag); - dict.insert_untagged("unit", UntaggedValue::string(sensor.unit())); + dict.insert_untagged("unit", value::string(sensor.unit())); if let Some(label) = sensor.label() { - dict.insert_untagged("label", UntaggedValue::string(label)); + dict.insert_untagged("label", value::string(label)); } dict.insert_untagged( "temp", - UntaggedValue::number( + value::number( sensor .current() .get::(), @@ -247,15 +236,13 @@ async fn temp(tag: Tag) -> Option { if let Some(high) = sensor.high() { dict.insert_untagged( "high", - UntaggedValue::number(high.get::()), + value::number(high.get::()), ); } if let Some(critical) = sensor.critical() { dict.insert_untagged( "critical", - UntaggedValue::number( - critical.get::(), - ), + value::number(critical.get::()), ); } @@ -276,14 +263,14 @@ async fn net(tag: Tag) -> Option { while let Some(nic) = io_counters.next().await { if let Ok(nic) = nic { let mut network_idx = TaggedDictBuilder::with_capacity(&tag, 3); - network_idx.insert_untagged("name", UntaggedValue::string(nic.interface())); + network_idx.insert_untagged("name", value::string(nic.interface())); network_idx.insert_untagged( "sent", - UntaggedValue::bytes(nic.bytes_sent().get::()), + value::bytes(nic.bytes_sent().get::()), ); network_idx.insert_untagged( "recv", - UntaggedValue::bytes(nic.bytes_recv().get::()), + value::bytes(nic.bytes_recv().get::()), ); output.push(network_idx.into_value()); } diff --git a/src/prelude.rs b/src/prelude.rs index 3c94ba8cfc..c5912ed264 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -68,19 +68,6 @@ macro_rules! trace_out_stream { }}; } -// These macros exist to differentiate between intentional writing to stdout -// and stray printlns left by accident - -#[macro_export] -macro_rules! outln { - ($($tokens:tt)*) => { println!($($tokens)*) } -} - -#[macro_export] -macro_rules! errln { - ($($tokens:tt)*) => { eprintln!($($tokens)*) } -} - #[macro_export] macro_rules! dict { ($( $key:expr => $value:expr ),*) => { @@ -100,40 +87,34 @@ macro_rules! dict { } } -pub(crate) use crate::cli::MaybeOwned; +pub(crate) use nu_protocol::{errln, outln}; + pub(crate) use crate::commands::command::{ - CallInfo, CommandAction, CommandArgs, ReturnSuccess, ReturnValue, RunnableContext, + CallInfoExt, CommandArgs, PerItemCommand, RawCommandArgs, RunnableContext, }; -pub(crate) use crate::commands::PerItemCommand; -pub(crate) use crate::commands::RawCommandArgs; pub(crate) use crate::context::CommandRegistry; pub(crate) use crate::context::Context; -pub(crate) use crate::data::base::{UntaggedValue, Value}; +pub(crate) use crate::data::base::property_get::ValueExt; pub(crate) use crate::data::types::ExtractType; -pub(crate) use crate::data::Primitive; +pub(crate) use crate::data::value; pub(crate) use crate::env::host::handle_unexpected; pub(crate) use crate::env::Host; -pub(crate) use crate::errors::{CoerceInto, ParseError, ShellError}; -pub(crate) use crate::parser::hir::SyntaxShape; -pub(crate) use crate::parser::parse::parser::Number; -pub(crate) use crate::parser::registry::Signature; pub(crate) use crate::shell::filesystem_shell::FilesystemShell; pub(crate) use crate::shell::help_shell::HelpShell; pub(crate) use crate::shell::shell_manager::ShellManager; pub(crate) use crate::shell::value_shell::ValueShell; pub(crate) use crate::stream::{InputStream, OutputStream}; -pub(crate) use crate::traits::{ShellTypeName, SpannedTypeName}; pub(crate) use async_stream::stream as async_stream; pub(crate) use bigdecimal::BigDecimal; pub(crate) use futures::stream::BoxStream; pub(crate) use futures::{FutureExt, Stream, StreamExt}; +pub(crate) use nu_protocol::{EvaluateTrait, MaybeOwned}; pub(crate) use nu_source::{ - b, AnchorLocation, DebugDocBuilder, HasFallibleSpan, HasSpan, PrettyDebug, + b, AnchorLocation, DebugDocBuilder, HasSpan, PrettyDebug, PrettyDebugWithSource, Span, SpannedItem, Tag, TaggedItem, Text, }; pub(crate) use num_bigint::BigInt; -pub(crate) use num_traits::cast::{FromPrimitive, ToPrimitive}; -pub(crate) use num_traits::identities::Zero; +pub(crate) use num_traits::cast::{ToPrimitive}; pub(crate) use serde::Deserialize; pub(crate) use std::collections::VecDeque; pub(crate) use std::future::Future; @@ -147,11 +128,11 @@ pub trait FromInputStream { impl FromInputStream for T where - T: Stream + Send + 'static, + T: Stream + Send + 'static, { fn from_input_stream(self) -> OutputStream { OutputStream { - values: self.map(ReturnSuccess::value).boxed(), + values: self.map(nu_protocol::ReturnSuccess::value).boxed(), } } } @@ -163,7 +144,7 @@ pub trait ToInputStream { impl ToInputStream for T where T: Stream + Send + 'static, - U: Into>, + U: Into>, { fn to_input_stream(self) -> InputStream { InputStream { @@ -179,7 +160,7 @@ pub trait ToOutputStream { impl ToOutputStream for T where T: Stream + Send + 'static, - U: Into, + U: Into, { fn to_output_stream(self) -> OutputStream { OutputStream { diff --git a/src/shell/filesystem_shell.rs b/src/shell/filesystem_shell.rs index 287c8baa60..15aaaec83c 100644 --- a/src/shell/filesystem_shell.rs +++ b/src/shell/filesystem_shell.rs @@ -8,6 +8,8 @@ use crate::prelude::*; use crate::shell::completer::NuCompleter; use crate::shell::shell::Shell; use crate::utils::FileStructure; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, UntaggedValue}; use nu_source::Tagged; use rustyline::completion::FilenameCompleter; use rustyline::hint::{Hinter, HistoryHinter}; diff --git a/src/shell/help_shell.rs b/src/shell/help_shell.rs index ec4156f4f0..2da32fa60c 100644 --- a/src/shell/help_shell.rs +++ b/src/shell/help_shell.rs @@ -6,6 +6,8 @@ use crate::commands::rm::RemoveArgs; use crate::data::{command_dict, TaggedDictBuilder}; use crate::prelude::*; use crate::shell::shell::Shell; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, ShellTypeName, UntaggedValue, Value}; use nu_source::Tagged; use std::ffi::OsStr; use std::path::PathBuf; diff --git a/src/shell/helper.rs b/src/shell/helper.rs index 2d830f6ae4..3008d5514d 100644 --- a/src/shell/helper.rs +++ b/src/shell/helper.rs @@ -1,9 +1,9 @@ use crate::context::Context; -use crate::parser::hir::syntax_shape::{color_fallible_syntax, FlatShape, PipelineShape}; -use crate::parser::hir::TokensIterator; -use crate::parser::parse::token_tree::TokenNode; use ansi_term::Color; use log::{log_enabled, trace}; +use nu_parser::hir::syntax_shape::color_fallible_syntax; +use nu_parser::{FlatShape, PipelineShape, TokenNode, TokensIterator}; +use nu_protocol::outln; use nu_source::{nom_input, HasSpan, Spanned, Tag, Tagged, Text}; use rustyline::completion::Completer; use rustyline::error::ReadlineError; @@ -63,7 +63,7 @@ impl Highlighter for Helper { } fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> { - let tokens = crate::parser::pipeline(nom_input(line)); + let tokens = nu_parser::pipeline(nom_input(line)); match tokens { Err(_) => Cow::Borrowed(line), diff --git a/src/shell/shell.rs b/src/shell/shell.rs index 41f5aa9a5c..cfc233ba7e 100644 --- a/src/shell/shell.rs +++ b/src/shell/shell.rs @@ -3,7 +3,7 @@ use crate::commands::cp::CopyArgs; use crate::commands::mkdir::MkdirArgs; use crate::commands::mv::MoveArgs; use crate::commands::rm::RemoveArgs; -use crate::errors::ShellError; +use nu_errors::ShellError; use crate::prelude::*; use crate::stream::OutputStream; use nu_source::Tagged; diff --git a/src/shell/shell_manager.rs b/src/shell/shell_manager.rs index fa49d0e4ed..e63b21e884 100644 --- a/src/shell/shell_manager.rs +++ b/src/shell/shell_manager.rs @@ -3,7 +3,7 @@ use crate::commands::cp::CopyArgs; use crate::commands::mkdir::MkdirArgs; use crate::commands::mv::MoveArgs; use crate::commands::rm::RemoveArgs; -use crate::errors::ShellError; +use nu_errors::ShellError; use crate::prelude::*; use crate::shell::filesystem_shell::FilesystemShell; use crate::shell::shell::Shell; diff --git a/src/shell/value_shell.rs b/src/shell/value_shell.rs index f0021e68bb..b655d73443 100644 --- a/src/shell/value_shell.rs +++ b/src/shell/value_shell.rs @@ -6,6 +6,8 @@ use crate::commands::rm::RemoveArgs; use crate::prelude::*; use crate::shell::shell::Shell; use crate::utils::ValueStructure; +use nu_errors::ShellError; +use nu_protocol::{ReturnSuccess, ShellTypeName, UntaggedValue, Value}; use nu_source::Tagged; use std::ffi::OsStr; use std::path::{Path, PathBuf}; @@ -216,7 +218,7 @@ impl Shell for ValueShell { fn pwd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result { let mut stream = VecDeque::new(); stream.push_back(ReturnSuccess::value( - UntaggedValue::string(self.path()).into_value(&args.call_info.name_tag), + value::string(self.path()).into_value(&args.call_info.name_tag), )); Ok(stream.into()) } diff --git a/src/stream.rs b/src/stream.rs index bf362b8b12..fcc430d6c3 100644 --- a/src/stream.rs +++ b/src/stream.rs @@ -1,4 +1,5 @@ use crate::prelude::*; +use nu_protocol::{ReturnSuccess, ReturnValue, Value}; pub struct InputStream { pub(crate) values: BoxStream<'static, Value>, diff --git a/src/utils.rs b/src/utils.rs index 75004aa915..c57a4b861b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,6 +1,5 @@ -use crate::data::base::{UntaggedValue, Value}; -use crate::errors::ShellError; -use crate::{PathMember, UnspannedPathMember}; +use nu_errors::ShellError; +use nu_protocol::{PathMember, UnspannedPathMember, UntaggedValue, Value}; use nu_source::{b, DebugDocBuilder, PrettyDebug}; use std::ops::Div; use std::path::{Component, Path, PathBuf}; @@ -161,22 +160,20 @@ impl<'a> Iterator for TaggedValueIter<'a> { } } -impl Value { - fn is_tagged_dir(value: &Value) -> bool { - match &value.value { - UntaggedValue::Row(_) | UntaggedValue::Table(_) => true, - _ => false, - } +fn is_value_tagged_dir(value: &Value) -> bool { + match &value.value { + UntaggedValue::Row(_) | UntaggedValue::Table(_) => true, + _ => false, } +} - fn tagged_entries(value: &Value) -> TaggedValueIter<'_> { - match &value.value { - UntaggedValue::Row(o) => { - let iter = o.entries.iter(); - TaggedValueIter::List(iter) - } - _ => TaggedValueIter::Empty, +fn tagged_entries_for(value: &Value) -> TaggedValueIter<'_> { + match &value.value { + UntaggedValue::Row(o) => { + let iter = o.entries.iter(); + TaggedValueIter::List(iter) } + _ => TaggedValueIter::Empty, } } @@ -237,7 +234,7 @@ impl ValueStructure { } fn build(&mut self, src: &Value, lvl: usize) -> Result<(), ShellError> { - for entry in Value::tagged_entries(src) { + for entry in tagged_entries_for(src) { let value = entry.1; let path = entry.0; @@ -246,7 +243,7 @@ impl ValueStructure { loc: PathBuf::from(path), }); - if Value::is_tagged_dir(value) { + if is_value_tagged_dir(value) { self.build(value, lvl + 1)?; } } @@ -335,8 +332,8 @@ impl FileStructure { #[cfg(test)] mod tests { use super::{FileStructure, Res, ValueResource, ValueStructure}; - use crate::data::base::{UntaggedValue, Value}; - use crate::data::TaggedDictBuilder; + use crate::data::{value, TaggedDictBuilder}; + use nu_protocol::Value; use nu_source::Tag; use pretty_assertions::assert_eq; use std::path::PathBuf; @@ -355,7 +352,7 @@ mod tests { fn structured_sample_record(key: &str, value: &str) -> Value { let mut record = TaggedDictBuilder::new(Tag::unknown()); - record.insert_untagged(key.clone(), UntaggedValue::string(value)); + record.insert_untagged(key.clone(), value::string(value)); record.into_value() }