From cef1629f9a98d8fac56aecff86db047c4f63cbb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20P=C3=A9rex?= Date: Fri, 27 Jun 2025 02:33:44 +0100 Subject: [PATCH] chore: add nushell --- nushell/.cargo/config.toml | 33 + nushell/.gitattributes | 2 + nushell/.githooks/pre-commit | 5 + nushell/.githooks/pre-push | 6 + nushell/.github/AUTO_ISSUE_TEMPLATE/README.md | 1 + .../AUTO_ISSUE_TEMPLATE/nightly-build-fail.md | 16 + nushell/.github/ISSUE_TEMPLATE/bug_report.yml | 50 + .../ISSUE_TEMPLATE/feature_request.yml | 35 + nushell/.github/ISSUE_TEMPLATE/question.yml | 21 + nushell/.github/dependabot.yml | 40 + nushell/.github/labeler.yml | 40 + nushell/.github/pull_request_template.md | 40 + nushell/.github/workflows/audit.yml | 25 + nushell/.github/workflows/beta-test.yml | 52 + nushell/.github/workflows/check-msrv.nu | 12 + nushell/.github/workflows/ci.yml | 212 + .../workflows/friendly-config-reminder.yml | 25 + nushell/.github/workflows/labels.yml | 19 + nushell/.github/workflows/milestone.yml | 30 + nushell/.github/workflows/nightly-build.yml | 284 + nushell/.github/workflows/release-msi.nu | 62 + nushell/.github/workflows/release-msi.yml | 103 + nushell/.github/workflows/release-pkg.nu | 254 + nushell/.github/workflows/release.yml | 141 + nushell/.github/workflows/typos.yml | 13 + .../.github/workflows/winget-submission.yml | 34 + nushell/.gitignore | 55 + nushell/CITATION.cff | 26 + nushell/CODE_OF_CONDUCT.md | 76 + nushell/CONTRIBUTING.md | 236 + nushell/Cargo.lock | 8867 +++++++++++++++++ nushell/Cargo.toml | 344 + nushell/Cross.toml | 18 + nushell/LICENSE | 21 + nushell/README.md | 237 + nushell/SECURITY.md | 29 + nushell/assets/icons/nushell-original.png | Bin 0 -> 3711 bytes nushell/assets/nu_logo.ico | Bin 0 -> 7488 bytes nushell/assets/nushell-autocomplete6.gif | Bin 0 -> 1260827 bytes nushell/benches/README.md | 7 + nushell/benches/benchmarks.rs | 541 + nushell/clippy/wasm/clippy.toml | 3 + nushell/crates/README.md | 13 + nushell/crates/nu-cli/Cargo.toml | 54 + nushell/crates/nu-cli/LICENSE | 21 + nushell/crates/nu-cli/README.md | 7 + .../src/commands/commandline/commandline_.rs | 35 + .../nu-cli/src/commands/commandline/edit.rs | 66 + .../src/commands/commandline/get_cursor.rs | 52 + .../nu-cli/src/commands/commandline/mod.rs | 9 + .../src/commands/commandline/set_cursor.rs | 65 + .../nu-cli/src/commands/default_context.rs | 36 + .../nu-cli/src/commands/history/fields.rs | 9 + .../nu-cli/src/commands/history/history_.rs | 206 + .../src/commands/history/history_import.rs | 440 + .../src/commands/history/history_session.rs | 38 + .../crates/nu-cli/src/commands/history/mod.rs | 8 + .../crates/nu-cli/src/commands/keybindings.rs | 41 + .../src/commands/keybindings_default.rs | 54 + .../nu-cli/src/commands/keybindings_list.rs | 117 + .../nu-cli/src/commands/keybindings_listen.rs | 200 + nushell/crates/nu-cli/src/commands/mod.rs | 16 + .../src/completions/attribute_completions.rs | 85 + nushell/crates/nu-cli/src/completions/base.rs | 49 + .../src/completions/cell_path_completions.rs | 153 + .../src/completions/command_completions.rs | 158 + .../nu-cli/src/completions/completer.rs | 873 ++ .../src/completions/completion_common.rs | 401 + .../src/completions/completion_options.rs | 349 + .../src/completions/custom_completions.rs | 168 + .../src/completions/directory_completions.rs | 88 + .../src/completions/dotnu_completions.rs | 209 + .../src/completions/exportable_completions.rs | 112 + .../src/completions/file_completions.rs | 97 + .../src/completions/flag_completions.rs | 58 + nushell/crates/nu-cli/src/completions/mod.rs | 30 + .../src/completions/operator_completions.rs | 277 + .../src/completions/variable_completions.rs | 79 + nushell/crates/nu-cli/src/config_files.rs | 368 + nushell/crates/nu-cli/src/eval_cmds.rs | 101 + nushell/crates/nu-cli/src/eval_file.rs | 154 + nushell/crates/nu-cli/src/lib.rs | 37 + .../nu-cli/src/menus/help_completions.rs | 172 + .../nu-cli/src/menus/menu_completions.rs | 171 + nushell/crates/nu-cli/src/menus/mod.rs | 5 + nushell/crates/nu-cli/src/nu_highlight.rs | 76 + nushell/crates/nu-cli/src/print.rs | 111 + nushell/crates/nu-cli/src/prompt.rs | 212 + nushell/crates/nu-cli/src/prompt_update.rs | 213 + nushell/crates/nu-cli/src/reedline_config.rs | 1514 +++ nushell/crates/nu-cli/src/repl.rs | 1651 +++ nushell/crates/nu-cli/src/syntax_highlight.rs | 526 + nushell/crates/nu-cli/src/util.rs | 352 + nushell/crates/nu-cli/src/validation.rs | 27 + .../nu-cli/tests/commands/history_import.rs | 296 + .../nu-cli/tests/commands/keybindings_list.rs | 7 + nushell/crates/nu-cli/tests/commands/mod.rs | 3 + .../nu-cli/tests/commands/nu_highlight.rs | 7 + .../crates/nu-cli/tests/completions/mod.rs | 2670 +++++ .../support/completions_helpers.rs | 209 + .../nu-cli/tests/completions/support/mod.rs | 5 + nushell/crates/nu-cli/tests/main.rs | 2 + nushell/crates/nu-cmd-base/Cargo.toml | 24 + nushell/crates/nu-cmd-base/LICENSE | 21 + nushell/crates/nu-cmd-base/README.md | 5 + nushell/crates/nu-cmd-base/src/formats/mod.rs | 1 + .../nu-cmd-base/src/formats/to/delimited.rs | 20 + .../crates/nu-cmd-base/src/formats/to/mod.rs | 1 + nushell/crates/nu-cmd-base/src/hook.rs | 343 + .../crates/nu-cmd-base/src/input_handler.rs | 86 + nushell/crates/nu-cmd-base/src/lib.rs | 8 + nushell/crates/nu-cmd-base/src/util.rs | 96 + nushell/crates/nu-cmd-base/src/wrap_call.rs | 101 + nushell/crates/nu-cmd-extra/Cargo.toml | 42 + nushell/crates/nu-cmd-extra/LICENSE | 21 + nushell/crates/nu-cmd-extra/README.md | 13 + .../nu-cmd-extra/assets/228_themes.json | 1 + .../crates/nu-cmd-extra/src/example_test.rs | 82 + .../crates/nu-cmd-extra/src/extra/bits/and.rs | 139 + .../nu-cmd-extra/src/extra/bits/bits_.rs | 34 + .../crates/nu-cmd-extra/src/extra/bits/mod.rs | 184 + .../crates/nu-cmd-extra/src/extra/bits/not.rs | 194 + .../crates/nu-cmd-extra/src/extra/bits/or.rs | 132 + .../src/extra/bits/rotate_left.rs | 252 + .../src/extra/bits/rotate_right.rs | 256 + .../nu-cmd-extra/src/extra/bits/shift_left.rs | 267 + .../src/extra/bits/shift_right.rs | 241 + .../crates/nu-cmd-extra/src/extra/bits/xor.rs | 132 + .../src/extra/filters/each_while.rs | 135 + .../nu-cmd-extra/src/extra/filters/mod.rs | 9 + .../src/extra/filters/roll/mod.rs | 90 + .../src/extra/filters/roll/roll_.rs | 38 + .../src/extra/filters/roll/roll_down.rs | 76 + .../src/extra/filters/roll/roll_left.rs | 115 + .../src/extra/filters/roll/roll_right.rs | 115 + .../src/extra/filters/roll/roll_up.rs | 76 + .../nu-cmd-extra/src/extra/filters/rotate.rs | 290 + .../src/extra/filters/update_cells.rs | 207 + .../src/extra/formats/from/mod.rs | 1 + .../src/extra/formats/from/url.rs | 79 + .../nu-cmd-extra/src/extra/formats/mod.rs | 5 + .../nu-cmd-extra/src/extra/formats/to/html.rs | 810 ++ .../nu-cmd-extra/src/extra/formats/to/mod.rs | 1 + .../nu-cmd-extra/src/extra/math/arccos.rs | 119 + .../nu-cmd-extra/src/extra/math/arccosh.rs | 105 + .../nu-cmd-extra/src/extra/math/arcsin.rs | 120 + .../nu-cmd-extra/src/extra/math/arcsinh.rs | 93 + .../nu-cmd-extra/src/extra/math/arctan.rs | 107 + .../nu-cmd-extra/src/extra/math/arctanh.rs | 106 + .../crates/nu-cmd-extra/src/extra/math/cos.rs | 113 + .../nu-cmd-extra/src/extra/math/cosh.rs | 93 + .../crates/nu-cmd-extra/src/extra/math/exp.rs | 98 + .../crates/nu-cmd-extra/src/extra/math/ln.rs | 105 + .../crates/nu-cmd-extra/src/extra/math/mod.rs | 33 + .../crates/nu-cmd-extra/src/extra/math/sin.rs | 113 + .../nu-cmd-extra/src/extra/math/sinh.rs | 92 + .../crates/nu-cmd-extra/src/extra/math/tan.rs | 111 + .../nu-cmd-extra/src/extra/math/tanh.rs | 91 + nushell/crates/nu-cmd-extra/src/extra/mod.rs | 96 + .../src/extra/platform/ansi/gradient.rs | 328 + .../src/extra/platform/ansi/mod.rs | 3 + .../nu-cmd-extra/src/extra/platform/mod.rs | 1 + .../extra/strings/encode_decode/decode_hex.rs | 76 + .../extra/strings/encode_decode/encode_hex.rs | 63 + .../src/extra/strings/format/bits.rs | 239 + .../src/extra/strings/format/command.rs | 276 + .../src/extra/strings/format/mod.rs | 7 + .../src/extra/strings/format/number.rs | 204 + .../nu-cmd-extra/src/extra/strings/mod.rs | 2 + .../src/extra/strings/str_/case/camel_case.rs | 96 + .../src/extra/strings/str_/case/kebab_case.rs | 95 + .../src/extra/strings/str_/case/mod.rs | 68 + .../extra/strings/str_/case/pascal_case.rs | 96 + .../strings/str_/case/screaming_snake_case.rs | 96 + .../src/extra/strings/str_/case/snake_case.rs | 96 + .../src/extra/strings/str_/case/str_.rs | 34 + .../src/extra/strings/str_/case/title_case.rs | 91 + .../src/extra/strings/str_/mod.rs | 1 + nushell/crates/nu-cmd-extra/src/lib.rs | 7 + .../tests/commands/bits/format.rs | 13 + .../nu-cmd-extra/tests/commands/bits/mod.rs | 1 + .../tests/commands/bytes/ends_with.rs | 120 + .../nu-cmd-extra/tests/commands/bytes/mod.rs | 2 + .../tests/commands/bytes/starts_with.rs | 120 + .../crates/nu-cmd-extra/tests/commands/mod.rs | 2 + nushell/crates/nu-cmd-extra/tests/main.rs | 1 + nushell/crates/nu-cmd-lang/Cargo.toml | 45 + nushell/crates/nu-cmd-lang/LICENSE | 21 + nushell/crates/nu-cmd-lang/README.md | 21 + nushell/crates/nu-cmd-lang/build.rs | 21 + .../nu-cmd-lang/src/core_commands/alias.rs | 58 + .../src/core_commands/attr/category.rs | 61 + .../src/core_commands/attr/deprecated.rs | 148 + .../src/core_commands/attr/example.rs | 159 + .../nu-cmd-lang/src/core_commands/attr/mod.rs | 9 + .../src/core_commands/attr/search_terms.rs | 57 + .../nu-cmd-lang/src/core_commands/break_.rs | 55 + .../nu-cmd-lang/src/core_commands/collect.rs | 129 + .../nu-cmd-lang/src/core_commands/const_.rs | 103 + .../src/core_commands/continue_.rs | 54 + .../nu-cmd-lang/src/core_commands/def.rs | 80 + .../nu-cmd-lang/src/core_commands/describe.rs | 506 + .../nu-cmd-lang/src/core_commands/do_.rs | 318 + .../nu-cmd-lang/src/core_commands/echo.rs | 91 + .../src/core_commands/error_make.rs | 262 + .../nu-cmd-lang/src/core_commands/export.rs | 52 + .../src/core_commands/export_alias.rs | 58 + .../src/core_commands/export_const.rs | 63 + .../src/core_commands/export_def.rs | 57 + .../src/core_commands/export_extern.rs | 54 + .../src/core_commands/export_module.rs | 72 + .../src/core_commands/export_use.rs | 62 + .../nu-cmd-lang/src/core_commands/extern_.rs | 50 + .../nu-cmd-lang/src/core_commands/for_.rs | 90 + .../nu-cmd-lang/src/core_commands/hide.rs | 67 + .../nu-cmd-lang/src/core_commands/hide_env.rs | 74 + .../nu-cmd-lang/src/core_commands/if_.rs | 144 + .../nu-cmd-lang/src/core_commands/ignore.rs | 78 + .../nu-cmd-lang/src/core_commands/let_.rs | 95 + .../nu-cmd-lang/src/core_commands/loop_.rs | 67 + .../nu-cmd-lang/src/core_commands/match_.rs | 112 + .../nu-cmd-lang/src/core_commands/mod.rs | 73 + .../nu-cmd-lang/src/core_commands/module.rs | 67 + .../nu-cmd-lang/src/core_commands/mut_.rs | 100 + .../src/core_commands/overlay/command.rs | 42 + .../src/core_commands/overlay/hide.rs | 137 + .../src/core_commands/overlay/list.rs | 50 + .../src/core_commands/overlay/mod.rs | 11 + .../src/core_commands/overlay/new.rs | 86 + .../src/core_commands/overlay/use_.rs | 230 + .../nu-cmd-lang/src/core_commands/return_.rs | 58 + .../src/core_commands/scope/aliases.rs | 54 + .../src/core_commands/scope/command.rs | 31 + .../src/core_commands/scope/commands.rs | 54 + .../src/core_commands/scope/engine_stats.rs | 55 + .../src/core_commands/scope/externs.rs | 54 + .../src/core_commands/scope/mod.rs | 15 + .../src/core_commands/scope/modules.rs | 54 + .../src/core_commands/scope/variables.rs | 54 + .../nu-cmd-lang/src/core_commands/try_.rs | 89 + .../nu-cmd-lang/src/core_commands/use_.rs | 213 + .../nu-cmd-lang/src/core_commands/version.rs | 222 + .../nu-cmd-lang/src/core_commands/while_.rs | 76 + .../crates/nu-cmd-lang/src/default_context.rs | 77 + .../crates/nu-cmd-lang/src/example_support.rs | 327 + .../crates/nu-cmd-lang/src/example_test.rs | 99 + nushell/crates/nu-cmd-lang/src/lib.rs | 14 + .../nu-cmd-lang/src/parse_const_test.rs | 19 + .../tests/commands/attr/deprecated.rs | 114 + .../nu-cmd-lang/tests/commands/attr/mod.rs | 1 + .../crates/nu-cmd-lang/tests/commands/mod.rs | 1 + nushell/crates/nu-cmd-lang/tests/main.rs | 1 + nushell/crates/nu-cmd-plugin/Cargo.toml | 23 + nushell/crates/nu-cmd-plugin/LICENSE | 21 + nushell/crates/nu-cmd-plugin/README.md | 3 + .../crates/nu-cmd-plugin/src/commands/mod.rs | 3 + .../nu-cmd-plugin/src/commands/plugin/add.rs | 142 + .../nu-cmd-plugin/src/commands/plugin/list.rs | 301 + .../nu-cmd-plugin/src/commands/plugin/mod.rs | 77 + .../nu-cmd-plugin/src/commands/plugin/rm.rs | 113 + .../nu-cmd-plugin/src/commands/plugin/stop.rs | 80 + .../nu-cmd-plugin/src/commands/plugin/use_.rs | 89 + .../nu-cmd-plugin/src/default_context.rs | 31 + nushell/crates/nu-cmd-plugin/src/lib.rs | 8 + nushell/crates/nu-cmd-plugin/src/util.rs | 145 + nushell/crates/nu-color-config/Cargo.toml | 25 + nushell/crates/nu-color-config/LICENSE | 21 + nushell/crates/nu-color-config/README.md | 5 + .../nu-color-config/src/color_config.rs | 159 + nushell/crates/nu-color-config/src/lib.rs | 14 + .../src/matching_brackets_style.rs | 31 + .../crates/nu-color-config/src/nu_style.rs | 599 ++ .../crates/nu-color-config/src/shape_color.rs | 61 + .../nu-color-config/src/style_computer.rs | 251 + .../crates/nu-color-config/src/text_style.rs | 433 + nushell/crates/nu-command/Cargo.toml | 238 + nushell/crates/nu-command/LICENSE | 21 + nushell/crates/nu-command/README.md | 7 + nushell/crates/nu-command/src/bytes/add.rs | 186 + nushell/crates/nu-command/src/bytes/at.rs | 193 + nushell/crates/nu-command/src/bytes/build_.rs | 89 + nushell/crates/nu-command/src/bytes/bytes_.rs | 34 + .../crates/nu-command/src/bytes/collect.rs | 101 + .../crates/nu-command/src/bytes/ends_with.rs | 159 + .../crates/nu-command/src/bytes/index_of.rs | 211 + nushell/crates/nu-command/src/bytes/length.rs | 99 + nushell/crates/nu-command/src/bytes/mod.rs | 27 + nushell/crates/nu-command/src/bytes/remove.rs | 197 + .../crates/nu-command/src/bytes/replace.rs | 161 + .../crates/nu-command/src/bytes/reverse.rs | 99 + nushell/crates/nu-command/src/bytes/split.rs | 109 + .../nu-command/src/bytes/starts_with.rs | 136 + .../nu-command/src/charting/hashable_value.rs | 339 + .../nu-command/src/charting/histogram.rs | 271 + nushell/crates/nu-command/src/charting/mod.rs | 4 + .../crates/nu-command/src/conversions/fill.rs | 245 + .../nu-command/src/conversions/into/binary.rs | 231 + .../nu-command/src/conversions/into/bool.rs | 235 + .../src/conversions/into/cell_path.rs | 238 + .../src/conversions/into/command.rs | 34 + .../src/conversions/into/datetime.rs | 1019 ++ .../src/conversions/into/duration.rs | 481 + .../src/conversions/into/filesize.rs | 202 + .../nu-command/src/conversions/into/float.rs | 175 + .../nu-command/src/conversions/into/glob.rs | 126 + .../nu-command/src/conversions/into/int.rs | 651 ++ .../nu-command/src/conversions/into/mod.rs | 27 + .../nu-command/src/conversions/into/record.rs | 248 + .../nu-command/src/conversions/into/string.rs | 311 + .../nu-command/src/conversions/into/value.rs | 561 ++ .../crates/nu-command/src/conversions/mod.rs | 7 + .../src/conversions/split_cell_path.rs | 179 + .../src/database/commands/into_sqlite.rs | 403 + .../nu-command/src/database/commands/mod.rs | 22 + .../src/database/commands/query_db.rs | 97 + .../src/database/commands/schema.rs | 218 + nushell/crates/nu-command/src/database/mod.rs | 15 + .../database/values/definitions/db_column.rs | 51 + .../values/definitions/db_constraint.rs | 26 + .../values/definitions/db_foreignkey.rs | 32 + .../database/values/definitions/db_index.rs | 32 + .../src/database/values/definitions/db_row.rs | 4 + .../database/values/definitions/db_schema.rs | 7 + .../database/values/definitions/db_table.rs | 8 + .../src/database/values/definitions/mod.rs | 7 + .../nu-command/src/database/values/mod.rs | 7 + .../nu-command/src/database/values/sqlite.rs | 791 ++ nushell/crates/nu-command/src/date/date_.rs | 47 + .../crates/nu-command/src/date/from_human.rs | 261 + .../crates/nu-command/src/date/humanize.rs | 105 + .../nu-command/src/date/list_timezone.rs | 55 + nushell/crates/nu-command/src/date/mod.rs | 16 + nushell/crates/nu-command/src/date/now.rs | 67 + nushell/crates/nu-command/src/date/parser.rs | 107 + .../crates/nu-command/src/date/to_timezone.rs | 152 + nushell/crates/nu-command/src/date/utils.rs | 301 + nushell/crates/nu-command/src/debug/ast.rs | 315 + nushell/crates/nu-command/src/debug/debug_.rs | 168 + nushell/crates/nu-command/src/debug/env.rs | 48 + .../crates/nu-command/src/debug/explain.rs | 301 + nushell/crates/nu-command/src/debug/info.rs | 185 + .../crates/nu-command/src/debug/inspect.rs | 59 + .../nu-command/src/debug/inspect_table.rs | 404 + .../crates/nu-command/src/debug/metadata.rs | 145 + .../nu-command/src/debug/metadata_access.rs | 84 + .../nu-command/src/debug/metadata_set.rs | 106 + nushell/crates/nu-command/src/debug/mod.rs | 38 + .../crates/nu-command/src/debug/profile.rs | 181 + nushell/crates/nu-command/src/debug/timeit.rs | 118 + nushell/crates/nu-command/src/debug/util.rs | 34 + nushell/crates/nu-command/src/debug/view.rs | 34 + .../nu-command/src/debug/view_blocks.rs | 71 + .../crates/nu-command/src/debug/view_files.rs | 76 + .../crates/nu-command/src/debug/view_ir.rs | 177 + .../nu-command/src/debug/view_source.rs | 269 + .../crates/nu-command/src/debug/view_span.rs | 70 + .../crates/nu-command/src/default_context.rs | 505 + .../nu-command/src/env/config/config_.rs | 140 + .../nu-command/src/env/config/config_env.rs | 83 + .../src/env/config/config_flatten.rs | 175 + .../nu-command/src/env/config/config_nu.rs | 92 + .../nu-command/src/env/config/config_reset.rs | 109 + .../src/env/config/config_use_colors.rs | 41 + .../crates/nu-command/src/env/config/mod.rs | 13 + .../crates/nu-command/src/env/export_env.rs | 95 + nushell/crates/nu-command/src/env/load_env.rs | 99 + nushell/crates/nu-command/src/env/mod.rs | 16 + .../crates/nu-command/src/env/source_env.rs | 124 + nushell/crates/nu-command/src/env/with_env.rs | 92 + nushell/crates/nu-command/src/example_test.rs | 144 + .../nu-command/src/experimental/is_admin.rs | 109 + .../crates/nu-command/src/experimental/job.rs | 34 + .../nu-command/src/experimental/job_flush.rs | 58 + .../nu-command/src/experimental/job_id.rs | 50 + .../nu-command/src/experimental/job_kill.rs | 64 + .../nu-command/src/experimental/job_list.rs | 79 + .../nu-command/src/experimental/job_recv.rs | 181 + .../nu-command/src/experimental/job_send.rs | 110 + .../nu-command/src/experimental/job_spawn.rs | 148 + .../nu-command/src/experimental/job_tag.rs | 70 + .../src/experimental/job_unfreeze.rs | 153 + .../crates/nu-command/src/experimental/mod.rs | 35 + .../crates/nu-command/src/filesystem/cd.rs | 175 + .../crates/nu-command/src/filesystem/du.rs | 234 + .../crates/nu-command/src/filesystem/glob.rs | 401 + .../crates/nu-command/src/filesystem/ls.rs | 999 ++ .../nu-command/src/filesystem/mktemp.rs | 125 + .../crates/nu-command/src/filesystem/mod.rs | 30 + .../crates/nu-command/src/filesystem/open.rs | 348 + .../crates/nu-command/src/filesystem/rm.rs | 466 + .../crates/nu-command/src/filesystem/save.rs | 548 + .../crates/nu-command/src/filesystem/start.rs | 164 + .../crates/nu-command/src/filesystem/ucp.rs | 400 + .../nu-command/src/filesystem/umkdir.rs | 106 + .../crates/nu-command/src/filesystem/umv.rs | 207 + .../crates/nu-command/src/filesystem/util.rs | 89 + .../nu-command/src/filesystem/utouch.rs | 299 + .../crates/nu-command/src/filesystem/watch.rs | 313 + nushell/crates/nu-command/src/filters/all.rs | 82 + nushell/crates/nu-command/src/filters/any.rs | 82 + .../crates/nu-command/src/filters/append.rs | 133 + .../crates/nu-command/src/filters/chunk_by.rs | 256 + .../crates/nu-command/src/filters/chunks.rs | 273 + .../crates/nu-command/src/filters/columns.rs | 147 + .../crates/nu-command/src/filters/compact.rs | 162 + .../crates/nu-command/src/filters/default.rs | 366 + .../nu-command/src/filters/drop/column.rs | 188 + .../nu-command/src/filters/drop/drop_.rs | 109 + .../crates/nu-command/src/filters/drop/mod.rs | 7 + .../crates/nu-command/src/filters/drop/nth.rs | 258 + nushell/crates/nu-command/src/filters/each.rs | 196 + .../crates/nu-command/src/filters/empty.rs | 74 + .../nu-command/src/filters/enumerate.rs | 82 + .../crates/nu-command/src/filters/every.rs | 95 + .../crates/nu-command/src/filters/filter.rs | 126 + nushell/crates/nu-command/src/filters/find.rs | 625 ++ .../crates/nu-command/src/filters/first.rs | 233 + .../crates/nu-command/src/filters/flatten.rs | 319 + nushell/crates/nu-command/src/filters/get.rs | 257 + .../crates/nu-command/src/filters/group_by.rs | 514 + .../crates/nu-command/src/filters/headers.rs | 179 + .../crates/nu-command/src/filters/insert.rs | 345 + .../nu-command/src/filters/interleave.rs | 161 + .../crates/nu-command/src/filters/is_empty.rs | 69 + .../nu-command/src/filters/is_not_empty.rs | 70 + .../crates/nu-command/src/filters/items.rs | 121 + nushell/crates/nu-command/src/filters/join.rs | 401 + nushell/crates/nu-command/src/filters/last.rs | 220 + .../crates/nu-command/src/filters/length.rs | 111 + .../crates/nu-command/src/filters/lines.rs | 123 + .../nu-command/src/filters/merge/common.rs | 175 + .../nu-command/src/filters/merge/deep.rs | 157 + .../nu-command/src/filters/merge/merge_.rs | 116 + .../nu-command/src/filters/merge/mod.rs | 6 + nushell/crates/nu-command/src/filters/mod.rs | 115 + .../crates/nu-command/src/filters/move_.rs | 532 + .../crates/nu-command/src/filters/par_each.rs | 258 + .../crates/nu-command/src/filters/prepend.rs | 134 + .../crates/nu-command/src/filters/reduce.rs | 144 + .../crates/nu-command/src/filters/reject.rs | 266 + .../crates/nu-command/src/filters/rename.rs | 246 + .../crates/nu-command/src/filters/reverse.rs | 80 + .../crates/nu-command/src/filters/select.rs | 332 + .../crates/nu-command/src/filters/shuffle.rs | 50 + .../crates/nu-command/src/filters/skip/mod.rs | 7 + .../nu-command/src/filters/skip/skip_.rs | 136 + .../nu-command/src/filters/skip/skip_until.rs | 106 + .../nu-command/src/filters/skip/skip_while.rs | 111 + .../crates/nu-command/src/filters/slice.rs | 125 + nushell/crates/nu-command/src/filters/sort.rs | 225 + .../crates/nu-command/src/filters/sort_by.rs | 188 + .../crates/nu-command/src/filters/take/mod.rs | 7 + .../nu-command/src/filters/take/take_.rs | 168 + .../nu-command/src/filters/take/take_until.rs | 99 + .../nu-command/src/filters/take/take_while.rs | 102 + nushell/crates/nu-command/src/filters/tee.rs | 577 ++ .../nu-command/src/filters/transpose.rs | 321 + nushell/crates/nu-command/src/filters/uniq.rs | 320 + .../crates/nu-command/src/filters/uniq_by.rs | 164 + .../crates/nu-command/src/filters/update.rs | 295 + .../crates/nu-command/src/filters/upsert.rs | 389 + .../crates/nu-command/src/filters/utils.rs | 43 + .../crates/nu-command/src/filters/values.rs | 202 + .../crates/nu-command/src/filters/where_.rs | 178 + .../crates/nu-command/src/filters/window.rs | 261 + nushell/crates/nu-command/src/filters/wrap.rs | 103 + nushell/crates/nu-command/src/filters/zip.rs | 129 + .../nu-command/src/formats/from/command.rs | 34 + .../crates/nu-command/src/formats/from/csv.rs | 243 + .../nu-command/src/formats/from/delimited.rs | 143 + .../nu-command/src/formats/from/json.rs | 290 + .../crates/nu-command/src/formats/from/mod.rs | 29 + .../nu-command/src/formats/from/msgpack.rs | 557 ++ .../nu-command/src/formats/from/msgpackz.rs | 75 + .../nu-command/src/formats/from/nuon.rs | 116 + .../crates/nu-command/src/formats/from/ods.rs | 187 + .../crates/nu-command/src/formats/from/ssv.rs | 532 + .../nu-command/src/formats/from/toml.rs | 367 + .../crates/nu-command/src/formats/from/tsv.rs | 202 + .../nu-command/src/formats/from/xlsx.rs | 200 + .../crates/nu-command/src/formats/from/xml.rs | 566 ++ .../nu-command/src/formats/from/yaml.rs | 432 + nushell/crates/nu-command/src/formats/mod.rs | 6 + .../nu-command/src/formats/nu_xml_format.rs | 3 + .../nu-command/src/formats/to/command.rs | 34 + .../crates/nu-command/src/formats/to/csv.rs | 180 + .../nu-command/src/formats/to/delimited.rs | 185 + .../crates/nu-command/src/formats/to/json.rs | 243 + .../crates/nu-command/src/formats/to/md.rs | 920 ++ .../crates/nu-command/src/formats/to/mod.rs | 28 + .../nu-command/src/formats/to/msgpack.rs | 364 + .../nu-command/src/formats/to/msgpackz.rs | 103 + .../crates/nu-command/src/formats/to/nuon.rs | 157 + .../crates/nu-command/src/formats/to/text.rs | 286 + .../crates/nu-command/src/formats/to/toml.rs | 332 + .../crates/nu-command/src/formats/to/tsv.rs | 148 + .../crates/nu-command/src/formats/to/xml.rs | 554 + .../crates/nu-command/src/formats/to/yaml.rs | 247 + .../crates/nu-command/src/generators/cal.rs | 401 + .../nu-command/src/generators/generate.rs | 276 + .../crates/nu-command/src/generators/mod.rs | 11 + .../crates/nu-command/src/generators/seq.rs | 203 + .../nu-command/src/generators/seq_char.rs | 150 + .../nu-command/src/generators/seq_date.rs | 489 + .../nu-command/src/hash/generic_digest.rs | 138 + nushell/crates/nu-command/src/hash/hash_.rs | 34 + nushell/crates/nu-command/src/hash/md5.rs | 87 + nushell/crates/nu-command/src/hash/mod.rs | 8 + nushell/crates/nu-command/src/hash/sha256.rs | 88 + nushell/crates/nu-command/src/help/help_.rs | 124 + .../nu-command/src/help/help_aliases.rs | 158 + .../nu-command/src/help/help_commands.rs | 217 + .../nu-command/src/help/help_escapes.rs | 149 + .../nu-command/src/help/help_externs.rs | 124 + .../nu-command/src/help/help_modules.rs | 245 + .../nu-command/src/help/help_operators.rs | 215 + .../src/help/help_pipe_and_redirect.rs | 143 + nushell/crates/nu-command/src/help/mod.rs | 21 + nushell/crates/nu-command/src/lib.rs | 77 + nushell/crates/nu-command/src/math/abs.rs | 132 + nushell/crates/nu-command/src/math/avg.rs | 109 + nushell/crates/nu-command/src/math/ceil.rs | 130 + nushell/crates/nu-command/src/math/floor.rs | 130 + nushell/crates/nu-command/src/math/log.rs | 188 + nushell/crates/nu-command/src/math/math_.rs | 34 + nushell/crates/nu-command/src/math/max.rs | 102 + nushell/crates/nu-command/src/math/median.rs | 156 + nushell/crates/nu-command/src/math/min.rs | 100 + nushell/crates/nu-command/src/math/mod.rs | 36 + nushell/crates/nu-command/src/math/mode.rs | 188 + nushell/crates/nu-command/src/math/product.rs | 93 + .../crates/nu-command/src/math/reducers.rs | 149 + nushell/crates/nu-command/src/math/round.rs | 180 + nushell/crates/nu-command/src/math/sqrt.rs | 154 + nushell/crates/nu-command/src/math/stddev.rs | 141 + nushell/crates/nu-command/src/math/sum.rs | 99 + nushell/crates/nu-command/src/math/utils.rs | 126 + .../crates/nu-command/src/math/variance.rs | 168 + nushell/crates/nu-command/src/misc/mod.rs | 7 + nushell/crates/nu-command/src/misc/panic.rs | 50 + nushell/crates/nu-command/src/misc/source.rs | 122 + nushell/crates/nu-command/src/misc/tutor.rs | 449 + .../nu-command/src/network/http/client.rs | 986 ++ .../nu-command/src/network/http/delete.rs | 257 + .../crates/nu-command/src/network/http/get.rs | 221 + .../nu-command/src/network/http/head.rs | 184 + .../nu-command/src/network/http/http_.rs | 145 + .../crates/nu-command/src/network/http/mod.rs | 18 + .../nu-command/src/network/http/options.rs | 202 + .../nu-command/src/network/http/patch.rs | 258 + .../nu-command/src/network/http/post.rs | 268 + .../crates/nu-command/src/network/http/put.rs | 259 + nushell/crates/nu-command/src/network/mod.rs | 19 + nushell/crates/nu-command/src/network/port.rs | 145 + .../src/network/tls/impl_native_tls.rs | 16 + .../nu-command/src/network/tls/impl_rustls.rs | 251 + .../crates/nu-command/src/network/tls/mod.rs | 26 + .../nu-command/src/network/tls/tls.rustdoc.md | 31 + .../nu-command/src/network/url/build_query.rs | 95 + .../nu-command/src/network/url/decode.rs | 119 + .../nu-command/src/network/url/encode.rs | 137 + .../crates/nu-command/src/network/url/join.rs | 383 + .../crates/nu-command/src/network/url/mod.rs | 16 + .../nu-command/src/network/url/parse.rs | 133 + .../nu-command/src/network/url/query.rs | 118 + .../nu-command/src/network/url/split_query.rs | 106 + .../crates/nu-command/src/network/url/url_.rs | 38 + .../nu-command/src/network/version_check.rs | 159 + .../crates/nu-command/src/path/basename.rs | 161 + nushell/crates/nu-command/src/path/dirname.rs | 197 + nushell/crates/nu-command/src/path/exists.rs | 172 + nushell/crates/nu-command/src/path/expand.rs | 202 + nushell/crates/nu-command/src/path/join.rs | 312 + nushell/crates/nu-command/src/path/mod.rs | 61 + nushell/crates/nu-command/src/path/parse.rs | 257 + nushell/crates/nu-command/src/path/path_.rs | 47 + .../crates/nu-command/src/path/relative_to.rs | 171 + nushell/crates/nu-command/src/path/self_.rs | 134 + nushell/crates/nu-command/src/path/split.rs | 198 + nushell/crates/nu-command/src/path/type.rs | 152 + .../crates/nu-command/src/platform/clear.rs | 86 + .../nu-command/src/platform/dir_info.rs | 270 + .../nu-command/src/platform/input/input_.rs | 244 + .../src/platform/input/input_listen.rs | 476 + .../src/platform/input/legacy_input.rs | 136 + .../nu-command/src/platform/input/list.rs | 268 + .../nu-command/src/platform/input/mod.rs | 9 + .../src/platform/input/reedline_prompt.rs | 62 + .../nu-command/src/platform/is_terminal.rs | 71 + .../crates/nu-command/src/platform/kill.rs | 169 + nushell/crates/nu-command/src/platform/mod.rs | 23 + .../crates/nu-command/src/platform/sleep.rs | 104 + .../nu-command/src/platform/term/mod.rs | 7 + .../nu-command/src/platform/term/term_.rs | 34 + .../src/platform/term/term_query.rs | 186 + .../nu-command/src/platform/term/term_size.rs | 65 + .../crates/nu-command/src/platform/ulimit.rs | 602 ++ .../crates/nu-command/src/platform/whoami.rs | 67 + nushell/crates/nu-command/src/progress_bar.rs | 53 + .../crates/nu-command/src/random/binary.rs | 94 + nushell/crates/nu-command/src/random/bool.rs | 94 + .../nu-command/src/random/byte_stream.rs | 50 + nushell/crates/nu-command/src/random/chars.rs | 114 + nushell/crates/nu-command/src/random/dice.rs | 100 + nushell/crates/nu-command/src/random/float.rs | 115 + nushell/crates/nu-command/src/random/int.rs | 127 + nushell/crates/nu-command/src/random/mod.rs | 18 + .../crates/nu-command/src/random/random_.rs | 38 + nushell/crates/nu-command/src/random/uuid.rs | 338 + .../crates/nu-command/src/removed/format.rs | 44 + .../crates/nu-command/src/removed/let_env.rs | 41 + nushell/crates/nu-command/src/removed/mod.rs | 7 + .../src/removed/removed_commands.rs | 15 + nushell/crates/nu-command/src/shells/exit.rs | 53 + nushell/crates/nu-command/src/shells/mod.rs | 3 + nushell/crates/nu-command/src/sort_utils.rs | 285 + nushell/crates/nu-command/src/stor/create.rs | 249 + nushell/crates/nu-command/src/stor/delete.rs | 137 + nushell/crates/nu-command/src/stor/export.rs | 94 + nushell/crates/nu-command/src/stor/import.rs | 92 + nushell/crates/nu-command/src/stor/insert.rs | 392 + nushell/crates/nu-command/src/stor/mod.rs | 19 + nushell/crates/nu-command/src/stor/open.rs | 78 + nushell/crates/nu-command/src/stor/reset.rs | 92 + nushell/crates/nu-command/src/stor/stor_.rs | 34 + nushell/crates/nu-command/src/stor/update.rs | 211 + .../nu-command/src/strings/ansi/ansi_.rs | 965 ++ .../nu-command/src/strings/ansi/link.rs | 155 + .../crates/nu-command/src/strings/ansi/mod.rs | 7 + .../nu-command/src/strings/ansi/strip.rs | 110 + .../nu-command/src/strings/base/base32.rs | 180 + .../nu-command/src/strings/base/base32hex.rs | 181 + .../nu-command/src/strings/base/base64.rs | 193 + .../crates/nu-command/src/strings/base/hex.rs | 151 + .../crates/nu-command/src/strings/base/mod.rs | 105 + .../crates/nu-command/src/strings/char_.rs | 461 + .../nu-command/src/strings/detect_columns.rs | 562 ++ .../src/strings/encode_decode/decode.rs | 184 + .../src/strings/encode_decode/encode.rs | 150 + .../src/strings/encode_decode/encoding.rs | 171 + .../src/strings/encode_decode/mod.rs | 6 + .../nu-command/src/strings/format/date.rs | 286 + .../nu-command/src/strings/format/duration.rs | 212 + .../nu-command/src/strings/format/filesize.rs | 157 + .../nu-command/src/strings/format/format_.rs | 34 + .../nu-command/src/strings/format/mod.rs | 9 + .../nu-command/src/strings/guess_width.rs | 671 ++ nushell/crates/nu-command/src/strings/mod.rs | 77 + .../crates/nu-command/src/strings/parse.rs | 417 + .../nu-command/src/strings/split/chars.rs | 179 + .../nu-command/src/strings/split/column.rs | 281 + .../nu-command/src/strings/split/command.rs | 34 + .../nu-command/src/strings/split/list.rs | 388 + .../nu-command/src/strings/split/mod.rs | 13 + .../nu-command/src/strings/split/row.rs | 245 + .../nu-command/src/strings/split/words.rs | 429 + .../src/strings/str_/case/capitalize.rs | 150 + .../src/strings/str_/case/downcase.rs | 148 + .../nu-command/src/strings/str_/case/mod.rs | 62 + .../nu-command/src/strings/str_/case/str_.rs | 34 + .../src/strings/str_/case/upcase.rs | 136 + .../nu-command/src/strings/str_/contains.rs | 192 + .../nu-command/src/strings/str_/distance.rs | 152 + .../nu-command/src/strings/str_/ends_with.rs | 154 + .../nu-command/src/strings/str_/expand.rs | 381 + .../nu-command/src/strings/str_/index_of.rs | 488 + .../nu-command/src/strings/str_/join.rs | 143 + .../nu-command/src/strings/str_/length.rs | 182 + .../crates/nu-command/src/strings/str_/mod.rs | 29 + .../nu-command/src/strings/str_/replace.rs | 337 + .../nu-command/src/strings/str_/reverse.rs | 122 + .../src/strings/str_/starts_with.rs | 166 + .../nu-command/src/strings/str_/stats.rs | 396 + .../nu-command/src/strings/str_/substring.rs | 325 + .../nu-command/src/strings/str_/trim/mod.rs | 2 + .../nu-command/src/strings/str_/trim/trim_.rs | 588 ++ .../crates/nu-command/src/system/complete.rs | 97 + nushell/crates/nu-command/src/system/exec.rs | 142 + nushell/crates/nu-command/src/system/mod.rs | 39 + .../crates/nu-command/src/system/nu_check.rs | 319 + nushell/crates/nu-command/src/system/ps.rs | 194 + .../nu-command/src/system/registry_query.rs | 334 + .../nu-command/src/system/run_external.rs | 818 ++ .../crates/nu-command/src/system/sys/cpu.rs | 92 + .../crates/nu-command/src/system/sys/disks.rs | 65 + .../crates/nu-command/src/system/sys/host.rs | 92 + .../crates/nu-command/src/system/sys/mem.rs | 57 + .../crates/nu-command/src/system/sys/mod.rs | 21 + .../crates/nu-command/src/system/sys/net.rs | 79 + .../crates/nu-command/src/system/sys/sys_.rs | 43 + .../crates/nu-command/src/system/sys/temp.rs | 65 + .../crates/nu-command/src/system/sys/users.rs | 62 + nushell/crates/nu-command/src/system/uname.rs | 95 + .../crates/nu-command/src/system/which_.rs | 235 + .../crates/nu-command/src/viewers/griddle.rs | 357 + nushell/crates/nu-command/src/viewers/mod.rs | 5 + .../crates/nu-command/src/viewers/table.rs | 1228 +++ .../crates/nu-command/tests/commands/alias.rs | 171 + .../crates/nu-command/tests/commands/all.rs | 106 + .../crates/nu-command/tests/commands/any.rs | 92 + .../nu-command/tests/commands/append.rs | 14 + .../tests/commands/assignment/concat.rs | 84 + .../tests/commands/assignment/mod.rs | 1 + .../nu-command/tests/commands/base/base32.rs | 56 + .../tests/commands/base/base32hex.rs | 56 + .../nu-command/tests/commands/base/base64.rs | 73 + .../nu-command/tests/commands/base/hex.rs | 38 + .../nu-command/tests/commands/base/mod.rs | 45 + .../nu-command/tests/commands/break_.rs | 17 + .../nu-command/tests/commands/bytes/at.rs | 77 + .../tests/commands/bytes/collect.rs | 27 + .../nu-command/tests/commands/bytes/mod.rs | 2 + .../crates/nu-command/tests/commands/cal.rs | 105 + .../crates/nu-command/tests/commands/cd.rs | 326 + .../nu-command/tests/commands/chunk_by.rs | 58 + .../nu-command/tests/commands/chunks.rs | 45 + .../nu-command/tests/commands/compact.rs | 94 + .../nu-command/tests/commands/complete.rs | 109 + .../tests/commands/config_env_default.rs | 11 + .../tests/commands/config_nu_default.rs | 11 + .../nu-command/tests/commands/continue_.rs | 8 + .../tests/commands/conversions/into/binary.rs | 13 + .../tests/commands/conversions/into/int.rs | 43 + .../tests/commands/conversions/into/mod.rs | 3 + .../tests/commands/conversions/into/record.rs | 8 + .../tests/commands/conversions/mod.rs | 1 + .../tests/commands/database/into_sqlite.rs | 497 + .../nu-command/tests/commands/database/mod.rs | 2 + .../tests/commands/database/query_db.rs | 115 + .../nu-command/tests/commands/date/format.rs | 105 + .../nu-command/tests/commands/date/mod.rs | 1 + .../nu-command/tests/commands/debug/mod.rs | 1 + .../nu-command/tests/commands/debug/timeit.rs | 16 + .../nu-command/tests/commands/debug_info.rs | 7 + .../crates/nu-command/tests/commands/def.rs | 357 + .../nu-command/tests/commands/default.rs | 246 + .../tests/commands/detect_columns.rs | 96 + .../crates/nu-command/tests/commands/do_.rs | 62 + .../crates/nu-command/tests/commands/drop.rs | 209 + .../crates/nu-command/tests/commands/du.rs | 120 + .../crates/nu-command/tests/commands/each.rs | 65 + .../crates/nu-command/tests/commands/echo.rs | 42 + .../crates/nu-command/tests/commands/empty.rs | 57 + .../nu-command/tests/commands/error_make.rs | 46 + .../crates/nu-command/tests/commands/every.rs | 204 + .../crates/nu-command/tests/commands/exec.rs | 58 + .../nu-command/tests/commands/export_def.rs | 12 + .../crates/nu-command/tests/commands/fill.rs | 23 + .../nu-command/tests/commands/filter.rs | 18 + .../crates/nu-command/tests/commands/find.rs | 312 + .../crates/nu-command/tests/commands/first.rs | 105 + .../nu-command/tests/commands/flatten.rs | 151 + .../crates/nu-command/tests/commands/for_.rs | 42 + .../nu-command/tests/commands/format.rs | 128 + .../nu-command/tests/commands/generate.rs | 172 + .../crates/nu-command/tests/commands/get.rs | 215 + .../crates/nu-command/tests/commands/glob.rs | 207 + .../nu-command/tests/commands/griddle.rs | 8 + .../nu-command/tests/commands/group_by.rs | 81 + .../nu-command/tests/commands/hash_/mod.rs | 84 + .../nu-command/tests/commands/headers.rs | 134 + .../crates/nu-command/tests/commands/help.rs | 379 + .../nu-command/tests/commands/histogram.rs | 103 + .../nu-command/tests/commands/ignore.rs | 7 + .../nu-command/tests/commands/insert.rs | 187 + .../nu-command/tests/commands/inspect.rs | 19 + .../nu-command/tests/commands/interleave.rs | 13 + .../tests/commands/into_datetime.rs | 121 + .../tests/commands/into_duration.rs | 126 + .../tests/commands/into_filesize.rs | 137 + .../nu-command/tests/commands/into_int.rs | 103 + .../crates/nu-command/tests/commands/job.rs | 440 + .../crates/nu-command/tests/commands/join.rs | 420 + .../crates/nu-command/tests/commands/last.rs | 104 + .../nu-command/tests/commands/length.rs | 35 + .../crates/nu-command/tests/commands/let_.rs | 125 + .../crates/nu-command/tests/commands/lines.rs | 71 + .../crates/nu-command/tests/commands/loop_.rs | 52 + .../crates/nu-command/tests/commands/ls.rs | 866 ++ .../nu-command/tests/commands/match_.rs | 289 + .../nu-command/tests/commands/math/abs.rs | 22 + .../nu-command/tests/commands/math/avg.rs | 42 + .../nu-command/tests/commands/math/ceil.rs | 22 + .../nu-command/tests/commands/math/floor.rs | 22 + .../nu-command/tests/commands/math/log.rs | 22 + .../nu-command/tests/commands/math/max.rs | 14 + .../nu-command/tests/commands/math/median.rs | 50 + .../nu-command/tests/commands/math/min.rs | 14 + .../nu-command/tests/commands/math/mod.rs | 499 + .../nu-command/tests/commands/math/mode.rs | 14 + .../nu-command/tests/commands/math/product.rs | 14 + .../nu-command/tests/commands/math/round.rs | 57 + .../nu-command/tests/commands/math/sqrt.rs | 43 + .../nu-command/tests/commands/math/stddev.rs | 22 + .../nu-command/tests/commands/math/sum.rs | 90 + .../tests/commands/math/variance.rs | 22 + .../crates/nu-command/tests/commands/merge.rs | 91 + .../nu-command/tests/commands/merge_deep.rs | 144 + .../nu-command/tests/commands/mktemp.rs | 44 + .../crates/nu-command/tests/commands/mod.rs | 139 + .../nu-command/tests/commands/move_/column.rs | 102 + .../nu-command/tests/commands/move_/mod.rs | 2 + .../nu-command/tests/commands/move_/umv.rs | 689 ++ .../crates/nu-command/tests/commands/mut_.rs | 167 + .../tests/commands/network/http/delete.rs | 145 + .../tests/commands/network/http/get.rs | 339 + .../tests/commands/network/http/head.rs | 113 + .../tests/commands/network/http/mod.rs | 7 + .../tests/commands/network/http/options.rs | 64 + .../tests/commands/network/http/patch.rs | 191 + .../tests/commands/network/http/post.rs | 305 + .../tests/commands/network/http/put.rs | 191 + .../nu-command/tests/commands/network/mod.rs | 2 + .../nu-command/tests/commands/network/port.rs | 56 + .../nu-command/tests/commands/nu_check.rs | 746 ++ .../crates/nu-command/tests/commands/open.rs | 467 + .../nu-command/tests/commands/par_each.rs | 9 + .../crates/nu-command/tests/commands/parse.rs | 236 + .../tests/commands/path/basename.rs | 89 + .../nu-command/tests/commands/path/dirname.rs | 143 + .../nu-command/tests/commands/path/exists.rs | 104 + .../nu-command/tests/commands/path/expand.rs | 136 + .../nu-command/tests/commands/path/join.rs | 63 + .../nu-command/tests/commands/path/mod.rs | 42 + .../nu-command/tests/commands/path/parse.rs | 133 + .../nu-command/tests/commands/path/self_.rs | 64 + .../nu-command/tests/commands/path/split.rs | 37 + .../nu-command/tests/commands/path/type_.rs | 87 + .../tests/commands/platform/ansi_.rs | 29 + .../tests/commands/platform/char_.rs | 22 + .../tests/commands/platform/kill.rs | 9 + .../nu-command/tests/commands/platform/mod.rs | 3 + .../nu-command/tests/commands/prepend.rs | 29 + .../crates/nu-command/tests/commands/print.rs | 27 + .../nu-command/tests/commands/query/db.rs | 44 + .../nu-command/tests/commands/query/mod.rs | 1 + .../tests/commands/random/binary.rs | 21 + .../nu-command/tests/commands/random/bool.rs | 11 + .../nu-command/tests/commands/random/chars.rs | 21 + .../nu-command/tests/commands/random/dice.rs | 10 + .../nu-command/tests/commands/random/float.rs | 32 + .../nu-command/tests/commands/random/int.rs | 22 + .../nu-command/tests/commands/random/mod.rs | 7 + .../nu-command/tests/commands/random/uuid.rs | 76 + .../nu-command/tests/commands/redirection.rs | 490 + .../nu-command/tests/commands/reduce.rs | 131 + .../nu-command/tests/commands/reject.rs | 193 + .../nu-command/tests/commands/rename.rs | 85 + .../nu-command/tests/commands/return_.rs | 40 + .../nu-command/tests/commands/reverse.rs | 18 + .../crates/nu-command/tests/commands/rm.rs | 589 ++ .../crates/nu-command/tests/commands/roll.rs | 182 + .../nu-command/tests/commands/rotate.rs | 101 + .../nu-command/tests/commands/run_external.rs | 585 ++ .../crates/nu-command/tests/commands/save.rs | 546 + .../nu-command/tests/commands/select.rs | 288 + .../nu-command/tests/commands/semicolon.rs | 24 + .../crates/nu-command/tests/commands/seq.rs | 15 + .../nu-command/tests/commands/seq_char.rs | 66 + .../nu-command/tests/commands/seq_date.rs | 19 + .../nu-command/tests/commands/skip/mod.rs | 3 + .../nu-command/tests/commands/skip/skip_.rs | 22 + .../nu-command/tests/commands/skip/until.rs | 43 + .../nu-command/tests/commands/skip/while_.rs | 43 + .../crates/nu-command/tests/commands/slice.rs | 82 + .../crates/nu-command/tests/commands/sort.rs | 115 + .../nu-command/tests/commands/sort_by.rs | 130 + .../nu-command/tests/commands/source_env.rs | 358 + .../nu-command/tests/commands/split_column.rs | 62 + .../nu-command/tests/commands/split_row.rs | 58 + .../crates/nu-command/tests/commands/start.rs | 120 + .../crates/nu-command/tests/commands/stor.rs | 37 + .../tests/commands/str_/into_string.rs | 221 + .../nu-command/tests/commands/str_/join.rs | 46 + .../nu-command/tests/commands/str_/mod.rs | 414 + .../crates/nu-command/tests/commands/table.rs | 3960 ++++++++ .../nu-command/tests/commands/take/mod.rs | 3 + .../nu-command/tests/commands/take/rows.rs | 60 + .../nu-command/tests/commands/take/until.rs | 44 + .../nu-command/tests/commands/take/while_.rs | 43 + .../crates/nu-command/tests/commands/tee.rs | 69 + .../nu-command/tests/commands/terminal.rs | 24 + .../nu-command/tests/commands/to_text.rs | 54 + .../nu-command/tests/commands/transpose.rs | 42 + .../crates/nu-command/tests/commands/try_.rs | 156 + .../crates/nu-command/tests/commands/ucp.rs | 1254 +++ .../nu-command/tests/commands/ulimit.rs | 222 + .../nu-command/tests/commands/umkdir.rs | 174 + .../crates/nu-command/tests/commands/uname.rs | 12 + .../crates/nu-command/tests/commands/uniq.rs | 206 + .../nu-command/tests/commands/uniq_by.rs | 174 + .../nu-command/tests/commands/update.rs | 146 + .../nu-command/tests/commands/upsert.rs | 219 + .../nu-command/tests/commands/url/decode.rs | 19 + .../nu-command/tests/commands/url/join.rs | 443 + .../nu-command/tests/commands/url/mod.rs | 3 + .../nu-command/tests/commands/url/parse.rs | 170 + .../crates/nu-command/tests/commands/use_.rs | 356 + .../nu-command/tests/commands/utouch.rs | 793 ++ .../nu-command/tests/commands/where_.rs | 230 + .../crates/nu-command/tests/commands/which.rs | 120 + .../nu-command/tests/commands/while_.rs | 34 + .../nu-command/tests/commands/window.rs | 105 + .../nu-command/tests/commands/with_env.rs | 72 + .../crates/nu-command/tests/commands/wrap.rs | 45 + .../crates/nu-command/tests/commands/zip.rs | 53 + .../tests/format_conversions/csv.rs | 489 + .../tests/format_conversions/html.rs | 83 + .../tests/format_conversions/json.rs | 299 + .../tests/format_conversions/markdown.rs | 79 + .../tests/format_conversions/mod.rs | 15 + .../tests/format_conversions/msgpack.rs | 161 + .../tests/format_conversions/msgpackz.rs | 28 + .../tests/format_conversions/nuon.rs | 524 + .../tests/format_conversions/ods.rs | 48 + .../tests/format_conversions/ssv.rs | 95 + .../tests/format_conversions/toml.rs | 96 + .../tests/format_conversions/tsv.rs | 295 + .../tests/format_conversions/url.rs | 16 + .../tests/format_conversions/xlsx.rs | 45 + .../tests/format_conversions/xml.rs | 112 + .../tests/format_conversions/yaml.rs | 81 + nushell/crates/nu-command/tests/main.rs | 4 + nushell/crates/nu-command/tests/sort_utils.rs | 559 ++ .../tests/string/format/duration.rs | 15 + .../tests/string/format/filesize.rs | 15 + .../nu-command/tests/string/format/mod.rs | 2 + nushell/crates/nu-command/tests/string/mod.rs | 1 + nushell/crates/nu-derive-value/Cargo.toml | 24 + nushell/crates/nu-derive-value/LICENSE | 21 + .../crates/nu-derive-value/src/attributes.rs | 133 + nushell/crates/nu-derive-value/src/case.rs | 76 + nushell/crates/nu-derive-value/src/error.rs | 104 + nushell/crates/nu-derive-value/src/from.rs | 664 ++ nushell/crates/nu-derive-value/src/into.rs | 291 + nushell/crates/nu-derive-value/src/lib.rs | 71 + nushell/crates/nu-derive-value/src/names.rs | 61 + nushell/crates/nu-derive-value/src/tests.rs | 242 + nushell/crates/nu-engine/Cargo.toml | 32 + nushell/crates/nu-engine/LICENSE | 21 + nushell/crates/nu-engine/README.md | 9 + nushell/crates/nu-engine/src/call_ext.rs | 400 + nushell/crates/nu-engine/src/closure_eval.rs | 275 + nushell/crates/nu-engine/src/column.rs | 36 + .../crates/nu-engine/src/command_prelude.rs | 10 + .../crates/nu-engine/src/compile/builder.rs | 599 ++ nushell/crates/nu-engine/src/compile/call.rs | 272 + .../nu-engine/src/compile/expression.rs | 572 ++ .../crates/nu-engine/src/compile/keyword.rs | 884 ++ nushell/crates/nu-engine/src/compile/mod.rs | 218 + .../crates/nu-engine/src/compile/operator.rs | 379 + .../crates/nu-engine/src/compile/redirect.rs | 159 + nushell/crates/nu-engine/src/documentation.rs | 599 ++ nushell/crates/nu-engine/src/env.rs | 431 + nushell/crates/nu-engine/src/eval.rs | 651 ++ nushell/crates/nu-engine/src/eval_helpers.rs | 93 + nushell/crates/nu-engine/src/eval_ir.rs | 1616 +++ nushell/crates/nu-engine/src/exit.rs | 37 + nushell/crates/nu-engine/src/glob_from.rs | 117 + nushell/crates/nu-engine/src/lib.rs | 28 + nushell/crates/nu-engine/src/scope.rs | 575 ++ nushell/crates/nu-explore/.gitignore | 22 + nushell/crates/nu-explore/Cargo.toml | 37 + nushell/crates/nu-explore/LICENSE | 21 + nushell/crates/nu-explore/README.md | 5 + .../crates/nu-explore/src/commands/expand.rs | 77 + .../crates/nu-explore/src/commands/help.rs | 113 + nushell/crates/nu-explore/src/commands/mod.rs | 56 + nushell/crates/nu-explore/src/commands/nu.rs | 123 + .../crates/nu-explore/src/commands/quit.rs | 38 + .../crates/nu-explore/src/commands/table.rs | 75 + nushell/crates/nu-explore/src/commands/try.rs | 55 + .../crates/nu-explore/src/default_context.rs | 17 + nushell/crates/nu-explore/src/explore.rs | 271 + nushell/crates/nu-explore/src/lib.rs | 131 + .../nu-explore/src/nu_common/command.rs | 119 + .../nu-explore/src/nu_common/lscolor.rs | 129 + .../crates/nu-explore/src/nu_common/mod.rs | 30 + .../crates/nu-explore/src/nu_common/string.rs | 16 + .../crates/nu-explore/src/nu_common/table.rs | 57 + .../crates/nu-explore/src/nu_common/value.rs | 188 + .../nu-explore/src/pager/command_bar.rs | 54 + nushell/crates/nu-explore/src/pager/events.rs | 66 + nushell/crates/nu-explore/src/pager/mod.rs | 1009 ++ nushell/crates/nu-explore/src/pager/report.rs | 62 + .../crates/nu-explore/src/pager/status_bar.rs | 131 + .../crates/nu-explore/src/registry/command.rs | 132 + nushell/crates/nu-explore/src/registry/mod.rs | 88 + .../src/views/binary/binary_widget.rs | 392 + .../crates/nu-explore/src/views/binary/mod.rs | 165 + .../src/views/colored_text_widget.rs | 154 + .../crates/nu-explore/src/views/cursor/mod.rs | 146 + .../src/views/cursor/window_cursor.rs | 146 + .../src/views/cursor/window_cursor_2d.rs | 305 + nushell/crates/nu-explore/src/views/mod.rs | 135 + .../crates/nu-explore/src/views/preview.rs | 138 + .../crates/nu-explore/src/views/record/mod.rs | 806 ++ .../src/views/record/table_widget.rs | 756 ++ nushell/crates/nu-explore/src/views/try.rs | 264 + nushell/crates/nu-explore/src/views/util.rs | 163 + nushell/crates/nu-glob/Cargo.toml | 22 + nushell/crates/nu-glob/LICENSE-APACHE | 201 + nushell/crates/nu-glob/LICENSE-MIT | 26 + nushell/crates/nu-glob/README.md | 28 + nushell/crates/nu-glob/src/lib.rs | 1622 +++ nushell/crates/nu-json/CHANGELOG.md | 187 + nushell/crates/nu-json/Cargo.toml | 35 + nushell/crates/nu-json/LICENSE | 29 + nushell/crates/nu-json/README.md | 79 + nushell/crates/nu-json/src/builder.rs | 115 + nushell/crates/nu-json/src/de.rs | 824 ++ nushell/crates/nu-json/src/error.rs | 166 + nushell/crates/nu-json/src/lib.rs | 17 + nushell/crates/nu-json/src/ser.rs | 1038 ++ nushell/crates/nu-json/src/util.rs | 322 + nushell/crates/nu-json/src/value.rs | 1158 +++ nushell/crates/nu-json/tests/main.rs | 201 + nushell/crates/nu-lsp/Cargo.toml | 38 + nushell/crates/nu-lsp/LICENSE | 28 + nushell/crates/nu-lsp/README.md | 7 + nushell/crates/nu-lsp/src/ast.rs | 547 + nushell/crates/nu-lsp/src/completion.rs | 713 ++ nushell/crates/nu-lsp/src/diagnostics.rs | 161 + nushell/crates/nu-lsp/src/goto.rs | 460 + nushell/crates/nu-lsp/src/hints.rs | 345 + nushell/crates/nu-lsp/src/hover.rs | 468 + nushell/crates/nu-lsp/src/lib.rs | 680 ++ nushell/crates/nu-lsp/src/notification.rs | 258 + nushell/crates/nu-lsp/src/semantic_tokens.rs | 153 + nushell/crates/nu-lsp/src/signature.rs | 407 + nushell/crates/nu-lsp/src/symbols.rs | 565 ++ nushell/crates/nu-lsp/src/workspace.rs | 1259 +++ nushell/crates/nu-parser/Cargo.toml | 34 + nushell/crates/nu-parser/LICENSE | 21 + nushell/crates/nu-parser/README.md | 98 + nushell/crates/nu-parser/fuzz/.gitignore | 8 + nushell/crates/nu-parser/fuzz/Cargo.toml | 36 + nushell/crates/nu-parser/fuzz/README.md | 13 + .../nu-parser/fuzz/fuzz_targets/parse.rs | 13 + .../fuzz/fuzz_targets/parse_with_keywords.rs | 14 + nushell/crates/nu-parser/fuzz/gather_seeds.nu | 6 + .../crates/nu-parser/fuzz/rust-toolchain.toml | 2 + nushell/crates/nu-parser/src/deparse.rs | 104 + nushell/crates/nu-parser/src/exportable.rs | 8 + nushell/crates/nu-parser/src/flatten.rs | 698 ++ .../crates/nu-parser/src/known_external.rs | 243 + nushell/crates/nu-parser/src/lex.rs | 699 ++ nushell/crates/nu-parser/src/lib.rs | 27 + nushell/crates/nu-parser/src/lite_parser.rs | 523 + .../crates/nu-parser/src/parse_keywords.rs | 4233 ++++++++ .../crates/nu-parser/src/parse_patterns.rs | 229 + .../crates/nu-parser/src/parse_shape_specs.rs | 323 + nushell/crates/nu-parser/src/parser.rs | 7127 +++++++++++++ nushell/crates/nu-parser/src/type_check.rs | 917 ++ nushell/crates/nu-parser/tests/test_lex.rs | 345 + nushell/crates/nu-parser/tests/test_parser.rs | 3075 ++++++ .../tests/test_parser_unicode_escapes.rs | 83 + nushell/crates/nu-path/Cargo.toml | 25 + nushell/crates/nu-path/LICENSE | 21 + nushell/crates/nu-path/README.md | 3 + nushell/crates/nu-path/fuzz/.gitignore | 7 + nushell/crates/nu-path/fuzz/Cargo.toml | 27 + nushell/crates/nu-path/fuzz/README.md | 8 + .../nu-path/fuzz/fuzz_targets/path_fuzzer.rs | 22 + .../crates/nu-path/fuzz/rust-toolchain.toml | 2 + nushell/crates/nu-path/src/assert_path_eq.rs | 50 + nushell/crates/nu-path/src/components.rs | 229 + nushell/crates/nu-path/src/dots.rs | 250 + nushell/crates/nu-path/src/expansions.rs | 139 + nushell/crates/nu-path/src/form.rs | 158 + nushell/crates/nu-path/src/helpers.rs | 36 + nushell/crates/nu-path/src/lib.rs | 19 + nushell/crates/nu-path/src/path.rs | 3097 ++++++ nushell/crates/nu-path/src/tilde.rs | 274 + nushell/crates/nu-path/src/trailing_slash.rs | 115 + nushell/crates/nu-plugin-core/Cargo.toml | 31 + nushell/crates/nu-plugin-core/LICENSE | 21 + nushell/crates/nu-plugin-core/README.md | 3 + .../communication_mode/local_socket/mod.rs | 70 + .../communication_mode/local_socket/tests.rs | 19 + .../src/communication_mode/mod.rs | 271 + .../nu-plugin-core/src/interface/mod.rs | 379 + .../src/interface/stream/mod.rs | 631 ++ .../src/interface/stream/tests.rs | 551 + .../nu-plugin-core/src/interface/test_util.rs | 134 + .../nu-plugin-core/src/interface/tests.rs | 486 + nushell/crates/nu-plugin-core/src/lib.rs | 24 + .../nu-plugin-core/src/serializers/json.rs | 148 + .../nu-plugin-core/src/serializers/mod.rs | 71 + .../nu-plugin-core/src/serializers/msgpack.rs | 117 + .../nu-plugin-core/src/serializers/tests.rs | 568 ++ nushell/crates/nu-plugin-core/src/util/mod.rs | 5 + .../nu-plugin-core/src/util/waitable.rs | 181 + .../src/util/with_custom_values_in.rs | 65 + nushell/crates/nu-plugin-engine/Cargo.toml | 38 + nushell/crates/nu-plugin-engine/LICENSE | 21 + nushell/crates/nu-plugin-engine/README.md | 3 + .../crates/nu-plugin-engine/src/context.rs | 378 + .../nu-plugin-engine/src/declaration.rs | 126 + nushell/crates/nu-plugin-engine/src/gc.rs | 304 + nushell/crates/nu-plugin-engine/src/init.rs | 312 + .../nu-plugin-engine/src/interface/mod.rs | 1385 +++ .../nu-plugin-engine/src/interface/tests.rs | 1531 +++ nushell/crates/nu-plugin-engine/src/lib.rs | 24 + .../crates/nu-plugin-engine/src/persistent.rs | 371 + .../plugin_custom_value_with_source/mod.rs | 274 + .../plugin_custom_value_with_source/tests.rs | 203 + .../crates/nu-plugin-engine/src/process.rs | 90 + nushell/crates/nu-plugin-engine/src/source.rs | 63 + .../crates/nu-plugin-engine/src/test_util.rs | 24 + .../crates/nu-plugin-engine/src/util/mod.rs | 3 + .../nu-plugin-engine/src/util/mutable_cow.rs | 35 + nushell/crates/nu-plugin-protocol/Cargo.toml | 27 + nushell/crates/nu-plugin-protocol/LICENSE | 21 + nushell/crates/nu-plugin-protocol/README.md | 5 + .../nu-plugin-protocol/src/evaluated_call.rs | 533 + nushell/crates/nu-plugin-protocol/src/lib.rs | 660 ++ .../src/plugin_custom_value/mod.rs | 221 + .../src/plugin_custom_value/tests.rs | 265 + .../nu-plugin-protocol/src/protocol_info.rs | 113 + .../nu-plugin-protocol/src/test_util.rs | 43 + .../crates/nu-plugin-protocol/src/tests.rs | 52 + .../crates/nu-plugin-test-support/Cargo.toml | 31 + nushell/crates/nu-plugin-test-support/LICENSE | 21 + .../crates/nu-plugin-test-support/README.md | 4 + .../crates/nu-plugin-test-support/src/diff.rs | 27 + .../src/fake_persistent_plugin.rs | 82 + .../src/fake_register.rs | 28 + .../crates/nu-plugin-test-support/src/lib.rs | 110 + .../nu-plugin-test-support/src/plugin_test.rs | 414 + .../src/spawn_fake_plugin.rs | 97 + .../tests/custom_value/mod.rs | 153 + .../nu-plugin-test-support/tests/hello/mod.rs | 92 + .../tests/lowercase/mod.rs | 90 + .../nu-plugin-test-support/tests/main.rs | 3 + nushell/crates/nu-plugin/Cargo.toml | 36 + nushell/crates/nu-plugin/LICENSE | 21 + nushell/crates/nu-plugin/README.md | 6 + nushell/crates/nu-plugin/src/lib.rs | 83 + .../crates/nu-plugin/src/plugin/command.rs | 396 + .../nu-plugin/src/plugin/interface/mod.rs | 1102 ++ .../nu-plugin/src/plugin/interface/tests.rs | 1216 +++ nushell/crates/nu-plugin/src/plugin/mod.rs | 734 ++ nushell/crates/nu-plugin/src/test_util.rs | 15 + nushell/crates/nu-pretty-hex/Cargo.toml | 24 + nushell/crates/nu-pretty-hex/LICENSE | 22 + nushell/crates/nu-pretty-hex/README.md | 81 + .../crates/nu-pretty-hex/examples/hex_demo.rs | 51 + nushell/crates/nu-pretty-hex/src/lib.rs | 61 + .../crates/nu-pretty-hex/src/pretty_hex.rs | 319 + nushell/crates/nu-pretty-hex/tests/256.txt | 17 + nushell/crates/nu-pretty-hex/tests/data | 1 + nushell/crates/nu-pretty-hex/tests/tests.rs | 164 + nushell/crates/nu-protocol/Cargo.toml | 79 + nushell/crates/nu-protocol/LICENSE | 21 + nushell/crates/nu-protocol/README.md | 3 + nushell/crates/nu-protocol/src/alias.rs | 64 + .../crates/nu-protocol/src/ast/attribute.rs | 13 + nushell/crates/nu-protocol/src/ast/block.rs | 110 + nushell/crates/nu-protocol/src/ast/call.rs | 424 + .../crates/nu-protocol/src/ast/cell_path.rs | 304 + nushell/crates/nu-protocol/src/ast/expr.rs | 164 + .../crates/nu-protocol/src/ast/expression.rs | 612 ++ .../nu-protocol/src/ast/import_pattern.rs | 96 + nushell/crates/nu-protocol/src/ast/keyword.rs | 10 + .../nu-protocol/src/ast/match_pattern.rs | 76 + nushell/crates/nu-protocol/src/ast/mod.rs | 34 + .../crates/nu-protocol/src/ast/operator.rs | 324 + .../crates/nu-protocol/src/ast/pipeline.rs | 214 + nushell/crates/nu-protocol/src/ast/range.rs | 10 + nushell/crates/nu-protocol/src/ast/table.rs | 8 + .../crates/nu-protocol/src/ast/traverse.rs | 303 + nushell/crates/nu-protocol/src/ast/unit.rs | 149 + .../nu-protocol/src/ast/value_with_unit.rs | 9 + nushell/crates/nu-protocol/src/casing.rs | 8 + .../nu-protocol/src/config/ansi_coloring.rs | 277 + .../nu-protocol/src/config/completions.rs | 153 + .../nu-protocol/src/config/datetime_format.rs | 39 + .../nu-protocol/src/config/display_errors.rs | 52 + .../crates/nu-protocol/src/config/error.rs | 87 + .../crates/nu-protocol/src/config/filesize.rs | 95 + .../crates/nu-protocol/src/config/helper.rs | 171 + .../crates/nu-protocol/src/config/history.rs | 91 + .../crates/nu-protocol/src/config/hooks.rs | 106 + nushell/crates/nu-protocol/src/config/ls.rs | 40 + nushell/crates/nu-protocol/src/config/mod.rs | 233 + .../crates/nu-protocol/src/config/output.rs | 95 + .../nu-protocol/src/config/plugin_gc.rs | 159 + .../crates/nu-protocol/src/config/prelude.rs | 4 + .../crates/nu-protocol/src/config/reedline.rs | 118 + nushell/crates/nu-protocol/src/config/rm.rs | 38 + .../src/config/shell_integration.rs | 56 + .../crates/nu-protocol/src/config/table.rs | 431 + .../src/debugger/debugger_trait.rs | 229 + .../crates/nu-protocol/src/debugger/mod.rs | 6 + .../nu-protocol/src/debugger/profiler.rs | 507 + nushell/crates/nu-protocol/src/deprecation.rs | 144 + .../crates/nu-protocol/src/did_you_mean.rs | 120 + .../crates/nu-protocol/src/engine/argument.rs | 124 + .../nu-protocol/src/engine/cached_file.rs | 15 + nushell/crates/nu-protocol/src/engine/call.rs | 224 + .../nu-protocol/src/engine/call_info.rs | 7 + .../crates/nu-protocol/src/engine/closure.rs | 35 + .../crates/nu-protocol/src/engine/command.rs | 169 + .../nu-protocol/src/engine/description.rs | 91 + .../nu-protocol/src/engine/engine_state.rs | 1430 +++ .../nu-protocol/src/engine/error_handler.rs | 55 + nushell/crates/nu-protocol/src/engine/jobs.rs | 405 + nushell/crates/nu-protocol/src/engine/mod.rs | 38 + .../crates/nu-protocol/src/engine/overlay.rs | 230 + .../nu-protocol/src/engine/pattern_match.rs | 259 + .../crates/nu-protocol/src/engine/sequence.rs | 64 + .../crates/nu-protocol/src/engine/stack.rs | 937 ++ .../nu-protocol/src/engine/stack_out_dest.rs | 286 + .../nu-protocol/src/engine/state_delta.rs | 145 + .../src/engine/state_working_set.rs | 1232 +++ .../crates/nu-protocol/src/engine/variable.rs | 20 + .../nu-protocol/src/errors/chained_error.rs | 120 + .../nu-protocol/src/errors/cli_error.rs | 181 + .../nu-protocol/src/errors/compile_error.rs | 250 + .../nu-protocol/src/errors/config_error.rs | 56 + .../nu-protocol/src/errors/labeled_error.rs | 255 + nushell/crates/nu-protocol/src/errors/mod.rs | 19 + .../nu-protocol/src/errors/parse_error.rs | 693 ++ .../nu-protocol/src/errors/parse_warning.rs | 50 + .../src/errors/shell_error/bridge.rs | 47 + .../nu-protocol/src/errors/shell_error/io.rs | 607 ++ .../nu-protocol/src/errors/shell_error/job.rs | 45 + .../src/errors/shell_error/location.rs | 56 + .../nu-protocol/src/errors/shell_error/mod.rs | 1579 +++ nushell/crates/nu-protocol/src/eval_base.rs | 415 + nushell/crates/nu-protocol/src/eval_const.rs | 548 + nushell/crates/nu-protocol/src/example.rs | 32 + nushell/crates/nu-protocol/src/id.rs | 132 + nushell/crates/nu-protocol/src/ir/call.rs | 351 + nushell/crates/nu-protocol/src/ir/display.rs | 459 + nushell/crates/nu-protocol/src/ir/mod.rs | 479 + .../crates/nu-protocol/src/lev_distance.rs | 221 + nushell/crates/nu-protocol/src/lib.rs | 51 + nushell/crates/nu-protocol/src/module.rs | 481 + nushell/crates/nu-protocol/src/parser_path.rs | 157 + .../nu-protocol/src/pipeline/byte_stream.rs | 1453 +++ .../nu-protocol/src/pipeline/handlers.rs | 139 + .../nu-protocol/src/pipeline/list_stream.rs | 183 + .../nu-protocol/src/pipeline/metadata.rs | 39 + .../crates/nu-protocol/src/pipeline/mod.rs | 15 + .../nu-protocol/src/pipeline/out_dest.rs | 65 + .../nu-protocol/src/pipeline/pipeline_data.rs | 940 ++ .../nu-protocol/src/pipeline/signals.rs | 100 + .../crates/nu-protocol/src/plugin/identity.rs | 149 + .../crates/nu-protocol/src/plugin/metadata.rs | 38 + nushell/crates/nu-protocol/src/plugin/mod.rs | 11 + .../nu-protocol/src/plugin/registered.rs | 42 + .../src/plugin/registry_file/mod.rs | 177 + .../src/plugin/registry_file/tests.rs | 127 + .../nu-protocol/src/plugin/signature.rs | 21 + .../crates/nu-protocol/src/process/child.rs | 460 + nushell/crates/nu-protocol/src/process/mod.rs | 4 + nushell/crates/nu-protocol/src/signature.rs | 801 ++ nushell/crates/nu-protocol/src/span.rs | 265 + .../crates/nu-protocol/src/syntax_shape.rs | 265 + nushell/crates/nu-protocol/src/ty.rs | 253 + .../nu-protocol/src/value/custom_value.rs | 98 + .../crates/nu-protocol/src/value/duration.rs | 181 + .../crates/nu-protocol/src/value/filesize.rs | 931 ++ .../crates/nu-protocol/src/value/format.rs | 16 + .../nu-protocol/src/value/from_value.rs | 863 ++ nushell/crates/nu-protocol/src/value/glob.rs | 41 + .../nu-protocol/src/value/into_value.rs | 299 + nushell/crates/nu-protocol/src/value/mod.rs | 4536 +++++++++ nushell/crates/nu-protocol/src/value/range.rs | 707 ++ .../crates/nu-protocol/src/value/record.rs | 753 ++ .../nu-protocol/src/value/test_derive.rs | 698 ++ .../crates/nu-protocol/tests/into_config.rs | 108 + nushell/crates/nu-protocol/tests/mod.rs | 1 + .../nu-protocol/tests/pipeline/byte_stream.rs | 285 + .../crates/nu-protocol/tests/pipeline/mod.rs | 1 + .../crates/nu-protocol/tests/test_config.rs | 107 + .../nu-protocol/tests/test_pipeline_data.rs | 15 + .../nu-protocol/tests/test_signature.rs | 172 + .../crates/nu-protocol/tests/test_value.rs | 75 + nushell/crates/nu-std/CONTRIBUTING.md | 248 + nushell/crates/nu-std/Cargo.toml | 23 + nushell/crates/nu-std/LICENSE | 21 + nushell/crates/nu-std/README.md | 47 + nushell/crates/nu-std/src/lib.rs | 189 + nushell/crates/nu-std/std-rfc/README.md | 30 + nushell/crates/nu-std/std-rfc/clip/mod.nu | 49 + .../crates/nu-std/std-rfc/conversions/mod.nu | 69 + nushell/crates/nu-std/std-rfc/iter/mod.nu | 222 + nushell/crates/nu-std/std-rfc/kv/mod.nu | 210 + nushell/crates/nu-std/std-rfc/mod.nu | 10 + nushell/crates/nu-std/std-rfc/path/mod.nu | 54 + nushell/crates/nu-std/std-rfc/str/mod.nu | 131 + nushell/crates/nu-std/std-rfc/tables/mod.nu | 204 + nushell/crates/nu-std/std/assert/mod.nu | 237 + nushell/crates/nu-std/std/bench/mod.nu | 173 + nushell/crates/nu-std/std/clip/mod.nu | 66 + nushell/crates/nu-std/std/config/mod.nu | 145 + nushell/crates/nu-std/std/dirs/mod.nu | 156 + nushell/crates/nu-std/std/dt/mod.nu | 263 + nushell/crates/nu-std/std/formats/mod.nu | 40 + nushell/crates/nu-std/std/help/mod.nu | 855 ++ nushell/crates/nu-std/std/input/mod.nu | 64 + nushell/crates/nu-std/std/iter/mod.nu | 143 + nushell/crates/nu-std/std/log/mod.nu | 323 + nushell/crates/nu-std/std/math/mod.nu | 5 + nushell/crates/nu-std/std/mod.nu | 36 + nushell/crates/nu-std/std/prelude/mod.nu | 54 + nushell/crates/nu-std/std/testing/mod.nu | 17 + nushell/crates/nu-std/std/util/mod.nu | 112 + nushell/crates/nu-std/std/xml/mod.nu | 217 + nushell/crates/nu-std/testing.nu | 382 + .../nu-std/tests/logger_tests/commons.nu | 20 + .../tests/logger_tests/test_basic_commands.nu | 98 + .../tests/logger_tests/test_log_custom.nu | 46 + .../logger_tests/test_log_format_flag.nu | 56 + .../tests/logger_tests/test_logger_env.nu | 45 + nushell/crates/nu-std/tests/test_asserts.nu | 82 + nushell/crates/nu-std/tests/test_dirs.nu | 188 + nushell/crates/nu-std/tests/test_dt.nu | 52 + nushell/crates/nu-std/tests/test_formats.nu | 145 + nushell/crates/nu-std/tests/test_help.nu | 15 + nushell/crates/nu-std/tests/test_iter.nu | 139 + nushell/crates/nu-std/tests/test_prelude.nu | 8 + .../nu-std/tests/test_setup_teardown.nu | 35 + .../nu-std/tests/test_std-rfc_conversions.nu | 111 + .../crates/nu-std/tests/test_std-rfc_iter.nu | 123 + .../crates/nu-std/tests/test_std-rfc_kv.nu | 304 + .../crates/nu-std/tests/test_std-rfc_path.nu | 39 + .../crates/nu-std/tests/test_std-rfc_str.nu | 293 + .../nu-std/tests/test_std-rfc_tables.nu | 332 + .../crates/nu-std/tests/test_std_formats.nu | 145 + .../crates/nu-std/tests/test_std_postload.nu | 12 + .../crates/nu-std/tests/test_std_preload.nu | 12 + nushell/crates/nu-std/tests/test_std_util.nu | 90 + nushell/crates/nu-std/tests/test_util.nu | 90 + nushell/crates/nu-std/tests/test_xml.nu | 48 + nushell/crates/nu-system/.gitignore | 1 + nushell/crates/nu-system/Cargo.toml | 51 + nushell/crates/nu-system/LICENSE | 21 + nushell/crates/nu-system/README.md | 7 + nushell/crates/nu-system/examples/sys_demo.rs | 31 + nushell/crates/nu-system/src/exit_status.rs | 64 + nushell/crates/nu-system/src/foreground.rs | 431 + nushell/crates/nu-system/src/freebsd.rs | 306 + nushell/crates/nu-system/src/lib.rs | 36 + nushell/crates/nu-system/src/linux.rs | 239 + nushell/crates/nu-system/src/macos.rs | 452 + nushell/crates/nu-system/src/netbsd.rs | 336 + nushell/crates/nu-system/src/os_info.rs | 18 + nushell/crates/nu-system/src/util.rs | 51 + nushell/crates/nu-system/src/windows.rs | 1069 ++ nushell/crates/nu-table/.gitignore | 22 + nushell/crates/nu-table/Cargo.toml | 26 + nushell/crates/nu-table/LICENSE | 21 + nushell/crates/nu-table/README.md | 7 + .../crates/nu-table/examples/table_demo.rs | 88 + nushell/crates/nu-table/src/common.rs | 226 + nushell/crates/nu-table/src/lib.rs | 17 + nushell/crates/nu-table/src/table.rs | 1155 +++ nushell/crates/nu-table/src/table_theme.rs | 189 + nushell/crates/nu-table/src/types/collapse.rs | 79 + nushell/crates/nu-table/src/types/expanded.rs | 684 ++ nushell/crates/nu-table/src/types/general.rs | 261 + nushell/crates/nu-table/src/types/mod.rs | 88 + .../crates/nu-table/src/unstructured_table.rs | 355 + nushell/crates/nu-table/src/util.rs | 183 + nushell/crates/nu-table/tests/common.rs | 118 + nushell/crates/nu-table/tests/constrains.rs | 306 + nushell/crates/nu-table/tests/expand.rs | 23 + nushell/crates/nu-table/tests/style.rs | 561 ++ nushell/crates/nu-term-grid/.gitignore | 22 + nushell/crates/nu-term-grid/Cargo.toml | 19 + nushell/crates/nu-term-grid/LICENSE | 22 + nushell/crates/nu-term-grid/README.md | 5 + .../crates/nu-term-grid/examples/grid_demo.rs | 30 + nushell/crates/nu-term-grid/src/grid.rs | 759 ++ nushell/crates/nu-term-grid/src/lib.rs | 4 + nushell/crates/nu-test-support/Cargo.toml | 24 + nushell/crates/nu-test-support/LICENSE | 21 + nushell/crates/nu-test-support/README.md | 7 + .../crates/nu-test-support/src/commands.rs | 72 + nushell/crates/nu-test-support/src/fs.rs | 115 + nushell/crates/nu-test-support/src/lib.rs | 100 + .../nu-test-support/src/locale_override.rs | 40 + nushell/crates/nu-test-support/src/macros.rs | 441 + .../crates/nu-test-support/src/playground.rs | 10 + .../src/playground/director.rs | 158 + .../src/playground/nu_process.rs | 99 + .../nu-test-support/src/playground/play.rs | 246 + .../nu-test-support/src/playground/tests.rs | 23 + .../tests/get_system_locale.rs | 21 + nushell/crates/nu-utils/.gitignore | 22 + nushell/crates/nu-utils/Cargo.toml | 42 + nushell/crates/nu-utils/LICENSE | 21 + nushell/crates/nu-utils/README.md | 6 + nushell/crates/nu-utils/src/casing.rs | 48 + nushell/crates/nu-utils/src/deansi.rs | 83 + .../nu-utils/src/default_files/README.md | 72 + .../src/default_files/default_config.nu | 68 + .../nu-utils/src/default_files/default_env.nu | 36 + .../nu-utils/src/default_files/doc_config.nu | 968 ++ .../nu-utils/src/default_files/doc_env.nu | 11 + .../src/default_files/scaffold_config.nu | 18 + .../src/default_files/scaffold_env.nu | 18 + nushell/crates/nu-utils/src/emoji.rs | 16 + nushell/crates/nu-utils/src/filesystem.rs | 156 + nushell/crates/nu-utils/src/flatten_json.rs | 259 + nushell/crates/nu-utils/src/lib.rs | 29 + nushell/crates/nu-utils/src/locale.rs | 42 + nushell/crates/nu-utils/src/main.rs | 10 + nushell/crates/nu-utils/src/quoting.rs | 43 + nushell/crates/nu-utils/src/shared_cow.rs | 113 + nushell/crates/nu-utils/src/utils.rs | 490 + .../crates/nu_plugin_custom_values/Cargo.toml | 19 + .../src/cool_custom_value.rs | 157 + .../nu_plugin_custom_values/src/drop_check.rs | 88 + .../nu_plugin_custom_values/src/generate.rs | 47 + .../nu_plugin_custom_values/src/generate2.rs | 71 + .../src/handle_custom_value.rs | 42 + .../nu_plugin_custom_values/src/handle_get.rs | 61 + .../src/handle_make.rs | 47 + .../src/handle_update.rs | 90 + .../nu_plugin_custom_values/src/main.rs | 107 + .../src/second_custom_value.rs | 81 + .../nu_plugin_custom_values/src/update.rs | 72 + .../nu_plugin_custom_values/src/update_arg.rs | 37 + nushell/crates/nu_plugin_example/Cargo.toml | 23 + nushell/crates/nu_plugin_example/README.md | 36 + .../src/commands/call_decl.rs | 78 + .../src/commands/collect_bytes.rs | 67 + .../nu_plugin_example/src/commands/config.rs | 80 + .../nu_plugin_example/src/commands/ctrlc.rs | 50 + .../src/commands/disable_gc.rs | 58 + .../nu_plugin_example/src/commands/echo.rs | 55 + .../nu_plugin_example/src/commands/env.rs | 79 + .../src/commands/for_each.rs | 64 + .../src/commands/generate.rs | 99 + .../nu_plugin_example/src/commands/main.rs | 47 + .../nu_plugin_example/src/commands/mod.rs | 43 + .../nu_plugin_example/src/commands/one.rs | 65 + .../nu_plugin_example/src/commands/seq.rs | 66 + .../nu_plugin_example/src/commands/sum.rs | 107 + .../nu_plugin_example/src/commands/three.rs | 44 + .../nu_plugin_example/src/commands/two.rs | 62 + .../src/commands/view_span.rs | 58 + .../crates/nu_plugin_example/src/example.rs | 53 + nushell/crates/nu_plugin_example/src/lib.rs | 41 + nushell/crates/nu_plugin_example/src/main.rs | 30 + nushell/crates/nu_plugin_formats/Cargo.toml | 23 + nushell/crates/nu_plugin_formats/README.md | 18 + .../crates/nu_plugin_formats/src/from/eml.rs | 180 + .../crates/nu_plugin_formats/src/from/ics.rs | 278 + .../crates/nu_plugin_formats/src/from/ini.rs | 105 + .../crates/nu_plugin_formats/src/from/mod.rs | 5 + .../nu_plugin_formats/src/from/plist.rs | 241 + .../crates/nu_plugin_formats/src/from/vcf.rs | 168 + nushell/crates/nu_plugin_formats/src/lib.rs | 30 + nushell/crates/nu_plugin_formats/src/main.rs | 6 + .../crates/nu_plugin_formats/src/to/mod.rs | 1 + .../crates/nu_plugin_formats/src/to/plist.rs | 111 + nushell/crates/nu_plugin_gstat/Cargo.toml | 22 + nushell/crates/nu_plugin_gstat/README.md | 13 + nushell/crates/nu_plugin_gstat/src/gstat.rs | 377 + nushell/crates/nu_plugin_gstat/src/lib.rs | 5 + nushell/crates/nu_plugin_gstat/src/main.rs | 6 + nushell/crates/nu_plugin_gstat/src/nu/mod.rs | 49 + nushell/crates/nu_plugin_inc/Cargo.toml | 22 + nushell/crates/nu_plugin_inc/README.md | 13 + nushell/crates/nu_plugin_inc/src/inc.rs | 156 + nushell/crates/nu_plugin_inc/src/lib.rs | 5 + nushell/crates/nu_plugin_inc/src/main.rs | 6 + nushell/crates/nu_plugin_inc/src/nu/mod.rs | 73 + .../nu_plugin_node_example.js | 248 + .../nu_plugin_nu_example.nu | 267 + nushell/crates/nu_plugin_polars/Cargo.toml | 110 + nushell/crates/nu_plugin_polars/LICENSE | 21 + .../crates/nu_plugin_polars/src/cache/get.rs | 99 + .../crates/nu_plugin_polars/src/cache/list.rs | 172 + .../crates/nu_plugin_polars/src/cache/mod.rs | 254 + .../crates/nu_plugin_polars/src/cache/rm.rs | 106 + .../crates/nu_plugin_polars/src/cloud/aws.rs | 67 + .../crates/nu_plugin_polars/src/cloud/mod.rs | 28 + .../nu_plugin_polars/src/dataframe/README.md | 12 + .../command/aggregation/agg_groups.rs | 94 + .../command/aggregation/aggregate.rs | 219 + .../dataframe/command/aggregation/count.rs | 89 + .../command/aggregation/cumulative.rs | 254 + .../dataframe/command/aggregation/groupby.rs | 158 + .../command/aggregation/horizontal.rs | 191 + .../dataframe/command/aggregation/implode.rs | 90 + .../src/dataframe/command/aggregation/max.rs | 143 + .../src/dataframe/command/aggregation/mean.rs | 143 + .../dataframe/command/aggregation/median.rs | 137 + .../src/dataframe/command/aggregation/min.rs | 143 + .../src/dataframe/command/aggregation/mod.rs | 66 + .../dataframe/command/aggregation/n_null.rs | 93 + .../dataframe/command/aggregation/n_unique.rs | 133 + .../src/dataframe/command/aggregation/over.rs | 129 + .../dataframe/command/aggregation/quantile.rs | 156 + .../dataframe/command/aggregation/rolling.rs | 190 + .../src/dataframe/command/aggregation/std.rs | 135 + .../src/dataframe/command/aggregation/sum.rs | 143 + .../command/aggregation/value_counts.rs | 120 + .../src/dataframe/command/aggregation/var.rs | 138 + .../dataframe/command/boolean/all_false.rs | 118 + .../src/dataframe/command/boolean/all_true.rs | 118 + .../src/dataframe/command/boolean/arg_true.rs | 126 + .../src/dataframe/command/boolean/expr_not.rs | 100 + .../command/boolean/is_duplicated.rs | 132 + .../src/dataframe/command/boolean/is_in.rs | 135 + .../dataframe/command/boolean/is_not_null.rs | 128 + .../src/dataframe/command/boolean/is_null.rs | 130 + .../dataframe/command/boolean/is_unique.rs | 132 + .../src/dataframe/command/boolean/mod.rs | 46 + .../src/dataframe/command/boolean/not.rs | 103 + .../dataframe/command/boolean/otherwise.rs | 125 + .../src/dataframe/command/boolean/set.rs | 209 + .../src/dataframe/command/boolean/when.rs | 154 + .../src/dataframe/command/computation/math.rs | 255 + .../src/dataframe/command/computation/mod.rs | 10 + .../src/dataframe/command/core/cache.rs | 79 + .../src/dataframe/command/core/columns.rs | 82 + .../src/dataframe/command/core/fetch.rs | 104 + .../src/dataframe/command/core/mod.rs | 48 + .../src/dataframe/command/core/open.rs | 655 ++ .../src/dataframe/command/core/profile.rs | 111 + .../src/dataframe/command/core/resource.rs | 85 + .../src/dataframe/command/core/save/arrow.rs | 75 + .../src/dataframe/command/core/save/avro.rs | 75 + .../src/dataframe/command/core/save/csv.rs | 127 + .../src/dataframe/command/core/save/mod.rs | 360 + .../src/dataframe/command/core/save/ndjson.rs | 76 + .../dataframe/command/core/save/parquet.rs | 76 + .../src/dataframe/command/core/schema.rs | 97 + .../src/dataframe/command/core/shape.rs | 90 + .../src/dataframe/command/core/summary.rs | 254 + .../src/dataframe/command/core/to_df.rs | 320 + .../src/dataframe/command/core/to_dtype.rs | 68 + .../src/dataframe/command/core/to_lazy.rs | 121 + .../src/dataframe/command/core/to_nu.rs | 162 + .../src/dataframe/command/core/to_repr.rs | 113 + .../src/dataframe/command/core/to_schema.rs | 74 + .../src/dataframe/command/data/alias.rs | 88 + .../src/dataframe/command/data/append.rs | 144 + .../src/dataframe/command/data/arg_where.rs | 82 + .../src/dataframe/command/data/cast.rs | 203 + .../src/dataframe/command/data/col.rs | 176 + .../src/dataframe/command/data/collect.rs | 117 + .../src/dataframe/command/data/concat.rs | 172 + .../src/dataframe/command/data/cut.rs | 92 + .../src/dataframe/command/data/drop.rs | 129 + .../dataframe/command/data/drop_duplicates.rs | 132 + .../src/dataframe/command/data/drop_nulls.rs | 152 + .../src/dataframe/command/data/dummies.rs | 116 + .../src/dataframe/command/data/explode.rs | 191 + .../src/dataframe/command/data/fill_nan.rs | 187 + .../src/dataframe/command/data/fill_null.rs | 126 + .../src/dataframe/command/data/filter.rs | 204 + .../src/dataframe/command/data/filter_with.rs | 164 + .../src/dataframe/command/data/first.rs | 198 + .../src/dataframe/command/data/flatten.rs | 136 + .../src/dataframe/command/data/get.rs | 104 + .../src/dataframe/command/data/join.rs | 350 + .../src/dataframe/command/data/join_where.rs | 119 + .../src/dataframe/command/data/last.rs | 172 + .../src/dataframe/command/data/len.rs | 76 + .../src/dataframe/command/data/lit.rs | 96 + .../src/dataframe/command/data/mod.rs | 126 + .../src/dataframe/command/data/pivot.rs | 351 + .../src/dataframe/command/data/qcut.rs | 101 + .../src/dataframe/command/data/query_df.rs | 112 + .../src/dataframe/command/data/rename.rs | 204 + .../src/dataframe/command/data/replace.rs | 335 + .../src/dataframe/command/data/reverse.rs | 82 + .../src/dataframe/command/data/sample.rs | 170 + .../src/dataframe/command/data/select.rs | 130 + .../src/dataframe/command/data/shift.rs | 217 + .../src/dataframe/command/data/slice.rs | 94 + .../dataframe/command/data/sort_by_expr.rs | 177 + .../src/dataframe/command/data/sql_context.rs | 229 + .../src/dataframe/command/data/sql_expr.rs | 201 + .../command/data/struct_json_encode.rs | 67 + .../src/dataframe/command/data/take.rs | 162 + .../src/dataframe/command/data/unique.rs | 270 + .../src/dataframe/command/data/unnest.rs | 147 + .../src/dataframe/command/data/unpivot.rs | 342 + .../src/dataframe/command/data/with_column.rs | 287 + .../src/dataframe/command/datetime/as_date.rs | 296 + .../dataframe/command/datetime/as_datetime.rs | 406 + .../command/datetime/convert_time_zone.rs | 175 + .../dataframe/command/datetime/datepart.rs | 175 + .../src/dataframe/command/datetime/get_day.rs | 170 + .../dataframe/command/datetime/get_hour.rs | 178 + .../dataframe/command/datetime/get_minute.rs | 162 + .../dataframe/command/datetime/get_month.rs | 162 + .../command/datetime/get_nanosecond.rs | 162 + .../dataframe/command/datetime/get_ordinal.rs | 165 + .../dataframe/command/datetime/get_second.rs | 162 + .../dataframe/command/datetime/get_week.rs | 162 + .../dataframe/command/datetime/get_weekday.rs | 162 + .../dataframe/command/datetime/get_year.rs | 162 + .../src/dataframe/command/datetime/mod.rs | 104 + .../command/datetime/replace_time_zone.rs | 298 + .../dataframe/command/datetime/strftime.rs | 173 + .../dataframe/command/datetime/truncate.rs | 215 + .../src/dataframe/command/index/arg_max.rs | 93 + .../src/dataframe/command/index/arg_min.rs | 93 + .../src/dataframe/command/index/arg_sort.rs | 139 + .../src/dataframe/command/index/arg_unique.rs | 101 + .../src/dataframe/command/index/mod.rs | 24 + .../dataframe/command/index/set_with_idx.rs | 226 + .../src/dataframe/command/integer/mod.rs | 12 + .../dataframe/command/integer/to_decimal.rs | 108 + .../dataframe/command/integer/to_integer.rs | 94 + .../src/dataframe/command/list/contains.rs | 167 + .../src/dataframe/command/list/mod.rs | 10 + .../src/dataframe/command/mod.rs | 11 + .../dataframe/command/string/concat_str.rs | 112 + .../src/dataframe/command/string/contains.rs | 181 + .../src/dataframe/command/string/mod.rs | 40 + .../src/dataframe/command/string/str_join.rs | 179 + .../dataframe/command/string/str_lengths.rs | 163 + .../dataframe/command/string/str_replace.rs | 196 + .../command/string/str_replace_all.rs | 200 + .../src/dataframe/command/string/str_slice.rs | 208 + .../src/dataframe/command/string/str_split.rs | 94 + .../command/string/str_strip_chars.rs | 192 + .../dataframe/command/string/to_lowercase.rs | 155 + .../dataframe/command/string/to_uppercase.rs | 159 + .../src/dataframe/command/stub.rs | 56 + .../nu_plugin_polars/src/dataframe/mod.rs | 15 + .../nu_plugin_polars/src/dataframe/utils.rs | 32 + .../src/dataframe/values/file_type.rs | 63 + .../src/dataframe/values/mod.rs | 611 ++ .../values/nu_dataframe/between_values.rs | 912 ++ .../values/nu_dataframe/conversion.rs | 1937 ++++ .../values/nu_dataframe/custom_value.rs | 124 + .../src/dataframe/values/nu_dataframe/mod.rs | 567 ++ .../values/nu_dataframe/operations.rs | 212 + .../dataframe/values/nu_dtype/custom_value.rs | 65 + .../src/dataframe/values/nu_dtype/mod.rs | 355 + .../values/nu_expression/custom_value.rs | 223 + .../src/dataframe/values/nu_expression/mod.rs | 588 ++ .../values/nu_lazyframe/custom_value.rs | 122 + .../src/dataframe/values/nu_lazyframe/mod.rs | 184 + .../values/nu_lazygroupby/custom_value.rs | 63 + .../dataframe/values/nu_lazygroupby/mod.rs | 92 + .../values/nu_schema/custom_value.rs | 65 + .../src/dataframe/values/nu_schema/mod.rs | 173 + .../dataframe/values/nu_when/custom_value.rs | 65 + .../src/dataframe/values/nu_when/mod.rs | 128 + .../src/dataframe/values/utils.rs | 128 + nushell/crates/nu_plugin_polars/src/lib.rs | 341 + nushell/crates/nu_plugin_polars/src/main.rs | 21 + .../nu_plugin_python_example.py | 268 + nushell/crates/nu_plugin_query/Cargo.toml | 28 + nushell/crates/nu_plugin_query/README.md | 13 + nushell/crates/nu_plugin_query/src/lib.rs | 12 + nushell/crates/nu_plugin_query/src/main.rs | 6 + nushell/crates/nu_plugin_query/src/query.rs | 60 + .../crates/nu_plugin_query/src/query_json.rs | 218 + .../crates/nu_plugin_query/src/query_web.rs | 557 ++ .../nu_plugin_query/src/query_webpage_info.rs | 470 + .../crates/nu_plugin_query/src/query_xml.rs | 246 + .../crates/nu_plugin_query/src/web_tables.rs | 1290 +++ .../nu_plugin_stress_internals/Cargo.toml | 19 + .../crates/nu_plugin_stress_internals/LICENSE | 21 + .../nu_plugin_stress_internals/src/main.rs | 227 + nushell/crates/nuon/Cargo.toml | 22 + nushell/crates/nuon/LICENSE | 21 + nushell/crates/nuon/README.md | 35 + nushell/crates/nuon/src/from.rs | 466 + nushell/crates/nuon/src/lib.rs | 512 + nushell/crates/nuon/src/to.rs | 279 + nushell/devdocs/FAQ.md | 40 + nushell/devdocs/HOWTOS.md | 42 + nushell/devdocs/PLATFORM_SUPPORT.md | 65 + nushell/devdocs/README.md | 12 + nushell/devdocs/rust_style.md | 51 + nushell/docker/Dockerfile | 55 + nushell/docker/debian.Dockerfile | 58 + nushell/docker/test_docker.nu | 153 + nushell/rust-toolchain.toml | 19 + nushell/scripts/README.md | 26 + nushell/scripts/build-all-maclin.sh | 36 + nushell/scripts/build-all-windows.cmd | 30 + nushell/scripts/build-all.nu | 41 + nushell/scripts/build.rs | 26 + nushell/scripts/coverage-local.nu | 63 + nushell/scripts/coverage-local.sh | 44 + nushell/scripts/install-all.ps1 | 32 + nushell/scripts/install-all.sh | 34 + nushell/scripts/test_virtualenv.nu | 57 + nushell/scripts/uninstall-all.sh | 24 + nushell/src/README.md | 5 + nushell/src/command.rs | 498 + nushell/src/command_context.rs | 239 + nushell/src/config_files.rs | 297 + nushell/src/ide.rs | 685 ++ nushell/src/logger.rs | 138 + nushell/src/main.rs | 543 + nushell/src/run.rs | 217 + nushell/src/signals.rs | 19 + nushell/src/terminal.rs | 148 + nushell/src/test_bins.rs | 369 + .../tests/assets/nu_json/charset_result.hjson | 5 + .../tests/assets/nu_json/charset_result.json | 5 + .../tests/assets/nu_json/charset_test.hjson | 6 + .../assets/nu_json/comments_result.hjson | 26 + .../tests/assets/nu_json/comments_result.json | 26 + .../tests/assets/nu_json/comments_test.hjson | 48 + .../tests/assets/nu_json/empty_result.hjson | 3 + .../tests/assets/nu_json/empty_result.json | 3 + nushell/tests/assets/nu_json/empty_test.hjson | 3 + .../assets/nu_json/failCharset1_test.hjson | 4 + .../tests/assets/nu_json/failJSON02_test.json | 1 + .../tests/assets/nu_json/failJSON05_test.json | 1 + .../tests/assets/nu_json/failJSON06_test.json | 1 + .../tests/assets/nu_json/failJSON07_test.json | 1 + .../tests/assets/nu_json/failJSON08_test.json | 1 + .../tests/assets/nu_json/failJSON10_test.json | 1 + .../tests/assets/nu_json/failJSON11_test.json | 1 + .../tests/assets/nu_json/failJSON12_test.json | 1 + .../tests/assets/nu_json/failJSON13_test.json | 1 + .../tests/assets/nu_json/failJSON14_test.json | 1 + .../tests/assets/nu_json/failJSON15_test.json | 1 + .../tests/assets/nu_json/failJSON16_test.json | 1 + .../tests/assets/nu_json/failJSON17_test.json | 1 + .../tests/assets/nu_json/failJSON19_test.json | 1 + .../tests/assets/nu_json/failJSON20_test.json | 1 + .../tests/assets/nu_json/failJSON21_test.json | 1 + .../tests/assets/nu_json/failJSON22_test.json | 1 + .../tests/assets/nu_json/failJSON23_test.json | 1 + .../tests/assets/nu_json/failJSON24_test.json | 1 + .../tests/assets/nu_json/failJSON26_test.json | 1 + .../tests/assets/nu_json/failJSON28_test.json | 2 + .../tests/assets/nu_json/failJSON29_test.json | 1 + .../tests/assets/nu_json/failJSON30_test.json | 1 + .../tests/assets/nu_json/failJSON31_test.json | 1 + .../tests/assets/nu_json/failJSON32_test.json | 1 + .../tests/assets/nu_json/failJSON33_test.json | 1 + .../tests/assets/nu_json/failJSON34_test.json | 2 + .../tests/assets/nu_json/failKey1_test.hjson | 4 + .../tests/assets/nu_json/failKey2_test.hjson | 4 + .../tests/assets/nu_json/failKey3_test.hjson | 4 + .../tests/assets/nu_json/failKey4_test.hjson | 4 + .../assets/nu_json/failMLStr1_test.hjson | 3 + .../tests/assets/nu_json/failObj1_test.hjson | 6 + .../tests/assets/nu_json/failObj2_test.hjson | 6 + .../tests/assets/nu_json/failObj3_test.hjson | 7 + .../tests/assets/nu_json/failStr1a_test.hjson | 4 + .../tests/assets/nu_json/failStr1b_test.hjson | 4 + .../tests/assets/nu_json/failStr1c_test.hjson | 5 + .../tests/assets/nu_json/failStr1d_test.hjson | 5 + .../tests/assets/nu_json/failStr2a_test.hjson | 4 + .../tests/assets/nu_json/failStr2b_test.hjson | 4 + .../tests/assets/nu_json/failStr2c_test.hjson | 5 + .../tests/assets/nu_json/failStr2d_test.hjson | 5 + .../tests/assets/nu_json/failStr3a_test.hjson | 4 + .../tests/assets/nu_json/failStr3b_test.hjson | 4 + .../tests/assets/nu_json/failStr3c_test.hjson | 5 + .../tests/assets/nu_json/failStr3d_test.hjson | 5 + .../tests/assets/nu_json/failStr4a_test.hjson | 4 + .../tests/assets/nu_json/failStr4b_test.hjson | 4 + .../tests/assets/nu_json/failStr4c_test.hjson | 5 + .../tests/assets/nu_json/failStr4d_test.hjson | 5 + .../tests/assets/nu_json/failStr5a_test.hjson | 4 + .../tests/assets/nu_json/failStr5b_test.hjson | 4 + .../tests/assets/nu_json/failStr5c_test.hjson | 5 + .../tests/assets/nu_json/failStr5d_test.hjson | 5 + .../tests/assets/nu_json/failStr6a_test.hjson | 4 + .../tests/assets/nu_json/failStr6b_test.hjson | 4 + .../tests/assets/nu_json/failStr6c_test.hjson | 6 + .../tests/assets/nu_json/failStr6d_test.hjson | 6 + nushell/tests/assets/nu_json/kan_result.hjson | 48 + nushell/tests/assets/nu_json/kan_result.json | 45 + nushell/tests/assets/nu_json/kan_test.hjson | 49 + .../tests/assets/nu_json/keys_result.hjson | 34 + nushell/tests/assets/nu_json/keys_result.json | 34 + nushell/tests/assets/nu_json/keys_test.hjson | 48 + nushell/tests/assets/nu_json/oa_result.hjson | 13 + nushell/tests/assets/nu_json/oa_result.json | 13 + nushell/tests/assets/nu_json/oa_test.hjson | 13 + .../tests/assets/nu_json/pass1_result.hjson | 78 + .../tests/assets/nu_json/pass1_result.json | 75 + nushell/tests/assets/nu_json/pass1_test.json | 58 + .../tests/assets/nu_json/pass2_result.hjson | 39 + .../tests/assets/nu_json/pass2_result.json | 39 + nushell/tests/assets/nu_json/pass2_test.json | 1 + .../tests/assets/nu_json/pass3_result.hjson | 7 + .../tests/assets/nu_json/pass3_result.json | 6 + nushell/tests/assets/nu_json/pass3_test.json | 6 + .../tests/assets/nu_json/pass4_result.hjson | 1 + .../tests/assets/nu_json/pass4_result.json | 1 + nushell/tests/assets/nu_json/pass4_test.json | 2 + .../assets/nu_json/passSingle_result.hjson | 1 + .../assets/nu_json/passSingle_result.json | 1 + .../assets/nu_json/passSingle_test.hjson | 1 + .../tests/assets/nu_json/root_result.hjson | 7 + nushell/tests/assets/nu_json/root_result.json | 6 + nushell/tests/assets/nu_json/root_test.hjson | 6 + .../assets/nu_json/stringify1_result.hjson | 49 + .../assets/nu_json/stringify1_result.json | 47 + .../assets/nu_json/stringify1_test.hjson | 50 + .../tests/assets/nu_json/strings_result.hjson | 75 + .../tests/assets/nu_json/strings_result.json | 55 + .../tests/assets/nu_json/strings_test.hjson | 80 + nushell/tests/assets/nu_json/testlist.txt | 75 + .../tests/assets/nu_json/trail_result.hjson | 3 + .../tests/assets/nu_json/trail_result.json | 3 + nushell/tests/assets/nu_json/trail_test.hjson | 2 + nushell/tests/const_/mod.rs | 447 + nushell/tests/eval/mod.rs | 471 + .../tests/fixtures/completions/.hidden_file | 0 .../.hidden_folder/.hidden_subfile | 0 .../fixtures/completions/another/newfile | 0 .../fixtures/completions/custom_completion.nu | 2 + .../folder_inside_folder/myfile | 0 .../completions/directory_completion/mod.nu | 0 nushell/tests/fixtures/completions/nushell | 0 .../tests/fixtures/completions/test_a/myfile | 0 .../tests/fixtures/completions/test_a_symlink | 1 + .../fixtures/completions/test_b/testfile | 0 nushell/tests/fixtures/cp/dir_with_10_files/0 | 0 nushell/tests/fixtures/cp/dir_with_10_files/1 | 0 nushell/tests/fixtures/cp/dir_with_10_files/2 | 0 nushell/tests/fixtures/cp/dir_with_10_files/3 | 0 nushell/tests/fixtures/cp/dir_with_10_files/4 | 0 nushell/tests/fixtures/cp/dir_with_10_files/5 | 0 nushell/tests/fixtures/cp/dir_with_10_files/6 | 0 nushell/tests/fixtures/cp/dir_with_10_files/7 | 0 nushell/tests/fixtures/cp/dir_with_10_files/8 | 0 nushell/tests/fixtures/cp/dir_with_10_files/9 | 0 .../fixtures/cp/dir_with_mount/copy_me.txt | 0 .../cp/dir_with_mount/copy_me/copy_me.txt | 0 nushell/tests/fixtures/cp/existing_file.txt | 1 + nushell/tests/fixtures/cp/hello_dir/hello.txt | 0 .../cp/hello_dir_with_file/hello_world.txt | 1 + nushell/tests/fixtures/cp/hello_world.txt | 1 + nushell/tests/fixtures/cp/how_are_you.txt | 1 + .../dotnu_completions/dir_module/mod.nu | 0 .../dotnu_completions/dir_module/plain.txt | 0 .../dir_module/sub module/sub.nu | 0 .../tests/fixtures/dotnu_completions/foo.nu | 0 .../dotnu_completions/lib-dir1/bar.nu | 0 .../dotnu_completions/lib-dir1/baz.nu | 0 .../dotnu_completions/lib-dir1/xyzzy.nu | 0 .../dotnu_completions/lib-dir2/asdf.nu | 0 .../dotnu_completions/lib-dir2/bat.nu | 0 .../dotnu_completions/lib-dir3/spam.nu | 0 nushell/tests/fixtures/eval/script.nu | 9 + .../dir with space/bar baz | 0 .../external_completions/dir with space/foo | 0 .../fixtures/external_completions/path/sleep | 0 .../external_completions/path/sleep.exe | 0 .../tests/fixtures/formats/activate-foo.nu | 1 + nushell/tests/fixtures/formats/appveyor.yml | 31 + .../fixtures/formats/caco3_plastics.arrow | Bin 0 -> 4663 bytes .../tests/fixtures/formats/caco3_plastics.csv | 10 + .../tests/fixtures/formats/caco3_plastics.tsv | 10 + .../tests/fixtures/formats/cargo_sample.toml | 55 + nushell/tests/fixtures/formats/code.nu | 1 + .../tests/fixtures/formats/early_return.nu | 3 + .../formats/early_return_outside_main.nu | 7 + nushell/tests/fixtures/formats/jt.xml | 22 + nushell/tests/fixtures/formats/lines_test.txt | 2 + .../tests/fixtures/formats/msgpack/.gitignore | 2 + .../fixtures/formats/msgpack/generate.nu | 130 + .../fixtures/formats/msgpack/objects.nuon | 6 + .../fixtures/formats/msgpack/sample.nuon | 53 + .../tests/fixtures/formats/random_numbers.csv | 51 + .../fixtures/formats/sample-ls-output.json | 1 + .../fixtures/formats/sample-ps-output.json | 1 + .../tests/fixtures/formats/sample-simple.json | 4 + .../fixtures/formats/sample-sys-output.json | 125 + .../formats/sample.blockcommandparser | 2 + nushell/tests/fixtures/formats/sample.db | Bin 0 -> 16384 bytes nushell/tests/fixtures/formats/sample.eml | 20 + nushell/tests/fixtures/formats/sample.ini | 19 + nushell/tests/fixtures/formats/sample.nuon | 20 + nushell/tests/fixtures/formats/sample.url | 1 + .../tests/fixtures/formats/sample_data.ods | Bin 0 -> 49626 bytes .../tests/fixtures/formats/sample_data.xlsx | Bin 0 -> 65801 bytes .../formats/sample_data_with_annotation.ods | Bin 0 -> 71562 bytes nushell/tests/fixtures/formats/sample_def.nu | 3 + .../fixtures/formats/sample_headers.xlsx | Bin 0 -> 4807 bytes nushell/tests/fixtures/formats/script.nu | 2 + .../fixtures/formats/script_multiline.nu | 2 + .../fixtures/formats/sgml_description.json | 30 + nushell/tests/fixtures/formats/utf16.ini | Bin 0 -> 504 bytes .../fixtures/lsp/completion/cell_path.nu | 2 + .../tests/fixtures/lsp/completion/command.nu | 14 + .../tests/fixtures/lsp/completion/external.nu | 1 + .../tests/fixtures/lsp/completion/fallback.nu | 8 + .../tests/fixtures/lsp/completion/keyword.nu | 1 + nushell/tests/fixtures/lsp/completion/use.nu | 8 + .../fixtures/lsp/completion/utf_pipeline.nu | 1 + nushell/tests/fixtures/lsp/completion/var.nu | 3 + nushell/tests/fixtures/lsp/diagnostics/pwd.nu | 1 + nushell/tests/fixtures/lsp/diagnostics/var.nu | 1 + nushell/tests/fixtures/lsp/goto/collect.nu | 2 + nushell/tests/fixtures/lsp/goto/command.nu | 5 + .../fixtures/lsp/goto/command_unicode.nu | 5 + nushell/tests/fixtures/lsp/goto/else.nu | 2 + nushell/tests/fixtures/lsp/goto/match.nu | 5 + nushell/tests/fixtures/lsp/goto/module.nu | 4 + nushell/tests/fixtures/lsp/goto/use_module.nu | 4 + nushell/tests/fixtures/lsp/goto/var.nu | 3 + .../tests/fixtures/lsp/hints/assignment.nu | 9 + nushell/tests/fixtures/lsp/hints/param.nu | 13 + nushell/tests/fixtures/lsp/hints/signature.nu | 17 + nushell/tests/fixtures/lsp/hints/type.nu | 8 + nushell/tests/fixtures/lsp/hover/cell_path.nu | 5 + nushell/tests/fixtures/lsp/hover/command.nu | 11 + nushell/tests/fixtures/lsp/hover/use.nu | 4 + nushell/tests/fixtures/lsp/hover/var.nu | 3 + .../fixtures/lsp/notifications/issue_11522.nu | 6 + .../fixtures/lsp/semantic_tokens/internals.nu | 18 + nushell/tests/fixtures/lsp/symbols/bar.nu | 5 + nushell/tests/fixtures/lsp/symbols/foo.nu | 6 + nushell/tests/fixtures/lsp/symbols/span.nu | 3 + nushell/tests/fixtures/lsp/workspace/bar.nu | 7 + nushell/tests/fixtures/lsp/workspace/baz.nu | 12 + nushell/tests/fixtures/lsp/workspace/foo.nu | 24 + .../final_partial/somefile | 0 .../partial_completions/partial-a/anotherfile | 0 .../partial-a/have_ext.exe | 0 .../partial-a/have_ext.txt | 0 .../partial_completions/partial-a/hello | 0 .../partial-a/hola/foo.txt | 0 .../partial_completions/partial-b/hello_b | 0 .../partial_completions/partial-b/hi_b | 0 .../partial_completions/partial-c/hello_c | 0 .../partial_completions/partial-d(/.gitkeep | 0 .../partial_completions/partial/hello.txt | 0 .../partial_completions/partial/hol/foo.txt | 0 .../tests/fixtures/quoted_completions/--help | 0 nushell/tests/fixtures/quoted_completions/-42 | 0 .../tests/fixtures/quoted_completions/-inf | 0 nushell/tests/fixtures/quoted_completions/4.2 | 0 .../fixtures/quoted_completions/[a] bc.txt | 0 .../quoted_completions/curly-bracket_{.txt | 0 .../quoted_completions/semicolon_;.txt | 0 .../quoted_completions/square-bracket_[.txt | 0 .../fixtures/quoted_completions/te st.txt | 0 .../fixtures/quoted_completions/te#st.txt | 0 .../fixtures/quoted_completions/te'st.txt | 0 .../fixtures/quoted_completions/te(st).txt | 0 .../quoted_completions/test dir/double quote | 0 .../quoted_completions/test dir/single quote | 0 nushell/tests/hooks/mod.rs | 566 ++ nushell/tests/hooks/samples/.nu-env | 1 + nushell/tests/main.rs | 16 + nushell/tests/modules/mod.rs | 945 ++ .../modules/samples/missing_mod_nu/test.nu | 0 nushell/tests/modules/samples/spam.nu | 1 + .../modules/samples/spam/bacon/beans/foo.nu | 1 + .../modules/samples/spam/bacon/beans/mod.nu | 5 + .../tests/modules/samples/spam/bacon/foo.nu | 1 + .../tests/modules/samples/spam/bacon/mod.nu | 6 + nushell/tests/modules/samples/spam/bar.nu | 3 + nushell/tests/modules/samples/spam/eggs.nu | 1 + nushell/tests/modules/samples/spam/foo.nu | 3 + nushell/tests/modules/samples/spam/mod.nu | 8 + nushell/tests/overlays/mod.rs | 1540 +++ nushell/tests/overlays/samples/spam.nu | 5 + nushell/tests/parsing/mod.rs | 369 + .../parsing/samples/multiline_end_pipe.nu | 2 + .../parsing/samples/multiline_end_pipe_win.nu | 2 + .../parsing/samples/multiline_start_pipe.nu | 2 + .../samples/multiline_start_pipe_win.nu | 2 + .../samples/recursive_func_with_alias.nu | 22 + nushell/tests/parsing/samples/single_line.nu | 1 + .../parsing/samples/source_circular_1.nu | 1 + .../parsing/samples/source_circular_2.nu | 1 + .../parsing/samples/source_file_relative.nu | 1 + nushell/tests/path/canonicalize.rs | 439 + nushell/tests/path/expand_path.rs | 254 + nushell/tests/path/mod.rs | 2 + nushell/tests/plugin_persistence/mod.rs | 390 + nushell/tests/plugins/call_decl.rs | 42 + nushell/tests/plugins/config.rs | 37 + nushell/tests/plugins/core_inc.rs | 163 + nushell/tests/plugins/custom_values.rs | 253 + nushell/tests/plugins/env.rs | 65 + nushell/tests/plugins/formats/eml.rs | 66 + nushell/tests/plugins/formats/ics.rs | 144 + nushell/tests/plugins/formats/ini.rs | 59 + nushell/tests/plugins/formats/mod.rs | 4 + nushell/tests/plugins/formats/vcf.rs | 123 + nushell/tests/plugins/mod.rs | 11 + nushell/tests/plugins/nu_plugin_nu_example.rs | 42 + nushell/tests/plugins/register.rs | 29 + nushell/tests/plugins/registry_file.rs | 518 + nushell/tests/plugins/stream.rs | 208 + nushell/tests/plugins/stress_internals.rs | 149 + nushell/tests/repl/mod.rs | 27 + nushell/tests/repl/test_bits.rs | 367 + nushell/tests/repl/test_cell_path.rs | 156 + nushell/tests/repl/test_commandline.rs | 142 + nushell/tests/repl/test_conditionals.rs | 77 + nushell/tests/repl/test_config.rs | 170 + nushell/tests/repl/test_config_path.rs | 401 + nushell/tests/repl/test_converters.rs | 55 + nushell/tests/repl/test_custom_commands.rs | 310 + nushell/tests/repl/test_engine.rs | 480 + nushell/tests/repl/test_env.rs | 49 + nushell/tests/repl/test_help.rs | 27 + nushell/tests/repl/test_hiding.rs | 407 + nushell/tests/repl/test_ide.rs | 10 + nushell/tests/repl/test_iteration.rs | 41 + nushell/tests/repl/test_known_external.rs | 175 + nushell/tests/repl/test_math.rs | 233 + nushell/tests/repl/test_modules.rs | 209 + nushell/tests/repl/test_parser.rs | 1024 ++ nushell/tests/repl/test_ranges.rs | 76 + nushell/tests/repl/test_regex.rs | 82 + nushell/tests/repl/test_signatures.rs | 379 + nushell/tests/repl/test_spread.rs | 202 + nushell/tests/repl/test_stdlib.rs | 11 + nushell/tests/repl/test_strings.rs | 177 + nushell/tests/repl/test_table_operations.rs | 313 + nushell/tests/repl/test_type_check.rs | 180 + nushell/tests/repl/tests.rs | 164 + nushell/tests/scope/mod.rs | 332 + nushell/tests/shell/environment/env.rs | 302 + nushell/tests/shell/environment/mod.rs | 1 + nushell/tests/shell/mod.rs | 447 + .../tests/shell/pipeline/commands/external.rs | 731 ++ .../tests/shell/pipeline/commands/internal.rs | 1223 +++ nushell/tests/shell/pipeline/commands/mod.rs | 2 + nushell/tests/shell/pipeline/mod.rs | 19 + nushell/tests/shell/repl.rs | 9 + nushell/toolkit.nu | 663 ++ nushell/typos.toml | 31 + nushell/wix/License.rtf | Bin 0 -> 1289 bytes nushell/wix/main.wixproj | 36 + nushell/wix/main.wxs | 297 + nushell/wix/nu.ico | Bin 0 -> 7488 bytes nushell/wix/windows-terminal-profile.json | 11 + 2042 files changed, 338629 insertions(+) create mode 100644 nushell/.cargo/config.toml create mode 100644 nushell/.gitattributes create mode 100755 nushell/.githooks/pre-commit create mode 100755 nushell/.githooks/pre-push create mode 100644 nushell/.github/AUTO_ISSUE_TEMPLATE/README.md create mode 100644 nushell/.github/AUTO_ISSUE_TEMPLATE/nightly-build-fail.md create mode 100644 nushell/.github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 nushell/.github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 nushell/.github/ISSUE_TEMPLATE/question.yml create mode 100644 nushell/.github/dependabot.yml create mode 100644 nushell/.github/labeler.yml create mode 100644 nushell/.github/pull_request_template.md create mode 100644 nushell/.github/workflows/audit.yml create mode 100644 nushell/.github/workflows/beta-test.yml create mode 100644 nushell/.github/workflows/check-msrv.nu create mode 100644 nushell/.github/workflows/ci.yml create mode 100644 nushell/.github/workflows/friendly-config-reminder.yml create mode 100644 nushell/.github/workflows/labels.yml create mode 100644 nushell/.github/workflows/milestone.yml create mode 100644 nushell/.github/workflows/nightly-build.yml create mode 100755 nushell/.github/workflows/release-msi.nu create mode 100644 nushell/.github/workflows/release-msi.yml create mode 100755 nushell/.github/workflows/release-pkg.nu create mode 100644 nushell/.github/workflows/release.yml create mode 100644 nushell/.github/workflows/typos.yml create mode 100644 nushell/.github/workflows/winget-submission.yml create mode 100644 nushell/.gitignore create mode 100644 nushell/CITATION.cff create mode 100644 nushell/CODE_OF_CONDUCT.md create mode 100644 nushell/CONTRIBUTING.md create mode 100644 nushell/Cargo.lock create mode 100644 nushell/Cargo.toml create mode 100644 nushell/Cross.toml create mode 100644 nushell/LICENSE create mode 100644 nushell/README.md create mode 100644 nushell/SECURITY.md create mode 100644 nushell/assets/icons/nushell-original.png create mode 100644 nushell/assets/nu_logo.ico create mode 100644 nushell/assets/nushell-autocomplete6.gif create mode 100644 nushell/benches/README.md create mode 100644 nushell/benches/benchmarks.rs create mode 100644 nushell/clippy/wasm/clippy.toml create mode 100644 nushell/crates/README.md create mode 100644 nushell/crates/nu-cli/Cargo.toml create mode 100644 nushell/crates/nu-cli/LICENSE create mode 100644 nushell/crates/nu-cli/README.md create mode 100644 nushell/crates/nu-cli/src/commands/commandline/commandline_.rs create mode 100644 nushell/crates/nu-cli/src/commands/commandline/edit.rs create mode 100644 nushell/crates/nu-cli/src/commands/commandline/get_cursor.rs create mode 100644 nushell/crates/nu-cli/src/commands/commandline/mod.rs create mode 100644 nushell/crates/nu-cli/src/commands/commandline/set_cursor.rs create mode 100644 nushell/crates/nu-cli/src/commands/default_context.rs create mode 100644 nushell/crates/nu-cli/src/commands/history/fields.rs create mode 100644 nushell/crates/nu-cli/src/commands/history/history_.rs create mode 100644 nushell/crates/nu-cli/src/commands/history/history_import.rs create mode 100644 nushell/crates/nu-cli/src/commands/history/history_session.rs create mode 100644 nushell/crates/nu-cli/src/commands/history/mod.rs create mode 100644 nushell/crates/nu-cli/src/commands/keybindings.rs create mode 100644 nushell/crates/nu-cli/src/commands/keybindings_default.rs create mode 100644 nushell/crates/nu-cli/src/commands/keybindings_list.rs create mode 100644 nushell/crates/nu-cli/src/commands/keybindings_listen.rs create mode 100644 nushell/crates/nu-cli/src/commands/mod.rs create mode 100644 nushell/crates/nu-cli/src/completions/attribute_completions.rs create mode 100644 nushell/crates/nu-cli/src/completions/base.rs create mode 100644 nushell/crates/nu-cli/src/completions/cell_path_completions.rs create mode 100644 nushell/crates/nu-cli/src/completions/command_completions.rs create mode 100644 nushell/crates/nu-cli/src/completions/completer.rs create mode 100644 nushell/crates/nu-cli/src/completions/completion_common.rs create mode 100644 nushell/crates/nu-cli/src/completions/completion_options.rs create mode 100644 nushell/crates/nu-cli/src/completions/custom_completions.rs create mode 100644 nushell/crates/nu-cli/src/completions/directory_completions.rs create mode 100644 nushell/crates/nu-cli/src/completions/dotnu_completions.rs create mode 100644 nushell/crates/nu-cli/src/completions/exportable_completions.rs create mode 100644 nushell/crates/nu-cli/src/completions/file_completions.rs create mode 100644 nushell/crates/nu-cli/src/completions/flag_completions.rs create mode 100644 nushell/crates/nu-cli/src/completions/mod.rs create mode 100644 nushell/crates/nu-cli/src/completions/operator_completions.rs create mode 100644 nushell/crates/nu-cli/src/completions/variable_completions.rs create mode 100644 nushell/crates/nu-cli/src/config_files.rs create mode 100644 nushell/crates/nu-cli/src/eval_cmds.rs create mode 100644 nushell/crates/nu-cli/src/eval_file.rs create mode 100644 nushell/crates/nu-cli/src/lib.rs create mode 100644 nushell/crates/nu-cli/src/menus/help_completions.rs create mode 100644 nushell/crates/nu-cli/src/menus/menu_completions.rs create mode 100644 nushell/crates/nu-cli/src/menus/mod.rs create mode 100644 nushell/crates/nu-cli/src/nu_highlight.rs create mode 100644 nushell/crates/nu-cli/src/print.rs create mode 100644 nushell/crates/nu-cli/src/prompt.rs create mode 100644 nushell/crates/nu-cli/src/prompt_update.rs create mode 100644 nushell/crates/nu-cli/src/reedline_config.rs create mode 100644 nushell/crates/nu-cli/src/repl.rs create mode 100644 nushell/crates/nu-cli/src/syntax_highlight.rs create mode 100644 nushell/crates/nu-cli/src/util.rs create mode 100644 nushell/crates/nu-cli/src/validation.rs create mode 100644 nushell/crates/nu-cli/tests/commands/history_import.rs create mode 100644 nushell/crates/nu-cli/tests/commands/keybindings_list.rs create mode 100644 nushell/crates/nu-cli/tests/commands/mod.rs create mode 100644 nushell/crates/nu-cli/tests/commands/nu_highlight.rs create mode 100644 nushell/crates/nu-cli/tests/completions/mod.rs create mode 100644 nushell/crates/nu-cli/tests/completions/support/completions_helpers.rs create mode 100644 nushell/crates/nu-cli/tests/completions/support/mod.rs create mode 100644 nushell/crates/nu-cli/tests/main.rs create mode 100644 nushell/crates/nu-cmd-base/Cargo.toml create mode 100644 nushell/crates/nu-cmd-base/LICENSE create mode 100644 nushell/crates/nu-cmd-base/README.md create mode 100644 nushell/crates/nu-cmd-base/src/formats/mod.rs create mode 100644 nushell/crates/nu-cmd-base/src/formats/to/delimited.rs create mode 100644 nushell/crates/nu-cmd-base/src/formats/to/mod.rs create mode 100644 nushell/crates/nu-cmd-base/src/hook.rs create mode 100644 nushell/crates/nu-cmd-base/src/input_handler.rs create mode 100644 nushell/crates/nu-cmd-base/src/lib.rs create mode 100644 nushell/crates/nu-cmd-base/src/util.rs create mode 100644 nushell/crates/nu-cmd-base/src/wrap_call.rs create mode 100644 nushell/crates/nu-cmd-extra/Cargo.toml create mode 100644 nushell/crates/nu-cmd-extra/LICENSE create mode 100644 nushell/crates/nu-cmd-extra/README.md create mode 100644 nushell/crates/nu-cmd-extra/assets/228_themes.json create mode 100644 nushell/crates/nu-cmd-extra/src/example_test.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/bits/and.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/bits/bits_.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/bits/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/bits/not.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/bits/or.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/bits/rotate_left.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/bits/rotate_right.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/bits/shift_left.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/bits/shift_right.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/bits/xor.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/filters/each_while.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/filters/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/filters/roll/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/filters/roll/roll_.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/filters/roll/roll_down.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/filters/roll/roll_left.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/filters/roll/roll_right.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/filters/roll/roll_up.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/filters/rotate.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/filters/update_cells.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/formats/from/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/formats/from/url.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/formats/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/formats/to/html.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/formats/to/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/math/arccos.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/math/arccosh.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/math/arcsin.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/math/arcsinh.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/math/arctan.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/math/arctanh.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/math/cos.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/math/cosh.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/math/exp.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/math/ln.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/math/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/math/sin.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/math/sinh.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/math/tan.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/math/tanh.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/platform/ansi/gradient.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/platform/ansi/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/platform/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/strings/encode_decode/decode_hex.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/strings/encode_decode/encode_hex.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/strings/format/bits.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/strings/format/command.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/strings/format/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/strings/format/number.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/strings/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/camel_case.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/kebab_case.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/pascal_case.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/screaming_snake_case.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/snake_case.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/str_.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/title_case.rs create mode 100644 nushell/crates/nu-cmd-extra/src/extra/strings/str_/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/src/lib.rs create mode 100644 nushell/crates/nu-cmd-extra/tests/commands/bits/format.rs create mode 100644 nushell/crates/nu-cmd-extra/tests/commands/bits/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/tests/commands/bytes/ends_with.rs create mode 100644 nushell/crates/nu-cmd-extra/tests/commands/bytes/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/tests/commands/bytes/starts_with.rs create mode 100644 nushell/crates/nu-cmd-extra/tests/commands/mod.rs create mode 100644 nushell/crates/nu-cmd-extra/tests/main.rs create mode 100644 nushell/crates/nu-cmd-lang/Cargo.toml create mode 100644 nushell/crates/nu-cmd-lang/LICENSE create mode 100644 nushell/crates/nu-cmd-lang/README.md create mode 100644 nushell/crates/nu-cmd-lang/build.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/alias.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/attr/category.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/attr/deprecated.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/attr/example.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/attr/mod.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/attr/search_terms.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/break_.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/collect.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/const_.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/continue_.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/def.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/describe.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/do_.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/echo.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/error_make.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/export.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/export_alias.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/export_const.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/export_def.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/export_extern.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/export_module.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/export_use.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/extern_.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/for_.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/hide.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/hide_env.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/if_.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/ignore.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/let_.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/loop_.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/match_.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/mod.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/module.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/mut_.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/overlay/command.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/overlay/hide.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/overlay/list.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/overlay/mod.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/overlay/new.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/overlay/use_.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/return_.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/scope/aliases.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/scope/command.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/scope/commands.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/scope/engine_stats.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/scope/externs.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/scope/mod.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/scope/modules.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/scope/variables.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/try_.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/use_.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/version.rs create mode 100644 nushell/crates/nu-cmd-lang/src/core_commands/while_.rs create mode 100644 nushell/crates/nu-cmd-lang/src/default_context.rs create mode 100644 nushell/crates/nu-cmd-lang/src/example_support.rs create mode 100644 nushell/crates/nu-cmd-lang/src/example_test.rs create mode 100644 nushell/crates/nu-cmd-lang/src/lib.rs create mode 100644 nushell/crates/nu-cmd-lang/src/parse_const_test.rs create mode 100644 nushell/crates/nu-cmd-lang/tests/commands/attr/deprecated.rs create mode 100644 nushell/crates/nu-cmd-lang/tests/commands/attr/mod.rs create mode 100644 nushell/crates/nu-cmd-lang/tests/commands/mod.rs create mode 100644 nushell/crates/nu-cmd-lang/tests/main.rs create mode 100644 nushell/crates/nu-cmd-plugin/Cargo.toml create mode 100644 nushell/crates/nu-cmd-plugin/LICENSE create mode 100644 nushell/crates/nu-cmd-plugin/README.md create mode 100644 nushell/crates/nu-cmd-plugin/src/commands/mod.rs create mode 100644 nushell/crates/nu-cmd-plugin/src/commands/plugin/add.rs create mode 100644 nushell/crates/nu-cmd-plugin/src/commands/plugin/list.rs create mode 100644 nushell/crates/nu-cmd-plugin/src/commands/plugin/mod.rs create mode 100644 nushell/crates/nu-cmd-plugin/src/commands/plugin/rm.rs create mode 100644 nushell/crates/nu-cmd-plugin/src/commands/plugin/stop.rs create mode 100644 nushell/crates/nu-cmd-plugin/src/commands/plugin/use_.rs create mode 100644 nushell/crates/nu-cmd-plugin/src/default_context.rs create mode 100644 nushell/crates/nu-cmd-plugin/src/lib.rs create mode 100644 nushell/crates/nu-cmd-plugin/src/util.rs create mode 100644 nushell/crates/nu-color-config/Cargo.toml create mode 100644 nushell/crates/nu-color-config/LICENSE create mode 100644 nushell/crates/nu-color-config/README.md create mode 100644 nushell/crates/nu-color-config/src/color_config.rs create mode 100644 nushell/crates/nu-color-config/src/lib.rs create mode 100644 nushell/crates/nu-color-config/src/matching_brackets_style.rs create mode 100644 nushell/crates/nu-color-config/src/nu_style.rs create mode 100644 nushell/crates/nu-color-config/src/shape_color.rs create mode 100644 nushell/crates/nu-color-config/src/style_computer.rs create mode 100644 nushell/crates/nu-color-config/src/text_style.rs create mode 100644 nushell/crates/nu-command/Cargo.toml create mode 100644 nushell/crates/nu-command/LICENSE create mode 100644 nushell/crates/nu-command/README.md create mode 100644 nushell/crates/nu-command/src/bytes/add.rs create mode 100644 nushell/crates/nu-command/src/bytes/at.rs create mode 100644 nushell/crates/nu-command/src/bytes/build_.rs create mode 100644 nushell/crates/nu-command/src/bytes/bytes_.rs create mode 100644 nushell/crates/nu-command/src/bytes/collect.rs create mode 100644 nushell/crates/nu-command/src/bytes/ends_with.rs create mode 100644 nushell/crates/nu-command/src/bytes/index_of.rs create mode 100644 nushell/crates/nu-command/src/bytes/length.rs create mode 100644 nushell/crates/nu-command/src/bytes/mod.rs create mode 100644 nushell/crates/nu-command/src/bytes/remove.rs create mode 100644 nushell/crates/nu-command/src/bytes/replace.rs create mode 100644 nushell/crates/nu-command/src/bytes/reverse.rs create mode 100644 nushell/crates/nu-command/src/bytes/split.rs create mode 100644 nushell/crates/nu-command/src/bytes/starts_with.rs create mode 100644 nushell/crates/nu-command/src/charting/hashable_value.rs create mode 100755 nushell/crates/nu-command/src/charting/histogram.rs create mode 100644 nushell/crates/nu-command/src/charting/mod.rs create mode 100644 nushell/crates/nu-command/src/conversions/fill.rs create mode 100644 nushell/crates/nu-command/src/conversions/into/binary.rs create mode 100644 nushell/crates/nu-command/src/conversions/into/bool.rs create mode 100644 nushell/crates/nu-command/src/conversions/into/cell_path.rs create mode 100644 nushell/crates/nu-command/src/conversions/into/command.rs create mode 100644 nushell/crates/nu-command/src/conversions/into/datetime.rs create mode 100644 nushell/crates/nu-command/src/conversions/into/duration.rs create mode 100644 nushell/crates/nu-command/src/conversions/into/filesize.rs create mode 100644 nushell/crates/nu-command/src/conversions/into/float.rs create mode 100644 nushell/crates/nu-command/src/conversions/into/glob.rs create mode 100644 nushell/crates/nu-command/src/conversions/into/int.rs create mode 100644 nushell/crates/nu-command/src/conversions/into/mod.rs create mode 100644 nushell/crates/nu-command/src/conversions/into/record.rs create mode 100644 nushell/crates/nu-command/src/conversions/into/string.rs create mode 100644 nushell/crates/nu-command/src/conversions/into/value.rs create mode 100644 nushell/crates/nu-command/src/conversions/mod.rs create mode 100644 nushell/crates/nu-command/src/conversions/split_cell_path.rs create mode 100644 nushell/crates/nu-command/src/database/commands/into_sqlite.rs create mode 100644 nushell/crates/nu-command/src/database/commands/mod.rs create mode 100644 nushell/crates/nu-command/src/database/commands/query_db.rs create mode 100644 nushell/crates/nu-command/src/database/commands/schema.rs create mode 100644 nushell/crates/nu-command/src/database/mod.rs create mode 100644 nushell/crates/nu-command/src/database/values/definitions/db_column.rs create mode 100644 nushell/crates/nu-command/src/database/values/definitions/db_constraint.rs create mode 100644 nushell/crates/nu-command/src/database/values/definitions/db_foreignkey.rs create mode 100644 nushell/crates/nu-command/src/database/values/definitions/db_index.rs create mode 100644 nushell/crates/nu-command/src/database/values/definitions/db_row.rs create mode 100644 nushell/crates/nu-command/src/database/values/definitions/db_schema.rs create mode 100644 nushell/crates/nu-command/src/database/values/definitions/db_table.rs create mode 100644 nushell/crates/nu-command/src/database/values/definitions/mod.rs create mode 100644 nushell/crates/nu-command/src/database/values/mod.rs create mode 100644 nushell/crates/nu-command/src/database/values/sqlite.rs create mode 100644 nushell/crates/nu-command/src/date/date_.rs create mode 100644 nushell/crates/nu-command/src/date/from_human.rs create mode 100644 nushell/crates/nu-command/src/date/humanize.rs create mode 100644 nushell/crates/nu-command/src/date/list_timezone.rs create mode 100644 nushell/crates/nu-command/src/date/mod.rs create mode 100644 nushell/crates/nu-command/src/date/now.rs create mode 100644 nushell/crates/nu-command/src/date/parser.rs create mode 100644 nushell/crates/nu-command/src/date/to_timezone.rs create mode 100644 nushell/crates/nu-command/src/date/utils.rs create mode 100644 nushell/crates/nu-command/src/debug/ast.rs create mode 100644 nushell/crates/nu-command/src/debug/debug_.rs create mode 100644 nushell/crates/nu-command/src/debug/env.rs create mode 100644 nushell/crates/nu-command/src/debug/explain.rs create mode 100644 nushell/crates/nu-command/src/debug/info.rs create mode 100644 nushell/crates/nu-command/src/debug/inspect.rs create mode 100644 nushell/crates/nu-command/src/debug/inspect_table.rs create mode 100644 nushell/crates/nu-command/src/debug/metadata.rs create mode 100644 nushell/crates/nu-command/src/debug/metadata_access.rs create mode 100644 nushell/crates/nu-command/src/debug/metadata_set.rs create mode 100644 nushell/crates/nu-command/src/debug/mod.rs create mode 100644 nushell/crates/nu-command/src/debug/profile.rs create mode 100644 nushell/crates/nu-command/src/debug/timeit.rs create mode 100644 nushell/crates/nu-command/src/debug/util.rs create mode 100644 nushell/crates/nu-command/src/debug/view.rs create mode 100644 nushell/crates/nu-command/src/debug/view_blocks.rs create mode 100644 nushell/crates/nu-command/src/debug/view_files.rs create mode 100644 nushell/crates/nu-command/src/debug/view_ir.rs create mode 100644 nushell/crates/nu-command/src/debug/view_source.rs create mode 100644 nushell/crates/nu-command/src/debug/view_span.rs create mode 100644 nushell/crates/nu-command/src/default_context.rs create mode 100644 nushell/crates/nu-command/src/env/config/config_.rs create mode 100644 nushell/crates/nu-command/src/env/config/config_env.rs create mode 100644 nushell/crates/nu-command/src/env/config/config_flatten.rs create mode 100644 nushell/crates/nu-command/src/env/config/config_nu.rs create mode 100644 nushell/crates/nu-command/src/env/config/config_reset.rs create mode 100644 nushell/crates/nu-command/src/env/config/config_use_colors.rs create mode 100644 nushell/crates/nu-command/src/env/config/mod.rs create mode 100644 nushell/crates/nu-command/src/env/export_env.rs create mode 100644 nushell/crates/nu-command/src/env/load_env.rs create mode 100644 nushell/crates/nu-command/src/env/mod.rs create mode 100644 nushell/crates/nu-command/src/env/source_env.rs create mode 100644 nushell/crates/nu-command/src/env/with_env.rs create mode 100644 nushell/crates/nu-command/src/example_test.rs create mode 100644 nushell/crates/nu-command/src/experimental/is_admin.rs create mode 100644 nushell/crates/nu-command/src/experimental/job.rs create mode 100644 nushell/crates/nu-command/src/experimental/job_flush.rs create mode 100644 nushell/crates/nu-command/src/experimental/job_id.rs create mode 100644 nushell/crates/nu-command/src/experimental/job_kill.rs create mode 100644 nushell/crates/nu-command/src/experimental/job_list.rs create mode 100644 nushell/crates/nu-command/src/experimental/job_recv.rs create mode 100644 nushell/crates/nu-command/src/experimental/job_send.rs create mode 100644 nushell/crates/nu-command/src/experimental/job_spawn.rs create mode 100644 nushell/crates/nu-command/src/experimental/job_tag.rs create mode 100644 nushell/crates/nu-command/src/experimental/job_unfreeze.rs create mode 100644 nushell/crates/nu-command/src/experimental/mod.rs create mode 100644 nushell/crates/nu-command/src/filesystem/cd.rs create mode 100644 nushell/crates/nu-command/src/filesystem/du.rs create mode 100644 nushell/crates/nu-command/src/filesystem/glob.rs create mode 100644 nushell/crates/nu-command/src/filesystem/ls.rs create mode 100644 nushell/crates/nu-command/src/filesystem/mktemp.rs create mode 100644 nushell/crates/nu-command/src/filesystem/mod.rs create mode 100644 nushell/crates/nu-command/src/filesystem/open.rs create mode 100644 nushell/crates/nu-command/src/filesystem/rm.rs create mode 100644 nushell/crates/nu-command/src/filesystem/save.rs create mode 100644 nushell/crates/nu-command/src/filesystem/start.rs create mode 100644 nushell/crates/nu-command/src/filesystem/ucp.rs create mode 100644 nushell/crates/nu-command/src/filesystem/umkdir.rs create mode 100644 nushell/crates/nu-command/src/filesystem/umv.rs create mode 100644 nushell/crates/nu-command/src/filesystem/util.rs create mode 100644 nushell/crates/nu-command/src/filesystem/utouch.rs create mode 100644 nushell/crates/nu-command/src/filesystem/watch.rs create mode 100644 nushell/crates/nu-command/src/filters/all.rs create mode 100644 nushell/crates/nu-command/src/filters/any.rs create mode 100644 nushell/crates/nu-command/src/filters/append.rs create mode 100644 nushell/crates/nu-command/src/filters/chunk_by.rs create mode 100644 nushell/crates/nu-command/src/filters/chunks.rs create mode 100644 nushell/crates/nu-command/src/filters/columns.rs create mode 100644 nushell/crates/nu-command/src/filters/compact.rs create mode 100644 nushell/crates/nu-command/src/filters/default.rs create mode 100644 nushell/crates/nu-command/src/filters/drop/column.rs create mode 100644 nushell/crates/nu-command/src/filters/drop/drop_.rs create mode 100644 nushell/crates/nu-command/src/filters/drop/mod.rs create mode 100644 nushell/crates/nu-command/src/filters/drop/nth.rs create mode 100644 nushell/crates/nu-command/src/filters/each.rs create mode 100644 nushell/crates/nu-command/src/filters/empty.rs create mode 100644 nushell/crates/nu-command/src/filters/enumerate.rs create mode 100644 nushell/crates/nu-command/src/filters/every.rs create mode 100644 nushell/crates/nu-command/src/filters/filter.rs create mode 100644 nushell/crates/nu-command/src/filters/find.rs create mode 100644 nushell/crates/nu-command/src/filters/first.rs create mode 100644 nushell/crates/nu-command/src/filters/flatten.rs create mode 100644 nushell/crates/nu-command/src/filters/get.rs create mode 100644 nushell/crates/nu-command/src/filters/group_by.rs create mode 100644 nushell/crates/nu-command/src/filters/headers.rs create mode 100644 nushell/crates/nu-command/src/filters/insert.rs create mode 100644 nushell/crates/nu-command/src/filters/interleave.rs create mode 100644 nushell/crates/nu-command/src/filters/is_empty.rs create mode 100644 nushell/crates/nu-command/src/filters/is_not_empty.rs create mode 100644 nushell/crates/nu-command/src/filters/items.rs create mode 100644 nushell/crates/nu-command/src/filters/join.rs create mode 100644 nushell/crates/nu-command/src/filters/last.rs create mode 100644 nushell/crates/nu-command/src/filters/length.rs create mode 100644 nushell/crates/nu-command/src/filters/lines.rs create mode 100644 nushell/crates/nu-command/src/filters/merge/common.rs create mode 100644 nushell/crates/nu-command/src/filters/merge/deep.rs create mode 100644 nushell/crates/nu-command/src/filters/merge/merge_.rs create mode 100644 nushell/crates/nu-command/src/filters/merge/mod.rs create mode 100644 nushell/crates/nu-command/src/filters/mod.rs create mode 100644 nushell/crates/nu-command/src/filters/move_.rs create mode 100644 nushell/crates/nu-command/src/filters/par_each.rs create mode 100644 nushell/crates/nu-command/src/filters/prepend.rs create mode 100644 nushell/crates/nu-command/src/filters/reduce.rs create mode 100644 nushell/crates/nu-command/src/filters/reject.rs create mode 100644 nushell/crates/nu-command/src/filters/rename.rs create mode 100644 nushell/crates/nu-command/src/filters/reverse.rs create mode 100644 nushell/crates/nu-command/src/filters/select.rs create mode 100644 nushell/crates/nu-command/src/filters/shuffle.rs create mode 100644 nushell/crates/nu-command/src/filters/skip/mod.rs create mode 100644 nushell/crates/nu-command/src/filters/skip/skip_.rs create mode 100644 nushell/crates/nu-command/src/filters/skip/skip_until.rs create mode 100644 nushell/crates/nu-command/src/filters/skip/skip_while.rs create mode 100644 nushell/crates/nu-command/src/filters/slice.rs create mode 100644 nushell/crates/nu-command/src/filters/sort.rs create mode 100644 nushell/crates/nu-command/src/filters/sort_by.rs create mode 100644 nushell/crates/nu-command/src/filters/take/mod.rs create mode 100644 nushell/crates/nu-command/src/filters/take/take_.rs create mode 100644 nushell/crates/nu-command/src/filters/take/take_until.rs create mode 100644 nushell/crates/nu-command/src/filters/take/take_while.rs create mode 100644 nushell/crates/nu-command/src/filters/tee.rs create mode 100644 nushell/crates/nu-command/src/filters/transpose.rs create mode 100644 nushell/crates/nu-command/src/filters/uniq.rs create mode 100644 nushell/crates/nu-command/src/filters/uniq_by.rs create mode 100644 nushell/crates/nu-command/src/filters/update.rs create mode 100644 nushell/crates/nu-command/src/filters/upsert.rs create mode 100644 nushell/crates/nu-command/src/filters/utils.rs create mode 100644 nushell/crates/nu-command/src/filters/values.rs create mode 100644 nushell/crates/nu-command/src/filters/where_.rs create mode 100644 nushell/crates/nu-command/src/filters/window.rs create mode 100644 nushell/crates/nu-command/src/filters/wrap.rs create mode 100644 nushell/crates/nu-command/src/filters/zip.rs create mode 100644 nushell/crates/nu-command/src/formats/from/command.rs create mode 100644 nushell/crates/nu-command/src/formats/from/csv.rs create mode 100644 nushell/crates/nu-command/src/formats/from/delimited.rs create mode 100644 nushell/crates/nu-command/src/formats/from/json.rs create mode 100644 nushell/crates/nu-command/src/formats/from/mod.rs create mode 100644 nushell/crates/nu-command/src/formats/from/msgpack.rs create mode 100644 nushell/crates/nu-command/src/formats/from/msgpackz.rs create mode 100644 nushell/crates/nu-command/src/formats/from/nuon.rs create mode 100644 nushell/crates/nu-command/src/formats/from/ods.rs create mode 100644 nushell/crates/nu-command/src/formats/from/ssv.rs create mode 100644 nushell/crates/nu-command/src/formats/from/toml.rs create mode 100644 nushell/crates/nu-command/src/formats/from/tsv.rs create mode 100644 nushell/crates/nu-command/src/formats/from/xlsx.rs create mode 100644 nushell/crates/nu-command/src/formats/from/xml.rs create mode 100644 nushell/crates/nu-command/src/formats/from/yaml.rs create mode 100644 nushell/crates/nu-command/src/formats/mod.rs create mode 100644 nushell/crates/nu-command/src/formats/nu_xml_format.rs create mode 100644 nushell/crates/nu-command/src/formats/to/command.rs create mode 100644 nushell/crates/nu-command/src/formats/to/csv.rs create mode 100644 nushell/crates/nu-command/src/formats/to/delimited.rs create mode 100644 nushell/crates/nu-command/src/formats/to/json.rs create mode 100644 nushell/crates/nu-command/src/formats/to/md.rs create mode 100644 nushell/crates/nu-command/src/formats/to/mod.rs create mode 100644 nushell/crates/nu-command/src/formats/to/msgpack.rs create mode 100644 nushell/crates/nu-command/src/formats/to/msgpackz.rs create mode 100644 nushell/crates/nu-command/src/formats/to/nuon.rs create mode 100644 nushell/crates/nu-command/src/formats/to/text.rs create mode 100644 nushell/crates/nu-command/src/formats/to/toml.rs create mode 100644 nushell/crates/nu-command/src/formats/to/tsv.rs create mode 100644 nushell/crates/nu-command/src/formats/to/xml.rs create mode 100644 nushell/crates/nu-command/src/formats/to/yaml.rs create mode 100644 nushell/crates/nu-command/src/generators/cal.rs create mode 100644 nushell/crates/nu-command/src/generators/generate.rs create mode 100644 nushell/crates/nu-command/src/generators/mod.rs create mode 100644 nushell/crates/nu-command/src/generators/seq.rs create mode 100644 nushell/crates/nu-command/src/generators/seq_char.rs create mode 100644 nushell/crates/nu-command/src/generators/seq_date.rs create mode 100644 nushell/crates/nu-command/src/hash/generic_digest.rs create mode 100644 nushell/crates/nu-command/src/hash/hash_.rs create mode 100644 nushell/crates/nu-command/src/hash/md5.rs create mode 100644 nushell/crates/nu-command/src/hash/mod.rs create mode 100644 nushell/crates/nu-command/src/hash/sha256.rs create mode 100644 nushell/crates/nu-command/src/help/help_.rs create mode 100644 nushell/crates/nu-command/src/help/help_aliases.rs create mode 100644 nushell/crates/nu-command/src/help/help_commands.rs create mode 100644 nushell/crates/nu-command/src/help/help_escapes.rs create mode 100644 nushell/crates/nu-command/src/help/help_externs.rs create mode 100644 nushell/crates/nu-command/src/help/help_modules.rs create mode 100644 nushell/crates/nu-command/src/help/help_operators.rs create mode 100644 nushell/crates/nu-command/src/help/help_pipe_and_redirect.rs create mode 100644 nushell/crates/nu-command/src/help/mod.rs create mode 100644 nushell/crates/nu-command/src/lib.rs create mode 100644 nushell/crates/nu-command/src/math/abs.rs create mode 100644 nushell/crates/nu-command/src/math/avg.rs create mode 100644 nushell/crates/nu-command/src/math/ceil.rs create mode 100644 nushell/crates/nu-command/src/math/floor.rs create mode 100644 nushell/crates/nu-command/src/math/log.rs create mode 100644 nushell/crates/nu-command/src/math/math_.rs create mode 100644 nushell/crates/nu-command/src/math/max.rs create mode 100644 nushell/crates/nu-command/src/math/median.rs create mode 100644 nushell/crates/nu-command/src/math/min.rs create mode 100644 nushell/crates/nu-command/src/math/mod.rs create mode 100644 nushell/crates/nu-command/src/math/mode.rs create mode 100644 nushell/crates/nu-command/src/math/product.rs create mode 100644 nushell/crates/nu-command/src/math/reducers.rs create mode 100644 nushell/crates/nu-command/src/math/round.rs create mode 100644 nushell/crates/nu-command/src/math/sqrt.rs create mode 100644 nushell/crates/nu-command/src/math/stddev.rs create mode 100644 nushell/crates/nu-command/src/math/sum.rs create mode 100644 nushell/crates/nu-command/src/math/utils.rs create mode 100644 nushell/crates/nu-command/src/math/variance.rs create mode 100644 nushell/crates/nu-command/src/misc/mod.rs create mode 100644 nushell/crates/nu-command/src/misc/panic.rs create mode 100644 nushell/crates/nu-command/src/misc/source.rs create mode 100644 nushell/crates/nu-command/src/misc/tutor.rs create mode 100644 nushell/crates/nu-command/src/network/http/client.rs create mode 100644 nushell/crates/nu-command/src/network/http/delete.rs create mode 100644 nushell/crates/nu-command/src/network/http/get.rs create mode 100644 nushell/crates/nu-command/src/network/http/head.rs create mode 100644 nushell/crates/nu-command/src/network/http/http_.rs create mode 100644 nushell/crates/nu-command/src/network/http/mod.rs create mode 100644 nushell/crates/nu-command/src/network/http/options.rs create mode 100644 nushell/crates/nu-command/src/network/http/patch.rs create mode 100644 nushell/crates/nu-command/src/network/http/post.rs create mode 100644 nushell/crates/nu-command/src/network/http/put.rs create mode 100644 nushell/crates/nu-command/src/network/mod.rs create mode 100644 nushell/crates/nu-command/src/network/port.rs create mode 100644 nushell/crates/nu-command/src/network/tls/impl_native_tls.rs create mode 100644 nushell/crates/nu-command/src/network/tls/impl_rustls.rs create mode 100644 nushell/crates/nu-command/src/network/tls/mod.rs create mode 100644 nushell/crates/nu-command/src/network/tls/tls.rustdoc.md create mode 100644 nushell/crates/nu-command/src/network/url/build_query.rs create mode 100644 nushell/crates/nu-command/src/network/url/decode.rs create mode 100644 nushell/crates/nu-command/src/network/url/encode.rs create mode 100644 nushell/crates/nu-command/src/network/url/join.rs create mode 100644 nushell/crates/nu-command/src/network/url/mod.rs create mode 100644 nushell/crates/nu-command/src/network/url/parse.rs create mode 100644 nushell/crates/nu-command/src/network/url/query.rs create mode 100644 nushell/crates/nu-command/src/network/url/split_query.rs create mode 100644 nushell/crates/nu-command/src/network/url/url_.rs create mode 100644 nushell/crates/nu-command/src/network/version_check.rs create mode 100644 nushell/crates/nu-command/src/path/basename.rs create mode 100644 nushell/crates/nu-command/src/path/dirname.rs create mode 100644 nushell/crates/nu-command/src/path/exists.rs create mode 100644 nushell/crates/nu-command/src/path/expand.rs create mode 100644 nushell/crates/nu-command/src/path/join.rs create mode 100644 nushell/crates/nu-command/src/path/mod.rs create mode 100644 nushell/crates/nu-command/src/path/parse.rs create mode 100644 nushell/crates/nu-command/src/path/path_.rs create mode 100644 nushell/crates/nu-command/src/path/relative_to.rs create mode 100644 nushell/crates/nu-command/src/path/self_.rs create mode 100644 nushell/crates/nu-command/src/path/split.rs create mode 100644 nushell/crates/nu-command/src/path/type.rs create mode 100644 nushell/crates/nu-command/src/platform/clear.rs create mode 100644 nushell/crates/nu-command/src/platform/dir_info.rs create mode 100644 nushell/crates/nu-command/src/platform/input/input_.rs create mode 100644 nushell/crates/nu-command/src/platform/input/input_listen.rs create mode 100644 nushell/crates/nu-command/src/platform/input/legacy_input.rs create mode 100644 nushell/crates/nu-command/src/platform/input/list.rs create mode 100644 nushell/crates/nu-command/src/platform/input/mod.rs create mode 100644 nushell/crates/nu-command/src/platform/input/reedline_prompt.rs create mode 100644 nushell/crates/nu-command/src/platform/is_terminal.rs create mode 100644 nushell/crates/nu-command/src/platform/kill.rs create mode 100644 nushell/crates/nu-command/src/platform/mod.rs create mode 100644 nushell/crates/nu-command/src/platform/sleep.rs create mode 100644 nushell/crates/nu-command/src/platform/term/mod.rs create mode 100644 nushell/crates/nu-command/src/platform/term/term_.rs create mode 100644 nushell/crates/nu-command/src/platform/term/term_query.rs create mode 100644 nushell/crates/nu-command/src/platform/term/term_size.rs create mode 100644 nushell/crates/nu-command/src/platform/ulimit.rs create mode 100644 nushell/crates/nu-command/src/platform/whoami.rs create mode 100644 nushell/crates/nu-command/src/progress_bar.rs create mode 100644 nushell/crates/nu-command/src/random/binary.rs create mode 100644 nushell/crates/nu-command/src/random/bool.rs create mode 100644 nushell/crates/nu-command/src/random/byte_stream.rs create mode 100644 nushell/crates/nu-command/src/random/chars.rs create mode 100644 nushell/crates/nu-command/src/random/dice.rs create mode 100644 nushell/crates/nu-command/src/random/float.rs create mode 100644 nushell/crates/nu-command/src/random/int.rs create mode 100644 nushell/crates/nu-command/src/random/mod.rs create mode 100644 nushell/crates/nu-command/src/random/random_.rs create mode 100644 nushell/crates/nu-command/src/random/uuid.rs create mode 100644 nushell/crates/nu-command/src/removed/format.rs create mode 100644 nushell/crates/nu-command/src/removed/let_env.rs create mode 100644 nushell/crates/nu-command/src/removed/mod.rs create mode 100644 nushell/crates/nu-command/src/removed/removed_commands.rs create mode 100644 nushell/crates/nu-command/src/shells/exit.rs create mode 100644 nushell/crates/nu-command/src/shells/mod.rs create mode 100644 nushell/crates/nu-command/src/sort_utils.rs create mode 100644 nushell/crates/nu-command/src/stor/create.rs create mode 100644 nushell/crates/nu-command/src/stor/delete.rs create mode 100644 nushell/crates/nu-command/src/stor/export.rs create mode 100644 nushell/crates/nu-command/src/stor/import.rs create mode 100644 nushell/crates/nu-command/src/stor/insert.rs create mode 100644 nushell/crates/nu-command/src/stor/mod.rs create mode 100644 nushell/crates/nu-command/src/stor/open.rs create mode 100644 nushell/crates/nu-command/src/stor/reset.rs create mode 100644 nushell/crates/nu-command/src/stor/stor_.rs create mode 100644 nushell/crates/nu-command/src/stor/update.rs create mode 100644 nushell/crates/nu-command/src/strings/ansi/ansi_.rs create mode 100644 nushell/crates/nu-command/src/strings/ansi/link.rs create mode 100644 nushell/crates/nu-command/src/strings/ansi/mod.rs create mode 100644 nushell/crates/nu-command/src/strings/ansi/strip.rs create mode 100644 nushell/crates/nu-command/src/strings/base/base32.rs create mode 100644 nushell/crates/nu-command/src/strings/base/base32hex.rs create mode 100644 nushell/crates/nu-command/src/strings/base/base64.rs create mode 100644 nushell/crates/nu-command/src/strings/base/hex.rs create mode 100644 nushell/crates/nu-command/src/strings/base/mod.rs create mode 100644 nushell/crates/nu-command/src/strings/char_.rs create mode 100644 nushell/crates/nu-command/src/strings/detect_columns.rs create mode 100644 nushell/crates/nu-command/src/strings/encode_decode/decode.rs create mode 100644 nushell/crates/nu-command/src/strings/encode_decode/encode.rs create mode 100644 nushell/crates/nu-command/src/strings/encode_decode/encoding.rs create mode 100644 nushell/crates/nu-command/src/strings/encode_decode/mod.rs create mode 100644 nushell/crates/nu-command/src/strings/format/date.rs create mode 100644 nushell/crates/nu-command/src/strings/format/duration.rs create mode 100644 nushell/crates/nu-command/src/strings/format/filesize.rs create mode 100644 nushell/crates/nu-command/src/strings/format/format_.rs create mode 100644 nushell/crates/nu-command/src/strings/format/mod.rs create mode 100644 nushell/crates/nu-command/src/strings/guess_width.rs create mode 100644 nushell/crates/nu-command/src/strings/mod.rs create mode 100644 nushell/crates/nu-command/src/strings/parse.rs create mode 100644 nushell/crates/nu-command/src/strings/split/chars.rs create mode 100644 nushell/crates/nu-command/src/strings/split/column.rs create mode 100644 nushell/crates/nu-command/src/strings/split/command.rs create mode 100644 nushell/crates/nu-command/src/strings/split/list.rs create mode 100644 nushell/crates/nu-command/src/strings/split/mod.rs create mode 100644 nushell/crates/nu-command/src/strings/split/row.rs create mode 100644 nushell/crates/nu-command/src/strings/split/words.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/case/capitalize.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/case/downcase.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/case/mod.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/case/str_.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/case/upcase.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/contains.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/distance.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/ends_with.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/expand.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/index_of.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/join.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/length.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/mod.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/replace.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/reverse.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/starts_with.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/stats.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/substring.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/trim/mod.rs create mode 100644 nushell/crates/nu-command/src/strings/str_/trim/trim_.rs create mode 100644 nushell/crates/nu-command/src/system/complete.rs create mode 100644 nushell/crates/nu-command/src/system/exec.rs create mode 100644 nushell/crates/nu-command/src/system/mod.rs create mode 100644 nushell/crates/nu-command/src/system/nu_check.rs create mode 100644 nushell/crates/nu-command/src/system/ps.rs create mode 100644 nushell/crates/nu-command/src/system/registry_query.rs create mode 100644 nushell/crates/nu-command/src/system/run_external.rs create mode 100644 nushell/crates/nu-command/src/system/sys/cpu.rs create mode 100644 nushell/crates/nu-command/src/system/sys/disks.rs create mode 100644 nushell/crates/nu-command/src/system/sys/host.rs create mode 100644 nushell/crates/nu-command/src/system/sys/mem.rs create mode 100644 nushell/crates/nu-command/src/system/sys/mod.rs create mode 100644 nushell/crates/nu-command/src/system/sys/net.rs create mode 100644 nushell/crates/nu-command/src/system/sys/sys_.rs create mode 100644 nushell/crates/nu-command/src/system/sys/temp.rs create mode 100644 nushell/crates/nu-command/src/system/sys/users.rs create mode 100644 nushell/crates/nu-command/src/system/uname.rs create mode 100644 nushell/crates/nu-command/src/system/which_.rs create mode 100644 nushell/crates/nu-command/src/viewers/griddle.rs create mode 100644 nushell/crates/nu-command/src/viewers/mod.rs create mode 100644 nushell/crates/nu-command/src/viewers/table.rs create mode 100644 nushell/crates/nu-command/tests/commands/alias.rs create mode 100644 nushell/crates/nu-command/tests/commands/all.rs create mode 100644 nushell/crates/nu-command/tests/commands/any.rs create mode 100644 nushell/crates/nu-command/tests/commands/append.rs create mode 100644 nushell/crates/nu-command/tests/commands/assignment/concat.rs create mode 100644 nushell/crates/nu-command/tests/commands/assignment/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/base/base32.rs create mode 100644 nushell/crates/nu-command/tests/commands/base/base32hex.rs create mode 100644 nushell/crates/nu-command/tests/commands/base/base64.rs create mode 100644 nushell/crates/nu-command/tests/commands/base/hex.rs create mode 100644 nushell/crates/nu-command/tests/commands/base/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/break_.rs create mode 100644 nushell/crates/nu-command/tests/commands/bytes/at.rs create mode 100644 nushell/crates/nu-command/tests/commands/bytes/collect.rs create mode 100644 nushell/crates/nu-command/tests/commands/bytes/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/cal.rs create mode 100644 nushell/crates/nu-command/tests/commands/cd.rs create mode 100644 nushell/crates/nu-command/tests/commands/chunk_by.rs create mode 100644 nushell/crates/nu-command/tests/commands/chunks.rs create mode 100644 nushell/crates/nu-command/tests/commands/compact.rs create mode 100644 nushell/crates/nu-command/tests/commands/complete.rs create mode 100644 nushell/crates/nu-command/tests/commands/config_env_default.rs create mode 100644 nushell/crates/nu-command/tests/commands/config_nu_default.rs create mode 100644 nushell/crates/nu-command/tests/commands/continue_.rs create mode 100644 nushell/crates/nu-command/tests/commands/conversions/into/binary.rs create mode 100644 nushell/crates/nu-command/tests/commands/conversions/into/int.rs create mode 100644 nushell/crates/nu-command/tests/commands/conversions/into/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/conversions/into/record.rs create mode 100644 nushell/crates/nu-command/tests/commands/conversions/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/database/into_sqlite.rs create mode 100644 nushell/crates/nu-command/tests/commands/database/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/database/query_db.rs create mode 100644 nushell/crates/nu-command/tests/commands/date/format.rs create mode 100644 nushell/crates/nu-command/tests/commands/date/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/debug/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/debug/timeit.rs create mode 100644 nushell/crates/nu-command/tests/commands/debug_info.rs create mode 100644 nushell/crates/nu-command/tests/commands/def.rs create mode 100644 nushell/crates/nu-command/tests/commands/default.rs create mode 100644 nushell/crates/nu-command/tests/commands/detect_columns.rs create mode 100644 nushell/crates/nu-command/tests/commands/do_.rs create mode 100644 nushell/crates/nu-command/tests/commands/drop.rs create mode 100644 nushell/crates/nu-command/tests/commands/du.rs create mode 100644 nushell/crates/nu-command/tests/commands/each.rs create mode 100644 nushell/crates/nu-command/tests/commands/echo.rs create mode 100644 nushell/crates/nu-command/tests/commands/empty.rs create mode 100644 nushell/crates/nu-command/tests/commands/error_make.rs create mode 100644 nushell/crates/nu-command/tests/commands/every.rs create mode 100644 nushell/crates/nu-command/tests/commands/exec.rs create mode 100644 nushell/crates/nu-command/tests/commands/export_def.rs create mode 100644 nushell/crates/nu-command/tests/commands/fill.rs create mode 100644 nushell/crates/nu-command/tests/commands/filter.rs create mode 100644 nushell/crates/nu-command/tests/commands/find.rs create mode 100644 nushell/crates/nu-command/tests/commands/first.rs create mode 100644 nushell/crates/nu-command/tests/commands/flatten.rs create mode 100644 nushell/crates/nu-command/tests/commands/for_.rs create mode 100644 nushell/crates/nu-command/tests/commands/format.rs create mode 100644 nushell/crates/nu-command/tests/commands/generate.rs create mode 100644 nushell/crates/nu-command/tests/commands/get.rs create mode 100644 nushell/crates/nu-command/tests/commands/glob.rs create mode 100644 nushell/crates/nu-command/tests/commands/griddle.rs create mode 100644 nushell/crates/nu-command/tests/commands/group_by.rs create mode 100644 nushell/crates/nu-command/tests/commands/hash_/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/headers.rs create mode 100644 nushell/crates/nu-command/tests/commands/help.rs create mode 100644 nushell/crates/nu-command/tests/commands/histogram.rs create mode 100644 nushell/crates/nu-command/tests/commands/ignore.rs create mode 100644 nushell/crates/nu-command/tests/commands/insert.rs create mode 100644 nushell/crates/nu-command/tests/commands/inspect.rs create mode 100644 nushell/crates/nu-command/tests/commands/interleave.rs create mode 100644 nushell/crates/nu-command/tests/commands/into_datetime.rs create mode 100644 nushell/crates/nu-command/tests/commands/into_duration.rs create mode 100644 nushell/crates/nu-command/tests/commands/into_filesize.rs create mode 100644 nushell/crates/nu-command/tests/commands/into_int.rs create mode 100644 nushell/crates/nu-command/tests/commands/job.rs create mode 100644 nushell/crates/nu-command/tests/commands/join.rs create mode 100644 nushell/crates/nu-command/tests/commands/last.rs create mode 100644 nushell/crates/nu-command/tests/commands/length.rs create mode 100644 nushell/crates/nu-command/tests/commands/let_.rs create mode 100644 nushell/crates/nu-command/tests/commands/lines.rs create mode 100644 nushell/crates/nu-command/tests/commands/loop_.rs create mode 100644 nushell/crates/nu-command/tests/commands/ls.rs create mode 100644 nushell/crates/nu-command/tests/commands/match_.rs create mode 100644 nushell/crates/nu-command/tests/commands/math/abs.rs create mode 100644 nushell/crates/nu-command/tests/commands/math/avg.rs create mode 100644 nushell/crates/nu-command/tests/commands/math/ceil.rs create mode 100644 nushell/crates/nu-command/tests/commands/math/floor.rs create mode 100644 nushell/crates/nu-command/tests/commands/math/log.rs create mode 100644 nushell/crates/nu-command/tests/commands/math/max.rs create mode 100644 nushell/crates/nu-command/tests/commands/math/median.rs create mode 100644 nushell/crates/nu-command/tests/commands/math/min.rs create mode 100644 nushell/crates/nu-command/tests/commands/math/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/math/mode.rs create mode 100644 nushell/crates/nu-command/tests/commands/math/product.rs create mode 100644 nushell/crates/nu-command/tests/commands/math/round.rs create mode 100644 nushell/crates/nu-command/tests/commands/math/sqrt.rs create mode 100644 nushell/crates/nu-command/tests/commands/math/stddev.rs create mode 100644 nushell/crates/nu-command/tests/commands/math/sum.rs create mode 100644 nushell/crates/nu-command/tests/commands/math/variance.rs create mode 100644 nushell/crates/nu-command/tests/commands/merge.rs create mode 100644 nushell/crates/nu-command/tests/commands/merge_deep.rs create mode 100644 nushell/crates/nu-command/tests/commands/mktemp.rs create mode 100644 nushell/crates/nu-command/tests/commands/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/move_/column.rs create mode 100644 nushell/crates/nu-command/tests/commands/move_/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/move_/umv.rs create mode 100644 nushell/crates/nu-command/tests/commands/mut_.rs create mode 100644 nushell/crates/nu-command/tests/commands/network/http/delete.rs create mode 100644 nushell/crates/nu-command/tests/commands/network/http/get.rs create mode 100644 nushell/crates/nu-command/tests/commands/network/http/head.rs create mode 100644 nushell/crates/nu-command/tests/commands/network/http/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/network/http/options.rs create mode 100644 nushell/crates/nu-command/tests/commands/network/http/patch.rs create mode 100644 nushell/crates/nu-command/tests/commands/network/http/post.rs create mode 100644 nushell/crates/nu-command/tests/commands/network/http/put.rs create mode 100644 nushell/crates/nu-command/tests/commands/network/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/network/port.rs create mode 100644 nushell/crates/nu-command/tests/commands/nu_check.rs create mode 100644 nushell/crates/nu-command/tests/commands/open.rs create mode 100644 nushell/crates/nu-command/tests/commands/par_each.rs create mode 100644 nushell/crates/nu-command/tests/commands/parse.rs create mode 100644 nushell/crates/nu-command/tests/commands/path/basename.rs create mode 100644 nushell/crates/nu-command/tests/commands/path/dirname.rs create mode 100644 nushell/crates/nu-command/tests/commands/path/exists.rs create mode 100644 nushell/crates/nu-command/tests/commands/path/expand.rs create mode 100644 nushell/crates/nu-command/tests/commands/path/join.rs create mode 100644 nushell/crates/nu-command/tests/commands/path/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/path/parse.rs create mode 100644 nushell/crates/nu-command/tests/commands/path/self_.rs create mode 100644 nushell/crates/nu-command/tests/commands/path/split.rs create mode 100644 nushell/crates/nu-command/tests/commands/path/type_.rs create mode 100644 nushell/crates/nu-command/tests/commands/platform/ansi_.rs create mode 100644 nushell/crates/nu-command/tests/commands/platform/char_.rs create mode 100644 nushell/crates/nu-command/tests/commands/platform/kill.rs create mode 100644 nushell/crates/nu-command/tests/commands/platform/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/prepend.rs create mode 100644 nushell/crates/nu-command/tests/commands/print.rs create mode 100644 nushell/crates/nu-command/tests/commands/query/db.rs create mode 100644 nushell/crates/nu-command/tests/commands/query/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/random/binary.rs create mode 100644 nushell/crates/nu-command/tests/commands/random/bool.rs create mode 100644 nushell/crates/nu-command/tests/commands/random/chars.rs create mode 100644 nushell/crates/nu-command/tests/commands/random/dice.rs create mode 100644 nushell/crates/nu-command/tests/commands/random/float.rs create mode 100644 nushell/crates/nu-command/tests/commands/random/int.rs create mode 100644 nushell/crates/nu-command/tests/commands/random/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/random/uuid.rs create mode 100644 nushell/crates/nu-command/tests/commands/redirection.rs create mode 100644 nushell/crates/nu-command/tests/commands/reduce.rs create mode 100644 nushell/crates/nu-command/tests/commands/reject.rs create mode 100644 nushell/crates/nu-command/tests/commands/rename.rs create mode 100644 nushell/crates/nu-command/tests/commands/return_.rs create mode 100644 nushell/crates/nu-command/tests/commands/reverse.rs create mode 100644 nushell/crates/nu-command/tests/commands/rm.rs create mode 100644 nushell/crates/nu-command/tests/commands/roll.rs create mode 100644 nushell/crates/nu-command/tests/commands/rotate.rs create mode 100644 nushell/crates/nu-command/tests/commands/run_external.rs create mode 100644 nushell/crates/nu-command/tests/commands/save.rs create mode 100644 nushell/crates/nu-command/tests/commands/select.rs create mode 100644 nushell/crates/nu-command/tests/commands/semicolon.rs create mode 100644 nushell/crates/nu-command/tests/commands/seq.rs create mode 100644 nushell/crates/nu-command/tests/commands/seq_char.rs create mode 100644 nushell/crates/nu-command/tests/commands/seq_date.rs create mode 100644 nushell/crates/nu-command/tests/commands/skip/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/skip/skip_.rs create mode 100644 nushell/crates/nu-command/tests/commands/skip/until.rs create mode 100644 nushell/crates/nu-command/tests/commands/skip/while_.rs create mode 100644 nushell/crates/nu-command/tests/commands/slice.rs create mode 100644 nushell/crates/nu-command/tests/commands/sort.rs create mode 100644 nushell/crates/nu-command/tests/commands/sort_by.rs create mode 100644 nushell/crates/nu-command/tests/commands/source_env.rs create mode 100644 nushell/crates/nu-command/tests/commands/split_column.rs create mode 100644 nushell/crates/nu-command/tests/commands/split_row.rs create mode 100644 nushell/crates/nu-command/tests/commands/start.rs create mode 100644 nushell/crates/nu-command/tests/commands/stor.rs create mode 100644 nushell/crates/nu-command/tests/commands/str_/into_string.rs create mode 100644 nushell/crates/nu-command/tests/commands/str_/join.rs create mode 100644 nushell/crates/nu-command/tests/commands/str_/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/table.rs create mode 100644 nushell/crates/nu-command/tests/commands/take/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/take/rows.rs create mode 100644 nushell/crates/nu-command/tests/commands/take/until.rs create mode 100644 nushell/crates/nu-command/tests/commands/take/while_.rs create mode 100644 nushell/crates/nu-command/tests/commands/tee.rs create mode 100644 nushell/crates/nu-command/tests/commands/terminal.rs create mode 100644 nushell/crates/nu-command/tests/commands/to_text.rs create mode 100644 nushell/crates/nu-command/tests/commands/transpose.rs create mode 100644 nushell/crates/nu-command/tests/commands/try_.rs create mode 100644 nushell/crates/nu-command/tests/commands/ucp.rs create mode 100644 nushell/crates/nu-command/tests/commands/ulimit.rs create mode 100644 nushell/crates/nu-command/tests/commands/umkdir.rs create mode 100644 nushell/crates/nu-command/tests/commands/uname.rs create mode 100644 nushell/crates/nu-command/tests/commands/uniq.rs create mode 100644 nushell/crates/nu-command/tests/commands/uniq_by.rs create mode 100644 nushell/crates/nu-command/tests/commands/update.rs create mode 100644 nushell/crates/nu-command/tests/commands/upsert.rs create mode 100644 nushell/crates/nu-command/tests/commands/url/decode.rs create mode 100644 nushell/crates/nu-command/tests/commands/url/join.rs create mode 100644 nushell/crates/nu-command/tests/commands/url/mod.rs create mode 100644 nushell/crates/nu-command/tests/commands/url/parse.rs create mode 100644 nushell/crates/nu-command/tests/commands/use_.rs create mode 100644 nushell/crates/nu-command/tests/commands/utouch.rs create mode 100644 nushell/crates/nu-command/tests/commands/where_.rs create mode 100644 nushell/crates/nu-command/tests/commands/which.rs create mode 100644 nushell/crates/nu-command/tests/commands/while_.rs create mode 100644 nushell/crates/nu-command/tests/commands/window.rs create mode 100644 nushell/crates/nu-command/tests/commands/with_env.rs create mode 100644 nushell/crates/nu-command/tests/commands/wrap.rs create mode 100644 nushell/crates/nu-command/tests/commands/zip.rs create mode 100644 nushell/crates/nu-command/tests/format_conversions/csv.rs create mode 100644 nushell/crates/nu-command/tests/format_conversions/html.rs create mode 100644 nushell/crates/nu-command/tests/format_conversions/json.rs create mode 100644 nushell/crates/nu-command/tests/format_conversions/markdown.rs create mode 100644 nushell/crates/nu-command/tests/format_conversions/mod.rs create mode 100644 nushell/crates/nu-command/tests/format_conversions/msgpack.rs create mode 100644 nushell/crates/nu-command/tests/format_conversions/msgpackz.rs create mode 100644 nushell/crates/nu-command/tests/format_conversions/nuon.rs create mode 100644 nushell/crates/nu-command/tests/format_conversions/ods.rs create mode 100644 nushell/crates/nu-command/tests/format_conversions/ssv.rs create mode 100644 nushell/crates/nu-command/tests/format_conversions/toml.rs create mode 100644 nushell/crates/nu-command/tests/format_conversions/tsv.rs create mode 100644 nushell/crates/nu-command/tests/format_conversions/url.rs create mode 100644 nushell/crates/nu-command/tests/format_conversions/xlsx.rs create mode 100644 nushell/crates/nu-command/tests/format_conversions/xml.rs create mode 100644 nushell/crates/nu-command/tests/format_conversions/yaml.rs create mode 100644 nushell/crates/nu-command/tests/main.rs create mode 100644 nushell/crates/nu-command/tests/sort_utils.rs create mode 100644 nushell/crates/nu-command/tests/string/format/duration.rs create mode 100644 nushell/crates/nu-command/tests/string/format/filesize.rs create mode 100644 nushell/crates/nu-command/tests/string/format/mod.rs create mode 100644 nushell/crates/nu-command/tests/string/mod.rs create mode 100644 nushell/crates/nu-derive-value/Cargo.toml create mode 100644 nushell/crates/nu-derive-value/LICENSE create mode 100644 nushell/crates/nu-derive-value/src/attributes.rs create mode 100644 nushell/crates/nu-derive-value/src/case.rs create mode 100644 nushell/crates/nu-derive-value/src/error.rs create mode 100644 nushell/crates/nu-derive-value/src/from.rs create mode 100644 nushell/crates/nu-derive-value/src/into.rs create mode 100644 nushell/crates/nu-derive-value/src/lib.rs create mode 100644 nushell/crates/nu-derive-value/src/names.rs create mode 100644 nushell/crates/nu-derive-value/src/tests.rs create mode 100644 nushell/crates/nu-engine/Cargo.toml create mode 100644 nushell/crates/nu-engine/LICENSE create mode 100644 nushell/crates/nu-engine/README.md create mode 100644 nushell/crates/nu-engine/src/call_ext.rs create mode 100644 nushell/crates/nu-engine/src/closure_eval.rs create mode 100644 nushell/crates/nu-engine/src/column.rs create mode 100644 nushell/crates/nu-engine/src/command_prelude.rs create mode 100644 nushell/crates/nu-engine/src/compile/builder.rs create mode 100644 nushell/crates/nu-engine/src/compile/call.rs create mode 100644 nushell/crates/nu-engine/src/compile/expression.rs create mode 100644 nushell/crates/nu-engine/src/compile/keyword.rs create mode 100644 nushell/crates/nu-engine/src/compile/mod.rs create mode 100644 nushell/crates/nu-engine/src/compile/operator.rs create mode 100644 nushell/crates/nu-engine/src/compile/redirect.rs create mode 100644 nushell/crates/nu-engine/src/documentation.rs create mode 100644 nushell/crates/nu-engine/src/env.rs create mode 100644 nushell/crates/nu-engine/src/eval.rs create mode 100644 nushell/crates/nu-engine/src/eval_helpers.rs create mode 100644 nushell/crates/nu-engine/src/eval_ir.rs create mode 100644 nushell/crates/nu-engine/src/exit.rs create mode 100644 nushell/crates/nu-engine/src/glob_from.rs create mode 100644 nushell/crates/nu-engine/src/lib.rs create mode 100644 nushell/crates/nu-engine/src/scope.rs create mode 100644 nushell/crates/nu-explore/.gitignore create mode 100644 nushell/crates/nu-explore/Cargo.toml create mode 100644 nushell/crates/nu-explore/LICENSE create mode 100644 nushell/crates/nu-explore/README.md create mode 100644 nushell/crates/nu-explore/src/commands/expand.rs create mode 100644 nushell/crates/nu-explore/src/commands/help.rs create mode 100644 nushell/crates/nu-explore/src/commands/mod.rs create mode 100644 nushell/crates/nu-explore/src/commands/nu.rs create mode 100644 nushell/crates/nu-explore/src/commands/quit.rs create mode 100644 nushell/crates/nu-explore/src/commands/table.rs create mode 100644 nushell/crates/nu-explore/src/commands/try.rs create mode 100644 nushell/crates/nu-explore/src/default_context.rs create mode 100644 nushell/crates/nu-explore/src/explore.rs create mode 100644 nushell/crates/nu-explore/src/lib.rs create mode 100644 nushell/crates/nu-explore/src/nu_common/command.rs create mode 100644 nushell/crates/nu-explore/src/nu_common/lscolor.rs create mode 100644 nushell/crates/nu-explore/src/nu_common/mod.rs create mode 100644 nushell/crates/nu-explore/src/nu_common/string.rs create mode 100644 nushell/crates/nu-explore/src/nu_common/table.rs create mode 100644 nushell/crates/nu-explore/src/nu_common/value.rs create mode 100644 nushell/crates/nu-explore/src/pager/command_bar.rs create mode 100644 nushell/crates/nu-explore/src/pager/events.rs create mode 100644 nushell/crates/nu-explore/src/pager/mod.rs create mode 100644 nushell/crates/nu-explore/src/pager/report.rs create mode 100644 nushell/crates/nu-explore/src/pager/status_bar.rs create mode 100644 nushell/crates/nu-explore/src/registry/command.rs create mode 100644 nushell/crates/nu-explore/src/registry/mod.rs create mode 100644 nushell/crates/nu-explore/src/views/binary/binary_widget.rs create mode 100644 nushell/crates/nu-explore/src/views/binary/mod.rs create mode 100644 nushell/crates/nu-explore/src/views/colored_text_widget.rs create mode 100644 nushell/crates/nu-explore/src/views/cursor/mod.rs create mode 100644 nushell/crates/nu-explore/src/views/cursor/window_cursor.rs create mode 100644 nushell/crates/nu-explore/src/views/cursor/window_cursor_2d.rs create mode 100644 nushell/crates/nu-explore/src/views/mod.rs create mode 100644 nushell/crates/nu-explore/src/views/preview.rs create mode 100644 nushell/crates/nu-explore/src/views/record/mod.rs create mode 100644 nushell/crates/nu-explore/src/views/record/table_widget.rs create mode 100644 nushell/crates/nu-explore/src/views/try.rs create mode 100644 nushell/crates/nu-explore/src/views/util.rs create mode 100644 nushell/crates/nu-glob/Cargo.toml create mode 100644 nushell/crates/nu-glob/LICENSE-APACHE create mode 100644 nushell/crates/nu-glob/LICENSE-MIT create mode 100644 nushell/crates/nu-glob/README.md create mode 100644 nushell/crates/nu-glob/src/lib.rs create mode 100644 nushell/crates/nu-json/CHANGELOG.md create mode 100644 nushell/crates/nu-json/Cargo.toml create mode 100644 nushell/crates/nu-json/LICENSE create mode 100644 nushell/crates/nu-json/README.md create mode 100644 nushell/crates/nu-json/src/builder.rs create mode 100644 nushell/crates/nu-json/src/de.rs create mode 100644 nushell/crates/nu-json/src/error.rs create mode 100644 nushell/crates/nu-json/src/lib.rs create mode 100644 nushell/crates/nu-json/src/ser.rs create mode 100644 nushell/crates/nu-json/src/util.rs create mode 100644 nushell/crates/nu-json/src/value.rs create mode 100644 nushell/crates/nu-json/tests/main.rs create mode 100644 nushell/crates/nu-lsp/Cargo.toml create mode 100644 nushell/crates/nu-lsp/LICENSE create mode 100644 nushell/crates/nu-lsp/README.md create mode 100644 nushell/crates/nu-lsp/src/ast.rs create mode 100644 nushell/crates/nu-lsp/src/completion.rs create mode 100644 nushell/crates/nu-lsp/src/diagnostics.rs create mode 100644 nushell/crates/nu-lsp/src/goto.rs create mode 100644 nushell/crates/nu-lsp/src/hints.rs create mode 100644 nushell/crates/nu-lsp/src/hover.rs create mode 100644 nushell/crates/nu-lsp/src/lib.rs create mode 100644 nushell/crates/nu-lsp/src/notification.rs create mode 100644 nushell/crates/nu-lsp/src/semantic_tokens.rs create mode 100644 nushell/crates/nu-lsp/src/signature.rs create mode 100644 nushell/crates/nu-lsp/src/symbols.rs create mode 100644 nushell/crates/nu-lsp/src/workspace.rs create mode 100644 nushell/crates/nu-parser/Cargo.toml create mode 100644 nushell/crates/nu-parser/LICENSE create mode 100644 nushell/crates/nu-parser/README.md create mode 100644 nushell/crates/nu-parser/fuzz/.gitignore create mode 100644 nushell/crates/nu-parser/fuzz/Cargo.toml create mode 100644 nushell/crates/nu-parser/fuzz/README.md create mode 100644 nushell/crates/nu-parser/fuzz/fuzz_targets/parse.rs create mode 100644 nushell/crates/nu-parser/fuzz/fuzz_targets/parse_with_keywords.rs create mode 100755 nushell/crates/nu-parser/fuzz/gather_seeds.nu create mode 100644 nushell/crates/nu-parser/fuzz/rust-toolchain.toml create mode 100644 nushell/crates/nu-parser/src/deparse.rs create mode 100644 nushell/crates/nu-parser/src/exportable.rs create mode 100644 nushell/crates/nu-parser/src/flatten.rs create mode 100644 nushell/crates/nu-parser/src/known_external.rs create mode 100644 nushell/crates/nu-parser/src/lex.rs create mode 100644 nushell/crates/nu-parser/src/lib.rs create mode 100644 nushell/crates/nu-parser/src/lite_parser.rs create mode 100644 nushell/crates/nu-parser/src/parse_keywords.rs create mode 100644 nushell/crates/nu-parser/src/parse_patterns.rs create mode 100644 nushell/crates/nu-parser/src/parse_shape_specs.rs create mode 100644 nushell/crates/nu-parser/src/parser.rs create mode 100644 nushell/crates/nu-parser/src/type_check.rs create mode 100644 nushell/crates/nu-parser/tests/test_lex.rs create mode 100644 nushell/crates/nu-parser/tests/test_parser.rs create mode 100644 nushell/crates/nu-parser/tests/test_parser_unicode_escapes.rs create mode 100644 nushell/crates/nu-path/Cargo.toml create mode 100644 nushell/crates/nu-path/LICENSE create mode 100644 nushell/crates/nu-path/README.md create mode 100644 nushell/crates/nu-path/fuzz/.gitignore create mode 100644 nushell/crates/nu-path/fuzz/Cargo.toml create mode 100644 nushell/crates/nu-path/fuzz/README.md create mode 100644 nushell/crates/nu-path/fuzz/fuzz_targets/path_fuzzer.rs create mode 100644 nushell/crates/nu-path/fuzz/rust-toolchain.toml create mode 100644 nushell/crates/nu-path/src/assert_path_eq.rs create mode 100644 nushell/crates/nu-path/src/components.rs create mode 100644 nushell/crates/nu-path/src/dots.rs create mode 100644 nushell/crates/nu-path/src/expansions.rs create mode 100644 nushell/crates/nu-path/src/form.rs create mode 100644 nushell/crates/nu-path/src/helpers.rs create mode 100644 nushell/crates/nu-path/src/lib.rs create mode 100644 nushell/crates/nu-path/src/path.rs create mode 100644 nushell/crates/nu-path/src/tilde.rs create mode 100644 nushell/crates/nu-path/src/trailing_slash.rs create mode 100644 nushell/crates/nu-plugin-core/Cargo.toml create mode 100644 nushell/crates/nu-plugin-core/LICENSE create mode 100644 nushell/crates/nu-plugin-core/README.md create mode 100644 nushell/crates/nu-plugin-core/src/communication_mode/local_socket/mod.rs create mode 100644 nushell/crates/nu-plugin-core/src/communication_mode/local_socket/tests.rs create mode 100644 nushell/crates/nu-plugin-core/src/communication_mode/mod.rs create mode 100644 nushell/crates/nu-plugin-core/src/interface/mod.rs create mode 100644 nushell/crates/nu-plugin-core/src/interface/stream/mod.rs create mode 100644 nushell/crates/nu-plugin-core/src/interface/stream/tests.rs create mode 100644 nushell/crates/nu-plugin-core/src/interface/test_util.rs create mode 100644 nushell/crates/nu-plugin-core/src/interface/tests.rs create mode 100644 nushell/crates/nu-plugin-core/src/lib.rs create mode 100644 nushell/crates/nu-plugin-core/src/serializers/json.rs create mode 100644 nushell/crates/nu-plugin-core/src/serializers/mod.rs create mode 100644 nushell/crates/nu-plugin-core/src/serializers/msgpack.rs create mode 100644 nushell/crates/nu-plugin-core/src/serializers/tests.rs create mode 100644 nushell/crates/nu-plugin-core/src/util/mod.rs create mode 100644 nushell/crates/nu-plugin-core/src/util/waitable.rs create mode 100644 nushell/crates/nu-plugin-core/src/util/with_custom_values_in.rs create mode 100644 nushell/crates/nu-plugin-engine/Cargo.toml create mode 100644 nushell/crates/nu-plugin-engine/LICENSE create mode 100644 nushell/crates/nu-plugin-engine/README.md create mode 100644 nushell/crates/nu-plugin-engine/src/context.rs create mode 100644 nushell/crates/nu-plugin-engine/src/declaration.rs create mode 100644 nushell/crates/nu-plugin-engine/src/gc.rs create mode 100644 nushell/crates/nu-plugin-engine/src/init.rs create mode 100644 nushell/crates/nu-plugin-engine/src/interface/mod.rs create mode 100644 nushell/crates/nu-plugin-engine/src/interface/tests.rs create mode 100644 nushell/crates/nu-plugin-engine/src/lib.rs create mode 100644 nushell/crates/nu-plugin-engine/src/persistent.rs create mode 100644 nushell/crates/nu-plugin-engine/src/plugin_custom_value_with_source/mod.rs create mode 100644 nushell/crates/nu-plugin-engine/src/plugin_custom_value_with_source/tests.rs create mode 100644 nushell/crates/nu-plugin-engine/src/process.rs create mode 100644 nushell/crates/nu-plugin-engine/src/source.rs create mode 100644 nushell/crates/nu-plugin-engine/src/test_util.rs create mode 100644 nushell/crates/nu-plugin-engine/src/util/mod.rs create mode 100644 nushell/crates/nu-plugin-engine/src/util/mutable_cow.rs create mode 100644 nushell/crates/nu-plugin-protocol/Cargo.toml create mode 100644 nushell/crates/nu-plugin-protocol/LICENSE create mode 100644 nushell/crates/nu-plugin-protocol/README.md create mode 100644 nushell/crates/nu-plugin-protocol/src/evaluated_call.rs create mode 100644 nushell/crates/nu-plugin-protocol/src/lib.rs create mode 100644 nushell/crates/nu-plugin-protocol/src/plugin_custom_value/mod.rs create mode 100644 nushell/crates/nu-plugin-protocol/src/plugin_custom_value/tests.rs create mode 100644 nushell/crates/nu-plugin-protocol/src/protocol_info.rs create mode 100644 nushell/crates/nu-plugin-protocol/src/test_util.rs create mode 100644 nushell/crates/nu-plugin-protocol/src/tests.rs create mode 100644 nushell/crates/nu-plugin-test-support/Cargo.toml create mode 100644 nushell/crates/nu-plugin-test-support/LICENSE create mode 100644 nushell/crates/nu-plugin-test-support/README.md create mode 100644 nushell/crates/nu-plugin-test-support/src/diff.rs create mode 100644 nushell/crates/nu-plugin-test-support/src/fake_persistent_plugin.rs create mode 100644 nushell/crates/nu-plugin-test-support/src/fake_register.rs create mode 100644 nushell/crates/nu-plugin-test-support/src/lib.rs create mode 100644 nushell/crates/nu-plugin-test-support/src/plugin_test.rs create mode 100644 nushell/crates/nu-plugin-test-support/src/spawn_fake_plugin.rs create mode 100644 nushell/crates/nu-plugin-test-support/tests/custom_value/mod.rs create mode 100644 nushell/crates/nu-plugin-test-support/tests/hello/mod.rs create mode 100644 nushell/crates/nu-plugin-test-support/tests/lowercase/mod.rs create mode 100644 nushell/crates/nu-plugin-test-support/tests/main.rs create mode 100644 nushell/crates/nu-plugin/Cargo.toml create mode 100644 nushell/crates/nu-plugin/LICENSE create mode 100644 nushell/crates/nu-plugin/README.md create mode 100644 nushell/crates/nu-plugin/src/lib.rs create mode 100644 nushell/crates/nu-plugin/src/plugin/command.rs create mode 100644 nushell/crates/nu-plugin/src/plugin/interface/mod.rs create mode 100644 nushell/crates/nu-plugin/src/plugin/interface/tests.rs create mode 100644 nushell/crates/nu-plugin/src/plugin/mod.rs create mode 100644 nushell/crates/nu-plugin/src/test_util.rs create mode 100644 nushell/crates/nu-pretty-hex/Cargo.toml create mode 100644 nushell/crates/nu-pretty-hex/LICENSE create mode 100644 nushell/crates/nu-pretty-hex/README.md create mode 100644 nushell/crates/nu-pretty-hex/examples/hex_demo.rs create mode 100644 nushell/crates/nu-pretty-hex/src/lib.rs create mode 100644 nushell/crates/nu-pretty-hex/src/pretty_hex.rs create mode 100644 nushell/crates/nu-pretty-hex/tests/256.txt create mode 100644 nushell/crates/nu-pretty-hex/tests/data create mode 100644 nushell/crates/nu-pretty-hex/tests/tests.rs create mode 100644 nushell/crates/nu-protocol/Cargo.toml create mode 100644 nushell/crates/nu-protocol/LICENSE create mode 100644 nushell/crates/nu-protocol/README.md create mode 100644 nushell/crates/nu-protocol/src/alias.rs create mode 100644 nushell/crates/nu-protocol/src/ast/attribute.rs create mode 100644 nushell/crates/nu-protocol/src/ast/block.rs create mode 100644 nushell/crates/nu-protocol/src/ast/call.rs create mode 100644 nushell/crates/nu-protocol/src/ast/cell_path.rs create mode 100644 nushell/crates/nu-protocol/src/ast/expr.rs create mode 100644 nushell/crates/nu-protocol/src/ast/expression.rs create mode 100644 nushell/crates/nu-protocol/src/ast/import_pattern.rs create mode 100644 nushell/crates/nu-protocol/src/ast/keyword.rs create mode 100644 nushell/crates/nu-protocol/src/ast/match_pattern.rs create mode 100644 nushell/crates/nu-protocol/src/ast/mod.rs create mode 100644 nushell/crates/nu-protocol/src/ast/operator.rs create mode 100644 nushell/crates/nu-protocol/src/ast/pipeline.rs create mode 100644 nushell/crates/nu-protocol/src/ast/range.rs create mode 100644 nushell/crates/nu-protocol/src/ast/table.rs create mode 100644 nushell/crates/nu-protocol/src/ast/traverse.rs create mode 100644 nushell/crates/nu-protocol/src/ast/unit.rs create mode 100644 nushell/crates/nu-protocol/src/ast/value_with_unit.rs create mode 100644 nushell/crates/nu-protocol/src/casing.rs create mode 100644 nushell/crates/nu-protocol/src/config/ansi_coloring.rs create mode 100644 nushell/crates/nu-protocol/src/config/completions.rs create mode 100644 nushell/crates/nu-protocol/src/config/datetime_format.rs create mode 100644 nushell/crates/nu-protocol/src/config/display_errors.rs create mode 100644 nushell/crates/nu-protocol/src/config/error.rs create mode 100644 nushell/crates/nu-protocol/src/config/filesize.rs create mode 100644 nushell/crates/nu-protocol/src/config/helper.rs create mode 100644 nushell/crates/nu-protocol/src/config/history.rs create mode 100644 nushell/crates/nu-protocol/src/config/hooks.rs create mode 100644 nushell/crates/nu-protocol/src/config/ls.rs create mode 100644 nushell/crates/nu-protocol/src/config/mod.rs create mode 100644 nushell/crates/nu-protocol/src/config/output.rs create mode 100644 nushell/crates/nu-protocol/src/config/plugin_gc.rs create mode 100644 nushell/crates/nu-protocol/src/config/prelude.rs create mode 100644 nushell/crates/nu-protocol/src/config/reedline.rs create mode 100644 nushell/crates/nu-protocol/src/config/rm.rs create mode 100644 nushell/crates/nu-protocol/src/config/shell_integration.rs create mode 100644 nushell/crates/nu-protocol/src/config/table.rs create mode 100644 nushell/crates/nu-protocol/src/debugger/debugger_trait.rs create mode 100644 nushell/crates/nu-protocol/src/debugger/mod.rs create mode 100644 nushell/crates/nu-protocol/src/debugger/profiler.rs create mode 100644 nushell/crates/nu-protocol/src/deprecation.rs create mode 100644 nushell/crates/nu-protocol/src/did_you_mean.rs create mode 100644 nushell/crates/nu-protocol/src/engine/argument.rs create mode 100644 nushell/crates/nu-protocol/src/engine/cached_file.rs create mode 100644 nushell/crates/nu-protocol/src/engine/call.rs create mode 100644 nushell/crates/nu-protocol/src/engine/call_info.rs create mode 100644 nushell/crates/nu-protocol/src/engine/closure.rs create mode 100644 nushell/crates/nu-protocol/src/engine/command.rs create mode 100644 nushell/crates/nu-protocol/src/engine/description.rs create mode 100644 nushell/crates/nu-protocol/src/engine/engine_state.rs create mode 100644 nushell/crates/nu-protocol/src/engine/error_handler.rs create mode 100644 nushell/crates/nu-protocol/src/engine/jobs.rs create mode 100644 nushell/crates/nu-protocol/src/engine/mod.rs create mode 100644 nushell/crates/nu-protocol/src/engine/overlay.rs create mode 100644 nushell/crates/nu-protocol/src/engine/pattern_match.rs create mode 100644 nushell/crates/nu-protocol/src/engine/sequence.rs create mode 100644 nushell/crates/nu-protocol/src/engine/stack.rs create mode 100644 nushell/crates/nu-protocol/src/engine/stack_out_dest.rs create mode 100644 nushell/crates/nu-protocol/src/engine/state_delta.rs create mode 100644 nushell/crates/nu-protocol/src/engine/state_working_set.rs create mode 100644 nushell/crates/nu-protocol/src/engine/variable.rs create mode 100644 nushell/crates/nu-protocol/src/errors/chained_error.rs create mode 100644 nushell/crates/nu-protocol/src/errors/cli_error.rs create mode 100644 nushell/crates/nu-protocol/src/errors/compile_error.rs create mode 100644 nushell/crates/nu-protocol/src/errors/config_error.rs create mode 100644 nushell/crates/nu-protocol/src/errors/labeled_error.rs create mode 100644 nushell/crates/nu-protocol/src/errors/mod.rs create mode 100644 nushell/crates/nu-protocol/src/errors/parse_error.rs create mode 100644 nushell/crates/nu-protocol/src/errors/parse_warning.rs create mode 100644 nushell/crates/nu-protocol/src/errors/shell_error/bridge.rs create mode 100644 nushell/crates/nu-protocol/src/errors/shell_error/io.rs create mode 100644 nushell/crates/nu-protocol/src/errors/shell_error/job.rs create mode 100644 nushell/crates/nu-protocol/src/errors/shell_error/location.rs create mode 100644 nushell/crates/nu-protocol/src/errors/shell_error/mod.rs create mode 100644 nushell/crates/nu-protocol/src/eval_base.rs create mode 100644 nushell/crates/nu-protocol/src/eval_const.rs create mode 100644 nushell/crates/nu-protocol/src/example.rs create mode 100644 nushell/crates/nu-protocol/src/id.rs create mode 100644 nushell/crates/nu-protocol/src/ir/call.rs create mode 100644 nushell/crates/nu-protocol/src/ir/display.rs create mode 100644 nushell/crates/nu-protocol/src/ir/mod.rs create mode 100644 nushell/crates/nu-protocol/src/lev_distance.rs create mode 100644 nushell/crates/nu-protocol/src/lib.rs create mode 100644 nushell/crates/nu-protocol/src/module.rs create mode 100644 nushell/crates/nu-protocol/src/parser_path.rs create mode 100644 nushell/crates/nu-protocol/src/pipeline/byte_stream.rs create mode 100644 nushell/crates/nu-protocol/src/pipeline/handlers.rs create mode 100644 nushell/crates/nu-protocol/src/pipeline/list_stream.rs create mode 100644 nushell/crates/nu-protocol/src/pipeline/metadata.rs create mode 100644 nushell/crates/nu-protocol/src/pipeline/mod.rs create mode 100644 nushell/crates/nu-protocol/src/pipeline/out_dest.rs create mode 100644 nushell/crates/nu-protocol/src/pipeline/pipeline_data.rs create mode 100644 nushell/crates/nu-protocol/src/pipeline/signals.rs create mode 100644 nushell/crates/nu-protocol/src/plugin/identity.rs create mode 100644 nushell/crates/nu-protocol/src/plugin/metadata.rs create mode 100644 nushell/crates/nu-protocol/src/plugin/mod.rs create mode 100644 nushell/crates/nu-protocol/src/plugin/registered.rs create mode 100644 nushell/crates/nu-protocol/src/plugin/registry_file/mod.rs create mode 100644 nushell/crates/nu-protocol/src/plugin/registry_file/tests.rs create mode 100644 nushell/crates/nu-protocol/src/plugin/signature.rs create mode 100644 nushell/crates/nu-protocol/src/process/child.rs create mode 100644 nushell/crates/nu-protocol/src/process/mod.rs create mode 100644 nushell/crates/nu-protocol/src/signature.rs create mode 100644 nushell/crates/nu-protocol/src/span.rs create mode 100644 nushell/crates/nu-protocol/src/syntax_shape.rs create mode 100644 nushell/crates/nu-protocol/src/ty.rs create mode 100644 nushell/crates/nu-protocol/src/value/custom_value.rs create mode 100644 nushell/crates/nu-protocol/src/value/duration.rs create mode 100644 nushell/crates/nu-protocol/src/value/filesize.rs create mode 100644 nushell/crates/nu-protocol/src/value/format.rs create mode 100644 nushell/crates/nu-protocol/src/value/from_value.rs create mode 100644 nushell/crates/nu-protocol/src/value/glob.rs create mode 100644 nushell/crates/nu-protocol/src/value/into_value.rs create mode 100644 nushell/crates/nu-protocol/src/value/mod.rs create mode 100644 nushell/crates/nu-protocol/src/value/range.rs create mode 100644 nushell/crates/nu-protocol/src/value/record.rs create mode 100644 nushell/crates/nu-protocol/src/value/test_derive.rs create mode 100644 nushell/crates/nu-protocol/tests/into_config.rs create mode 100644 nushell/crates/nu-protocol/tests/mod.rs create mode 100644 nushell/crates/nu-protocol/tests/pipeline/byte_stream.rs create mode 100644 nushell/crates/nu-protocol/tests/pipeline/mod.rs create mode 100644 nushell/crates/nu-protocol/tests/test_config.rs create mode 100644 nushell/crates/nu-protocol/tests/test_pipeline_data.rs create mode 100644 nushell/crates/nu-protocol/tests/test_signature.rs create mode 100644 nushell/crates/nu-protocol/tests/test_value.rs create mode 100644 nushell/crates/nu-std/CONTRIBUTING.md create mode 100644 nushell/crates/nu-std/Cargo.toml create mode 100644 nushell/crates/nu-std/LICENSE create mode 100644 nushell/crates/nu-std/README.md create mode 100644 nushell/crates/nu-std/src/lib.rs create mode 100644 nushell/crates/nu-std/std-rfc/README.md create mode 100644 nushell/crates/nu-std/std-rfc/clip/mod.nu create mode 100644 nushell/crates/nu-std/std-rfc/conversions/mod.nu create mode 100644 nushell/crates/nu-std/std-rfc/iter/mod.nu create mode 100644 nushell/crates/nu-std/std-rfc/kv/mod.nu create mode 100644 nushell/crates/nu-std/std-rfc/mod.nu create mode 100644 nushell/crates/nu-std/std-rfc/path/mod.nu create mode 100644 nushell/crates/nu-std/std-rfc/str/mod.nu create mode 100644 nushell/crates/nu-std/std-rfc/tables/mod.nu create mode 100644 nushell/crates/nu-std/std/assert/mod.nu create mode 100644 nushell/crates/nu-std/std/bench/mod.nu create mode 100644 nushell/crates/nu-std/std/clip/mod.nu create mode 100644 nushell/crates/nu-std/std/config/mod.nu create mode 100644 nushell/crates/nu-std/std/dirs/mod.nu create mode 100644 nushell/crates/nu-std/std/dt/mod.nu create mode 100644 nushell/crates/nu-std/std/formats/mod.nu create mode 100644 nushell/crates/nu-std/std/help/mod.nu create mode 100644 nushell/crates/nu-std/std/input/mod.nu create mode 100644 nushell/crates/nu-std/std/iter/mod.nu create mode 100644 nushell/crates/nu-std/std/log/mod.nu create mode 100644 nushell/crates/nu-std/std/math/mod.nu create mode 100644 nushell/crates/nu-std/std/mod.nu create mode 100644 nushell/crates/nu-std/std/prelude/mod.nu create mode 100644 nushell/crates/nu-std/std/testing/mod.nu create mode 100644 nushell/crates/nu-std/std/util/mod.nu create mode 100644 nushell/crates/nu-std/std/xml/mod.nu create mode 100644 nushell/crates/nu-std/testing.nu create mode 100644 nushell/crates/nu-std/tests/logger_tests/commons.nu create mode 100644 nushell/crates/nu-std/tests/logger_tests/test_basic_commands.nu create mode 100644 nushell/crates/nu-std/tests/logger_tests/test_log_custom.nu create mode 100644 nushell/crates/nu-std/tests/logger_tests/test_log_format_flag.nu create mode 100644 nushell/crates/nu-std/tests/logger_tests/test_logger_env.nu create mode 100644 nushell/crates/nu-std/tests/test_asserts.nu create mode 100644 nushell/crates/nu-std/tests/test_dirs.nu create mode 100644 nushell/crates/nu-std/tests/test_dt.nu create mode 100644 nushell/crates/nu-std/tests/test_formats.nu create mode 100644 nushell/crates/nu-std/tests/test_help.nu create mode 100644 nushell/crates/nu-std/tests/test_iter.nu create mode 100644 nushell/crates/nu-std/tests/test_prelude.nu create mode 100644 nushell/crates/nu-std/tests/test_setup_teardown.nu create mode 100644 nushell/crates/nu-std/tests/test_std-rfc_conversions.nu create mode 100644 nushell/crates/nu-std/tests/test_std-rfc_iter.nu create mode 100644 nushell/crates/nu-std/tests/test_std-rfc_kv.nu create mode 100644 nushell/crates/nu-std/tests/test_std-rfc_path.nu create mode 100644 nushell/crates/nu-std/tests/test_std-rfc_str.nu create mode 100644 nushell/crates/nu-std/tests/test_std-rfc_tables.nu create mode 100644 nushell/crates/nu-std/tests/test_std_formats.nu create mode 100644 nushell/crates/nu-std/tests/test_std_postload.nu create mode 100644 nushell/crates/nu-std/tests/test_std_preload.nu create mode 100644 nushell/crates/nu-std/tests/test_std_util.nu create mode 100644 nushell/crates/nu-std/tests/test_util.nu create mode 100644 nushell/crates/nu-std/tests/test_xml.nu create mode 100644 nushell/crates/nu-system/.gitignore create mode 100644 nushell/crates/nu-system/Cargo.toml create mode 100644 nushell/crates/nu-system/LICENSE create mode 100644 nushell/crates/nu-system/README.md create mode 100644 nushell/crates/nu-system/examples/sys_demo.rs create mode 100644 nushell/crates/nu-system/src/exit_status.rs create mode 100644 nushell/crates/nu-system/src/foreground.rs create mode 100644 nushell/crates/nu-system/src/freebsd.rs create mode 100644 nushell/crates/nu-system/src/lib.rs create mode 100644 nushell/crates/nu-system/src/linux.rs create mode 100644 nushell/crates/nu-system/src/macos.rs create mode 100644 nushell/crates/nu-system/src/netbsd.rs create mode 100644 nushell/crates/nu-system/src/os_info.rs create mode 100644 nushell/crates/nu-system/src/util.rs create mode 100644 nushell/crates/nu-system/src/windows.rs create mode 100644 nushell/crates/nu-table/.gitignore create mode 100644 nushell/crates/nu-table/Cargo.toml create mode 100644 nushell/crates/nu-table/LICENSE create mode 100644 nushell/crates/nu-table/README.md create mode 100644 nushell/crates/nu-table/examples/table_demo.rs create mode 100644 nushell/crates/nu-table/src/common.rs create mode 100644 nushell/crates/nu-table/src/lib.rs create mode 100644 nushell/crates/nu-table/src/table.rs create mode 100644 nushell/crates/nu-table/src/table_theme.rs create mode 100644 nushell/crates/nu-table/src/types/collapse.rs create mode 100644 nushell/crates/nu-table/src/types/expanded.rs create mode 100644 nushell/crates/nu-table/src/types/general.rs create mode 100644 nushell/crates/nu-table/src/types/mod.rs create mode 100644 nushell/crates/nu-table/src/unstructured_table.rs create mode 100644 nushell/crates/nu-table/src/util.rs create mode 100644 nushell/crates/nu-table/tests/common.rs create mode 100644 nushell/crates/nu-table/tests/constrains.rs create mode 100644 nushell/crates/nu-table/tests/expand.rs create mode 100644 nushell/crates/nu-table/tests/style.rs create mode 100644 nushell/crates/nu-term-grid/.gitignore create mode 100644 nushell/crates/nu-term-grid/Cargo.toml create mode 100644 nushell/crates/nu-term-grid/LICENSE create mode 100644 nushell/crates/nu-term-grid/README.md create mode 100644 nushell/crates/nu-term-grid/examples/grid_demo.rs create mode 100644 nushell/crates/nu-term-grid/src/grid.rs create mode 100644 nushell/crates/nu-term-grid/src/lib.rs create mode 100644 nushell/crates/nu-test-support/Cargo.toml create mode 100644 nushell/crates/nu-test-support/LICENSE create mode 100644 nushell/crates/nu-test-support/README.md create mode 100644 nushell/crates/nu-test-support/src/commands.rs create mode 100644 nushell/crates/nu-test-support/src/fs.rs create mode 100644 nushell/crates/nu-test-support/src/lib.rs create mode 100644 nushell/crates/nu-test-support/src/locale_override.rs create mode 100644 nushell/crates/nu-test-support/src/macros.rs create mode 100644 nushell/crates/nu-test-support/src/playground.rs create mode 100644 nushell/crates/nu-test-support/src/playground/director.rs create mode 100644 nushell/crates/nu-test-support/src/playground/nu_process.rs create mode 100644 nushell/crates/nu-test-support/src/playground/play.rs create mode 100644 nushell/crates/nu-test-support/src/playground/tests.rs create mode 100644 nushell/crates/nu-test-support/tests/get_system_locale.rs create mode 100644 nushell/crates/nu-utils/.gitignore create mode 100644 nushell/crates/nu-utils/Cargo.toml create mode 100644 nushell/crates/nu-utils/LICENSE create mode 100644 nushell/crates/nu-utils/README.md create mode 100644 nushell/crates/nu-utils/src/casing.rs create mode 100644 nushell/crates/nu-utils/src/deansi.rs create mode 100644 nushell/crates/nu-utils/src/default_files/README.md create mode 100644 nushell/crates/nu-utils/src/default_files/default_config.nu create mode 100644 nushell/crates/nu-utils/src/default_files/default_env.nu create mode 100644 nushell/crates/nu-utils/src/default_files/doc_config.nu create mode 100644 nushell/crates/nu-utils/src/default_files/doc_env.nu create mode 100644 nushell/crates/nu-utils/src/default_files/scaffold_config.nu create mode 100644 nushell/crates/nu-utils/src/default_files/scaffold_env.nu create mode 100644 nushell/crates/nu-utils/src/emoji.rs create mode 100644 nushell/crates/nu-utils/src/filesystem.rs create mode 100644 nushell/crates/nu-utils/src/flatten_json.rs create mode 100644 nushell/crates/nu-utils/src/lib.rs create mode 100644 nushell/crates/nu-utils/src/locale.rs create mode 100644 nushell/crates/nu-utils/src/main.rs create mode 100644 nushell/crates/nu-utils/src/quoting.rs create mode 100644 nushell/crates/nu-utils/src/shared_cow.rs create mode 100644 nushell/crates/nu-utils/src/utils.rs create mode 100644 nushell/crates/nu_plugin_custom_values/Cargo.toml create mode 100644 nushell/crates/nu_plugin_custom_values/src/cool_custom_value.rs create mode 100644 nushell/crates/nu_plugin_custom_values/src/drop_check.rs create mode 100644 nushell/crates/nu_plugin_custom_values/src/generate.rs create mode 100644 nushell/crates/nu_plugin_custom_values/src/generate2.rs create mode 100644 nushell/crates/nu_plugin_custom_values/src/handle_custom_value.rs create mode 100644 nushell/crates/nu_plugin_custom_values/src/handle_get.rs create mode 100644 nushell/crates/nu_plugin_custom_values/src/handle_make.rs create mode 100644 nushell/crates/nu_plugin_custom_values/src/handle_update.rs create mode 100644 nushell/crates/nu_plugin_custom_values/src/main.rs create mode 100644 nushell/crates/nu_plugin_custom_values/src/second_custom_value.rs create mode 100644 nushell/crates/nu_plugin_custom_values/src/update.rs create mode 100644 nushell/crates/nu_plugin_custom_values/src/update_arg.rs create mode 100644 nushell/crates/nu_plugin_example/Cargo.toml create mode 100644 nushell/crates/nu_plugin_example/README.md create mode 100644 nushell/crates/nu_plugin_example/src/commands/call_decl.rs create mode 100644 nushell/crates/nu_plugin_example/src/commands/collect_bytes.rs create mode 100644 nushell/crates/nu_plugin_example/src/commands/config.rs create mode 100644 nushell/crates/nu_plugin_example/src/commands/ctrlc.rs create mode 100644 nushell/crates/nu_plugin_example/src/commands/disable_gc.rs create mode 100644 nushell/crates/nu_plugin_example/src/commands/echo.rs create mode 100644 nushell/crates/nu_plugin_example/src/commands/env.rs create mode 100644 nushell/crates/nu_plugin_example/src/commands/for_each.rs create mode 100644 nushell/crates/nu_plugin_example/src/commands/generate.rs create mode 100644 nushell/crates/nu_plugin_example/src/commands/main.rs create mode 100644 nushell/crates/nu_plugin_example/src/commands/mod.rs create mode 100644 nushell/crates/nu_plugin_example/src/commands/one.rs create mode 100644 nushell/crates/nu_plugin_example/src/commands/seq.rs create mode 100644 nushell/crates/nu_plugin_example/src/commands/sum.rs create mode 100644 nushell/crates/nu_plugin_example/src/commands/three.rs create mode 100644 nushell/crates/nu_plugin_example/src/commands/two.rs create mode 100644 nushell/crates/nu_plugin_example/src/commands/view_span.rs create mode 100644 nushell/crates/nu_plugin_example/src/example.rs create mode 100644 nushell/crates/nu_plugin_example/src/lib.rs create mode 100644 nushell/crates/nu_plugin_example/src/main.rs create mode 100644 nushell/crates/nu_plugin_formats/Cargo.toml create mode 100644 nushell/crates/nu_plugin_formats/README.md create mode 100644 nushell/crates/nu_plugin_formats/src/from/eml.rs create mode 100644 nushell/crates/nu_plugin_formats/src/from/ics.rs create mode 100644 nushell/crates/nu_plugin_formats/src/from/ini.rs create mode 100644 nushell/crates/nu_plugin_formats/src/from/mod.rs create mode 100644 nushell/crates/nu_plugin_formats/src/from/plist.rs create mode 100644 nushell/crates/nu_plugin_formats/src/from/vcf.rs create mode 100644 nushell/crates/nu_plugin_formats/src/lib.rs create mode 100644 nushell/crates/nu_plugin_formats/src/main.rs create mode 100644 nushell/crates/nu_plugin_formats/src/to/mod.rs create mode 100644 nushell/crates/nu_plugin_formats/src/to/plist.rs create mode 100644 nushell/crates/nu_plugin_gstat/Cargo.toml create mode 100644 nushell/crates/nu_plugin_gstat/README.md create mode 100644 nushell/crates/nu_plugin_gstat/src/gstat.rs create mode 100644 nushell/crates/nu_plugin_gstat/src/lib.rs create mode 100644 nushell/crates/nu_plugin_gstat/src/main.rs create mode 100644 nushell/crates/nu_plugin_gstat/src/nu/mod.rs create mode 100644 nushell/crates/nu_plugin_inc/Cargo.toml create mode 100644 nushell/crates/nu_plugin_inc/README.md create mode 100644 nushell/crates/nu_plugin_inc/src/inc.rs create mode 100644 nushell/crates/nu_plugin_inc/src/lib.rs create mode 100644 nushell/crates/nu_plugin_inc/src/main.rs create mode 100644 nushell/crates/nu_plugin_inc/src/nu/mod.rs create mode 100644 nushell/crates/nu_plugin_javascript/nu_plugin_node_example.js create mode 100755 nushell/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu create mode 100644 nushell/crates/nu_plugin_polars/Cargo.toml create mode 100644 nushell/crates/nu_plugin_polars/LICENSE create mode 100644 nushell/crates/nu_plugin_polars/src/cache/get.rs create mode 100644 nushell/crates/nu_plugin_polars/src/cache/list.rs create mode 100644 nushell/crates/nu_plugin_polars/src/cache/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/cache/rm.rs create mode 100644 nushell/crates/nu_plugin_polars/src/cloud/aws.rs create mode 100644 nushell/crates/nu_plugin_polars/src/cloud/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/README.md create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/agg_groups.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/aggregate.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/count.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/cumulative.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/groupby.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/horizontal.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/implode.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/max.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/mean.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/median.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/min.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/n_null.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/n_unique.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/over.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/quantile.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/rolling.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/std.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/sum.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/value_counts.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/aggregation/var.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/boolean/all_false.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/boolean/all_true.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/boolean/arg_true.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/boolean/expr_not.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/boolean/is_duplicated.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/boolean/is_in.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/boolean/is_not_null.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/boolean/is_null.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/boolean/is_unique.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/boolean/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/boolean/not.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/boolean/otherwise.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/boolean/set.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/boolean/when.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/computation/math.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/computation/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/cache.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/columns.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/fetch.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/open.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/profile.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/resource.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/save/arrow.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/save/avro.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/save/csv.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/save/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/save/ndjson.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/save/parquet.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/schema.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/shape.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/summary.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/to_df.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/to_dtype.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/to_lazy.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/to_nu.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/to_repr.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/core/to_schema.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/alias.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/append.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/arg_where.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/cast.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/col.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/collect.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/concat.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/cut.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/drop.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/drop_duplicates.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/drop_nulls.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/dummies.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/explode.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/fill_nan.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/fill_null.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/filter.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/filter_with.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/first.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/flatten.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/get.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/join.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/join_where.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/last.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/len.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/lit.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/pivot.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/qcut.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/query_df.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/rename.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/replace.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/reverse.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/sample.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/select.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/shift.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/slice.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/sort_by_expr.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/sql_context.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/sql_expr.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/struct_json_encode.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/take.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/unique.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/unnest.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/unpivot.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/data/with_column.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/as_date.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/as_datetime.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/convert_time_zone.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/datepart.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/get_day.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/get_hour.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/get_minute.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/get_month.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/get_nanosecond.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/get_ordinal.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/get_second.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/get_week.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/get_weekday.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/get_year.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/replace_time_zone.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/strftime.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/datetime/truncate.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/index/arg_max.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/index/arg_min.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/index/arg_sort.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/index/arg_unique.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/index/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/index/set_with_idx.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/integer/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/integer/to_decimal.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/integer/to_integer.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/list/contains.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/list/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/string/concat_str.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/string/contains.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/string/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/string/str_join.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/string/str_lengths.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/string/str_replace.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/string/str_replace_all.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/string/str_slice.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/string/str_split.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/string/str_strip_chars.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/string/to_lowercase.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/string/to_uppercase.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/command/stub.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/utils.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/file_type.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/between_values.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/conversion.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/custom_value.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/operations.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_dtype/custom_value.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_dtype/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_expression/custom_value.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_expression/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_lazyframe/custom_value.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_lazyframe/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_lazygroupby/custom_value.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_lazygroupby/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_schema/custom_value.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_schema/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_when/custom_value.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/nu_when/mod.rs create mode 100644 nushell/crates/nu_plugin_polars/src/dataframe/values/utils.rs create mode 100644 nushell/crates/nu_plugin_polars/src/lib.rs create mode 100644 nushell/crates/nu_plugin_polars/src/main.rs create mode 100755 nushell/crates/nu_plugin_python/nu_plugin_python_example.py create mode 100644 nushell/crates/nu_plugin_query/Cargo.toml create mode 100644 nushell/crates/nu_plugin_query/README.md create mode 100644 nushell/crates/nu_plugin_query/src/lib.rs create mode 100644 nushell/crates/nu_plugin_query/src/main.rs create mode 100644 nushell/crates/nu_plugin_query/src/query.rs create mode 100644 nushell/crates/nu_plugin_query/src/query_json.rs create mode 100644 nushell/crates/nu_plugin_query/src/query_web.rs create mode 100644 nushell/crates/nu_plugin_query/src/query_webpage_info.rs create mode 100644 nushell/crates/nu_plugin_query/src/query_xml.rs create mode 100644 nushell/crates/nu_plugin_query/src/web_tables.rs create mode 100644 nushell/crates/nu_plugin_stress_internals/Cargo.toml create mode 100644 nushell/crates/nu_plugin_stress_internals/LICENSE create mode 100644 nushell/crates/nu_plugin_stress_internals/src/main.rs create mode 100644 nushell/crates/nuon/Cargo.toml create mode 100644 nushell/crates/nuon/LICENSE create mode 100644 nushell/crates/nuon/README.md create mode 100644 nushell/crates/nuon/src/from.rs create mode 100644 nushell/crates/nuon/src/lib.rs create mode 100644 nushell/crates/nuon/src/to.rs create mode 100644 nushell/devdocs/FAQ.md create mode 100644 nushell/devdocs/HOWTOS.md create mode 100644 nushell/devdocs/PLATFORM_SUPPORT.md create mode 100644 nushell/devdocs/README.md create mode 100644 nushell/devdocs/rust_style.md create mode 100644 nushell/docker/Dockerfile create mode 100644 nushell/docker/debian.Dockerfile create mode 100755 nushell/docker/test_docker.nu create mode 100644 nushell/rust-toolchain.toml create mode 100644 nushell/scripts/README.md create mode 100755 nushell/scripts/build-all-maclin.sh create mode 100644 nushell/scripts/build-all-windows.cmd create mode 100644 nushell/scripts/build-all.nu create mode 100644 nushell/scripts/build.rs create mode 100755 nushell/scripts/coverage-local.nu create mode 100755 nushell/scripts/coverage-local.sh create mode 100644 nushell/scripts/install-all.ps1 create mode 100755 nushell/scripts/install-all.sh create mode 100644 nushell/scripts/test_virtualenv.nu create mode 100755 nushell/scripts/uninstall-all.sh create mode 100644 nushell/src/README.md create mode 100644 nushell/src/command.rs create mode 100644 nushell/src/command_context.rs create mode 100644 nushell/src/config_files.rs create mode 100644 nushell/src/ide.rs create mode 100644 nushell/src/logger.rs create mode 100644 nushell/src/main.rs create mode 100644 nushell/src/run.rs create mode 100644 nushell/src/signals.rs create mode 100644 nushell/src/terminal.rs create mode 100644 nushell/src/test_bins.rs create mode 100644 nushell/tests/assets/nu_json/charset_result.hjson create mode 100644 nushell/tests/assets/nu_json/charset_result.json create mode 100644 nushell/tests/assets/nu_json/charset_test.hjson create mode 100644 nushell/tests/assets/nu_json/comments_result.hjson create mode 100644 nushell/tests/assets/nu_json/comments_result.json create mode 100644 nushell/tests/assets/nu_json/comments_test.hjson create mode 100644 nushell/tests/assets/nu_json/empty_result.hjson create mode 100644 nushell/tests/assets/nu_json/empty_result.json create mode 100644 nushell/tests/assets/nu_json/empty_test.hjson create mode 100644 nushell/tests/assets/nu_json/failCharset1_test.hjson create mode 100644 nushell/tests/assets/nu_json/failJSON02_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON05_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON06_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON07_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON08_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON10_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON11_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON12_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON13_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON14_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON15_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON16_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON17_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON19_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON20_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON21_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON22_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON23_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON24_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON26_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON28_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON29_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON30_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON31_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON32_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON33_test.json create mode 100644 nushell/tests/assets/nu_json/failJSON34_test.json create mode 100644 nushell/tests/assets/nu_json/failKey1_test.hjson create mode 100644 nushell/tests/assets/nu_json/failKey2_test.hjson create mode 100644 nushell/tests/assets/nu_json/failKey3_test.hjson create mode 100644 nushell/tests/assets/nu_json/failKey4_test.hjson create mode 100644 nushell/tests/assets/nu_json/failMLStr1_test.hjson create mode 100644 nushell/tests/assets/nu_json/failObj1_test.hjson create mode 100644 nushell/tests/assets/nu_json/failObj2_test.hjson create mode 100644 nushell/tests/assets/nu_json/failObj3_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr1a_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr1b_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr1c_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr1d_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr2a_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr2b_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr2c_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr2d_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr3a_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr3b_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr3c_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr3d_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr4a_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr4b_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr4c_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr4d_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr5a_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr5b_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr5c_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr5d_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr6a_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr6b_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr6c_test.hjson create mode 100644 nushell/tests/assets/nu_json/failStr6d_test.hjson create mode 100644 nushell/tests/assets/nu_json/kan_result.hjson create mode 100644 nushell/tests/assets/nu_json/kan_result.json create mode 100644 nushell/tests/assets/nu_json/kan_test.hjson create mode 100644 nushell/tests/assets/nu_json/keys_result.hjson create mode 100644 nushell/tests/assets/nu_json/keys_result.json create mode 100644 nushell/tests/assets/nu_json/keys_test.hjson create mode 100644 nushell/tests/assets/nu_json/oa_result.hjson create mode 100644 nushell/tests/assets/nu_json/oa_result.json create mode 100644 nushell/tests/assets/nu_json/oa_test.hjson create mode 100644 nushell/tests/assets/nu_json/pass1_result.hjson create mode 100644 nushell/tests/assets/nu_json/pass1_result.json create mode 100644 nushell/tests/assets/nu_json/pass1_test.json create mode 100644 nushell/tests/assets/nu_json/pass2_result.hjson create mode 100644 nushell/tests/assets/nu_json/pass2_result.json create mode 100644 nushell/tests/assets/nu_json/pass2_test.json create mode 100644 nushell/tests/assets/nu_json/pass3_result.hjson create mode 100644 nushell/tests/assets/nu_json/pass3_result.json create mode 100644 nushell/tests/assets/nu_json/pass3_test.json create mode 100644 nushell/tests/assets/nu_json/pass4_result.hjson create mode 100644 nushell/tests/assets/nu_json/pass4_result.json create mode 100644 nushell/tests/assets/nu_json/pass4_test.json create mode 100644 nushell/tests/assets/nu_json/passSingle_result.hjson create mode 100644 nushell/tests/assets/nu_json/passSingle_result.json create mode 100644 nushell/tests/assets/nu_json/passSingle_test.hjson create mode 100644 nushell/tests/assets/nu_json/root_result.hjson create mode 100644 nushell/tests/assets/nu_json/root_result.json create mode 100644 nushell/tests/assets/nu_json/root_test.hjson create mode 100644 nushell/tests/assets/nu_json/stringify1_result.hjson create mode 100644 nushell/tests/assets/nu_json/stringify1_result.json create mode 100644 nushell/tests/assets/nu_json/stringify1_test.hjson create mode 100644 nushell/tests/assets/nu_json/strings_result.hjson create mode 100644 nushell/tests/assets/nu_json/strings_result.json create mode 100644 nushell/tests/assets/nu_json/strings_test.hjson create mode 100644 nushell/tests/assets/nu_json/testlist.txt create mode 100644 nushell/tests/assets/nu_json/trail_result.hjson create mode 100644 nushell/tests/assets/nu_json/trail_result.json create mode 100644 nushell/tests/assets/nu_json/trail_test.hjson create mode 100644 nushell/tests/const_/mod.rs create mode 100644 nushell/tests/eval/mod.rs create mode 100644 nushell/tests/fixtures/completions/.hidden_file create mode 100644 nushell/tests/fixtures/completions/.hidden_folder/.hidden_subfile create mode 100644 nushell/tests/fixtures/completions/another/newfile create mode 100644 nushell/tests/fixtures/completions/custom_completion.nu create mode 100644 nushell/tests/fixtures/completions/directory_completion/folder_inside_folder/myfile create mode 100644 nushell/tests/fixtures/completions/directory_completion/mod.nu create mode 100644 nushell/tests/fixtures/completions/nushell create mode 100644 nushell/tests/fixtures/completions/test_a/myfile create mode 120000 nushell/tests/fixtures/completions/test_a_symlink create mode 100644 nushell/tests/fixtures/completions/test_b/testfile create mode 100644 nushell/tests/fixtures/cp/dir_with_10_files/0 create mode 100644 nushell/tests/fixtures/cp/dir_with_10_files/1 create mode 100644 nushell/tests/fixtures/cp/dir_with_10_files/2 create mode 100644 nushell/tests/fixtures/cp/dir_with_10_files/3 create mode 100644 nushell/tests/fixtures/cp/dir_with_10_files/4 create mode 100644 nushell/tests/fixtures/cp/dir_with_10_files/5 create mode 100644 nushell/tests/fixtures/cp/dir_with_10_files/6 create mode 100644 nushell/tests/fixtures/cp/dir_with_10_files/7 create mode 100644 nushell/tests/fixtures/cp/dir_with_10_files/8 create mode 100644 nushell/tests/fixtures/cp/dir_with_10_files/9 create mode 100644 nushell/tests/fixtures/cp/dir_with_mount/copy_me.txt create mode 100644 nushell/tests/fixtures/cp/dir_with_mount/copy_me/copy_me.txt create mode 100644 nushell/tests/fixtures/cp/existing_file.txt create mode 100644 nushell/tests/fixtures/cp/hello_dir/hello.txt create mode 100644 nushell/tests/fixtures/cp/hello_dir_with_file/hello_world.txt create mode 100644 nushell/tests/fixtures/cp/hello_world.txt create mode 100644 nushell/tests/fixtures/cp/how_are_you.txt create mode 100644 nushell/tests/fixtures/dotnu_completions/dir_module/mod.nu create mode 100644 nushell/tests/fixtures/dotnu_completions/dir_module/plain.txt create mode 100644 nushell/tests/fixtures/dotnu_completions/dir_module/sub module/sub.nu create mode 100644 nushell/tests/fixtures/dotnu_completions/foo.nu create mode 100644 nushell/tests/fixtures/dotnu_completions/lib-dir1/bar.nu create mode 100644 nushell/tests/fixtures/dotnu_completions/lib-dir1/baz.nu create mode 100644 nushell/tests/fixtures/dotnu_completions/lib-dir1/xyzzy.nu create mode 100644 nushell/tests/fixtures/dotnu_completions/lib-dir2/asdf.nu create mode 100644 nushell/tests/fixtures/dotnu_completions/lib-dir2/bat.nu create mode 100644 nushell/tests/fixtures/dotnu_completions/lib-dir3/spam.nu create mode 100644 nushell/tests/fixtures/eval/script.nu create mode 100644 nushell/tests/fixtures/external_completions/dir with space/bar baz create mode 100644 nushell/tests/fixtures/external_completions/dir with space/foo create mode 100755 nushell/tests/fixtures/external_completions/path/sleep create mode 100644 nushell/tests/fixtures/external_completions/path/sleep.exe create mode 100644 nushell/tests/fixtures/formats/activate-foo.nu create mode 100644 nushell/tests/fixtures/formats/appveyor.yml create mode 100644 nushell/tests/fixtures/formats/caco3_plastics.arrow create mode 100644 nushell/tests/fixtures/formats/caco3_plastics.csv create mode 100644 nushell/tests/fixtures/formats/caco3_plastics.tsv create mode 100644 nushell/tests/fixtures/formats/cargo_sample.toml create mode 100644 nushell/tests/fixtures/formats/code.nu create mode 100644 nushell/tests/fixtures/formats/early_return.nu create mode 100644 nushell/tests/fixtures/formats/early_return_outside_main.nu create mode 100644 nushell/tests/fixtures/formats/jt.xml create mode 100644 nushell/tests/fixtures/formats/lines_test.txt create mode 100644 nushell/tests/fixtures/formats/msgpack/.gitignore create mode 100644 nushell/tests/fixtures/formats/msgpack/generate.nu create mode 100644 nushell/tests/fixtures/formats/msgpack/objects.nuon create mode 100644 nushell/tests/fixtures/formats/msgpack/sample.nuon create mode 100644 nushell/tests/fixtures/formats/random_numbers.csv create mode 100644 nushell/tests/fixtures/formats/sample-ls-output.json create mode 100644 nushell/tests/fixtures/formats/sample-ps-output.json create mode 100644 nushell/tests/fixtures/formats/sample-simple.json create mode 100644 nushell/tests/fixtures/formats/sample-sys-output.json create mode 100644 nushell/tests/fixtures/formats/sample.blockcommandparser create mode 100644 nushell/tests/fixtures/formats/sample.db create mode 100644 nushell/tests/fixtures/formats/sample.eml create mode 100644 nushell/tests/fixtures/formats/sample.ini create mode 100644 nushell/tests/fixtures/formats/sample.nuon create mode 100644 nushell/tests/fixtures/formats/sample.url create mode 100644 nushell/tests/fixtures/formats/sample_data.ods create mode 100644 nushell/tests/fixtures/formats/sample_data.xlsx create mode 100644 nushell/tests/fixtures/formats/sample_data_with_annotation.ods create mode 100644 nushell/tests/fixtures/formats/sample_def.nu create mode 100644 nushell/tests/fixtures/formats/sample_headers.xlsx create mode 100755 nushell/tests/fixtures/formats/script.nu create mode 100644 nushell/tests/fixtures/formats/script_multiline.nu create mode 100644 nushell/tests/fixtures/formats/sgml_description.json create mode 100644 nushell/tests/fixtures/formats/utf16.ini create mode 100644 nushell/tests/fixtures/lsp/completion/cell_path.nu create mode 100644 nushell/tests/fixtures/lsp/completion/command.nu create mode 100644 nushell/tests/fixtures/lsp/completion/external.nu create mode 100644 nushell/tests/fixtures/lsp/completion/fallback.nu create mode 100644 nushell/tests/fixtures/lsp/completion/keyword.nu create mode 100644 nushell/tests/fixtures/lsp/completion/use.nu create mode 100644 nushell/tests/fixtures/lsp/completion/utf_pipeline.nu create mode 100644 nushell/tests/fixtures/lsp/completion/var.nu create mode 100644 nushell/tests/fixtures/lsp/diagnostics/pwd.nu create mode 100644 nushell/tests/fixtures/lsp/diagnostics/var.nu create mode 100644 nushell/tests/fixtures/lsp/goto/collect.nu create mode 100644 nushell/tests/fixtures/lsp/goto/command.nu create mode 100644 nushell/tests/fixtures/lsp/goto/command_unicode.nu create mode 100644 nushell/tests/fixtures/lsp/goto/else.nu create mode 100644 nushell/tests/fixtures/lsp/goto/match.nu create mode 100644 nushell/tests/fixtures/lsp/goto/module.nu create mode 100644 nushell/tests/fixtures/lsp/goto/use_module.nu create mode 100644 nushell/tests/fixtures/lsp/goto/var.nu create mode 100644 nushell/tests/fixtures/lsp/hints/assignment.nu create mode 100644 nushell/tests/fixtures/lsp/hints/param.nu create mode 100644 nushell/tests/fixtures/lsp/hints/signature.nu create mode 100644 nushell/tests/fixtures/lsp/hints/type.nu create mode 100644 nushell/tests/fixtures/lsp/hover/cell_path.nu create mode 100644 nushell/tests/fixtures/lsp/hover/command.nu create mode 100644 nushell/tests/fixtures/lsp/hover/use.nu create mode 100644 nushell/tests/fixtures/lsp/hover/var.nu create mode 100644 nushell/tests/fixtures/lsp/notifications/issue_11522.nu create mode 100644 nushell/tests/fixtures/lsp/semantic_tokens/internals.nu create mode 100644 nushell/tests/fixtures/lsp/symbols/bar.nu create mode 100644 nushell/tests/fixtures/lsp/symbols/foo.nu create mode 100644 nushell/tests/fixtures/lsp/symbols/span.nu create mode 100644 nushell/tests/fixtures/lsp/workspace/bar.nu create mode 100644 nushell/tests/fixtures/lsp/workspace/baz.nu create mode 100644 nushell/tests/fixtures/lsp/workspace/foo.nu create mode 100644 nushell/tests/fixtures/partial_completions/final_partial/somefile create mode 100644 nushell/tests/fixtures/partial_completions/partial-a/anotherfile create mode 100644 nushell/tests/fixtures/partial_completions/partial-a/have_ext.exe create mode 100644 nushell/tests/fixtures/partial_completions/partial-a/have_ext.txt create mode 100644 nushell/tests/fixtures/partial_completions/partial-a/hello create mode 100644 nushell/tests/fixtures/partial_completions/partial-a/hola/foo.txt create mode 100644 nushell/tests/fixtures/partial_completions/partial-b/hello_b create mode 100644 nushell/tests/fixtures/partial_completions/partial-b/hi_b create mode 100644 nushell/tests/fixtures/partial_completions/partial-c/hello_c create mode 100644 nushell/tests/fixtures/partial_completions/partial-d(/.gitkeep create mode 100644 nushell/tests/fixtures/partial_completions/partial/hello.txt create mode 100644 nushell/tests/fixtures/partial_completions/partial/hol/foo.txt create mode 100644 nushell/tests/fixtures/quoted_completions/--help create mode 100644 nushell/tests/fixtures/quoted_completions/-42 create mode 100644 nushell/tests/fixtures/quoted_completions/-inf create mode 100644 nushell/tests/fixtures/quoted_completions/4.2 create mode 100644 nushell/tests/fixtures/quoted_completions/[a] bc.txt create mode 100644 nushell/tests/fixtures/quoted_completions/curly-bracket_{.txt create mode 100644 nushell/tests/fixtures/quoted_completions/semicolon_;.txt create mode 100644 nushell/tests/fixtures/quoted_completions/square-bracket_[.txt create mode 100644 nushell/tests/fixtures/quoted_completions/te st.txt create mode 100644 nushell/tests/fixtures/quoted_completions/te#st.txt create mode 100644 nushell/tests/fixtures/quoted_completions/te'st.txt create mode 100644 nushell/tests/fixtures/quoted_completions/te(st).txt create mode 100644 nushell/tests/fixtures/quoted_completions/test dir/double quote create mode 100644 nushell/tests/fixtures/quoted_completions/test dir/single quote create mode 100644 nushell/tests/hooks/mod.rs create mode 100644 nushell/tests/hooks/samples/.nu-env create mode 100644 nushell/tests/main.rs create mode 100644 nushell/tests/modules/mod.rs create mode 100644 nushell/tests/modules/samples/missing_mod_nu/test.nu create mode 100644 nushell/tests/modules/samples/spam.nu create mode 100644 nushell/tests/modules/samples/spam/bacon/beans/foo.nu create mode 100644 nushell/tests/modules/samples/spam/bacon/beans/mod.nu create mode 100644 nushell/tests/modules/samples/spam/bacon/foo.nu create mode 100644 nushell/tests/modules/samples/spam/bacon/mod.nu create mode 100644 nushell/tests/modules/samples/spam/bar.nu create mode 100644 nushell/tests/modules/samples/spam/eggs.nu create mode 100644 nushell/tests/modules/samples/spam/foo.nu create mode 100644 nushell/tests/modules/samples/spam/mod.nu create mode 100644 nushell/tests/overlays/mod.rs create mode 100644 nushell/tests/overlays/samples/spam.nu create mode 100644 nushell/tests/parsing/mod.rs create mode 100644 nushell/tests/parsing/samples/multiline_end_pipe.nu create mode 100644 nushell/tests/parsing/samples/multiline_end_pipe_win.nu create mode 100644 nushell/tests/parsing/samples/multiline_start_pipe.nu create mode 100644 nushell/tests/parsing/samples/multiline_start_pipe_win.nu create mode 100644 nushell/tests/parsing/samples/recursive_func_with_alias.nu create mode 100644 nushell/tests/parsing/samples/single_line.nu create mode 100644 nushell/tests/parsing/samples/source_circular_1.nu create mode 100644 nushell/tests/parsing/samples/source_circular_2.nu create mode 100644 nushell/tests/parsing/samples/source_file_relative.nu create mode 100644 nushell/tests/path/canonicalize.rs create mode 100644 nushell/tests/path/expand_path.rs create mode 100644 nushell/tests/path/mod.rs create mode 100644 nushell/tests/plugin_persistence/mod.rs create mode 100644 nushell/tests/plugins/call_decl.rs create mode 100644 nushell/tests/plugins/config.rs create mode 100644 nushell/tests/plugins/core_inc.rs create mode 100644 nushell/tests/plugins/custom_values.rs create mode 100644 nushell/tests/plugins/env.rs create mode 100644 nushell/tests/plugins/formats/eml.rs create mode 100644 nushell/tests/plugins/formats/ics.rs create mode 100644 nushell/tests/plugins/formats/ini.rs create mode 100644 nushell/tests/plugins/formats/mod.rs create mode 100644 nushell/tests/plugins/formats/vcf.rs create mode 100644 nushell/tests/plugins/mod.rs create mode 100644 nushell/tests/plugins/nu_plugin_nu_example.rs create mode 100644 nushell/tests/plugins/register.rs create mode 100644 nushell/tests/plugins/registry_file.rs create mode 100644 nushell/tests/plugins/stream.rs create mode 100644 nushell/tests/plugins/stress_internals.rs create mode 100644 nushell/tests/repl/mod.rs create mode 100644 nushell/tests/repl/test_bits.rs create mode 100644 nushell/tests/repl/test_cell_path.rs create mode 100644 nushell/tests/repl/test_commandline.rs create mode 100644 nushell/tests/repl/test_conditionals.rs create mode 100644 nushell/tests/repl/test_config.rs create mode 100644 nushell/tests/repl/test_config_path.rs create mode 100644 nushell/tests/repl/test_converters.rs create mode 100644 nushell/tests/repl/test_custom_commands.rs create mode 100644 nushell/tests/repl/test_engine.rs create mode 100644 nushell/tests/repl/test_env.rs create mode 100644 nushell/tests/repl/test_help.rs create mode 100644 nushell/tests/repl/test_hiding.rs create mode 100644 nushell/tests/repl/test_ide.rs create mode 100644 nushell/tests/repl/test_iteration.rs create mode 100644 nushell/tests/repl/test_known_external.rs create mode 100644 nushell/tests/repl/test_math.rs create mode 100644 nushell/tests/repl/test_modules.rs create mode 100644 nushell/tests/repl/test_parser.rs create mode 100644 nushell/tests/repl/test_ranges.rs create mode 100644 nushell/tests/repl/test_regex.rs create mode 100644 nushell/tests/repl/test_signatures.rs create mode 100644 nushell/tests/repl/test_spread.rs create mode 100644 nushell/tests/repl/test_stdlib.rs create mode 100644 nushell/tests/repl/test_strings.rs create mode 100644 nushell/tests/repl/test_table_operations.rs create mode 100644 nushell/tests/repl/test_type_check.rs create mode 100644 nushell/tests/repl/tests.rs create mode 100644 nushell/tests/scope/mod.rs create mode 100644 nushell/tests/shell/environment/env.rs create mode 100644 nushell/tests/shell/environment/mod.rs create mode 100644 nushell/tests/shell/mod.rs create mode 100644 nushell/tests/shell/pipeline/commands/external.rs create mode 100644 nushell/tests/shell/pipeline/commands/internal.rs create mode 100644 nushell/tests/shell/pipeline/commands/mod.rs create mode 100644 nushell/tests/shell/pipeline/mod.rs create mode 100644 nushell/tests/shell/repl.rs create mode 100644 nushell/toolkit.nu create mode 100644 nushell/typos.toml create mode 100644 nushell/wix/License.rtf create mode 100644 nushell/wix/main.wixproj create mode 100644 nushell/wix/main.wxs create mode 100644 nushell/wix/nu.ico create mode 100644 nushell/wix/windows-terminal-profile.json diff --git a/nushell/.cargo/config.toml b/nushell/.cargo/config.toml new file mode 100644 index 0000000..ad1e8ce --- /dev/null +++ b/nushell/.cargo/config.toml @@ -0,0 +1,33 @@ +[target.x86_64-pc-windows-msvc] +# increase the default windows stack size +# statically link the CRT so users don't have to install it +rustflags = ["-C", "link-args=-stack:10000000", "-C", "target-feature=+crt-static"] + +# keeping this but commentting out in case we need them in the future + +# set a 2 gb stack size (0x80000000 = 2147483648 bytes = 2 GB) +# [target.x86_64-unknown-linux-gnu] +# rustflags = ["-C", "link-args=-Wl,-z stack-size=0x80000000"] + +# set a 2 gb stack size (0x80000000 = 2147483648 bytes = 2 GB) +# [target.x86_64-apple-darwin] +# rustflags = ["-C", "link-args=-Wl,-stack_size,0x80000000"] + +# How to use mold in linux and mac + +# [target.x86_64-unknown-linux-gnu] +# linker = "clang" +# rustflags = ["-C", "link-arg=-fuse-ld=/usr/local/bin/mold"] + +# [target.x86_64-apple-darwin] +# linker = "clang" +# rustflags = ["-C", "link-arg=-fuse-ld=mold"] + +# [target.aarch64-apple-darwin] +# linker = "clang" +# rustflags = ["-C", "link-arg=-fuse-ld=mold"] + +[target.aarch64-apple-darwin] +# We can guarantee that this target will always run on a CPU with _at least_ +# these capabilities, so let's optimize for them +rustflags = ["-Ctarget-cpu=apple-m1"] \ No newline at end of file diff --git a/nushell/.gitattributes b/nushell/.gitattributes new file mode 100644 index 0000000..71fd44c --- /dev/null +++ b/nushell/.gitattributes @@ -0,0 +1,2 @@ +# Example of a `.gitattributes` file which reclassifies `.nu` files as Nushell: +*.nu linguist-language=Nushell diff --git a/nushell/.githooks/pre-commit b/nushell/.githooks/pre-commit new file mode 100755 index 0000000..f83086c --- /dev/null +++ b/nushell/.githooks/pre-commit @@ -0,0 +1,5 @@ +#!/usr/bin/env nu + +use ../toolkit.nu fmt + +fmt --check --verbose \ No newline at end of file diff --git a/nushell/.githooks/pre-push b/nushell/.githooks/pre-push new file mode 100755 index 0000000..0ba83ea --- /dev/null +++ b/nushell/.githooks/pre-push @@ -0,0 +1,6 @@ +#!/usr/bin/env nu + +use ../toolkit.nu [fmt, clippy] + +fmt --check --verbose +clippy --verbose \ No newline at end of file diff --git a/nushell/.github/AUTO_ISSUE_TEMPLATE/README.md b/nushell/.github/AUTO_ISSUE_TEMPLATE/README.md new file mode 100644 index 0000000..2d65248 --- /dev/null +++ b/nushell/.github/AUTO_ISSUE_TEMPLATE/README.md @@ -0,0 +1 @@ +This directory is intended for templates to automatically create issues with the [create-an-issue](https://github.com/JasonEtco/create-an-issue) action. diff --git a/nushell/.github/AUTO_ISSUE_TEMPLATE/nightly-build-fail.md b/nushell/.github/AUTO_ISSUE_TEMPLATE/nightly-build-fail.md new file mode 100644 index 0000000..5013e09 --- /dev/null +++ b/nushell/.github/AUTO_ISSUE_TEMPLATE/nightly-build-fail.md @@ -0,0 +1,16 @@ +--- +name: Nightly build of release binaries failed +about: Used to submit issues related to binaries release workflow +title: 'Attention: Nightly build of release binaries failed' +labels: ['build-package', 'priority'] +assignees: '' + +--- + +**Nightly build of release binaries failed** + +Hi there: + +If you see me here that means there is a release failure for the nightly build + +Please **click the status badge** to see more details: [![Nightly Build](https://github.com/nushell/nushell/actions/workflows/nightly-build.yml/badge.svg)](https://github.com/nushell/nushell/actions/workflows/nightly-build.yml) diff --git a/nushell/.github/ISSUE_TEMPLATE/bug_report.yml b/nushell/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..7003641 --- /dev/null +++ b/nushell/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,50 @@ +name: Bug Report +description: Create a report to help us improve +labels: ["needs-triage"] +body: + - type: textarea + id: description + attributes: + label: Describe the bug + description: Thank you for your bug report. + validations: + required: true + - type: textarea + id: repro + attributes: + label: How to reproduce + description: Steps to reproduce the behavior (including succinct code examples or screenshots of the observed behavior) + placeholder: | + 1. + 2. + 3. + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected behavior + description: A clear and concise description of what you expected to happen. + placeholder: I expected nu to... + validations: + required: true + - type: textarea + id: config + attributes: + label: Configuration + description: "Please run `version | transpose key value | to md --pretty` and paste the output to show OS, features, etc." + placeholder: | + > version | transpose key value | to md --pretty + | key | value | + | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | version | 0.40.0 | + | build_os | linux-x86_64 | + | rust_version | rustc 1.56.1 | + | cargo_version | cargo 1.56.0 | + | pkg_version | 0.40.0 | + | build_time | 1980-01-01 00:00:00 +00:00 | + | build_rust_channel | release | + | features | clipboard-cli, ctrlc, dataframe, default, rustyline, term, trash, uuid, which, zip | + | installed_plugins | binaryview, chart bar, chart line, fetch, from bson, from sqlite, inc, match, post, ps, query json, s3, selector, start, sys, textview, to bson, to sqlite, tree, xpath | + validations: + required: true diff --git a/nushell/.github/ISSUE_TEMPLATE/feature_request.yml b/nushell/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..7e192c6 --- /dev/null +++ b/nushell/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,35 @@ +name: Feature Request +description: "When you want a new feature for something that doesn't already exist" +labels: ["needs-triage", "enhancement"] +body: + - type: textarea + id: problem + attributes: + label: Related problem + description: Thank you for your feature request. + placeholder: | + A clear and concise description of what the problem is. + Example: I am trying to do [...] but [...] + validations: + required: false + - type: textarea + id: desired + attributes: + label: "Describe the solution you'd like" + description: A clear and concise description of what you want to happen. + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: "Describe alternatives you've considered" + description: "A clear and concise description of any alternative solutions or features you've considered." + validations: + required: false + - type: textarea + id: context + attributes: + label: Additional context and details + description: Add any other context or screenshots about the feature request here. + validations: + required: false diff --git a/nushell/.github/ISSUE_TEMPLATE/question.yml b/nushell/.github/ISSUE_TEMPLATE/question.yml new file mode 100644 index 0000000..6ed045b --- /dev/null +++ b/nushell/.github/ISSUE_TEMPLATE/question.yml @@ -0,0 +1,21 @@ +name: Question +description: "When you have a question to ask" +labels: "question" +body: + - type: textarea + id: problem + attributes: + label: Question + description: Leave your question here + placeholder: | + A clear and concise question + Example: Is there any equivalent of bash's $CDPATH in Nu? + validations: + required: true + - type: textarea + id: context + attributes: + label: Additional context and details + description: Add any other context, screenshots or other media that will help us understand your question here, if needed. + validations: + required: false diff --git a/nushell/.github/dependabot.yml b/nushell/.github/dependabot.yml new file mode 100644 index 0000000..07e0b2b --- /dev/null +++ b/nushell/.github/dependabot.yml @@ -0,0 +1,40 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +# docs +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file +version: 2 +updates: + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "weekly" + # We release on Tuesdays and open dependabot PRs will rebase after the + # version bump and thus consume unnecessary workers during release, thus + # let's open new ones on Wednesday + day: "wednesday" + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-patch"] + groups: + # Only update polars as a whole as there are many subcrates that need to + # be updated at once. We explicitly depend on some of them, so batch their + # updates to not take up dependabot PR slots with dysfunctional PRs + polars: + patterns: + - "polars" + - "polars-*" + # uutils/coreutils also versions all their workspace crates the same at the moment + # Most of them have bleeding edge version requirements (some not) + # see: https://github.com/uutils/coreutils/blob/main/Cargo.toml + uutils: + patterns: + - "uucore" + - "uu_*" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "wednesday" diff --git a/nushell/.github/labeler.yml b/nushell/.github/labeler.yml new file mode 100644 index 0000000..cb500a3 --- /dev/null +++ b/nushell/.github/labeler.yml @@ -0,0 +1,40 @@ +# A bot for automatically labelling pull requests +# See https://github.com/actions/labeler + +dataframe: + - changed-files: + - any-glob-to-any-file: + - crates/nu_plugin_polars/** + +std-library: + - changed-files: + - any-glob-to-any-file: + - crates/nu-std/** + +ci: + - changed-files: + - any-glob-to-any-file: + - .github/workflows/** + + +LSP: + - changed-files: + - any-glob-to-any-file: + - crates/nu-lsp/** + +parser: + - changed-files: + - any-glob-to-any-file: + - crates/nu-parser/** + +pr:plugins: + - changed-files: + - any-glob-to-any-file: + # plugins API + - crates/nu-plugin/** + - crates/nu-plugin-core/** + - crates/nu-plugin-engine/** + - crates/nu-plugin-protocol/** + - crates/nu-plugin-test-support/** + # specific plugins (like polars) + - crates/nu_plugin_*/** diff --git a/nushell/.github/pull_request_template.md b/nushell/.github/pull_request_template.md new file mode 100644 index 0000000..23d6a5f --- /dev/null +++ b/nushell/.github/pull_request_template.md @@ -0,0 +1,40 @@ + + +# Description + + +# User-Facing Changes + + +# Tests + Formatting + + +# After Submitting + diff --git a/nushell/.github/workflows/audit.yml b/nushell/.github/workflows/audit.yml new file mode 100644 index 0000000..d6044d2 --- /dev/null +++ b/nushell/.github/workflows/audit.yml @@ -0,0 +1,25 @@ +name: Security audit +on: + pull_request: + paths: + - '**/Cargo.toml' + - '**/Cargo.lock' + push: + branches: + - main + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 + +jobs: + security_audit: + runs-on: ubuntu-latest + # Prevent sudden announcement of a new advisory from failing ci: + continue-on-error: true + steps: + - uses: actions/checkout@v4.1.7 + - uses: rustsec/audit-check@v2.0.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/nushell/.github/workflows/beta-test.yml b/nushell/.github/workflows/beta-test.yml new file mode 100644 index 0000000..7770c6a --- /dev/null +++ b/nushell/.github/workflows/beta-test.yml @@ -0,0 +1,52 @@ +name: Test on Beta Toolchain +# This workflow is made to run our tests on the beta toolchain to validate that +# the beta toolchain works. +# We do not intend to test here that we are working correctly but rather that +# the beta toolchain works correctly. +# The ci.yml handles our actual testing with our guarantees. + +on: + schedule: + # If this workflow fails, GitHub notifications will go to the last person + # who edited this line. + # See: https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/monitoring-workflows/notifications-for-workflow-runs + - cron: '0 0 * * *' # Runs daily at midnight UTC + +env: + NUSHELL_CARGO_PROFILE: ci + NU_LOG_LEVEL: DEBUG + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + build-and-test: + # this job is more for testing the beta toolchain and not our tests, so if + # this fails but the tests of the regular ci pass, then this is fine + continue-on-error: true + + strategy: + fail-fast: true + matrix: + platform: [windows-latest, macos-latest, ubuntu-22.04] + + runs-on: ${{ matrix.platform }} + + steps: + - uses: actions/checkout@v4 + + - run: rustup update beta + + - name: Tests + run: cargo +beta test --workspace --profile ci --exclude nu_plugin_* + - name: Check for clean repo + shell: bash + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "there are changes"; + git status --porcelain + exit 1 + else + echo "no changes in working directory"; + fi diff --git a/nushell/.github/workflows/check-msrv.nu b/nushell/.github/workflows/check-msrv.nu new file mode 100644 index 0000000..f0c92fe --- /dev/null +++ b/nushell/.github/workflows/check-msrv.nu @@ -0,0 +1,12 @@ +let toolchain_spec = open rust-toolchain.toml | get toolchain.channel +let msrv_spec = open Cargo.toml | get package.rust-version + +# This check is conservative in the sense that we use `rust-toolchain.toml`'s +# override to ensure that this is the upper-bound for the minimum supported +# rust version +if $toolchain_spec != $msrv_spec { + print -e "Mismatching rust compiler versions specified in `Cargo.toml` and `rust-toolchain.toml`" + print -e $"Cargo.toml: ($msrv_spec)" + print -e $"rust-toolchain.toml: ($toolchain_spec)" + exit 1 +} diff --git a/nushell/.github/workflows/ci.yml b/nushell/.github/workflows/ci.yml new file mode 100644 index 0000000..f918a73 --- /dev/null +++ b/nushell/.github/workflows/ci.yml @@ -0,0 +1,212 @@ +on: + pull_request: + push: + branches: + - main + - 'patch-release-*' + +name: continuous-integration + +env: + NUSHELL_CARGO_PROFILE: ci + NU_LOG_LEVEL: DEBUG + # If changing these settings also change toolkit.nu + CLIPPY_OPTIONS: "-D warnings -D clippy::unwrap_used -D clippy::unchecked_duration_subtraction" + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + fmt-clippy: + strategy: + fail-fast: true + matrix: + # Pinning to Ubuntu 22.04 because building on newer Ubuntu versions causes linux-gnu + # builds to link against a too-new-for-many-Linux-installs glibc version. Consider + # revisiting this when 22.04 is closer to EOL (June 2027) + # + # Using macOS 13 runner because 14 is based on the M1 and has half as much RAM (7 GB, + # instead of 14 GB) which is too little for us right now. Revisit when `dfr` commands are + # removed and we're only building the `polars` plugin instead + platform: [windows-latest, macos-13, ubuntu-22.04] + + runs-on: ${{ matrix.platform }} + + steps: + - uses: actions/checkout@v4.1.7 + + - name: Setup Rust toolchain and cache + uses: actions-rust-lang/setup-rust-toolchain@v1.12.0 + + - name: cargo fmt + run: cargo fmt --all -- --check + + # If changing these settings also change toolkit.nu + - name: Clippy + run: cargo clippy --workspace --exclude nu_plugin_* -- $CLIPPY_OPTIONS + + # In tests we don't have to deny unwrap + - name: Clippy of tests + run: cargo clippy --tests --workspace --exclude nu_plugin_* -- -D warnings + + - name: Clippy of benchmarks + run: cargo clippy --benches --workspace --exclude nu_plugin_* -- -D warnings + + tests: + strategy: + fail-fast: true + matrix: + platform: [windows-latest, macos-latest, ubuntu-22.04] + + runs-on: ${{ matrix.platform }} + + steps: + - uses: actions/checkout@v4.1.7 + + - name: Setup Rust toolchain and cache + uses: actions-rust-lang/setup-rust-toolchain@v1.12.0 + + - name: Tests + run: cargo test --workspace --profile ci --exclude nu_plugin_* + - name: Check for clean repo + shell: bash + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "there are changes"; + git status --porcelain + exit 1 + else + echo "no changes in working directory"; + fi + + std-lib-and-python-virtualenv: + strategy: + fail-fast: true + matrix: + platform: [ubuntu-22.04, macos-latest, windows-latest] + py: + - py + + runs-on: ${{ matrix.platform }} + + steps: + - uses: actions/checkout@v4.1.7 + + - name: Setup Rust toolchain and cache + uses: actions-rust-lang/setup-rust-toolchain@v1.12.0 + + - name: Install Nushell + run: cargo install --path . --locked --force + + - name: Standard library tests + run: nu -c 'use crates/nu-std/testing.nu; testing run-tests --path crates/nu-std' + + - name: Ensure that Cargo.toml MSRV and rust-toolchain.toml use the same version + run: nu .github/workflows/check-msrv.nu + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - name: Install virtualenv + run: pip install virtualenv + shell: bash + + - name: Test Nushell in virtualenv + run: nu scripts/test_virtualenv.nu + shell: bash + + - name: Check for clean repo + shell: bash + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "there are changes"; + git status --porcelain + exit 1 + else + echo "no changes in working directory"; + fi + + plugins: + strategy: + fail-fast: true + matrix: + # Using macOS 13 runner because 14 is based on the M1 and has half as much RAM (7 GB, + # instead of 14 GB) which is too little for us right now. + # + # Failure occurring with clippy for rust 1.77.2 + platform: [windows-latest, macos-13, ubuntu-22.04] + + runs-on: ${{ matrix.platform }} + + steps: + - uses: actions/checkout@v4.1.7 + + - name: Setup Rust toolchain and cache + uses: actions-rust-lang/setup-rust-toolchain@v1.12.0 + + - name: Clippy + run: cargo clippy --package nu_plugin_* -- $CLIPPY_OPTIONS + + - name: Tests + run: cargo test --profile ci --package nu_plugin_* + + - name: Check for clean repo + shell: bash + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "there are changes"; + git status --porcelain + exit 1 + else + echo "no changes in working directory"; + fi + + wasm: + env: + WASM_OPTIONS: --no-default-features --target wasm32-unknown-unknown + CLIPPY_CONF_DIR: ${{ github.workspace }}/clippy/wasm/ + + strategy: + matrix: + job: + - name: Build WASM + command: cargo build + args: + - name: Clippy WASM + command: cargo clippy + args: -- $CLIPPY_OPTIONS + + name: ${{ matrix.job.name }} + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4.1.7 + + - name: Setup Rust toolchain and cache + uses: actions-rust-lang/setup-rust-toolchain@v1.12.0 + + - name: Add wasm32-unknown-unknown target + run: rustup target add wasm32-unknown-unknown + + - run: ${{ matrix.job.command }} -p nu-cmd-base $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-cmd-extra $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-cmd-lang $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-color-config $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-command $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-derive-value $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-engine $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-glob $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-json $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-parser $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-path $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-pretty-hex $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-protocol $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-std $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-system $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-table $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-term-grid $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nu-utils $WASM_OPTIONS ${{ matrix.job.args }} + - run: ${{ matrix.job.command }} -p nuon $WASM_OPTIONS ${{ matrix.job.args }} diff --git a/nushell/.github/workflows/friendly-config-reminder.yml b/nushell/.github/workflows/friendly-config-reminder.yml new file mode 100644 index 0000000..a45e9d2 --- /dev/null +++ b/nushell/.github/workflows/friendly-config-reminder.yml @@ -0,0 +1,25 @@ +name: Comment on changes to the config +on: + pull_request_target: + paths: + - 'crates/nu-protocol/src/config/**' +jobs: + comment: + runs-on: ubuntu-latest + steps: + - name: Check if there is already a bot comment + uses: peter-evans/find-comment@v3 + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: Hey, just a bot checking in! + - name: Create comment if there is not + if: steps.fc.outputs.comment-id == '' + uses: peter-evans/create-or-update-comment@v4 + with: + issue-number: ${{ github.event.pull_request.number }} + body: | + Hey, just a bot checking in! You edited files related to the configuration. + If you changed any of the default values or added a new config option, don't forget to update the [`doc_config.nu`](https://github.com/nushell/nushell/blob/main/crates/nu-utils/src/default_files/doc_config.nu) which documents the options for our users including the defaults provided by the Rust implementation. + If you didn't make a change here, you can just ignore me. diff --git a/nushell/.github/workflows/labels.yml b/nushell/.github/workflows/labels.yml new file mode 100644 index 0000000..96b84c6 --- /dev/null +++ b/nushell/.github/workflows/labels.yml @@ -0,0 +1,19 @@ +# Automatically labels PRs based on the configuration file +# you are probably looking for 👉 `.github/labeler.yml` +name: Label PRs + +on: + - pull_request_target + +jobs: + triage: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + if: github.repository_owner == 'nushell' + steps: + - uses: actions/labeler@v5 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" + sync-labels: true \ No newline at end of file diff --git a/nushell/.github/workflows/milestone.yml b/nushell/.github/workflows/milestone.yml new file mode 100644 index 0000000..18eef42 --- /dev/null +++ b/nushell/.github/workflows/milestone.yml @@ -0,0 +1,30 @@ +# Description: +# - Add milestone to a merged PR automatically +# - Add milestone to a closed issue that has a merged PR fix (if any) + +name: Milestone Action +on: + issues: + types: [closed] + pull_request_target: + types: [closed] + +jobs: + update-milestone: + runs-on: ubuntu-latest + name: Milestone Update + steps: + - name: Set Milestone for PR + uses: hustcer/milestone-action@main + if: github.event.pull_request.merged == true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # Bind milestone to closed issue that has a merged PR fix + - name: Set Milestone for Issue + uses: hustcer/milestone-action@v2 + if: github.event.issue.state == 'closed' + with: + action: bind-issue + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/nushell/.github/workflows/nightly-build.yml b/nushell/.github/workflows/nightly-build.yml new file mode 100644 index 0000000..5fdf3ef --- /dev/null +++ b/nushell/.github/workflows/nightly-build.yml @@ -0,0 +1,284 @@ +# +# REF: +# 1. https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrixinclude +# 2. https://github.com/JasonEtco/create-an-issue +# 3. https://docs.github.com/en/actions/learn-github-actions/variables +# 4. https://github.com/actions/github-script +# 5. https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idneeds +# +name: Nightly Build + +on: + push: + branches: + - nightly # Just for test purpose only with the nightly repo + # This schedule will run only from the default branch + schedule: + - cron: '15 0 * * *' # run at 00:15 AM UTC + workflow_dispatch: + +defaults: + run: + shell: bash + +jobs: + prepare: + name: Prepare + runs-on: ubuntu-latest + # This job is required by the release job, so we should make it run both from Nushell repo and nightly repo + # if: github.repository == 'nushell/nightly' + # Map a step output to a job output + outputs: + skip: ${{ steps.vars.outputs.skip }} + build_date: ${{ steps.vars.outputs.build_date }} + nightly_tag: ${{ steps.vars.outputs.nightly_tag }} + steps: + - name: Checkout + uses: actions/checkout@v4 + if: github.repository == 'nushell/nightly' + with: + ref: main + fetch-depth: 0 + # Configure PAT here: https://github.com/settings/tokens for the push operation in the following steps + token: ${{ secrets.WORKFLOW_TOKEN }} + + - name: Setup Nushell + uses: hustcer/setup-nu@v3 + if: github.repository == 'nushell/nightly' + with: + version: 0.105.1 + + # Synchronize the main branch of nightly repo with the main branch of Nushell official repo + - name: Prepare for Nightly Release + shell: nu {0} + if: github.repository == 'nushell/nightly' + run: | + cd $env.GITHUB_WORKSPACE + git checkout main + # We can't push if no user name and email are configured + git config user.name 'hustcer' + git config user.email 'hustcer@outlook.com' + git pull origin main + git remote add src https://github.com/nushell/nushell.git + git fetch src main + # All the changes will be overwritten by the upstream main branch + git reset --hard src/main + git push origin main -f + + - name: Create Tag and Output Tag Name + if: github.repository == 'nushell/nightly' + id: vars + shell: nu {0} + run: | + let date = date now | format date %m%d + let version = open Cargo.toml | get package.version + let sha_short = (git rev-parse --short origin/main | str trim | str substring 0..6) + let latest_meta = http get https://api.github.com/repos/nushell/nightly/releases + | sort-by -r created_at + | where tag_name =~ nightly + | get tag_name?.0? | default '' + | parse '{version}-nightly.{build}+{hash}' + if ($latest_meta.0?.hash? | default '') == $sha_short { + print $'(ansi g)Latest nightly build is up-to-date, skip rebuilding.(ansi reset)' + $'skip=true(char nl)' o>> $env.GITHUB_OUTPUT + exit 0 + } + let prev_ver = $latest_meta.0?.version? | default '0.0.0' + let build = if ($latest_meta | is-empty) or ($version != $prev_ver) { 1 } else { + ($latest_meta | get build?.0? | default 0 | into int) + 1 + } + let nightly_tag = $'($version)-nightly.($build)+($sha_short)' + $'build_date=($date)(char nl)' o>> $env.GITHUB_OUTPUT + $'nightly_tag=($nightly_tag)(char nl)' o>> $env.GITHUB_OUTPUT + if (git ls-remote --tags origin $nightly_tag | is-empty) { + ls **/Cargo.toml | each {|file| + open --raw $file.name + | str replace --all $'version = "($version)"' $'version = "($version)-nightly.($build)"' + | save --force $file.name + } + # Disable the following two workflows for the automatic committed changes + rm .github/workflows/ci.yml + rm .github/workflows/audit.yml + + git add . + git commit -m $'Update version to ($version)-nightly.($build)' + git tag -a $nightly_tag -m $'Nightly build from ($sha_short)' + git push origin --tags + git push origin main -f + } + + release: + name: Nu + needs: prepare + if: needs.prepare.outputs.skip != 'true' + strategy: + fail-fast: false + matrix: + target: + - aarch64-apple-darwin + - x86_64-apple-darwin + - x86_64-pc-windows-msvc + - aarch64-pc-windows-msvc + - x86_64-unknown-linux-gnu + - x86_64-unknown-linux-musl + - aarch64-unknown-linux-gnu + - aarch64-unknown-linux-musl + - armv7-unknown-linux-gnueabihf + - armv7-unknown-linux-musleabihf + - riscv64gc-unknown-linux-gnu + - loongarch64-unknown-linux-gnu + - loongarch64-unknown-linux-musl + include: + - target: aarch64-apple-darwin + os: macos-latest + - target: x86_64-apple-darwin + os: macos-latest + - target: x86_64-pc-windows-msvc + os: windows-latest + - target: aarch64-pc-windows-msvc + os: windows-11-arm + - target: x86_64-unknown-linux-gnu + os: ubuntu-22.04 + - target: x86_64-unknown-linux-musl + os: ubuntu-22.04 + - target: aarch64-unknown-linux-gnu + os: ubuntu-22.04 + - target: aarch64-unknown-linux-musl + os: ubuntu-22.04 + - target: armv7-unknown-linux-gnueabihf + os: ubuntu-22.04 + - target: armv7-unknown-linux-musleabihf + os: ubuntu-22.04 + - target: riscv64gc-unknown-linux-gnu + os: ubuntu-22.04 + - target: loongarch64-unknown-linux-gnu + os: ubuntu-22.04 + - target: loongarch64-unknown-linux-musl + os: ubuntu-22.04 + + runs-on: ${{matrix.os}} + steps: + - uses: actions/checkout@v4 + with: + ref: main + fetch-depth: 0 + + - name: Install Wix Toolset 6 for Windows + shell: pwsh + if: ${{ startsWith(matrix.os, 'windows') }} + run: | + dotnet tool install --global wix --version 6.0.0 + dotnet workload install wix + $wixPath = "$env:USERPROFILE\.dotnet\tools" + echo "$wixPath" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + $env:PATH = "$wixPath;$env:PATH" + wix --version + + - name: Update Rust Toolchain Target + run: | + echo "targets = ['${{matrix.target}}']" >> rust-toolchain.toml + + - name: Setup Rust toolchain and cache + uses: actions-rust-lang/setup-rust-toolchain@v1 + # WARN: Keep the rustflags to prevent from the winget submission error: `CAQuietExec: Error 0xc0000135` + with: + cache: false + rustflags: '' + + - name: Setup Nushell + uses: hustcer/setup-nu@v3 + with: + version: 0.105.1 + + - name: Release Nu Binary + id: nu + run: nu .github/workflows/release-pkg.nu + env: + OS: ${{ matrix.os }} + REF: ${{ github.ref }} + TARGET: ${{ matrix.target }} + + - name: Create an Issue for Release Failure + if: ${{ failure() }} + uses: JasonEtco/create-an-issue@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + update_existing: true + search_existing: open + filename: .github/AUTO_ISSUE_TEMPLATE/nightly-build-fail.md + + # REF: https://github.com/marketplace/actions/gh-release + # Create a release only in nushell/nightly repo + - name: Publish Archive + uses: softprops/action-gh-release@v2.0.9 + if: ${{ startsWith(github.repository, 'nushell/nightly') }} + with: + prerelease: true + files: | + ${{ steps.nu.outputs.msi }} + ${{ steps.nu.outputs.archive }} + tag_name: ${{ needs.prepare.outputs.nightly_tag }} + name: ${{ needs.prepare.outputs.build_date }}-${{ needs.prepare.outputs.nightly_tag }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + sha256sum: + needs: [prepare, release] + name: Create Sha256sum + runs-on: ubuntu-latest + if: github.repository == 'nushell/nightly' + steps: + - name: Download Release Archives + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: >- + gh release download ${{ needs.prepare.outputs.nightly_tag }} + --repo ${{ github.repository }} + --pattern '*' + --dir release + - name: Create Checksums + run: cd release && shasum -a 256 * > ../SHA256SUMS + - name: Publish Checksums + uses: softprops/action-gh-release@v2.0.9 + with: + draft: false + prerelease: true + files: SHA256SUMS + tag_name: ${{ needs.prepare.outputs.nightly_tag }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + cleanup: + name: Cleanup + # Should only run in nushell/nightly repo + if: github.repository == 'nushell/nightly' + needs: [release, sha256sum] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: main + + - name: Setup Nushell + uses: hustcer/setup-nu@v3 + with: + version: 0.105.1 + + # Keep the last a few releases + - name: Delete Older Releases + shell: nu {0} + run: | + let KEEP_COUNT = 10 + let deprecated = (http get https://api.github.com/repos/nushell/nightly/releases | sort-by -r created_at | select tag_name id | slice $KEEP_COUNT..) + for release in $deprecated { + print $'Deleting tag ($release.tag_name)' + git push origin --delete $release.tag_name + print $'Deleting release ($release.tag_name)' + let delete_url = $'https://api.github.com/repos/nushell/nightly/releases/($release.id)' + let version = "X-GitHub-Api-Version: 2022-11-28" + let accept = "Accept: application/vnd.github+json" + let auth = "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" + # http delete $delete_url -H $version -H $auth -H $accept + curl -L -X DELETE -H $accept -H $auth -H $version $delete_url + } diff --git a/nushell/.github/workflows/release-msi.nu b/nushell/.github/workflows/release-msi.nu new file mode 100755 index 0000000..df7bbb7 --- /dev/null +++ b/nushell/.github/workflows/release-msi.nu @@ -0,0 +1,62 @@ +#!/usr/bin/env nu + +# Created: 2025/05/21 19:05:20 +# Description: +# A script to build Windows MSI packages for NuShell. Need wix 6.0 to be installed. +# The script will download the specified NuShell release, extract it, and create an MSI package. +# Can be run locally or in GitHub Actions. +# To run this script locally: +# load-env { TARGET: 'x86_64-pc-windows-msvc' REF: '0.103.0' GITHUB_REPOSITORY: 'nushell/nushell' } +# nu .github/workflows/release-msi.nu + +def build-msi [] { + let target = $env.TARGET + # We should read the version from the environment variable first + # As we may build the MSI package for a specific version not the latest one + let version = $env.MSI_VERSION? | default (open Cargo.toml | get package.version) + let arch = if $nu.os-info.arch =~ 'x86_64' { 'x64' } else { 'arm64' } + + print $'Building msi package for (ansi g)($target)(ansi reset) with version (ansi g)($version)(ansi reset) from tag (ansi g)($env.REF)(ansi reset)...' + fetch-nu-pkg + # Create extra Windows msi release package if dotnet and wix are available + let installed = [dotnet wix] | all { (which $in | length) > 0 } + if $installed and (wix --version | split row . | first | into int) >= 6 { + + print $'(char nl)Start creating Windows msi package with the following contents...' + cd wix; hr-line + cp nu/README.txt . + ls -f nu/* | print + ./nu/nu.exe -c $'NU_RELEASE_VERSION=($version) dotnet build -c Release -p:Platform=($arch)' + glob **/*.msi | print + # Workaround for https://github.com/softprops/action-gh-release/issues/280 + let wixRelease = (glob **/*.msi | where $it =~ bin | get 0 | str replace --all '\' '/') + let msi = $'($wixRelease | path dirname)/nu-($version)-($target).msi' + mv $wixRelease $msi + print $'MSI archive: ---> ($msi)'; + # Run only in GitHub Actions + if ($env.GITHUB_ACTIONS? | default false | into bool) { + echo $"msi=($msi)(char nl)" o>> $env.GITHUB_OUTPUT + } + } +} + +def fetch-nu-pkg [] { + mkdir wix/nu + # See: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#default-environment-variables + gh release download $env.REF --repo $env.GITHUB_REPOSITORY --pattern $'*-($env.TARGET).zip' --dir wix/nu + cd wix/nu + let pkg = ls *.zip | get name.0 + unzip $pkg + rm $pkg + ls | print +} + +# Print a horizontal line marker +def 'hr-line' [ + --blank-line(-b) +] { + print $'(ansi g)---------------------------------------------------------------------------->(ansi reset)' + if $blank_line { char nl } +} + +alias main = build-msi diff --git a/nushell/.github/workflows/release-msi.yml b/nushell/.github/workflows/release-msi.yml new file mode 100644 index 0000000..6a00f35 --- /dev/null +++ b/nushell/.github/workflows/release-msi.yml @@ -0,0 +1,103 @@ +# +# REF: +# 1. https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrixinclude +# +name: Build Windows MSI + +on: + workflow_dispatch: + inputs: + tag: + required: true + description: 'Tag to Rebuild MSI' + version: + description: 'Version of Rebuild MSI' + +permissions: + contents: write + packages: write + +defaults: + run: + shell: bash + +jobs: + release: + name: Nu + + strategy: + fail-fast: false + matrix: + target: + - x86_64-pc-windows-msvc + - aarch64-pc-windows-msvc + extra: ['bin'] + + include: + - target: x86_64-pc-windows-msvc + os: windows-latest + - target: aarch64-pc-windows-msvc + os: windows-11-arm + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + + - name: Install Wix Toolset 6 for Windows + shell: pwsh + if: ${{ startsWith(matrix.os, 'windows') }} + run: | + dotnet tool install --global wix --version 6.0.0 + dotnet workload install wix + $wixPath = "$env:USERPROFILE\.dotnet\tools" + echo "$wixPath" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + $env:PATH = "$wixPath;$env:PATH" + wix --version + + - name: Setup Nushell + uses: hustcer/setup-nu@v3 + with: + version: 0.105.1 + + - name: Release MSI Packages + id: nu + run: nu .github/workflows/release-msi.nu + env: + OS: ${{ matrix.os }} + REF: ${{ inputs.tag }} + TARGET: ${{ matrix.target }} + MSI_VERSION: ${{ inputs.version }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # REF: https://github.com/marketplace/actions/gh-release + - name: Publish Archive + uses: softprops/action-gh-release@v2.0.5 + with: + tag_name: ${{ inputs.tag }} + files: ${{ steps.nu.outputs.msi }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + sha256sum: + needs: release + name: Create Sha256sum + runs-on: ubuntu-latest + steps: + - name: Download Release Archives + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: >- + gh release download ${{ inputs.tag }} + --repo ${{ github.repository }} + --pattern '*' + --dir release + - name: Create Checksums + run: cd release && rm -f SHA256SUMS && shasum -a 256 * > ../SHA256SUMS + - name: Publish Checksums + uses: softprops/action-gh-release@v2.0.5 + with: + files: SHA256SUMS + tag_name: ${{ inputs.tag }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/nushell/.github/workflows/release-pkg.nu b/nushell/.github/workflows/release-pkg.nu new file mode 100755 index 0000000..0d78aff --- /dev/null +++ b/nushell/.github/workflows/release-pkg.nu @@ -0,0 +1,254 @@ +#!/usr/bin/env nu + +# Created: 2022/05/26 19:05:20 +# Description: +# A script to do the github release task, need nushell to be installed. +# REF: +# 1. https://github.com/volks73/cargo-wix + +# Instructions for manually creating an MSI for Winget Releases when they fail +# Added 2022-11-29 when Windows packaging wouldn't work +# Updated again on 2023-02-23 because MSIs are still failing validation +# To run this manual for windows here are the steps I take +# checkout the release you want to publish +# 1. git checkout 0.103.0 +# unset CARGO_TARGET_DIR if set (I have to do this in the parent shell to get it to work) +# 2. $env:CARGO_TARGET_DIR = "" +# 2. hide-env CARGO_TARGET_DIR +# 3. $env.TARGET = 'x86_64-pc-windows-msvc' +# 4. $env.GITHUB_WORKSPACE = 'D:\nushell' +# 5. $env.GITHUB_OUTPUT = 'D:\nushell\output\out.txt' +# 6. $env.OS = 'windows-latest' +# make sure 7z.exe is in your path https://www.7-zip.org/download.html +# 7. $env.Path = ($env.Path | append 'c:\apps\7-zip') +# make sure aria2c.exe is in your path https://github.com/aria2/aria2 +# 8. $env.Path = ($env.Path | append 'c:\path\to\aria2c') +# make sure you have the wix 6.0 installed: dotnet tool install --global wix --version 6.0.0 +# then build nu*.exe and the MSI installer by running: +# 9. source .github\workflows\release-pkg.nu +# After msi is generated, you have to update winget-pkgs repo, you'll need to patch the release +# by deleting the existing msi and uploading this new msi. Then you'll need to update the hash +# on the winget-pkgs PR. To generate the hash, run this command +# 10. open wix\bin\x64\Release\nu-0.103.0-x86_64-pc-windows-msvc.msi | hash sha256 +# Then, just take the output and put it in the winget-pkgs PR for the hash on the msi + + +# The main binary file to be released +let bin = 'nu' +let os = $env.OS +let target = $env.TARGET +# Repo source dir like `/home/runner/work/nushell/nushell` +let src = $env.GITHUB_WORKSPACE +let dist = $'($env.GITHUB_WORKSPACE)/output' +let version = (open Cargo.toml | get package.version) + +print $'Debugging info:' +print { version: $version, bin: $bin, os: $os, target: $target, src: $src, dist: $dist }; hr-line -b + +# $env + +let USE_UBUNTU = $os starts-with ubuntu + +print $'(char nl)Packaging ($bin) v($version) for ($target) in ($src)...'; hr-line -b +if not ('Cargo.lock' | path exists) { cargo generate-lockfile } + +print $'Start building ($bin)...'; hr-line + +# ---------------------------------------------------------------------------- +# Build for Ubuntu and macOS +# ---------------------------------------------------------------------------- +if $os in ['macos-latest'] or $USE_UBUNTU { + if $USE_UBUNTU { + sudo apt update + sudo apt-get install libxcb-composite0-dev -y + } + match $target { + 'aarch64-unknown-linux-gnu' => { + sudo apt-get install gcc-aarch64-linux-gnu -y + $env.CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER = 'aarch64-linux-gnu-gcc' + cargo-build-nu + } + 'riscv64gc-unknown-linux-gnu' => { + sudo apt-get install gcc-riscv64-linux-gnu -y + $env.CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER = 'riscv64-linux-gnu-gcc' + cargo-build-nu + } + 'armv7-unknown-linux-gnueabihf' => { + sudo apt-get install pkg-config gcc-arm-linux-gnueabihf -y + $env.CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER = 'arm-linux-gnueabihf-gcc' + cargo-build-nu + } + 'aarch64-unknown-linux-musl' => { + aria2c https://github.com/nushell/integrations/releases/download/build-tools/aarch64-linux-musl-cross.tgz + tar -xf aarch64-linux-musl-cross.tgz -C $env.HOME + $env.PATH = ($env.PATH | split row (char esep) | prepend $'($env.HOME)/aarch64-linux-musl-cross/bin') + $env.CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER = 'aarch64-linux-musl-gcc' + cargo-build-nu + } + 'armv7-unknown-linux-musleabihf' => { + aria2c https://github.com/nushell/integrations/releases/download/build-tools/armv7r-linux-musleabihf-cross.tgz + tar -xf armv7r-linux-musleabihf-cross.tgz -C $env.HOME + $env.PATH = ($env.PATH | split row (char esep) | prepend $'($env.HOME)/armv7r-linux-musleabihf-cross/bin') + $env.CARGO_TARGET_ARMV7_UNKNOWN_LINUX_MUSLEABIHF_LINKER = 'armv7r-linux-musleabihf-gcc' + cargo-build-nu + } + 'loongarch64-unknown-linux-gnu' => { + aria2c https://github.com/loongson/build-tools/releases/download/2024.08.08/x86_64-cross-tools-loongarch64-binutils_2.43-gcc_14.2.0-glibc_2.40.tar.xz + tar xf x86_64-cross-tools-loongarch64-*.tar.xz + $env.PATH = ($env.PATH | split row (char esep) | prepend $'($env.PWD)/cross-tools/bin') + $env.CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_LINKER = 'loongarch64-unknown-linux-gnu-gcc' + cargo-build-nu + } + 'loongarch64-unknown-linux-musl' => { + print $"(ansi g)Downloading LoongArch64 musl cross-compilation toolchain...(ansi reset)" + aria2c -q https://github.com/LoongsonLab/oscomp-toolchains-for-oskernel/releases/download/loongarch64-linux-musl-cross-gcc-13.2.0/loongarch64-linux-musl-cross.tgz + tar -xf loongarch64-linux-musl-cross.tgz + $env.PATH = ($env.PATH | split row (char esep) | prepend $'($env.PWD)/loongarch64-linux-musl-cross/bin') + $env.CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_MUSL_LINKER = "loongarch64-linux-musl-gcc" + cargo-build-nu + } + _ => { + # musl-tools to fix 'Failed to find tool. Is `musl-gcc` installed?' + # Actually just for x86_64-unknown-linux-musl target + if $USE_UBUNTU { sudo apt install musl-tools -y } + cargo-build-nu + } + } +} + +# ---------------------------------------------------------------------------- +# Build for Windows without static-link-openssl feature +# ---------------------------------------------------------------------------- +if $os =~ 'windows' { + cargo-build-nu +} + +# ---------------------------------------------------------------------------- +# Prepare for the release archive +# ---------------------------------------------------------------------------- +let suffix = if $os =~ 'windows' { '.exe' } +# nu, nu_plugin_* were all included +let executable = $'target/($target)/release/($bin)*($suffix)' +print $'Current executable file: ($executable)' + +cd $src; mkdir $dist; +rm -rf ...(glob $'target/($target)/release/*.d') ...(glob $'target/($target)/release/nu_pretty_hex*') +print $'(char nl)All executable files:'; hr-line +# We have to use `print` here to make sure the command output is displayed +print (ls -f ($executable | into glob)); sleep 1sec + +print $'(char nl)Copying release files...'; hr-line +"To use the included Nushell plugins, register the binaries with the `plugin add` command to tell Nu where to find the plugin. +Then you can use `plugin use` to load the plugin into your session. +For example: + +> plugin add ./nu_plugin_query +> plugin use query + +For more information, refer to https://www.nushell.sh/book/plugins.html +" | save $'($dist)/README.txt' -f +[LICENSE ...(glob $executable)] | each {|it| cp -rv $it $dist } | flatten + +print $'(char nl)Check binary release version detail:'; hr-line +let ver = if $os =~ 'windows' { + (do -i { .\output\nu.exe -c 'version' }) | default '' | str join +} else { + (do -i { ./output/nu -c 'version' }) | default '' | str join +} +if ($ver | str trim | is-empty) { + print $'(ansi r)Incompatible Nu binary: The binary cross compiled is not runnable on current arch...(ansi reset)' +} else { print $ver } + +# ---------------------------------------------------------------------------- +# Create a release archive and send it to output for the following steps +# ---------------------------------------------------------------------------- +cd $dist; print $'(char nl)Creating release archive...'; hr-line +if $os in ['macos-latest'] or $USE_UBUNTU { + + let files = (ls | get name) + let dest = $'($bin)-($version)-($target)' + let archive = $'($dist)/($dest).tar.gz' + + mkdir $dest + $files | each {|it| cp -v $it $dest } + + print $'(char nl)(ansi g)Archive contents:(ansi reset)'; hr-line; ls $dest | print + + tar -czf $archive $dest + print $'archive: ---> ($archive)'; ls $archive + # REF: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/ + echo $"archive=($archive)(char nl)" o>> $env.GITHUB_OUTPUT + +} else if $os =~ 'windows' { + + let releaseStem = $'($bin)-($version)-($target)' + let arch = if $nu.os-info.arch =~ 'x86_64' { 'x64' } else { 'arm64' } + fetch-less $arch + + print $'(char nl)(ansi g)Archive contents:(ansi reset)'; hr-line; ls | print + let archive = $'($dist)/($releaseStem).zip' + 7z a $archive ...(glob *) + let pkg = (ls -f $archive | get name) + if not ($pkg | is-empty) { + # Workaround for https://github.com/softprops/action-gh-release/issues/280 + let archive = ($pkg | get 0 | str replace --all '\' '/') + print $'archive: ---> ($archive)' + echo $"archive=($archive)(char nl)" o>> $env.GITHUB_OUTPUT + } + + # Create extra Windows msi release package if dotnet and wix are available + let installed = [dotnet wix] | all { (which $in | length) > 0 } + if $installed and (wix --version | split row . | first | into int) >= 6 { + + print $'(char nl)Start creating Windows msi package with the following contents...' + cd $src; cd wix; hr-line; mkdir nu + # Wix need the binaries be stored in nu folder + cp -r ($'($dist)/*' | into glob) nu/ + cp $'($dist)/README.txt' . + ls -f nu/* | print + ./nu/nu.exe -c $'NU_RELEASE_VERSION=($version) dotnet build -c Release -p:Platform=($arch)' + glob **/*.msi | print + # Workaround for https://github.com/softprops/action-gh-release/issues/280 + let wixRelease = (glob **/*.msi | where $it =~ bin | get 0 | str replace --all '\' '/') + let msi = $'($wixRelease | path dirname)/nu-($version)-($target).msi' + mv $wixRelease $msi + print $'MSI archive: ---> ($msi)'; + echo $"msi=($msi)(char nl)" o>> $env.GITHUB_OUTPUT + } +} + +def fetch-less [ + arch: string = 'x64' # The architecture to fetch +] { + let less_zip = $'less-($arch).zip' + print $'Fetching less archive: (ansi g)($less_zip)(ansi reset)' + let url = $'https://github.com/jftuga/less-Windows/releases/download/less-v668/($less_zip)' + http get https://github.com/jftuga/less-Windows/blob/master/LICENSE | save -rf LICENSE-for-less.txt + http get $url | save -rf $less_zip + unzip $less_zip + rm $less_zip lesskey.exe +} + +def 'cargo-build-nu' [] { + if $os =~ 'windows' { + cargo build --release --all --target $target + } else { + cargo build --release --all --target $target --features=static-link-openssl + } +} + +# Print a horizontal line marker +def 'hr-line' [ + --blank-line(-b) +] { + print $'(ansi g)---------------------------------------------------------------------------->(ansi reset)' + if $blank_line { char nl } +} + +# Get the specified env key's value or '' +def 'get-env' [ + key: string # The key to get it's env value + default: string = '' # The default value for an empty env +] { + $env | get -i $key | default $default +} diff --git a/nushell/.github/workflows/release.yml b/nushell/.github/workflows/release.yml new file mode 100644 index 0000000..728b590 --- /dev/null +++ b/nushell/.github/workflows/release.yml @@ -0,0 +1,141 @@ +# +# REF: +# 1. https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrixinclude +# +name: Create Release Draft + +on: + workflow_dispatch: + push: + tags: + - '[0-9]+.[0-9]+.[0-9]+*' + - '!*nightly*' # Don't trigger release for nightly tags + +defaults: + run: + shell: bash + +jobs: + release: + name: Nu + + strategy: + fail-fast: false + matrix: + target: + - aarch64-apple-darwin + - x86_64-apple-darwin + - x86_64-pc-windows-msvc + - aarch64-pc-windows-msvc + - x86_64-unknown-linux-gnu + - x86_64-unknown-linux-musl + - aarch64-unknown-linux-gnu + - aarch64-unknown-linux-musl + - armv7-unknown-linux-gnueabihf + - armv7-unknown-linux-musleabihf + - riscv64gc-unknown-linux-gnu + - loongarch64-unknown-linux-gnu + - loongarch64-unknown-linux-musl + include: + - target: aarch64-apple-darwin + os: macos-latest + - target: x86_64-apple-darwin + os: macos-latest + - target: x86_64-pc-windows-msvc + os: windows-latest + - target: aarch64-pc-windows-msvc + os: windows-11-arm + - target: x86_64-unknown-linux-gnu + os: ubuntu-22.04 + - target: x86_64-unknown-linux-musl + os: ubuntu-22.04 + - target: aarch64-unknown-linux-gnu + os: ubuntu-22.04 + - target: aarch64-unknown-linux-musl + os: ubuntu-22.04 + - target: armv7-unknown-linux-gnueabihf + os: ubuntu-22.04 + - target: armv7-unknown-linux-musleabihf + os: ubuntu-22.04 + - target: riscv64gc-unknown-linux-gnu + os: ubuntu-22.04 + - target: loongarch64-unknown-linux-gnu + os: ubuntu-22.04 + - target: loongarch64-unknown-linux-musl + os: ubuntu-22.04 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v4 + + - name: Install Wix Toolset 6 for Windows + shell: pwsh + if: ${{ startsWith(matrix.os, 'windows') }} + run: | + dotnet tool install --global wix --version 6.0.0 + dotnet workload install wix + $wixPath = "$env:USERPROFILE\.dotnet\tools" + echo "$wixPath" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + $env:PATH = "$wixPath;$env:PATH" + wix --version + + - name: Update Rust Toolchain Target + run: | + echo "targets = ['${{matrix.target}}']" >> rust-toolchain.toml + + - name: Setup Rust toolchain + uses: actions-rust-lang/setup-rust-toolchain@v1.12.0 + # WARN: Keep the rustflags to prevent from the winget submission error: `CAQuietExec: Error 0xc0000135` + with: + cache: false + rustflags: '' + + - name: Setup Nushell + uses: hustcer/setup-nu@v3 + with: + version: 0.105.1 + + - name: Release Nu Binary + id: nu + run: nu .github/workflows/release-pkg.nu + env: + OS: ${{ matrix.os }} + REF: ${{ github.ref }} + TARGET: ${{ matrix.target }} + + # WARN: Don't upgrade this action due to the release per asset issue. + # See: https://github.com/softprops/action-gh-release/issues/445 + - name: Publish Archive + uses: softprops/action-gh-release@v2.0.5 + if: ${{ startsWith(github.ref, 'refs/tags/') }} + with: + draft: true + files: | + ${{ steps.nu.outputs.msi }} + ${{ steps.nu.outputs.archive }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + sha256sum: + needs: release + name: Create Sha256sum + runs-on: ubuntu-latest + steps: + - name: Download Release Archives + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: >- + gh release download ${{ github.ref_name }} + --repo ${{ github.repository }} + --pattern '*' + --dir release + - name: Create Checksums + run: cd release && shasum -a 256 * > ../SHA256SUMS + - name: Publish Checksums + uses: softprops/action-gh-release@v2.0.5 + with: + draft: true + files: SHA256SUMS + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/nushell/.github/workflows/typos.yml b/nushell/.github/workflows/typos.yml new file mode 100644 index 0000000..8a87fa3 --- /dev/null +++ b/nushell/.github/workflows/typos.yml @@ -0,0 +1,13 @@ +name: Typos +on: [pull_request] + +jobs: + run: + name: Spell Check with Typos + runs-on: ubuntu-latest + steps: + - name: Checkout Actions Repository + uses: actions/checkout@v4.1.7 + + - name: Check spelling + uses: crate-ci/typos@v1.33.1 diff --git a/nushell/.github/workflows/winget-submission.yml b/nushell/.github/workflows/winget-submission.yml new file mode 100644 index 0000000..01981fd --- /dev/null +++ b/nushell/.github/workflows/winget-submission.yml @@ -0,0 +1,34 @@ +name: Submit Nushell package to Windows Package Manager Community Repository + +on: + release: + types: [released] + workflow_dispatch: + inputs: + tag_name: + description: 'Specific tag name' + required: true + type: string + +permissions: + contents: write + packages: write + pull-requests: write + +jobs: + + winget: + name: Publish winget package + runs-on: ubuntu-latest + steps: + - name: Submit package to Windows Package Manager Community Repository + uses: vedantmgoyal2009/winget-releaser@v2 + with: + identifier: Nushell.Nushell + # Exclude all `*-msvc-full.msi` full release files, + # and only the default `*msvc.msi` files will be included + installers-regex: 'msvc\.msi$' + version: ${{ inputs.tag_name || github.event.release.tag_name }} + release-tag: ${{ inputs.tag_name || github.event.release.tag_name }} + token: ${{ secrets.NUSHELL_PAT }} + fork-user: nushell diff --git a/nushell/.gitignore b/nushell/.gitignore new file mode 100644 index 0000000..9a080ea --- /dev/null +++ b/nushell/.gitignore @@ -0,0 +1,55 @@ +/target +/scratch +**/*.rs.bk +history.txt +tests/fixtures/nuplayground +crates/*/target +.mailmap + +# Debian/Ubuntu +debian/.debhelper/ +debian/debhelper-build-stamp +debian/files +debian/nu.substvars +debian/nu/ + +# macOS junk +.DS_Store + +# JetBrains' IDE items +.idea/* + +# VSCode's IDE items +.vscode/* + +# JetBrains' Fleet IDE +.fleet/* + +# Visual Studio Extension SourceGear Rust items +VSWorkspaceSettings.json +unstable_cargo_features.txt + +# Helix configuration folder +.helix/* +.helix +wix/bin/ +wix/obj/ +wix/nu/ + +# Coverage tools +lcov.info +tarpaulin-report.html + +# Visual Studio +.vs/* +*.rsproj +*.rsproj.user +*.sln +*.code-workspace + +# direnv +.direnv/ +.envrc + +# pre-commit-hooks +.pre-commit-config.yaml diff --git a/nushell/CITATION.cff b/nushell/CITATION.cff new file mode 100644 index 0000000..25731e8 --- /dev/null +++ b/nushell/CITATION.cff @@ -0,0 +1,26 @@ +cff-version: 1.2.0 +title: 'Nushell' +message: >- + If you use this software and wish to cite it, + you can use the metadata from this file. +type: software +authors: + - name: "The Nushell Project Team" +identifiers: + - type: url + value: 'https://github.com/nushell/nushell' + description: Repository +repository-code: 'https://github.com/nushell/nushell' +url: 'https://www.nushell.sh/' +abstract: >- + The goal of the Nushell project is to take the Unix + philosophy of shells, where pipes connect simple commands + together, and bring it to the modern style of development. + Thus, rather than being either a shell, or a programming + language, Nushell connects both by bringing a rich + programming language and a full-featured shell together + into one package. +keywords: + - nushell + - shell +license: MIT diff --git a/nushell/CODE_OF_CONDUCT.md b/nushell/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..9f5a648 --- /dev/null +++ b/nushell/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to make participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies within all project spaces, and it also applies when +an individual is representing the project or its community in public spaces. +Examples of representing a project or community include using an official +project e-mail address, posting via an official social media account, or acting +as an appointed representative at an online or offline event. Representation of +a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at wycats@gmail.com via email or by reaching out to @jturner, @gedge, or @andras_io on discord. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see + diff --git a/nushell/CONTRIBUTING.md b/nushell/CONTRIBUTING.md new file mode 100644 index 0000000..a04d374 --- /dev/null +++ b/nushell/CONTRIBUTING.md @@ -0,0 +1,236 @@ +# Contributing + +Welcome to Nushell and thank you for considering contributing! + +## Table of contents +- [Proposing design changes](#proposing-design-changes) +- [Developing](#developing) + - [Setup](#setup) + - [Tests](#tests) + - [Useful commands](#useful-commands) + - [Debugging tips](#debugging-tips) +- [Git etiquette](#git-etiquette) +- [License](#license) + +## Other helpful resources + +More resources can be found in the nascent [developer documentation](devdocs/README.md) in this repo. + +- [Developer FAQ](devdocs/FAQ.md) +- [Platform support policy](devdocs/PLATFORM_SUPPORT.md) +- [Our Rust style](devdocs/rust_style.md) + +## Proposing design changes + +First of all, before diving into the code, if you want to create a new feature, change something significantly, and especially if the change is user-facing, it is a good practice to first get an approval from the core team before starting to work on it. +This saves both your and our time if we realize the change needs to go another direction before spending time on it. +So, please, reach out and tell us what you want to do. +This will significantly increase the chance of your PR being accepted. + +The review process can be summarized as follows: +1. You want to make some change to Nushell that is more involved than simple bug-fixing. +2. Go to [Discord](https://discordapp.com/invite/NtAbbGn) or a [GitHub issue](https://github.com/nushell/nushell/issues/new/choose) and chat with some core team members and/or other contributors about it. +3. After getting a green light from the core team, implement the feature, open a pull request (PR) and write a concise but comprehensive description of the change. +4. If your PR includes any user-facing features (such as adding a flag to a command), clearly list them in the PR description. +5. Then, core team members and other regular contributors will review the PR and suggest changes. +6. When we all agree, the PR will be merged. +7. If your PR includes any user-facing features, make sure the changes are also reflected in [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged. +8. Congratulate yourself, you just improved Nushell! :-) + +## Developing + +### Setup + +Nushell requires a recent Rust toolchain and some dependencies; [refer to the Nu Book for up-to-date requirements](https://www.nushell.sh/book/installation.html#build-from-source). After installing dependencies, you should be able to clone+build Nu like any other Rust project: + +```bash +git clone https://github.com/nushell/nushell +cd nushell +cargo build +``` + +### Tests + +It is good practice to cover your changes with a test. Also, try to think about corner cases and various ways how your changes could break. Cover those in the tests as well. + +Tests can be found in different places: +* `/tests` +* command examples +* crate-specific tests + +Most of the tests are built upon the `nu-test-support` crate. For testing specific features, such as running Nushell in a REPL mode, we have so called "testbins". For simple tests, you can find `run_test()` and `fail_test()` functions. + +### Useful Commands + +As Nushell is built using a cargo workspace consisting of multiple crates keep in mind that you may need to pass additional flags compared to how you may be used to it from a single crate project. +Read cargo's documentation for more details: https://doc.rust-lang.org/cargo/reference/workspaces.html + +- Build and run Nushell: + + ```nushell + cargo run + ``` + +- Run Clippy on Nushell: + + ```nushell + cargo clippy --workspace -- -D warnings -D clippy::unwrap_used + ``` + or via the `toolkit.nu` command: + ```nushell + use toolkit.nu clippy + clippy + ``` + +- Run all tests: + + ```nushell + cargo test --workspace + ``` + + or via the `toolkit.nu` command: + ```nushell + use toolkit.nu test + test + ``` + +- Run all tests for a specific command + + ```nushell + cargo test --package nu-cli --test main -- commands:: + ``` + +- Check to see if there are code formatting issues + + ```nushell + cargo fmt --all -- --check + ``` + or via the `toolkit.nu` command: + ```nushell + use toolkit.nu fmt + fmt --check + ``` + +- Format the code in the project + + ```nushell + cargo fmt --all + ``` + or via the `toolkit.nu` command: + ```nushell + use toolkit.nu fmt + fmt + ``` + +- Set up `git` hooks to check formatting and run `clippy` before committing and pushing: + + ```nushell + use toolkit.nu setup-git-hooks + setup-git-hooks + ``` + _Unfortunately, this hook isn't available on Windows._ + +### Debugging Tips + +- To view verbose logs when developing, enable the `trace` log level. + + ```nushell + cargo run --release -- --log-level trace + ``` + +- To redirect trace logs to a file, enable the `--log-target file` switch. + ```nushell + cargo run --release -- --log-level trace --log-target file + open $"($nu.temp-path)/nu-($nu.pid).log" + ``` + +## Git etiquette + +As nushell thrives on its broad base of volunteer contributors and maintainers with different backgrounds we have a few guidelines for how we best utilize git and GitHub for our contributions. We strive to balance three goals with those recommendations: + +1. The **volunteer maintainers and contributors** can easily follow the changes you propose, gauge the impact, and come to help you or make a decision. +2. **You as a contributor** can focus most of your time on improving the quality of the nushell project and contributing your expertise to the code or documentation. +3. Making sure we can trace back *why* decisions were made in the past. +This includes discarded approaches. Also we want to quickly identify regressions and fix when something broke. + +### How we merge PRs + +In general the maintainers **squash** all changes of your PR into a single commit when merging. + +This keeps a clean enough linear history, while not forcing you to conform to a too strict style while iterating in your PR or fixing small problems. As an added benefit the commits on the `main` branch are tied to the discussion that happened in the PR through their `#1234` issue number. + +> **Note** +> **Pro advice:** In some circumstances, we can agree on rebase-merging a particularly large but connected PR as a series of atomic commits onto the `main` branch to ensure we can more easily revert or bisect particular aspects. + +### A good PR makes a change! + +As a result of this PR-centric strategy and the general goal that the reviewers should easily understand your change, the **PR title and description matters** a great deal! + +Make sure your description is **concise** but contains all relevant information and context. +This means demonstrating what changes, ideally through nushell code or output **examples**. +Furthermore links to technical documentation or instructions for folks that want to play with your change make the review process much easier. + +> **Note** +> Try to follow the suggestions in our PR message template to make sure we can quickly focus on the technical merits and impact on the users. + +#### A PR should limit itself to a single functional change or related set of same changes. + +Mixing different changes in the same PR will make the review process much harder. A PR might get stuck on one aspect while we would actually like to land another change. Furthermore, if we are forced to revert a change, mixing and matching different aspects makes fixing bugs or regressions much harder. + +Thus, please try to **separate out unrelated changes**! +**Don't** mix unrelated refactors with a potentially contested change. +Stylistic fixes and housekeeping can be bundled up into singular PRs. + +#### Guidelines for the PR title + +The PR title should be concise but contain everything for a contributor to know if they should help out in the review of this particular change. + +**DON'T** +- `Update file/in/some/deeply/nested/path.rs` + - Why are you making this change? +- `Fix 2134` + - What has to be fixed? + - Hard to follow when not online on GitHub. +- ``Ignore `~` expansion`` + - In what context should this change take effect? +- `[feature] refactor the whole parser and also make nushell indentation-sensitive, upgrade to using Cpython. Let me know what you think!` + - Be concise + - Maybe break up into smaller commits or PRs if the title already appears too long? + +**DO** +- Mention the nushell feature or command that is affected. + - ``Fix URL parsing in `http get` (issue #1234)`` +- You can mention the issue number if other context is there. + - In general, mention all related issues in the description to crosslink (e.g. `Fixes #1234`, `Closes #6789`) +- For internal changes mention the area or symbols affected if it helps to clarify + - ``Factor out `quote_string()` from parser to reuse in `explore` `` + +### Review process / Merge conflicts + +> **Note** +> Keep in mind that the maintainers are volunteers that need to allocate their attention to several different areas and active PRs. We will try to get back to you as soon as possible. + +You can help us to make the review process a smooth experience: +- Testing: + - We generally review in detail after all the tests pass. Let us know if there is a problem you want to discuss to fix a test failure or forces us to accept a breaking change. + - If you fix a bug, it is highly recommended that you add a test that reproduces the original issue/panic in a minimal form. + - In general, added tests help us to understand which assumptions go into a particular addition/change. + - Try to also test corner cases where those assumptions might break. This can be more valuable than simply adding many similar tests. +- Commit history inside a PR during code review: + - Good **atomic commits** can help follow larger changes, but we are not pedantic. + - We don't shame fixup commits while you try to figure out a problem. They can help others see what you tried and what didn't work. (see our [squash policy](#how-we-merge-prs)) + - During active review constant **force pushing** just to amend changes can be confusing! + - GitHub's UI presents reviewers with less options to compare diffs + - fetched branches for experimentation become invalid! + - the notification a maintainer receives has a low signal-to-noise ratio + - Git pros *can* use their judgement to rebase/squash to clean up the history *if it aids the understanding* of a larger change during review +- Merge conflicts: + - In general you should take care of resolving merge conflicts. + - Use your judgement whether to `git merge main` or to `git rebase main` + - Choose what simplifies having confidence in the conflict resolution and the review. **Merge commits in your branch are OK** in the squash model. + - Feel free to notify your reviewers or affected PR authors if your change might cause larger conflicts with another change. + - During the rollup of multiple PRs, we may choose to resolve merge conflicts and CI failures ourselves. (Allow maintainers to push to your branch to enable us to do this quickly.) + +## License + +We use the [MIT License](https://github.com/nushell/nushell/blob/main/LICENSE) in all of our Nushell projects. If you are including or referencing a crate that uses the [GPL License](https://www.gnu.org/licenses/gpl-3.0.en.html#license-text) unfortunately we will not be able to accept your PR. diff --git a/nushell/Cargo.lock b/nushell/Cargo.lock new file mode 100644 index 0000000..72366f8 --- /dev/null +++ b/nushell/Cargo.lock @@ -0,0 +1,8867 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom 0.2.15", + "once_cell", + "version_check", + "zerocopy 0.7.35", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "alloca" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4" +dependencies = [ + "cc", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "alphanumeric-sort" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d67c60c5f10f11c6ee04de72b2dd98bb9d2548cbc314d22a609bfa8bd9e87e8f" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "ansi-str" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "060de1453b69f46304b28274f382132f4e72c55637cf362920926a70d090890d" +dependencies = [ + "ansitok", +] + +[[package]] +name = "ansitok" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0a8acea8c2f1c60f0a92a8cd26bf96ca97db56f10bbcab238bbe0cceba659ee" +dependencies = [ + "nom 7.1.3", + "vte 0.14.1", +] + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + +[[package]] +name = "anyhow" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "arboard" +version = "3.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df099ccb16cd014ff054ac1bf392c67feeef57164b05c42f037cd40f5d4357f4" +dependencies = [ + "clipboard-win", + "log", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "parking_lot", + "wl-clipboard-rs", + "x11rb", +] + +[[package]] +name = "argminmax" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70f13d10a41ac8d2ec79ee34178d61e6f47a29c2edfe7ef1721c7383b0359e65" +dependencies = [ + "num-traits", +] + +[[package]] +name = "array-init-cursor" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed51fe0f224d1d4ea768be38c51f9f831dee9d05c163c11fba0b8c44387b1fc3" + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "assert-json-diff" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "assert_cmd" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "libc", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "atoi_simd" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4790f9e8961209112beb783d85449b508673cf4a6a419c8449b210743ac4dbe9" + +[[package]] +name = "atomic" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "avro-schema" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5281855b39aba9684d2f47bf96983fbfd8f1725f12fabb0513a8ab879647bbd" +dependencies = [ + "crc", + "fallible-streaming-iterator", + "libflate", + "serde", + "serde_json", + "snap", +] + +[[package]] +name = "aws-config" +version = "1.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b49afaa341e8dd8577e1a2200468f98956d6eda50bcf4a53246cc00174ba924" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-sdk-sso", + "aws-sdk-ssooidc", + "aws-sdk-sts", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "hex", + "http 0.2.12", + "ring", + "time", + "tokio", + "tracing", + "url", + "zeroize", +] + +[[package]] +name = "aws-credential-types" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60e8f6b615cb5fc60a98132268508ad104310f0cfb25a1c22eee76efdf9154da" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "zeroize", +] + +[[package]] +name = "aws-runtime" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a10d5c055aa540164d9561a0e2e74ad30f0dcf7393c3a92f6733ddf9c5762468" +dependencies = [ + "aws-credential-types", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "http 0.2.12", + "http-body 0.4.6", + "once_cell", + "percent-encoding", + "pin-project-lite", + "tracing", + "uuid", +] + +[[package]] +name = "aws-sdk-sso" +version = "1.49.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09677244a9da92172c8dc60109b4a9658597d4d298b188dd0018b6a66b410ca4" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "http 0.2.12", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-ssooidc" +version = "1.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fea2f3a8bb3bd10932ae7ad59cc59f65f270fc9183a7e91f501dc5efbef7ee" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "http 0.2.12", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-sts" +version = "1.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ada54e5f26ac246dc79727def52f7f8ed38915cb47781e2a72213957dc3a7d5" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-query", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-smithy-xml", + "aws-types", + "http 0.2.12", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sigv4" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5619742a0d8f253be760bfbb8e8e8368c69e3587e4637af5754e488a611499b1" +dependencies = [ + "aws-credential-types", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "form_urlencoded", + "hex", + "hmac", + "http 0.2.12", + "http 1.2.0", + "once_cell", + "percent-encoding", + "sha2", + "time", + "tracing", +] + +[[package]] +name = "aws-smithy-async" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62220bc6e97f946ddd51b5f1361f78996e704677afc518a4ff66b7a72ea1378c" +dependencies = [ + "futures-util", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "aws-smithy-http" +version = "0.60.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8bc3e8fdc6b8d07d976e301c02fe553f72a39b7a9fea820e023268467d7ab6" +dependencies = [ + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "bytes-utils", + "futures-core", + "http 0.2.12", + "http-body 0.4.6", + "once_cell", + "percent-encoding", + "pin-project-lite", + "pin-utils", + "tracing", +] + +[[package]] +name = "aws-smithy-json" +version = "0.60.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4683df9469ef09468dad3473d129960119a0d3593617542b7d52086c8486f2d6" +dependencies = [ + "aws-smithy-types", +] + +[[package]] +name = "aws-smithy-query" +version = "0.60.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fbd61ceb3fe8a1cb7352e42689cec5335833cd9f94103a61e98f9bb61c64bb" +dependencies = [ + "aws-smithy-types", + "urlencoding", +] + +[[package]] +name = "aws-smithy-runtime" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be28bd063fa91fd871d131fc8b68d7cd4c5fa0869bea68daca50dcb1cbd76be2" +dependencies = [ + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "fastrand", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "http-body 1.0.1", + "httparse", + "hyper 0.14.31", + "hyper-rustls 0.24.2", + "once_cell", + "pin-project-lite", + "pin-utils", + "rustls 0.21.12", + "tokio", + "tracing", +] + +[[package]] +name = "aws-smithy-runtime-api" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92165296a47a812b267b4f41032ff8069ab7ff783696d217f0994a0d7ab585cd" +dependencies = [ + "aws-smithy-async", + "aws-smithy-types", + "bytes", + "http 0.2.12", + "http 1.2.0", + "pin-project-lite", + "tokio", + "tracing", + "zeroize", +] + +[[package]] +name = "aws-smithy-types" +version = "1.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fbd94a32b3a7d55d3806fe27d98d3ad393050439dd05eb53ece36ec5e3d3510" +dependencies = [ + "base64-simd", + "bytes", + "bytes-utils", + "http 0.2.12", + "http 1.2.0", + "http-body 0.4.6", + "http-body 1.0.1", + "http-body-util", + "itoa", + "num-integer", + "pin-project-lite", + "pin-utils", + "ryu", + "serde", + "time", +] + +[[package]] +name = "aws-smithy-xml" +version = "0.60.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab0b0166827aa700d3dc519f72f8b3a91c35d0b8d042dc5d643a91e6f80648fc" +dependencies = [ + "xmlparser", +] + +[[package]] +name = "aws-types" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5221b91b3e441e6675310829fd8984801b772cb1546ef6c0e54dec9f1ac13fef" +dependencies = [ + "aws-credential-types", + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "rustc_version", + "tracing", +] + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "backtrace-ext" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" +dependencies = [ + "backtrace", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref", + "vsimd", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bindgen" +version = "0.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +dependencies = [ + "bitflags 2.6.0", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn 2.0.90", +] + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] + +[[package]] +name = "blake3" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2", +] + +[[package]] +name = "boxcar" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c4925bc979b677330a8c7fe7a8c94af2dbb4a2d37b4a20a80d884400f46baa" + +[[package]] +name = "bracoxide" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3572b24445a122332bb25a2637248d62ca8b567351d98b1194ca4132c61810bd" + +[[package]] +name = "brotli" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bstr" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786a307d683a5bf92e6fd5fd69a7eb613751668d1d8d67d802846dfe367c62c8" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bytecount" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" + +[[package]] +name = "bytemuck" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" +dependencies = [ + "serde", +] + +[[package]] +name = "bytes-utils" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" +dependencies = [ + "bytes", + "either", +] + +[[package]] +name = "bytesize" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e93abca9e28e0a1b9877922aacb20576e05d4679ffa78c3d6dc22a26a216659" + +[[package]] +name = "calamine" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e02a18e79de779a78b0a6ec84a3deed1ff0607dd970a11369f993263f99f1a" +dependencies = [ + "atoi_simd", + "byteorder", + "chrono", + "codepage", + "encoding_rs", + "fast-float2", + "log", + "quick-xml 0.37.1", + "serde", + "zip", +] + +[[package]] +name = "cassowary" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" + +[[package]] +name = "castaway" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" +dependencies = [ + "rustversion", +] + +[[package]] +name = "cc" +version = "1.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom 7.1.3", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chardetng" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b8f0b65b7b08ae3c8187e8d77174de20cb6777864c6b832d8ad365999cf1ea" +dependencies = [ + "cfg-if", + "encoding_rs", + "memchr", +] + +[[package]] +name = "charset" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f927b07c74ba84c7e5fe4db2baeb3e996ab2688992e39ac68ce3220a677c7e" +dependencies = [ + "base64 0.22.1", + "encoding_rs", +] + +[[package]] +name = "chrono" +version = "0.4.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "pure-rust-locales", + "serde", + "wasm-bindgen", + "windows-targets 0.52.6", +] + +[[package]] +name = "chrono-humanize" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799627e6b4d27827a814e837b9d8a504832086081806d45b1afa34dc982b023b" +dependencies = [ + "chrono", +] + +[[package]] +name = "chrono-tz" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6dd8046d00723a59a2f8c5f295c515b9bb9a331ee4f8f3d4dd49e428acd3b6" +dependencies = [ + "chrono", + "chrono-tz-build", + "phf", +] + +[[package]] +name = "chrono-tz-build" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94fea34d77a245229e7746bd2beb786cd2a896f306ff491fb8cecb3074b10a7" +dependencies = [ + "parse-zoneinfo", + "phf_codegen", +] + +[[package]] +name = "chumsky" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9" +dependencies = [ + "hashbrown 0.14.5", + "stacker", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.5.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", + "terminal_size", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "clipboard-win" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892" +dependencies = [ + "error-code", +] + +[[package]] +name = "codepage" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48f68d061bc2828ae826206326e61251aca94c1e4a5305cf52d9138639c918b4" +dependencies = [ + "encoding_rs", +] + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "colorz" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ceb37c5798821e37369cb546f430f19da2f585e0364c9615ae340a9f2e6067b" +dependencies = [ + "supports-color", +] + +[[package]] +name = "comfy-table" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24f165e7b643266ea80cb858aed492ad9280e3e05ce24d4a99d7d7b889b6a4d9" +dependencies = [ + "crossterm", + "strum", + "strum_macros", + "unicode-width 0.2.0", +] + +[[package]] +name = "compact_str" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6050c3a16ddab2e412160b31f2c871015704239bca62f72f6e5f0be631d3f644" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "rustversion", + "ryu", + "serde", + "static_assertions", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width 0.1.11", + "windows-sys 0.52.0", +] + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.15", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "const_format" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crossterm" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" +dependencies = [ + "bitflags 2.6.0", + "crossterm_winapi", + "mio 1.0.3", + "parking_lot", + "rustix 0.38.42", + "serde", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cssparser" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c66d1cd8ed61bf80b38432613a7a2f09401ab8d0501110655f8b341484a3e3" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.90", +] + +[[package]] +name = "csv" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", +] + +[[package]] +name = "ctrlc" +version = "3.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" +dependencies = [ + "nix 0.29.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "curl" +version = "0.4.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9fb4d13a1be2b58f14d60adba57c9834b78c62fd86c3e76a148f732686e9265" +dependencies = [ + "curl-sys", + "libc", + "openssl-probe", + "openssl-sys", + "schannel", + "socket2", + "windows-sys 0.52.0", +] + +[[package]] +name = "curl-sys" +version = "0.4.78+curl-8.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eec768341c5c7789611ae51cf6c459099f22e64a5d5d0ce4892434e33821eaf" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", + "windows-sys 0.52.0", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.90", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "data-encoding" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive-new" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "derive_arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "devicons" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830e47e2f330cf4fdd5a958dcef921b9523ffc21ab6713aa5e77ba2cce03904b" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "dialoguer" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" +dependencies = [ + "console", + "fuzzy-matcher", + "shell-words", + "thiserror 1.0.69", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + +[[package]] +name = "dlv-list" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" +dependencies = [ + "const-random", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "doctest-file" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac81fa3e28d21450aa4d2ac065992ba96a1d7303efbce51a95f4fd175b67562" + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "dtparse" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23fb403c0926d35af2cc54d961bc2696a10d40725c08360ef69db04a4c201fd7" +dependencies = [ + "chrono", + "lazy_static", + "num-traits", + "rust_decimal", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "ego-tree" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2972feb8dffe7bc8c5463b1dacda1b0dfbed3710e50f977d965429692d74cd8" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +dependencies = [ + "serde", +] + +[[package]] +name = "eml-parser" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7db8d15f812e08f76427c555195583e3ab8a99fd8b208f8d9e2899262e80f2e" +dependencies = [ + "regex", + "rfc2047-decoder", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_home" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" + +[[package]] +name = "env_logger" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "erased-serde" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" +dependencies = [ + "serde", + "typeid", +] + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "error-code" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" + +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + +[[package]] +name = "ethnum" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" + +[[package]] +name = "event-listener" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + +[[package]] +name = "fancy-regex" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e24cb5a94bcae1e5408b0effca5cd7172ea3c5755049c5f3af4cd283a165298" +dependencies = [ + "bit-set", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "fast-float2" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8eb564c5c7423d25c886fb561d1e4ee69f72354d16918afa32c08811f6b6a55" + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fd-lock" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947" +dependencies = [ + "cfg-if", + "rustix 0.38.42", + "windows-sys 0.52.0", +] + +[[package]] +name = "file-id" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bc904b9bbefcadbd8e3a9fb0d464a9b979de6324c03b3c663e8994f46a5be36" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "filesize" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12d741e2415d4e2e5bd1c1d00409d1a8865a57892c2d689b504365655d237d43" +dependencies = [ + "winapi", +] + +[[package]] +name = "filetime" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "libz-rs-sys", + "miniz_oxide", +] + +[[package]] +name = "float-cmp" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" +dependencies = [ + "num-traits", +] + +[[package]] +name = "fluent-uri" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17c704e9dbe1ddd863da1e6ff3567795087b1eb201ce80d8fa81162e1516500d" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fs4" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8640e34b88f7652208ce9e88b1a37a2ae95227d84abec377ccd3c5cfeb141ed4" +dependencies = [ + "rustix 1.0.7", + "windows-sys 0.59.0", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fuzzy-matcher" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94" +dependencies = [ + "thread_local", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +dependencies = [ + "libc", + "windows-targets 0.48.5", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "git2" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fda788993cc341f69012feba8bf45c0ba4f3291fcc08e214b4d5a7332d88aff" +dependencies = [ + "bitflags 2.6.0", + "libc", + "libgit2-sys", + "log", + "openssl-probe", + "openssl-sys", + "url", +] + +[[package]] +name = "gjson" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43503cc176394dd30a6525f5f36e838339b8b5619be33ed9a7783841580a97b6" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "glob-match" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985c9503b412198aa4197559e9a318524ebc4519c229bfa05a535828c950b9d" + +[[package]] +name = "goblin" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27c1b4369c2cd341b5de549380158b105a04c331be5db9110eef7b6d2742134" +dependencies = [ + "log", + "plain", + "scroll", +] + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.2.0", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "halfbrown" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8588661a8607108a5ca69cab034063441a0413a0b041c13618a7dd348021ef6f" +dependencies = [ + "hashbrown 0.14.5", + "serde", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", + "rayon", + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", + "rayon", + "serde", +] + +[[package]] +name = "hashlink" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +dependencies = [ + "hashbrown 0.14.5", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "html5ever" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +dependencies = [ + "log", + "mac", + "markup5ever 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "html5ever" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e15626aaf9c351bc696217cbe29cb9b5e86c43f8a46b5e2f5c6c5cf7cb904ce" +dependencies = [ + "log", + "mac", + "markup5ever 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.2.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.2.0", + "http-body 1.0.1", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "human-date-parser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "406f83c56de4b2c9183be52ae9a4fefa22c0e0c3d3d7ef80be26eaee11c7110e" +dependencies = [ + "chrono", + "pest", + "pest_consume", + "pest_derive", + "thiserror 1.0.69", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.7", + "http 1.2.0", + "http-body 1.0.1", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper 0.14.31", + "log", + "rustls 0.21.12", + "rustls-native-certs 0.6.3", + "tokio", + "tokio-rustls 0.24.1", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http 1.2.0", + "hyper 1.5.1", + "hyper-util", + "rustls 0.23.20", + "rustls-native-certs 0.8.1", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.1", + "tower-service", + "webpki-roots 0.26.8", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.5.1", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.2.0", + "http-body 1.0.1", + "hyper 1.5.1", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core 0.52.0", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ical" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7cab7543a8b7729a19e2c04309f902861293dcdae6558dfbeb634454d279f6" +dependencies = [ + "thiserror 1.0.69", +] + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", + "serde", +] + +[[package]] +name = "indicatif" +version = "0.17.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf675b85ed934d3c67b5c5469701eec7db22689d0a2139d856e0925fa28b281" +dependencies = [ + "console", + "number_prefix", + "portable-atomic", + "unicode-width 0.2.0", + "web-time", +] + +[[package]] +name = "indoc" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" + +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + +[[package]] +name = "instability" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf9fed6d91cfb734e7476a06bde8300a1b94e217e1b523b6f0cd1a01998c71d" +dependencies = [ + "darling", + "indoc", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "interprocess" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "894148491d817cb36b6f778017b8ac46b17408d522dd90f539d677ea938362eb" +dependencies = [ + "doctest-file", + "libc", + "recvmsg", + "widestring", + "windows-sys 0.52.0", +] + +[[package]] +name = "inventory" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767" + +[[package]] +name = "ipnet" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[package]] +name = "is-docker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" +dependencies = [ + "once_cell", +] + +[[package]] +name = "is-wsl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" +dependencies = [ + "is-docker", + "once_cell", +] + +[[package]] +name = "is_ci" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" + +[[package]] +name = "is_debug" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fe266d2e243c931d8190177f20bf7f24eed45e96f39e87dc49a27b32d12d407" + +[[package]] +name = "is_executable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a1b5bad6f9072935961dfbf1cced2f3d129963d091b6f69f007fe04e758ae2" +dependencies = [ + "winapi", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "jsonpath_lib_polars_vendor" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4bd9354947622f7471ff713eacaabdb683ccb13bba4edccaab9860abf480b7d" +dependencies = [ + "log", + "serde", + "serde_json", +] + +[[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.168" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" + +[[package]] +name = "libflate" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ff4ae71b685bbad2f2f391fe74f6b7659a34871c08b210fdc039e43bee07d18" +dependencies = [ + "adler32", + "crc32fast", + "libflate_lz77", +] + +[[package]] +name = "libflate_lz77" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a52d3a8bfc85f250440e4424db7d857e241a3aebbbe301f3eb606ab15c39acbf" +dependencies = [ + "rle-decode-fast", +] + +[[package]] +name = "libgit2-sys" +version = "0.18.0+1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1a117465e7e1597e8febea8bb0c410f1c7fb93b1e1cddf34363f8390367ffec" +dependencies = [ + "cc", + "libc", + "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", +] + +[[package]] +name = "libloading" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +dependencies = [ + "cfg-if", + "windows-targets 0.52.6", +] + +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + +[[package]] +name = "libproc" +version = "0.14.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78a09b56be5adbcad5aa1197371688dc6bb249a26da3bca2011ee2fb987ebfb" +dependencies = [ + "bindgen", + "errno", + "libc", +] + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", + "redox_syscall", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c10584274047cb335c23d3e61bcef8e323adae7c5c8c760540f73610177fc3f" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libssh2-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libz-rs-sys" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "172a788537a2221661b480fee8dc5f96c580eb34fa88764d3205dc356c7e4221" +dependencies = [ + "zlib-rs", +] + +[[package]] +name = "libz-sys" +version = "1.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +dependencies = [ + "serde", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "lockfree-object-pool" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +dependencies = [ + "hashbrown 0.15.2", +] + +[[package]] +name = "lscolors" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61183da5de8ba09a58e330d55e5ea796539d8443bd00fdeb863eac39724aa4ab" +dependencies = [ + "aho-corasick", + "nu-ansi-term", +] + +[[package]] +name = "lsp-server" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9462c4dc73e17f971ec1f171d44bfffb72e65a130117233388a0ebc7ec5656f9" +dependencies = [ + "crossbeam-channel", + "log", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "lsp-textdocument" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d564d595f4e3dcd3c071bf472dbd2cac53bc3665ae7222d2abfecd18feaed2c" +dependencies = [ + "lsp-types", + "serde_json", +] + +[[package]] +name = "lsp-types" +version = "0.97.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53353550a17c04ac46c585feb189c2db82154fc84b79c7a66c96c2c644f66071" +dependencies = [ + "bitflags 1.3.2", + "fluent-uri", + "serde", + "serde_json", + "serde_repr", +] + +[[package]] +name = "lz4" +version = "1.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d1febb2b4a79ddd1980eede06a8f7902197960aa0383ffcfdd62fe723036725" +dependencies = [ + "lz4-sys", +] + +[[package]] +name = "lz4-sys" +version = "1.11.1+lz4-1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + +[[package]] +name = "markup5ever" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" +dependencies = [ + "log", + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "markup5ever" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82c88c6129bd24319e62a0359cb6b958fa7e8be6e19bb1663bc396b90883aca5" +dependencies = [ + "log", + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "markup5ever_rcdom" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edaa21ab3701bfee5099ade5f7e1f84553fd19228cf332f13cd6e964bf59be18" +dependencies = [ + "html5ever 0.27.0", + "markup5ever 0.12.1", + "tendril", + "xml5ever", +] + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memmap2" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +dependencies = [ + "libc", +] + +[[package]] +name = "miette" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" +dependencies = [ + "backtrace", + "backtrace-ext", + "cfg-if", + "miette-derive", + "owo-colors", + "supports-color", + "supports-hyperlinks", + "supports-unicode", + "terminal_size", + "textwrap", + "unicode-width 0.1.11", +] + +[[package]] +name = "miette-derive" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.48.0", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + +[[package]] +name = "mockito" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7760e0e418d9b7e5777c0374009ca4c93861b9066f18cb334a20ce50ab63aa48" +dependencies = [ + "assert-json-diff", + "bytes", + "futures-util", + "http 1.2.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.5.1", + "hyper-util", + "log", + "rand 0.9.0", + "regex", + "serde_json", + "serde_urlencoded", + "similar", + "tokio", +] + +[[package]] +name = "multipart-rs" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cae00e7e52aa5072342ef9a2ccd71669be913c2176a81a665b1f9cd79345f2" +dependencies = [ + "bytes", + "futures-core", + "futures-util", + "memchr", + "mime", + "uuid", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework 2.11.1", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases 0.1.1", + "libc", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases 0.2.1", + "libc", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "notify" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +dependencies = [ + "bitflags 2.6.0", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "log", + "mio 0.8.11", + "walkdir", + "windows-sys 0.48.0", +] + +[[package]] +name = "notify-debouncer-full" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb7fd166739789c9ff169e654dc1501373db9d80a4c3f972817c8a4d7cf8f34e" +dependencies = [ + "file-id", + "log", + "notify", + "parking_lot", + "walkdir", +] + +[[package]] +name = "now" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d89e9874397a1f0a52fc1f197a8effd9735223cb2390e9dcc83ac6cd02923d0" +dependencies = [ + "chrono", +] + +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + +[[package]] +name = "nu" +version = "0.105.2" +dependencies = [ + "assert_cmd", + "crossterm", + "ctrlc", + "dirs", + "fancy-regex", + "log", + "miette", + "multipart-rs", + "nix 0.29.0", + "nu-cli", + "nu-cmd-base", + "nu-cmd-extra", + "nu-cmd-lang", + "nu-cmd-plugin", + "nu-command", + "nu-engine", + "nu-explore", + "nu-lsp", + "nu-parser", + "nu-path", + "nu-plugin-core", + "nu-plugin-engine", + "nu-plugin-protocol", + "nu-protocol", + "nu-std", + "nu-system", + "nu-test-support", + "nu-utils", + "openssl", + "pretty_assertions", + "reedline", + "rstest", + "serde_json", + "serial_test", + "simplelog", + "tango-bench", + "tempfile", + "time", + "winresource", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "nu-cli" +version = "0.105.2" +dependencies = [ + "chrono", + "crossterm", + "fancy-regex", + "is_executable", + "log", + "lscolors", + "miette", + "nu-ansi-term", + "nu-cmd-base", + "nu-cmd-lang", + "nu-color-config", + "nu-command", + "nu-engine", + "nu-glob", + "nu-parser", + "nu-path", + "nu-plugin-engine", + "nu-protocol", + "nu-std", + "nu-test-support", + "nu-utils", + "nucleo-matcher", + "percent-encoding", + "reedline", + "rstest", + "strum", + "sysinfo", + "tempfile", + "unicode-segmentation", + "uuid", + "which", +] + +[[package]] +name = "nu-cmd-base" +version = "0.105.2" +dependencies = [ + "indexmap", + "miette", + "nu-engine", + "nu-parser", + "nu-path", + "nu-protocol", +] + +[[package]] +name = "nu-cmd-extra" +version = "0.105.2" +dependencies = [ + "fancy-regex", + "heck", + "itertools 0.14.0", + "mime", + "nu-ansi-term", + "nu-cmd-base", + "nu-cmd-lang", + "nu-command", + "nu-engine", + "nu-json", + "nu-parser", + "nu-pretty-hex", + "nu-protocol", + "nu-test-support", + "nu-utils", + "num-traits", + "rust-embed", + "serde", + "serde_urlencoded", + "v_htmlescape", +] + +[[package]] +name = "nu-cmd-lang" +version = "0.105.2" +dependencies = [ + "itertools 0.14.0", + "miette", + "nu-cmd-base", + "nu-engine", + "nu-parser", + "nu-protocol", + "nu-utils", + "quickcheck", + "quickcheck_macros", + "shadow-rs", +] + +[[package]] +name = "nu-cmd-plugin" +version = "0.105.2" +dependencies = [ + "itertools 0.14.0", + "nu-engine", + "nu-path", + "nu-plugin-engine", + "nu-protocol", +] + +[[package]] +name = "nu-color-config" +version = "0.105.2" +dependencies = [ + "nu-ansi-term", + "nu-engine", + "nu-json", + "nu-protocol", + "nu-test-support", + "serde", +] + +[[package]] +name = "nu-command" +version = "0.105.2" +dependencies = [ + "alphanumeric-sort", + "base64 0.22.1", + "bracoxide", + "brotli", + "byteorder", + "bytesize", + "calamine", + "chardetng", + "chrono", + "chrono-humanize", + "chrono-tz", + "crossterm", + "csv", + "data-encoding", + "devicons", + "dialoguer", + "digest", + "dirs", + "dtparse", + "encoding_rs", + "fancy-regex", + "filesize", + "filetime", + "getrandom 0.2.15", + "human-date-parser", + "indexmap", + "indicatif", + "itertools 0.14.0", + "log", + "lscolors", + "md-5", + "mime", + "mime_guess", + "mockito", + "multipart-rs", + "native-tls", + "nix 0.29.0", + "notify-debouncer-full", + "nu-ansi-term", + "nu-cmd-base", + "nu-cmd-lang", + "nu-color-config", + "nu-engine", + "nu-glob", + "nu-json", + "nu-parser", + "nu-path", + "nu-pretty-hex", + "nu-protocol", + "nu-system", + "nu-table", + "nu-term-grid", + "nu-test-support", + "nu-utils", + "num-format", + "num-traits", + "nuon", + "oem_cp", + "open", + "os_pipe", + "pathdiff", + "percent-encoding", + "pretty_assertions", + "print-positions", + "procfs", + "quick-xml 0.37.1", + "rand 0.9.0", + "rand_chacha 0.9.0", + "rayon", + "reedline", + "rmp", + "roxmltree", + "rstest", + "rstest_reuse", + "rusqlite", + "rustls 0.23.20", + "rustls-native-certs 0.8.1", + "scopeguard", + "serde", + "serde_json", + "serde_urlencoded", + "serde_yaml", + "sha2", + "sysinfo", + "tabled", + "tempfile", + "titlecase", + "toml", + "trash", + "umask", + "unicode-segmentation", + "unicode-width 0.2.0", + "update-informer", + "ureq", + "url", + "uu_cp", + "uu_mkdir", + "uu_mktemp", + "uu_mv", + "uu_touch", + "uu_uname", + "uu_whoami", + "uucore", + "uuid", + "v_htmlescape", + "wax", + "web-time", + "webpki-roots 1.0.0", + "which", + "windows 0.56.0", + "winreg", +] + +[[package]] +name = "nu-derive-value" +version = "0.105.2" +dependencies = [ + "heck", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "nu-engine" +version = "0.105.2" +dependencies = [ + "log", + "nu-glob", + "nu-path", + "nu-protocol", + "nu-utils", +] + +[[package]] +name = "nu-explore" +version = "0.105.2" +dependencies = [ + "ansi-str", + "anyhow", + "crossterm", + "log", + "lscolors", + "nu-ansi-term", + "nu-color-config", + "nu-engine", + "nu-json", + "nu-parser", + "nu-path", + "nu-pretty-hex", + "nu-protocol", + "nu-table", + "nu-utils", + "ratatui", + "strip-ansi-escapes", + "unicode-width 0.2.0", +] + +[[package]] +name = "nu-glob" +version = "0.105.2" +dependencies = [ + "doc-comment", +] + +[[package]] +name = "nu-json" +version = "0.105.2" +dependencies = [ + "fancy-regex", + "linked-hash-map", + "nu-path", + "nu-test-support", + "num-traits", + "serde", + "serde_json", +] + +[[package]] +name = "nu-lsp" +version = "0.105.2" +dependencies = [ + "assert-json-diff", + "crossbeam-channel", + "lsp-server", + "lsp-textdocument", + "lsp-types", + "memchr", + "miette", + "nu-cli", + "nu-cmd-lang", + "nu-command", + "nu-engine", + "nu-glob", + "nu-parser", + "nu-protocol", + "nu-std", + "nu-test-support", + "nu-utils", + "nucleo-matcher", + "serde", + "serde_json", + "url", +] + +[[package]] +name = "nu-parser" +version = "0.105.2" +dependencies = [ + "bytesize", + "chrono", + "itertools 0.14.0", + "log", + "nu-engine", + "nu-path", + "nu-plugin-engine", + "nu-protocol", + "nu-utils", + "rstest", + "serde_json", +] + +[[package]] +name = "nu-path" +version = "0.105.2" +dependencies = [ + "dirs", + "omnipath", + "pwd", + "ref-cast", +] + +[[package]] +name = "nu-plugin" +version = "0.105.2" +dependencies = [ + "log", + "nix 0.29.0", + "nu-engine", + "nu-plugin-core", + "nu-plugin-protocol", + "nu-protocol", + "nu-utils", + "serde", + "thiserror 2.0.12", + "typetag", +] + +[[package]] +name = "nu-plugin-core" +version = "0.105.2" +dependencies = [ + "interprocess", + "log", + "nu-plugin-protocol", + "nu-protocol", + "rmp-serde", + "serde", + "serde_json", + "windows 0.56.0", +] + +[[package]] +name = "nu-plugin-engine" +version = "0.105.2" +dependencies = [ + "log", + "nu-engine", + "nu-plugin-core", + "nu-plugin-protocol", + "nu-protocol", + "nu-system", + "nu-utils", + "serde", + "typetag", + "windows 0.56.0", +] + +[[package]] +name = "nu-plugin-protocol" +version = "0.105.2" +dependencies = [ + "nu-protocol", + "nu-utils", + "rmp-serde", + "semver", + "serde", + "typetag", +] + +[[package]] +name = "nu-plugin-test-support" +version = "0.105.2" +dependencies = [ + "nu-ansi-term", + "nu-cmd-lang", + "nu-engine", + "nu-parser", + "nu-plugin", + "nu-plugin-core", + "nu-plugin-engine", + "nu-plugin-protocol", + "nu-protocol", + "serde", + "similar", + "typetag", +] + +[[package]] +name = "nu-pretty-hex" +version = "0.105.2" +dependencies = [ + "heapless", + "nu-ansi-term", + "rand 0.8.5", +] + +[[package]] +name = "nu-protocol" +version = "0.105.2" +dependencies = [ + "brotli", + "bytes", + "chrono", + "chrono-humanize", + "dirs", + "dirs-sys", + "fancy-regex", + "heck", + "indexmap", + "log", + "lru", + "memchr", + "miette", + "nix 0.29.0", + "nu-derive-value", + "nu-glob", + "nu-path", + "nu-system", + "nu-test-support", + "nu-utils", + "num-format", + "os_pipe", + "pretty_assertions", + "rmp-serde", + "rstest", + "serde", + "serde_json", + "strum", + "strum_macros", + "tempfile", + "thiserror 2.0.12", + "typetag", + "web-time", + "windows 0.56.0", + "windows-sys 0.48.0", +] + +[[package]] +name = "nu-std" +version = "0.105.2" +dependencies = [ + "log", + "miette", + "nu-engine", + "nu-parser", + "nu-protocol", +] + +[[package]] +name = "nu-system" +version = "0.105.2" +dependencies = [ + "chrono", + "itertools 0.14.0", + "libc", + "libproc", + "log", + "mach2", + "nix 0.29.0", + "ntapi", + "procfs", + "sysinfo", + "web-time", + "windows 0.56.0", +] + +[[package]] +name = "nu-table" +version = "0.105.2" +dependencies = [ + "fancy-regex", + "nu-ansi-term", + "nu-color-config", + "nu-engine", + "nu-protocol", + "nu-utils", + "tabled", +] + +[[package]] +name = "nu-term-grid" +version = "0.105.2" +dependencies = [ + "nu-utils", + "unicode-width 0.2.0", +] + +[[package]] +name = "nu-test-support" +version = "0.105.2" +dependencies = [ + "nu-glob", + "nu-path", + "nu-utils", + "num-format", + "tempfile", + "which", +] + +[[package]] +name = "nu-utils" +version = "0.105.2" +dependencies = [ + "crossterm", + "crossterm_winapi", + "fancy-regex", + "log", + "lscolors", + "nix 0.29.0", + "num-format", + "serde", + "serde_json", + "strip-ansi-escapes", + "sys-locale", + "unicase", +] + +[[package]] +name = "nu_plugin_custom_values" +version = "0.1.0" +dependencies = [ + "nu-plugin", + "nu-plugin-test-support", + "nu-protocol", + "serde", + "typetag", +] + +[[package]] +name = "nu_plugin_example" +version = "0.105.2" +dependencies = [ + "nu-cmd-lang", + "nu-plugin", + "nu-plugin-test-support", + "nu-protocol", +] + +[[package]] +name = "nu_plugin_formats" +version = "0.105.2" +dependencies = [ + "chrono", + "eml-parser", + "ical", + "indexmap", + "nu-plugin", + "nu-plugin-test-support", + "nu-protocol", + "plist", + "rust-ini", +] + +[[package]] +name = "nu_plugin_gstat" +version = "0.105.2" +dependencies = [ + "git2", + "nu-plugin", + "nu-protocol", +] + +[[package]] +name = "nu_plugin_inc" +version = "0.105.2" +dependencies = [ + "nu-plugin", + "nu-protocol", + "semver", +] + +[[package]] +name = "nu_plugin_polars" +version = "0.105.2" +dependencies = [ + "aws-config", + "aws-credential-types", + "chrono", + "chrono-tz", + "env_logger 0.11.5", + "fancy-regex", + "hashbrown 0.15.2", + "indexmap", + "log", + "nu-cmd-lang", + "nu-command", + "nu-engine", + "nu-parser", + "nu-path", + "nu-plugin", + "nu-plugin-test-support", + "nu-protocol", + "nu-utils", + "num", + "object_store", + "polars", + "polars-arrow", + "polars-io", + "polars-ops", + "polars-plan", + "polars-utils", + "serde", + "sqlparser", + "tempfile", + "tokio", + "typetag", + "url", + "uuid", +] + +[[package]] +name = "nu_plugin_query" +version = "0.105.2" +dependencies = [ + "gjson", + "nu-plugin", + "nu-protocol", + "scraper", + "serde", + "serde_json", + "sxd-document", + "sxd-xpath", + "webpage", +] + +[[package]] +name = "nu_plugin_stress_internals" +version = "0.105.2" +dependencies = [ + "interprocess", + "serde", + "serde_json", +] + +[[package]] +name = "nucleo-matcher" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf33f538733d1a5a3494b836ba913207f14d9d4a1d3cd67030c5061bdd2cac85" +dependencies = [ + "memchr", + "unicode-segmentation", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec", + "itoa", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "nuon" +version = "0.105.2" +dependencies = [ + "chrono", + "nu-engine", + "nu-parser", + "nu-protocol", + "nu-utils", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.6.0", + "block2", + "libc", + "objc2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-encode" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.6.0", + "block2", + "libc", + "objc2", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "object_store" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d94ac16b433c0ccf75326388c893d2835ab7457ea35ab8ba5d745c053ef5fa16" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bytes", + "chrono", + "form_urlencoded", + "futures", + "http 1.2.0", + "http-body-util", + "humantime", + "hyper 1.5.1", + "itertools 0.14.0", + "md-5", + "parking_lot", + "percent-encoding", + "quick-xml 0.37.1", + "rand 0.9.0", + "reqwest", + "ring", + "serde", + "serde_json", + "serde_urlencoded", + "thiserror 2.0.12", + "tokio", + "tracing", + "url", + "walkdir", + "wasm-bindgen-futures", + "web-time", +] + +[[package]] +name = "oem_cp" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330138902ab4dab09a86e6b7ab7ddeffb5f8435d52fe0df1bce8b06a17b10ee4" +dependencies = [ + "phf", + "phf_codegen", + "serde", + "serde_json", +] + +[[package]] +name = "omnipath" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80adb31078122c880307e9cdfd4e3361e6545c319f9b9dcafcb03acd3b51a575" + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "open" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ecd52f0b8d15c40ce4820aa251ed5de032e5d91fab27f7db2f40d42a8bdf69c" +dependencies = [ + "is-wsl", + "libc", + "pathdiff", +] + +[[package]] +name = "openssl" +version = "0.10.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-src" +version = "300.4.1+3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faa4eac4138c62414b5622d1b31c5c304f34b406b013c079c2bbc652fdd6678c" +dependencies = [ + "cc", +] + +[[package]] +name = "openssl-sys" +version = "0.9.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" +dependencies = [ + "cc", + "libc", + "openssl-src", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-multimap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" +dependencies = [ + "dlv-list", + "hashbrown 0.14.5", +] + +[[package]] +name = "os_display" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6229bad892b46b0dcfaaeb18ad0d2e56400f5aaea05b768bde96e73676cf75" +dependencies = [ + "unicode-width 0.1.11", +] + +[[package]] +name = "os_pipe" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "outref" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a" + +[[package]] +name = "owo-colors" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56" + +[[package]] +name = "papergrid" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6978128c8b51d8f4080631ceb2302ab51e32cc6e8615f735ee2f83fd269ae3f1" +dependencies = [ + "ansi-str", + "ansitok", + "bytecount", + "fnv", + "unicode-width 0.2.0", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "parse-zoneinfo" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24" +dependencies = [ + "regex", +] + +[[package]] +name = "parse_datetime" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bffd1156cebf13f681d7769924d3edfb9d9d71ba206a8d8e8e7eb9df4f4b1e7" +dependencies = [ + "chrono", + "nom 8.0.0", + "regex", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pathdiff" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "peresil" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f658886ed52e196e850cfbbfddab9eaa7f6d90dd0929e264c31e5cec07e09e57" + +[[package]] +name = "pest" +version = "2.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" +dependencies = [ + "memchr", + "thiserror 2.0.12", + "ucd-trie", +] + +[[package]] +name = "pest_consume" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79447402d15d18e7142e14c72f2e63fa3d155be1bc5b70b3ccbb610ac55f536b" +dependencies = [ + "pest", + "pest_consume_macros", + "pest_derive", +] + +[[package]] +name = "pest_consume_macros" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d8630a7a899cb344ec1c16ba0a6b24240029af34bdc0a21f84e411d7f793f29" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "pest_derive" +version = "2.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "pest_meta" +version = "2.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.5", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "planus" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3daf8e3d4b712abe1d690838f6e29fb76b76ea19589c4afa39ec30e12f62af71" +dependencies = [ + "array-init-cursor", + "hashbrown 0.15.2", +] + +[[package]] +name = "platform-info" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91077ffd05d058d70d79eefcd7d7f6aac34980860a7519960f7913b6563a8c3a" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "plist" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" +dependencies = [ + "base64 0.22.1", + "indexmap", + "quick-xml 0.32.0", + "serde", + "time", +] + +[[package]] +name = "polars" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443824f43bca39b178353d6c09e4b44e115b21f107a5654d5f980d20b432a303" +dependencies = [ + "getrandom 0.2.15", + "polars-arrow", + "polars-core", + "polars-error", + "polars-io", + "polars-lazy", + "polars-ops", + "polars-parquet", + "polars-sql", + "polars-time", + "polars-utils", + "version_check", +] + +[[package]] +name = "polars-arrow" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809c5340e9e6c16eee5a07585161bae99f903f53af7402075efec23ee75fce5b" +dependencies = [ + "atoi_simd", + "avro-schema", + "bitflags 2.6.0", + "bytemuck", + "chrono", + "chrono-tz", + "dyn-clone", + "either", + "ethnum", + "getrandom 0.2.15", + "hashbrown 0.15.2", + "itoa", + "lz4", + "num-traits", + "polars-arrow-format", + "polars-error", + "polars-schema", + "polars-utils", + "serde", + "simdutf8", + "streaming-iterator", + "strum_macros", + "version_check", + "zstd", +] + +[[package]] +name = "polars-arrow-format" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "863c04c514be005eced7db7053e20d49f7e7a58048a282fa52dfea1fd5434e78" +dependencies = [ + "planus", + "serde", +] + +[[package]] +name = "polars-compute" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b8802ff2cccea01a845ea8267a7600e495747ed109035bb5020c33eb8717ff4" +dependencies = [ + "atoi_simd", + "bytemuck", + "chrono", + "either", + "fast-float2", + "hashbrown 0.15.2", + "itoa", + "num-traits", + "polars-arrow", + "polars-error", + "polars-utils", + "rand 0.8.5", + "ryu", + "serde", + "skiplist", + "strength_reduce", + "strum_macros", + "version_check", +] + +[[package]] +name = "polars-core" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fc3c99d7000be1be11665e1e260b93dc3b927342b9da3b53d9a1ac264e4343d" +dependencies = [ + "bitflags 2.6.0", + "boxcar", + "bytemuck", + "chrono", + "chrono-tz", + "comfy-table", + "either", + "hashbrown 0.14.5", + "hashbrown 0.15.2", + "indexmap", + "itoa", + "num-traits", + "polars-arrow", + "polars-compute", + "polars-error", + "polars-row", + "polars-schema", + "polars-utils", + "rand 0.8.5", + "rand_distr", + "rayon", + "regex", + "serde", + "serde_json", + "strum_macros", + "uuid", + "version_check", + "xxhash-rust", +] + +[[package]] +name = "polars-error" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1397c17712e61a55fdd45c033a69f0451fde2973ff2609c22e363e21d68f11ef" +dependencies = [ + "avro-schema", + "object_store", + "parking_lot", + "polars-arrow-format", + "regex", + "signal-hook", + "simdutf8", +] + +[[package]] +name = "polars-expr" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d3aa6722c9a3e0b721ec2bcdc4affd9e50e4cb606cd81bb94535a9a5a6ade9" +dependencies = [ + "bitflags 2.6.0", + "hashbrown 0.15.2", + "num-traits", + "polars-arrow", + "polars-compute", + "polars-core", + "polars-io", + "polars-ops", + "polars-plan", + "polars-row", + "polars-time", + "polars-utils", + "rand 0.8.5", + "rayon", + "recursive", +] + +[[package]] +name = "polars-io" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a632d442a99821250a8fa66f7d488bf5ee98e5f515e65256b12956cb81fc110" +dependencies = [ + "async-trait", + "atoi_simd", + "blake3", + "bytes", + "chrono", + "chrono-tz", + "fast-float2", + "flate2", + "fs4", + "futures", + "glob", + "hashbrown 0.15.2", + "home", + "itoa", + "memchr", + "memmap2", + "num-traits", + "object_store", + "percent-encoding", + "polars-arrow", + "polars-core", + "polars-error", + "polars-json", + "polars-parquet", + "polars-schema", + "polars-time", + "polars-utils", + "rayon", + "regex", + "reqwest", + "ryu", + "serde", + "serde_json", + "simd-json", + "simdutf8", + "tokio", + "tokio-util", + "url", + "zstd", +] + +[[package]] +name = "polars-json" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd891735404ebb9d6ace066cfb4b8f6edb321bc841d354a0d917a3a1f2d1ca5b" +dependencies = [ + "chrono", + "chrono-tz", + "fallible-streaming-iterator", + "hashbrown 0.15.2", + "indexmap", + "itoa", + "num-traits", + "polars-arrow", + "polars-compute", + "polars-error", + "polars-utils", + "ryu", + "simd-json", + "streaming-iterator", +] + +[[package]] +name = "polars-lazy" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ed0c87bdc8820447a38ae8efdb5a51a5a93e8bd528cffb05d05cf1145e4161" +dependencies = [ + "bitflags 2.6.0", + "chrono", + "either", + "futures", + "memchr", + "polars-arrow", + "polars-compute", + "polars-core", + "polars-expr", + "polars-io", + "polars-json", + "polars-mem-engine", + "polars-ops", + "polars-plan", + "polars-stream", + "polars-time", + "polars-utils", + "rayon", + "tokio", + "version_check", +] + +[[package]] +name = "polars-mem-engine" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "675294ddf9174029e48caa4e59b0665ea64bfb784a366b197690895a6ed65c68" +dependencies = [ + "futures", + "memmap2", + "polars-arrow", + "polars-core", + "polars-error", + "polars-expr", + "polars-io", + "polars-json", + "polars-ops", + "polars-plan", + "polars-time", + "polars-utils", + "rayon", + "recursive", + "tokio", +] + +[[package]] +name = "polars-ops" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1eb4db68956f857c52eeda072d87644a7b42eac41d55073af94dfac8441af6cf" +dependencies = [ + "argminmax", + "base64 0.22.1", + "bytemuck", + "chrono", + "chrono-tz", + "either", + "hashbrown 0.15.2", + "hex", + "indexmap", + "jsonpath_lib_polars_vendor", + "libm", + "memchr", + "num-traits", + "polars-arrow", + "polars-compute", + "polars-core", + "polars-error", + "polars-json", + "polars-schema", + "polars-utils", + "rand 0.8.5", + "rand_distr", + "rayon", + "regex", + "regex-syntax", + "serde", + "serde_json", + "strum_macros", + "unicode-normalization", + "unicode-reverse", + "version_check", +] + +[[package]] +name = "polars-parquet" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c849c10edd9511ccd4ec4130e283ee3a8b3bb48a7d74ac6354c1c20add81065" +dependencies = [ + "async-stream", + "base64 0.22.1", + "brotli", + "bytemuck", + "ethnum", + "flate2", + "futures", + "hashbrown 0.15.2", + "lz4", + "num-traits", + "polars-arrow", + "polars-compute", + "polars-error", + "polars-parquet-format", + "polars-utils", + "serde", + "simdutf8", + "snap", + "streaming-decompression", + "zstd", +] + +[[package]] +name = "polars-parquet-format" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c025243dcfe8dbc57e94d9f82eb3bef10b565ab180d5b99bed87fd8aea319ce1" +dependencies = [ + "async-trait", + "futures", +] + +[[package]] +name = "polars-plan" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fb4412c42bf637c2c02a617381c682ed425d9c8e4bd1fcb85cf352ed2a67c6" +dependencies = [ + "bitflags 2.6.0", + "bytemuck", + "bytes", + "chrono", + "chrono-tz", + "either", + "futures", + "hashbrown 0.15.2", + "memmap2", + "num-traits", + "percent-encoding", + "polars-arrow", + "polars-compute", + "polars-core", + "polars-io", + "polars-json", + "polars-ops", + "polars-parquet", + "polars-time", + "polars-utils", + "rayon", + "recursive", + "regex", + "serde", + "strum_macros", + "version_check", +] + +[[package]] +name = "polars-row" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08fb77ac1d37340d9cfe57cf58000cf3d9cce429e10d25066952c6145c684cc0" +dependencies = [ + "bitflags 2.6.0", + "bytemuck", + "polars-arrow", + "polars-compute", + "polars-error", + "polars-utils", +] + +[[package]] +name = "polars-schema" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ada7c7e2fbbeffbdd67628cd8a89f02b0a8d21c71d34e297e2463a7c17575203" +dependencies = [ + "indexmap", + "polars-error", + "polars-utils", + "serde", + "version_check", +] + +[[package]] +name = "polars-sql" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a8e512b1f05ffda9963fe8f6a7c62dcba86be85218bc033ecdad2802cc1b1a0" +dependencies = [ + "bitflags 2.6.0", + "hex", + "polars-core", + "polars-error", + "polars-lazy", + "polars-ops", + "polars-plan", + "polars-time", + "polars-utils", + "rand 0.8.5", + "regex", + "serde", + "sqlparser", +] + +[[package]] +name = "polars-stream" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0a02d8050acd9b64ed7e36c5bc96f6d4f46a940220f9c0e34c96b51f830f8c" +dependencies = [ + "async-channel", + "async-trait", + "atomic-waker", + "bitflags 2.6.0", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils", + "futures", + "memmap2", + "parking_lot", + "percent-encoding", + "pin-project-lite", + "polars-arrow", + "polars-core", + "polars-error", + "polars-expr", + "polars-io", + "polars-mem-engine", + "polars-ops", + "polars-parquet", + "polars-plan", + "polars-utils", + "rand 0.8.5", + "rayon", + "recursive", + "slotmap", + "tokio", + "version_check", +] + +[[package]] +name = "polars-time" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72e84a30110880ffede8d93c085fc429ab1b8bf1acf3d6d489143dd34be374c4" +dependencies = [ + "atoi_simd", + "bytemuck", + "chrono", + "chrono-tz", + "now", + "num-traits", + "polars-arrow", + "polars-compute", + "polars-core", + "polars-error", + "polars-ops", + "polars-utils", + "rayon", + "regex", + "serde", + "strum_macros", +] + +[[package]] +name = "polars-utils" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a05e033960552c47fc35afe14d5af5b29696acc97ae5d3c585ebc33c246cc15f" +dependencies = [ + "bincode", + "bytemuck", + "bytes", + "compact_str", + "flate2", + "foldhash", + "hashbrown 0.15.2", + "indexmap", + "libc", + "memmap2", + "num-traits", + "polars-error", + "rand 0.8.5", + "raw-cpuid", + "rayon", + "regex", + "rmp-serde", + "serde", + "serde_json", + "slotmap", + "stacker", + "version_check", +] + +[[package]] +name = "pori" +version = "0.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a63d338dec139f56dacc692ca63ad35a6be6a797442479b55acd611d79e906" +dependencies = [ + "nom 7.1.3", +] + +[[package]] +name = "portable-atomic" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy 0.7.35", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "predicates" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" +dependencies = [ + "anstyle", + "difflib", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" + +[[package]] +name = "predicates-tree" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + +[[package]] +name = "print-positions" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df593470e3ef502e48cb0cfc9a3a61e5f61e967b78e1ed35a67ac615cfbd208" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "procfs" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc5b72d8145275d844d4b5f6d4e1eef00c8cd889edb6035c21675d1bb1f45c9f" +dependencies = [ + "bitflags 2.6.0", + "chrono", + "flate2", + "hex", + "procfs-core", + "rustix 0.38.42", +] + +[[package]] +name = "procfs-core" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239df02d8349b06fc07398a3a1697b06418223b1c7725085e801e7c0fc6a12ec" +dependencies = [ + "bitflags 2.6.0", + "chrono", + "hex", +] + +[[package]] +name = "psm" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" +dependencies = [ + "cc", +] + +[[package]] +name = "pure-rust-locales" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1190fd18ae6ce9e137184f207593877e70f39b015040156b1e05081cdfe3733a" + +[[package]] +name = "pwd" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c71c0c79b9701efe4e1e4b563b2016dd4ee789eb99badcb09d61ac4b92e4a2" +dependencies = [ + "libc", + "thiserror 1.0.69", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quick-xml" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" +dependencies = [ + "memchr", +] + +[[package]] +name = "quick-xml" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "quick-xml" +version = "0.37.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f22f29bdff3987b4d8632ef95fd6424ec7e4e0a57e2f4fc63e489e75357f6a03" +dependencies = [ + "encoding_rs", + "memchr", + "serde", +] + +[[package]] +name = "quickcheck" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" +dependencies = [ + "env_logger 0.8.4", + "log", + "rand 0.8.5", +] + +[[package]] +name = "quickcheck_macros" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f71ee38b42f8459a88d3362be6f9b841ad2d5421844f61eb1c59c11bff3ac14a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "quinn" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.0", + "rustls 0.23.20", + "socket2", + "thiserror 2.0.12", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" +dependencies = [ + "bytes", + "getrandom 0.2.15", + "rand 0.8.5", + "ring", + "rustc-hash 2.1.0", + "rustls 0.23.20", + "rustls-pki-types", + "slab", + "thiserror 2.0.12", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52cd4b1eff68bf27940dd39811292c49e007f4d0b4c357358dc9b0197be6b527" +dependencies = [ + "cfg_aliases 0.2.1", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "quoted_printable" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "640c9bd8497b02465aeef5375144c26062e0dcd5939dfcbb0f5db76cb8c17c73" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", + "zerocopy 0.8.23", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.1", +] + +[[package]] +name = "rand_distr" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "ratatui" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" +dependencies = [ + "bitflags 2.6.0", + "cassowary", + "compact_str", + "crossterm", + "indoc", + "instability", + "itertools 0.13.0", + "lru", + "paste", + "strum", + "unicode-segmentation", + "unicode-truncate", + "unicode-width 0.2.0", +] + +[[package]] +name = "raw-cpuid" +version = "11.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "recursive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0786a43debb760f491b1bc0269fe5e84155353c67482b9e60d0cfb596054b43e" +dependencies = [ + "recursive-proc-macro-impl", + "stacker", +] + +[[package]] +name = "recursive-proc-macro-impl" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76009fbe0614077fc1a2ce255e3a1881a2e3a3527097d5dc6d8212c585e7e38b" +dependencies = [ + "quote", + "syn 2.0.90", +] + +[[package]] +name = "recvmsg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3edd4d5d42c92f0a659926464d4cce56b562761267ecf0f469d85b7de384175" + +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.15", + "libredox", + "thiserror 1.0.69", +] + +[[package]] +name = "reedline" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5cdfab7494d13ebfb6ce64828648518205d3ce8541ef1f94a27887f29d2d50b" +dependencies = [ + "arboard", + "chrono", + "crossterm", + "fd-lock", + "itertools 0.13.0", + "nu-ansi-term", + "rusqlite", + "serde", + "serde_json", + "strip-ansi-escapes", + "strum", + "strum_macros", + "thiserror 2.0.12", + "unicode-segmentation", + "unicode-width 0.2.0", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-lite" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + +[[package]] +name = "reqwest" +version = "0.12.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.4.7", + "http 1.2.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.5.1", + "hyper-rustls 0.27.3", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls 0.23.20", + "rustls-native-certs 0.8.1", + "rustls-pemfile 2.2.0", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-native-tls", + "tokio-rustls 0.26.1", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "webpki-roots 0.26.8", + "windows-registry", +] + +[[package]] +name = "rfc2047-decoder" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc36545d1021456a751b573517cb52e8c339b2f662e6b2778ef629282678de29" +dependencies = [ + "base64 0.22.1", + "charset", + "chumsky", + "memchr", + "quoted_printable", + "thiserror 2.0.12", +] + +[[package]] +name = "ring" +version = "0.17.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.15", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rle-decode-fast" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" + +[[package]] +name = "rmp" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" +dependencies = [ + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + +[[package]] +name = "rstest" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2c585be59b6b5dd66a9d2084aa1d8bd52fbdb806eafdeffb52791147862035" +dependencies = [ + "rstest_macros", + "rustc_version", +] + +[[package]] +name = "rstest_macros" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "825ea780781b15345a146be27eaefb05085e337e869bff01b4306a4fd4a9ad5a" +dependencies = [ + "cfg-if", + "glob", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn 2.0.90", + "unicode-ident", +] + +[[package]] +name = "rstest_reuse" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a8fb4672e840a587a66fc577a5491375df51ddb88f2a2c2a792598c326fe14" +dependencies = [ + "quote", + "rand 0.8.5", + "syn 2.0.90", +] + +[[package]] +name = "rusqlite" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b838eba278d213a8beaf485bd313fd580ca4505a00d5871caeb1457c55322cae" +dependencies = [ + "bitflags 2.6.0", + "chrono", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + +[[package]] +name = "rust-embed" +version = "8.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5fbc0ee50fcb99af7cebb442e5df7b5b45e9460ffa3f8f549cd26b862bec49d" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bf418c9a2e3f6663ca38b8a7134cc2c2167c9d69688860e8961e3faa731702e" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn 2.0.90", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d55b95147fe01265d06b3955db798bdaed52e60e2211c41137701b3aba8e21" +dependencies = [ + "sha2", + "walkdir", +] + +[[package]] +name = "rust-ini" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e310ef0e1b6eeb79169a1171daf9abcb87a2e17c03bee2c4bb100b55c75409f" +dependencies = [ + "cfg-if", + "ordered-multimap", + "trim-in-place", +] + +[[package]] +name = "rust_decimal" +version = "1.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" +dependencies = [ + "arrayvec", + "num-traits", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys 0.4.14", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] + +[[package]] +name = "rustls" +version = "0.23.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile 1.0.4", + "schannel", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework 3.0.1", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" +dependencies = [ + "web-time", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scc" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea091f6cac2595aa38993f04f4ee692ed43757035c36e67c180b6828356385b1" +dependencies = [ + "sdd", +] + +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scraper" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527e65d9d888567588db4c12da1087598d0f6f8b346cc2c5abc91f05fc2dffe2" +dependencies = [ + "cssparser", + "ego-tree", + "html5ever 0.29.0", + "precomputed-hash", + "selectors", + "tendril", +] + +[[package]] +name = "scroll" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" +dependencies = [ + "scroll_derive", +] + +[[package]] +name = "scroll_derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sdd" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07779b9b918cc05650cb30f404d4d7835d26df37c235eded8a6832e2fb82cca" + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1415a607e92bec364ea2cf9264646dcce0f91e6d65281bd6f2819cca3bf39c8" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd568a4c9bb598e291a08244a5c1f5a8a6650bee243b5b0f8dbb3d9cc1d87fe8" +dependencies = [ + "bitflags 2.6.0", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf", + "phf_codegen", + "precomputed-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.216" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.216" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "serde_json" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +dependencies = [ + "indexmap", + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "serial_test" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" +dependencies = [ + "futures", + "log", + "once_cell", + "parking_lot", + "scc", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "servo_arc" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae65c4249478a2647db249fb43e23cec56a2c8974a427e7bd8cb5a1d0964921a" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "sha1_smol" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shadow-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6fd27df794ced2ef39872879c93a9f87c012607318af8621cd56d2c3a8b3a2" +dependencies = [ + "const_format", + "is_debug", + "time", + "tzdb", +] + +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +dependencies = [ + "libc", + "mio 1.0.3", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simd-json" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2bcf6c6e164e81bc7a5d49fc6988b3d515d9e8c07457d7b74ffb9324b9cd40" +dependencies = [ + "ahash", + "getrandom 0.2.15", + "halfbrown", + "once_cell", + "ref-cast", + "serde", + "serde_json", + "simdutf8", + "value-trait", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "similar" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" + +[[package]] +name = "simplelog" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16257adbfaef1ee58b1363bdc0664c9b8e1e30aed86049635fb5f147d065a9c0" +dependencies = [ + "log", + "termcolor", + "time", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "skiplist" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eec25f46463fcdc5e02f388c2780b1b58e01be81a8378e62ec60931beccc3f6" +dependencies = [ + "rand 0.8.5", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "snap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" + +[[package]] +name = "socket2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "socks" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c3dbbd9ae980613c6dd8e28a9407b50509d3803b57624d5dfe8315218cd58b" +dependencies = [ + "byteorder", + "libc", + "winapi", +] + +[[package]] +name = "sqlparser" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05a528114c392209b3264855ad491fcce534b94a38771b0a0b97a79379275ce8" +dependencies = [ + "log", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stacker" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "windows-sys 0.59.0", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "streaming-decompression" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf6cc3b19bfb128a8ad11026086e31d3ce9ad23f8ea37354b31383a187c44cf3" +dependencies = [ + "fallible-streaming-iterator", +] + +[[package]] +name = "streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" + +[[package]] +name = "strength_reduce" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "strip-ansi-escapes" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ff8ef943b384c414f54aefa961dd2bd853add74ec75e7ac74cf91dba62bcfa" +dependencies = [ + "vte 0.11.1", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.90", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "supports-color" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" +dependencies = [ + "is_ci", +] + +[[package]] +name = "supports-hyperlinks" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804f44ed3c63152de6a9f90acbea1a110441de43006ea51bcce8f436196a288b" + +[[package]] +name = "supports-unicode" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" + +[[package]] +name = "sxd-document" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94d82f37be9faf1b10a82c4bd492b74f698e40082f0f40de38ab275f31d42078" +dependencies = [ + "peresil", + "typed-arena", +] + +[[package]] +name = "sxd-xpath" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36e39da5d30887b5690e29de4c5ebb8ddff64ebd9933f98a01daaa4fd11b36ea" +dependencies = [ + "peresil", + "quick-error 1.2.3", + "sxd-document", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" +dependencies = [ + "libc", +] + +[[package]] +name = "sysinfo" +version = "0.33.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fc858248ea01b66f19d8e8a6d55f41deaf91e9d495246fd01368d99935c6c01" +dependencies = [ + "core-foundation-sys", + "libc", + "memchr", + "ntapi", + "rayon", + "windows 0.57.0", +] + +[[package]] +name = "tabled" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e39a2ee1fbcd360805a771e1b300f78cc88fec7b8d3e2f71cd37bbf23e725c7d" +dependencies = [ + "ansi-str", + "ansitok", + "papergrid", + "testing_table", +] + +[[package]] +name = "tango-bench" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "257822358c6f206fed78bfe6369cf959063b0644d70f88df6b19f2dadc93423e" +dependencies = [ + "alloca", + "anyhow", + "clap", + "colorz", + "glob-match", + "goblin", + "libloading", + "log", + "num-traits", + "rand 0.8.5", + "scroll", + "tempfile", + "thiserror 1.0.69", +] + +[[package]] +name = "tempfile" +version = "3.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +dependencies = [ + "fastrand", + "getrandom 0.3.1", + "once_cell", + "rustix 1.0.7", + "windows-sys 0.59.0", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "terminal_size" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9" +dependencies = [ + "rustix 0.38.42", + "windows-sys 0.59.0", +] + +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + +[[package]] +name = "testing_table" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f8daae29995a24f65619e19d8d31dea5b389f3d853d8bf297bbf607cd0014cc" +dependencies = [ + "ansitok", + "unicode-width 0.2.0", +] + +[[package]] +name = "textwrap" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" +dependencies = [ + "unicode-linebreak", + "unicode-width 0.1.11", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +dependencies = [ + "deranged", + "itoa", + "libc", + "num-conv", + "num_threads", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "titlecase" +version = "3.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb567088a91d59b492520c8149e2be5ce10d5deb2d9a383f3378df3259679d40" +dependencies = [ + "regex", +] + +[[package]] +name = "tokio" +version = "1.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio 1.0.3", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" +dependencies = [ + "rustls 0.23.20", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", +] + +[[package]] +name = "trash" +version = "5.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8e5ca62c20366b4685e3e41fba17bc7c9bbdcb82e65a89d6fda2ceea5fffd2f" +dependencies = [ + "chrono", + "libc", + "log", + "objc2", + "objc2-foundation", + "once_cell", + "percent-encoding", + "scopeguard", + "urlencoding", + "windows 0.56.0", +] + +[[package]] +name = "tree_magic_mini" +version = "3.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac5e8971f245c3389a5a76e648bfc80803ae066a1243a75db0064d7c1129d63" +dependencies = [ + "fnv", + "memchr", + "nom 7.1.3", + "once_cell", + "petgraph", +] + +[[package]] +name = "trim-in-place" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343e926fc669bc8cde4fa3129ab681c63671bae288b1f1081ceee6d9d37904fc" + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typed-arena" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d" + +[[package]] +name = "typeid" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "typetag" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ba3b6e86ffe0054b2c44f2d86407388b933b16cb0a70eea3929420db1d9bbe" +dependencies = [ + "erased-serde", + "inventory", + "once_cell", + "serde", + "typetag-impl", +] + +[[package]] +name = "typetag-impl" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70b20a22c42c8f1cd23ce5e34f165d4d37038f5b663ad20fb6adbdf029172483" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tz-rs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1450bf2b99397e72070e7935c89facaa80092ac812502200375f1f7d33c71a1" + +[[package]] +name = "tzdb" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0be2ea5956f295449f47c0b825c5e109022ff1a6a53bb4f77682a87c2341fbf5" +dependencies = [ + "iana-time-zone", + "tz-rs", + "tzdb_data", +] + +[[package]] +name = "tzdb_data" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0604b35c1f390a774fdb138cac75a99981078895d24bcab175987440bbff803b" +dependencies = [ + "tz-rs", +] + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "umask" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec9a46c2549e35c054e0ffe281a3a6ec0007793db4df106604d37ed3f4d73d1c" +dependencies = [ + "thiserror 1.0.69", +] + +[[package]] +name = "unicase" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-reverse" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b6f4888ebc23094adfb574fdca9fdc891826287a6397d2cd28802ffd6f20c76" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-truncate" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" +dependencies = [ + "itertools 0.13.0", + "unicode-segmentation", + "unicode-width 0.1.11", +] + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "update-informer" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53813bf5d5f0d8430794f8cc48e99521cc9e298066958d16383ccb8b39d182a7" +dependencies = [ + "etcetera", + "reqwest", + "semver", + "serde", + "serde_json", + "ureq", +] + +[[package]] +name = "ureq" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" +dependencies = [ + "base64 0.22.1", + "encoding_rs", + "flate2", + "log", + "native-tls", + "once_cell", + "rustls 0.23.20", + "rustls-pki-types", + "serde", + "serde_json", + "socks", + "url", + "webpki-roots 0.26.8", +] + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uu_cp" +version = "0.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf2f3906b7896f79519055d36760095577373e40ec244f46b259f502a4a91147" +dependencies = [ + "clap", + "filetime", + "indicatif", + "libc", + "quick-error 2.0.1", + "uucore", + "walkdir", + "xattr", +] + +[[package]] +name = "uu_mkdir" +version = "0.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be556a5d852f55b92bba460d7a97030a340ba4a3f4c510a8d0a893bfaf48356" +dependencies = [ + "clap", + "uucore", +] + +[[package]] +name = "uu_mktemp" +version = "0.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5305fcf4f7f480e7438e19ff433ae60dea886bd528f87543029eb6b95d351afc" +dependencies = [ + "clap", + "rand 0.9.0", + "tempfile", + "thiserror 2.0.12", + "uucore", +] + +[[package]] +name = "uu_mv" +version = "0.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be214b96554e4f7aa079b26c86c3ecf1b9ea15023ca2ec62d608273d12c7049" +dependencies = [ + "clap", + "fs_extra", + "indicatif", + "libc", + "thiserror 2.0.12", + "uucore", + "windows-sys 0.59.0", +] + +[[package]] +name = "uu_touch" +version = "0.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e58581a0245de8e3ef75b115ab29592cfb60d4851149d4951604601d14ea420" +dependencies = [ + "chrono", + "clap", + "filetime", + "parse_datetime", + "thiserror 2.0.12", + "uucore", + "windows-sys 0.59.0", +] + +[[package]] +name = "uu_uname" +version = "0.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "324d96a21da91a81be334206ab65aad16d164d34cddeb640e1c56cd8d1854dd4" +dependencies = [ + "clap", + "platform-info", + "uucore", +] + +[[package]] +name = "uu_whoami" +version = "0.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee254de8b172a5978f12fe6cd9d4f2b60ea9ef1e37f0cb53bfee2c993b3e96a" +dependencies = [ + "clap", + "libc", + "uucore", + "windows-sys 0.59.0", +] + +[[package]] +name = "uucore" +version = "0.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71f4e82877d06de779c611a3d54720f56f1e68b228fb30a5b6c66ef07e68263d" +dependencies = [ + "chrono", + "chrono-tz", + "clap", + "dunce", + "glob", + "iana-time-zone", + "libc", + "nix 0.29.0", + "number_prefix", + "os_display", + "uucore_procs", + "walkdir", + "wild", + "winapi-util", + "windows-sys 0.59.0", + "xattr", +] + +[[package]] +name = "uucore_procs" +version = "0.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c72435859e812e602e225dea48d014abb6b1072220a8d44f2fe0565553b1f7e4" +dependencies = [ + "proc-macro2", + "quote", + "uuhelp_parser", +] + +[[package]] +name = "uuhelp_parser" +version = "0.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb6d972f580f8223cb7052d8580aea2b7061e368cf476de32ea9457b19459ed" + +[[package]] +name = "uuid" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" +dependencies = [ + "atomic", + "getrandom 0.3.1", + "js-sys", + "md-5", + "serde", + "sha1_smol", + "wasm-bindgen", +] + +[[package]] +name = "v_htmlescape" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c" + +[[package]] +name = "value-trait" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9170e001f458781e92711d2ad666110f153e4e50bfd5cbd02db6547625714187" +dependencies = [ + "float-cmp", + "halfbrown", + "itoa", + "ryu", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + +[[package]] +name = "vte" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" +dependencies = [ + "utf8parse", + "vte_generate_state_changes", +] + +[[package]] +name = "vte" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "231fdcd7ef3037e8330d8e17e61011a2c244126acc0a982f4040ac3f9f0bc077" +dependencies = [ + "arrayvec", + "memchr", +] + +[[package]] +name = "vte_generate_state_changes" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.90", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" + +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wax" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d12a78aa0bab22d2f26ed1a96df7ab58e8a93506a3e20adb47c51a93b4e1357" +dependencies = [ + "const_format", + "itertools 0.11.0", + "nom 7.1.3", + "pori", + "regex", + "thiserror 1.0.69", + "walkdir", +] + +[[package]] +name = "wayland-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" +dependencies = [ + "cc", + "downcast-rs", + "rustix 0.38.42", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66249d3fc69f76fd74c82cc319300faa554e9d865dab1f7cd66cc20db10b280" +dependencies = [ + "bitflags 2.6.0", + "rustix 0.38.42", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" +dependencies = [ + "bitflags 2.6.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" +dependencies = [ + "bitflags 2.6.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" +dependencies = [ + "proc-macro2", + "quick-xml 0.36.2", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" +dependencies = [ + "dlib", + "log", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpage" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70862efc041d46e6bbaa82bb9c34ae0596d090e86cbd14bd9e93b36ee6802eac" +dependencies = [ + "curl", + "html5ever 0.27.0", + "markup5ever_rcdom", + "serde", + "serde_json", + "url", +] + +[[package]] +name = "webpki-roots" +version = "0.26.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "webpki-roots" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "which" +version = "7.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d643ce3fd3e5b54854602a080f34fb10ab75e0b813ee32d00ca2b44fa74762" +dependencies = [ + "either", + "env_home", + "rustix 1.0.7", + "winsafe", +] + +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" + +[[package]] +name = "wild" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3131afc8c575281e1e80f36ed6a092aa502c08b18ed7524e86fbbb12bb410e1" +dependencies = [ + "glob", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" +dependencies = [ + "windows-core 0.56.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" +dependencies = [ + "windows-implement 0.56.0", + "windows-interface 0.56.0", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement 0.57.0", + "windows-interface 0.57.0", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "windows-interface" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result 0.2.0", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "winresource" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7276691b353ad4547af8c3268488d1311f4be791ffdc0c65b8cfa8f41eed693b" +dependencies = [ + "toml", + "version_check", +] + +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "wl-clipboard-rs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12b41773911497b18ca8553c3daaf8ec9fe9819caf93d451d3055f69de028adb" +dependencies = [ + "derive-new", + "libc", + "log", + "nix 0.28.0", + "os_pipe", + "tempfile", + "thiserror 1.0.69", + "tree_magic_mini", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-wlr", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "x11rb" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" +dependencies = [ + "gethostname", + "rustix 0.38.42", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" + +[[package]] +name = "xattr" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" +dependencies = [ + "libc", + "linux-raw-sys 0.4.14", + "rustix 0.38.42", +] + +[[package]] +name = "xml5ever" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bbb26405d8e919bc1547a5aa9abc95cbfa438f04844f5fdd9dc7596b748bf69" +dependencies = [ + "log", + "mac", + "markup5ever 0.12.1", +] + +[[package]] +name = "xmlparser" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" + +[[package]] +name = "xxhash-rust" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" +dependencies = [ + "zerocopy-derive 0.8.23", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "zip" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7dcdb4229c0e79c2531a24de7726a0e980417a74fb4d030a35f535665439a0" +dependencies = [ + "arbitrary", + "crc32fast", + "flate2", + "indexmap", + "memchr", + "zopfli", +] + +[[package]] +name = "zlib-rs" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626bd9fa9734751fc50d6060752170984d7053f5a39061f524cda68023d4db8a" + +[[package]] +name = "zopfli" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" +dependencies = [ + "bumpalo", + "crc32fast", + "lockfree-object-pool", + "log", + "once_cell", + "simd-adler32", +] + +[[package]] +name = "zstd" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.13+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/nushell/Cargo.toml b/nushell/Cargo.toml new file mode 100644 index 0000000..6e39971 --- /dev/null +++ b/nushell/Cargo.toml @@ -0,0 +1,344 @@ +[package] +authors = ["The Nushell Project Developers"] +build = "scripts/build.rs" +default-run = "nu" +description = "A new type of shell" +documentation = "https://www.nushell.sh/book/" +edition = "2024" +exclude = ["images"] +homepage = "https://www.nushell.sh" +license = "MIT" +name = "nu" +repository = "https://github.com/nushell/nushell" +#rust-version = "1.85.1" +version = "0.105.2" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[package.metadata.binstall] +pkg-url = "{ repo }/releases/download/{ version }/{ name }-{ version }-{ target }.{ archive-format }" +pkg-fmt = "tgz" + +[package.metadata.binstall.overrides.x86_64-pc-windows-msvc] +pkg-fmt = "zip" + +[workspace] +members = [ + "crates/nu-cli", + "crates/nu-engine", + "crates/nu-parser", + "crates/nu-system", + "crates/nu-cmd-base", + "crates/nu-cmd-extra", + "crates/nu-cmd-lang", + "crates/nu-cmd-plugin", + "crates/nu-command", + "crates/nu-color-config", + "crates/nu-explore", + "crates/nu-json", + "crates/nu-lsp", + "crates/nu-pretty-hex", + "crates/nu-protocol", + "crates/nu-derive-value", + "crates/nu-plugin", + "crates/nu-plugin-core", + "crates/nu-plugin-engine", + "crates/nu-plugin-protocol", + "crates/nu-plugin-test-support", + "crates/nu_plugin_inc", + "crates/nu_plugin_gstat", + "crates/nu_plugin_example", + "crates/nu_plugin_query", + "crates/nu_plugin_custom_values", + "crates/nu_plugin_formats", + "crates/nu_plugin_polars", + "crates/nu_plugin_stress_internals", + "crates/nu-std", + "crates/nu-table", + "crates/nu-term-grid", + "crates/nu-test-support", + "crates/nu-utils", + "crates/nuon", +] + +[workspace.dependencies] +alphanumeric-sort = "1.5" +ansi-str = "0.9" +anyhow = "1.0.82" +base64 = "0.22.1" +bracoxide = "0.1.6" +brotli = "7.0" +byteorder = "1.5" +bytes = "1" +bytesize = "1.3.3" +calamine = "0.28" +chardetng = "0.1.17" +chrono = { default-features = false, version = "0.4.34" } +chrono-humanize = "0.2.3" +chrono-tz = "0.10" +crossbeam-channel = "0.5.8" +crossterm = "0.28.1" +csv = "1.3" +ctrlc = "3.4" +devicons = "0.6.12" +dialoguer = { default-features = false, version = "0.11" } +digest = { default-features = false, version = "0.10" } +dirs = "5.0" +dirs-sys = "0.4" +dtparse = "2.0" +encoding_rs = "0.8" +fancy-regex = "0.14" +filesize = "0.2" +filetime = "0.2" +heck = "0.5.0" +human-date-parser = "0.3.0" +indexmap = "2.9" +indicatif = "0.17" +interprocess = "2.2.0" +is_executable = "1.0" +itertools = "0.14" +libc = "0.2" +libproc = "0.14" +log = "0.4" +lru = "0.12" +lscolors = { version = "0.20", default-features = false } +lsp-server = "0.7.8" +lsp-types = { version = "0.97.0", features = ["proposed"] } +lsp-textdocument = "0.4.2" +mach2 = "0.4" +md5 = { version = "0.10", package = "md-5" } +miette = "7.6" +mime = "0.3.17" +mime_guess = "2.0" +mockito = { version = "1.7", default-features = false } +multipart-rs = "0.1.13" +native-tls = "0.2" +nix = { version = "0.29", default-features = false } +notify-debouncer-full = { version = "0.3", default-features = false } +nu-ansi-term = "0.50.1" +nucleo-matcher = "0.3" +num-format = "0.4" +num-traits = "0.2" +oem_cp = "2.0.0" +omnipath = "0.1" +open = "5.3" +os_pipe = { version = "1.2", features = ["io_safety"] } +pathdiff = "0.2" +percent-encoding = "2" +pretty_assertions = "1.4" +print-positions = "0.6" +proc-macro-error2 = "2.0" +proc-macro2 = "1.0" +procfs = "0.17.0" +pwd = "1.3" +quick-xml = "0.37.0" +quickcheck = "1.0" +quickcheck_macros = "1.1" +quote = "1.0" +rand = "0.9" +getrandom = "0.2" # pick same version that rand requires +rand_chacha = "0.9" +ratatui = "0.29" +rayon = "1.10" +reedline = "0.40.0" +rmp = "0.8" +rmp-serde = "1.3" +roxmltree = "0.20" +rstest = { version = "0.23", default-features = false } +rstest_reuse = "0.7" +rusqlite = "0.31" +rust-embed = "8.7.0" +rustls = { version = "0.23", default-features = false, features = ["std", "tls12"] } +rustls-native-certs = "0.8" +scopeguard = { version = "1.2.0" } +serde = { version = "1.0" } +serde_json = "1.0.97" +serde_urlencoded = "0.7.1" +serde_yaml = "0.9.33" +sha2 = "0.10" +strip-ansi-escapes = "0.2.0" +strum = "0.26" +strum_macros = "0.26" +syn = "2.0" +sysinfo = "0.33" +tabled = { version = "0.20", default-features = false } +tempfile = "3.20" +titlecase = "3.6" +toml = "0.8" +trash = "5.2" +update-informer = { version = "1.2.0", default-features = false, features = ["github", "ureq"] } +umask = "2.1" +unicode-segmentation = "1.12" +unicode-width = "0.2" +ureq = { version = "2.12", default-features = false, features = ["socks-proxy"] } +url = "2.2" +uu_cp = "0.0.30" +uu_mkdir = "0.0.30" +uu_mktemp = "0.0.30" +uu_mv = "0.0.30" +uu_touch = "0.0.30" +uu_whoami = "0.0.30" +uu_uname = "0.0.30" +uucore = "0.0.30" +uuid = "1.16.0" +v_htmlescape = "0.15.0" +wax = "0.6" +web-time = "1.1.0" +which = "7.0.3" +windows = "0.56" +windows-sys = "0.48" +winreg = "0.52" +memchr = "2.7.4" +webpki-roots = "1.0" + +[workspace.lints.clippy] +# Warning: workspace lints affect library code as well as tests, so don't enable lints that would be too noisy in tests like that. +# todo = "warn" +unchecked_duration_subtraction = "warn" +used_underscore_binding = "warn" + +[lints] +workspace = true + +[dependencies] +nu-cli = { path = "./crates/nu-cli", version = "0.105.2" } +nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.105.2" } +nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.105.2" } +nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.105.2", optional = true } +nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.105.2" } +nu-command = { path = "./crates/nu-command", version = "0.105.2", default-features = false, features = ["os"] } +nu-engine = { path = "./crates/nu-engine", version = "0.105.2" } +nu-explore = { path = "./crates/nu-explore", version = "0.105.2" } +nu-lsp = { path = "./crates/nu-lsp/", version = "0.105.2" } +nu-parser = { path = "./crates/nu-parser", version = "0.105.2" } +nu-path = { path = "./crates/nu-path", version = "0.105.2" } +nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.105.2" } +nu-protocol = { path = "./crates/nu-protocol", version = "0.105.2" } +nu-std = { path = "./crates/nu-std", version = "0.105.2" } +nu-system = { path = "./crates/nu-system", version = "0.105.2" } +nu-utils = { path = "./crates/nu-utils", version = "0.105.2" } +reedline = { workspace = true, features = ["bashisms", "sqlite"] } + +crossterm = { workspace = true } +ctrlc = { workspace = true } +dirs = { workspace = true } +log = { workspace = true } +miette = { workspace = true, features = ["fancy-no-backtrace", "fancy"] } +multipart-rs = { workspace = true } +serde_json = { workspace = true } +simplelog = "0.12" +time = "0.3" + +[target.'cfg(not(target_os = "windows"))'.dependencies] +# Our dependencies don't use OpenSSL on Windows +openssl = { version = "0.10", features = ["vendored"], optional = true } + +[target.'cfg(windows)'.build-dependencies] +winresource = "0.1" + +[target.'cfg(target_family = "unix")'.dependencies] +nix = { workspace = true, default-features = false, features = [ + "signal", + "process", + "fs", + "term", +] } + +[dev-dependencies] +nu-test-support = { path = "./crates/nu-test-support", version = "0.105.2" } +nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.105.2" } +nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.105.2" } +assert_cmd = "2.0" +dirs = { workspace = true } +tango-bench = "0.6" +pretty_assertions = { workspace = true } +fancy-regex = { workspace = true } +rstest = { workspace = true, default-features = false } +serial_test = "3.2" +tempfile = { workspace = true } + +[features] +# Enable all features while still avoiding mutually exclusive features. +# Use this if `--all-features` fails. +full = ["plugin", "rustls-tls", "system-clipboard", "trash-support", "sqlite"] + +plugin = [ + # crates + "dep:nu-cmd-plugin", + "dep:nu-plugin-engine", + + # features + "nu-cli/plugin", + "nu-cmd-lang/plugin", + "nu-command/plugin", + "nu-engine/plugin", + "nu-engine/plugin", + "nu-parser/plugin", + "nu-protocol/plugin", +] + +native-tls = ["nu-command/native-tls"] +rustls-tls = ["nu-command/rustls-tls"] + +default = [ + "plugin", + "trash-support", + "sqlite", + "rustls-tls" +] +stable = ["default"] +# NOTE: individual features are also passed to `nu-cmd-lang` that uses them to generate the feature matrix in the `version` command + +# Enable to statically link OpenSSL (perl is required, to build OpenSSL https://docs.rs/openssl/latest/openssl/); +# otherwise the system version will be used. Not enabled by default because it takes a while to build +static-link-openssl = ["dep:openssl"] + +# Optional system clipboard support in `reedline`, this behavior has problematic compatibility with some systems. +# Missing X server/ Wayland can cause issues +system-clipboard = [ + "reedline/system_clipboard", + "nu-cli/system-clipboard", +] + +# Stable (Default) +trash-support = ["nu-command/trash-support"] + +# SQLite commands for nushell +sqlite = ["nu-command/sqlite", "nu-std/sqlite"] + +[profile.release] +opt-level = "s" # Optimize for size +strip = "debuginfo" +lto = "thin" + +# build with `cargo build --profile profiling` +# to analyze performance with tooling like linux perf +[profile.profiling] +inherits = "release" +strip = false +debug = true + +# build with `cargo build --profile ci` +# to analyze performance with tooling like linux perf +[profile.ci] +inherits = "dev" +strip = false +debug = false + +# Main nu binary +[[bin]] +name = "nu" +path = "src/main.rs" +bench = false + +# To use a development version of a dependency please use a global override here +# changing versions in each sub-crate of the workspace is tedious +[patch.crates-io] +# reedline = { git = "https://github.com/nushell/reedline", branch = "main" } +# nu-ansi-term = {git = "https://github.com/nushell/nu-ansi-term.git", branch = "main"} + +# Run all benchmarks with `cargo bench` +# Run individual benchmarks like `cargo bench -- ` e.g. `cargo bench -- parse` +[[bench]] +name = "benchmarks" +harness = false diff --git a/nushell/Cross.toml b/nushell/Cross.toml new file mode 100644 index 0000000..804afeb --- /dev/null +++ b/nushell/Cross.toml @@ -0,0 +1,18 @@ +# Configuration for cross-rs: https://github.com/cross-rs/cross +# Run cross-rs like this: +# cross build --target aarch64-unknown-linux-gnu --release +# or +# cross build --target aarch64-unknown-linux-musl --release --features=static-link-openssl + +[target.aarch64-unknown-linux-gnu] +pre-build = [ + "dpkg --add-architecture $CROSS_DEB_ARCH", + "apt-get update && apt-get install --assume-yes libssl-dev:$CROSS_DEB_ARCH clang" +] + +# NOTE: for musl you will need to build with --features=static-link-openssl +[target.aarch64-unknown-linux-musl] +pre-build = [ + "dpkg --add-architecture $CROSS_DEB_ARCH", + "apt-get update && apt-get install --assume-yes clang" +] diff --git a/nushell/LICENSE b/nushell/LICENSE new file mode 100644 index 0000000..1ecbafd --- /dev/null +++ b/nushell/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 - 2025 The Nushell Project Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/nushell/README.md b/nushell/README.md new file mode 100644 index 0000000..ff5ffe4 --- /dev/null +++ b/nushell/README.md @@ -0,0 +1,237 @@ +# Nushell +[![Crates.io](https://img.shields.io/crates/v/nu.svg)](https://crates.io/crates/nu) +[![Build Status](https://img.shields.io/github/actions/workflow/status/nushell/nushell/ci.yml?branch=main)](https://github.com/nushell/nushell/actions) +[![Nightly Build](https://github.com/nushell/nushell/actions/workflows/nightly-build.yml/badge.svg)](https://github.com/nushell/nushell/actions/workflows/nightly-build.yml) +[![Discord](https://img.shields.io/discord/601130461678272522.svg?logo=discord)](https://discord.gg/NtAbbGn) +[![The Changelog #363](https://img.shields.io/badge/The%20Changelog-%23363-61c192.svg)](https://changelog.com/podcast/363) +[![GitHub commit activity](https://img.shields.io/github/commit-activity/m/nushell/nushell)](https://github.com/nushell/nushell/graphs/commit-activity) +[![GitHub contributors](https://img.shields.io/github/contributors/nushell/nushell)](https://github.com/nushell/nushell/graphs/contributors) + +A new type of shell. + +![Example of nushell](assets/nushell-autocomplete6.gif "Example of nushell") + +## Table of Contents + +- [Status](#status) +- [Learning About Nu](#learning-about-nu) +- [Installation](#installation) +- [Configuration](#configuration) +- [Philosophy](#philosophy) + - [Pipelines](#pipelines) + - [Opening files](#opening-files) + - [Plugins](#plugins) +- [Goals](#goals) +- [Officially Supported By](#officially-supported-by) +- [Contributing](#contributing) +- [License](#license) + +## Status + +This project has reached a minimum-viable-product level of quality. Many people use it as their daily driver, but it may be unstable for some commands. Nu's design is subject to change as it matures. + +## Learning About Nu + +The [Nushell book](https://www.nushell.sh/book/) is the primary source of Nushell documentation. You can find [a full list of Nu commands in the book](https://www.nushell.sh/commands/), and we have many examples of using Nu in our [cookbook](https://www.nushell.sh/cookbook/). + +We're also active on [Discord](https://discord.gg/NtAbbGn); come and chat with us! + +## Installation + +To quickly install Nu: + +```bash +# Linux and macOS +brew install nushell +# Windows +winget install nushell +``` + +To use `Nu` in GitHub Action, check [setup-nu](https://github.com/marketplace/actions/setup-nu) for more detail. + +Detailed installation instructions can be found in the [installation chapter of the book](https://www.nushell.sh/book/installation.html). Nu is available via many package managers: + +[![Packaging status](https://repology.org/badge/vertical-allrepos/nushell.svg?columns=3)](https://repology.org/project/nushell/versions) + +For details about which platforms the Nushell team actively supports, see [our platform support policy](devdocs/PLATFORM_SUPPORT.md). + +## Configuration + +The default configurations can be found at [sample_config](crates/nu-utils/src/default_files) +which are the configuration files one gets when they startup Nushell for the first time. + +It sets all of the default configuration to run Nushell. From here one can +then customize this file for their specific needs. + +To see where *config.nu* is located on your system simply type this command. + +```rust +$nu.config-path +``` + +Please see our [book](https://www.nushell.sh) for all of the Nushell documentation. + + +## Philosophy + +Nu draws inspiration from projects like PowerShell, functional programming languages, and modern CLI tools. +Rather than thinking of files and data as raw streams of text, Nu looks at each input as something with structure. +For example, when you list the contents of a directory what you get back is a table of rows, where each row represents an item in that directory. +These values can be piped through a series of steps, in a series of commands called a 'pipeline'. + +### Pipelines + +In Unix, it's common to pipe between commands to split up a sophisticated command over multiple steps. +Nu takes this a step further and builds heavily on the idea of _pipelines_. +As in the Unix philosophy, Nu allows commands to output to stdout and read from stdin. +Additionally, commands can output structured data (you can think of this as a third kind of stream). +Commands that work in the pipeline fit into one of three categories: + +- Commands that produce a stream (e.g., `ls`) +- Commands that filter a stream (e.g., `where type == "dir"`) +- Commands that consume the output of the pipeline (e.g., `table`) + +Commands are separated by the pipe symbol (`|`) to denote a pipeline flowing left to right. + +```shell +ls | where type == "dir" | table +# => ╭────┬──────────┬──────┬─────────┬───────────────╮ +# => │ # │ name │ type │ size │ modified │ +# => ├────┼──────────┼──────┼─────────┼───────────────┤ +# => │ 0 │ .cargo │ dir │ 0 B │ 9 minutes ago │ +# => │ 1 │ assets │ dir │ 0 B │ 2 weeks ago │ +# => │ 2 │ crates │ dir │ 4.0 KiB │ 2 weeks ago │ +# => │ 3 │ docker │ dir │ 0 B │ 2 weeks ago │ +# => │ 4 │ docs │ dir │ 0 B │ 2 weeks ago │ +# => │ 5 │ images │ dir │ 0 B │ 2 weeks ago │ +# => │ 6 │ pkg_mgrs │ dir │ 0 B │ 2 weeks ago │ +# => │ 7 │ samples │ dir │ 0 B │ 2 weeks ago │ +# => │ 8 │ src │ dir │ 4.0 KiB │ 2 weeks ago │ +# => │ 9 │ target │ dir │ 0 B │ a day ago │ +# => │ 10 │ tests │ dir │ 4.0 KiB │ 2 weeks ago │ +# => │ 11 │ wix │ dir │ 0 B │ 2 weeks ago │ +# => ╰────┴──────────┴──────┴─────────┴───────────────╯ +``` + +Because most of the time you'll want to see the output of a pipeline, `table` is assumed. +We could have also written the above: + +```shell +ls | where type == "dir" +``` + +Being able to use the same commands and compose them differently is an important philosophy in Nu. +For example, we could use the built-in `ps` command to get a list of the running processes, using the same `where` as above. + +```shell +ps | where cpu > 0 +# => ╭───┬───────┬───────────┬───────┬───────────┬───────────╮ +# => │ # │ pid │ name │ cpu │ mem │ virtual │ +# => ├───┼───────┼───────────┼───────┼───────────┼───────────┤ +# => │ 0 │ 2240 │ Slack.exe │ 16.40 │ 178.3 MiB │ 232.6 MiB │ +# => │ 1 │ 16948 │ Slack.exe │ 16.32 │ 205.0 MiB │ 197.9 MiB │ +# => │ 2 │ 17700 │ nu.exe │ 3.77 │ 26.1 MiB │ 8.8 MiB │ +# => ╰───┴───────┴───────────┴───────┴───────────┴───────────╯ +``` + +### Opening files + +Nu can load file and URL contents as raw text or structured data (if it recognizes the format). +For example, you can load a .toml file as structured data and explore it: + +```shell +open Cargo.toml +# => ╭──────────────────┬────────────────────╮ +# => │ bin │ [table 1 row] │ +# => │ dependencies │ {record 25 fields} │ +# => │ dev-dependencies │ {record 8 fields} │ +# => │ features │ {record 10 fields} │ +# => │ package │ {record 13 fields} │ +# => │ patch │ {record 1 field} │ +# => │ profile │ {record 3 fields} │ +# => │ target │ {record 3 fields} │ +# => │ workspace │ {record 1 field} │ +# => ╰──────────────────┴────────────────────╯ +``` + +We can pipe this into a command that gets the contents of one of the columns: + +```shell +open Cargo.toml | get package +# => ╭───────────────┬────────────────────────────────────╮ +# => │ authors │ [list 1 item] │ +# => │ default-run │ nu │ +# => │ description │ A new type of shell │ +# => │ documentation │ https://www.nushell.sh/book/ │ +# => │ edition │ 2018 │ +# => │ exclude │ [list 1 item] │ +# => │ homepage │ https://www.nushell.sh │ +# => │ license │ MIT │ +# => │ metadata │ {record 1 field} │ +# => │ name │ nu │ +# => │ repository │ https://github.com/nushell/nushell │ +# => │ rust-version │ 1.60 │ +# => │ version │ 0.72.0 │ +# => ╰───────────────┴────────────────────────────────────╯ +``` + +And if needed we can drill down further: + +```shell +open Cargo.toml | get package.version +# => 0.72.0 +``` + +### Plugins + +Nu supports plugins that offer additional functionality to the shell and follow the same structured data model that built-in commands use. There are a few examples in the `crates/nu_plugins_*` directories. + +Plugins are binaries that are available in your path and follow a `nu_plugin_*` naming convention. +These binaries interact with nu via a simple JSON-RPC protocol where the command identifies itself and passes along its configuration, making it available for use. +If the plugin is a filter, data streams to it one element at a time, and it can stream data back in return via stdin/stdout. +If the plugin is a sink, it is given the full vector of final data and is given free reign over stdin/stdout to use as it pleases. + +The [awesome-nu repo](https://github.com/nushell/awesome-nu#plugins) lists a variety of nu-plugins while the [showcase repo](https://github.com/nushell/showcase) *shows* off informative blog posts that have been written about Nushell along with videos that highlight technical +topics that have been presented. + +## Goals + +Nu adheres closely to a set of goals that make up its design philosophy. As features are added, they are checked against these goals. + +- First and foremost, Nu is cross-platform. Commands and techniques should work across platforms and Nu has [first-class support for Windows, macOS, and Linux](devdocs/PLATFORM_SUPPORT.md). + +- Nu ensures compatibility with existing platform-specific executables. + +- Nu's workflow and tools should have the usability expected of modern software in 2022 (and beyond). + +- Nu views data as either structured or unstructured. It is a structured shell like PowerShell. + +- Finally, Nu views data functionally. Rather than using mutation, pipelines act as a means to load, change, and save data without mutable state. + +## Officially Supported By + +Please submit an issue or PR to be added to this list. + +- [zoxide](https://github.com/ajeetdsouza/zoxide) +- [starship](https://github.com/starship/starship) +- [oh-my-posh](https://ohmyposh.dev) +- [Couchbase Shell](https://couchbase.sh) +- [virtualenv](https://github.com/pypa/virtualenv) +- [atuin](https://github.com/ellie/atuin) +- [clap](https://github.com/clap-rs/clap/tree/master/clap_complete_nushell) +- [Dorothy](http://github.com/bevry/dorothy) +- [Direnv](https://github.com/direnv/direnv/blob/master/docs/hook.md#nushell) +- [x-cmd](https://x-cmd.com/mod/nu) +- [vfox](https://github.com/version-fox/vfox) + +## Contributing + +See [Contributing](CONTRIBUTING.md) for details. Thanks to all the people who already contributed! + + + + + +## License + +The project is made available under the MIT license. See the `LICENSE` file for more information. diff --git a/nushell/SECURITY.md b/nushell/SECURITY.md new file mode 100644 index 0000000..3f161a7 --- /dev/null +++ b/nushell/SECURITY.md @@ -0,0 +1,29 @@ +# Security Policy + +As a shell and programming language Nushell provides you with great powers and the potential to do dangerous things to your computer and data. Whenever there is a risk that a malicious actor can abuse a bug or a violation of documented behavior/assumptions in Nushell to harm you this is a *security* risk. +We want to fix those issues without exposing our users to unnecessary risk. Thus we want to explain our security policy. +Additional issues may be part of *safety* where the behavior of Nushell as designed and implemented can cause unintended harm or a bug causes damage without the involvement of a third party. + +## Supported Versions + +As Nushell is still under very active pre-stable development, the only version the core team prioritizes for security and safety fixes is the [most recent version as published on GitHub](https://github.com/nushell/nushell/releases/latest). +Only if you provide a strong reasoning and the necessary resources, will we consider blessing a backported fix with an official patch release for a previous version. + +## Reporting a Vulnerability + +If you suspect that a bug or behavior of Nushell can affect security or may be potentially exploitable, please report the issue to us in private. +Either reach out to the core team on [our Discord server](https://discord.gg/NtAbbGn) to arrange a private channel or use the [GitHub vulnerability reporting form](https://github.com/nushell/nushell/security/advisories/new). +Please try to answer the following questions: +- How can we reach you for further questions? +- What is the bug? Which system of Nushell may be affected? +- Do you have proof-of-concept for a potential exploit or have you observed an exploit in the wild? +- What is your assessment of the severity based on what could be impacted should the bug be exploited? +- Are additional people aware of the issue or deserve credit for identifying the issue? + +We will try to get back to you within a week with: +- acknowledging the receipt of the report +- an initial plan of how we want to address this including the primary points of contact for further communication +- our preliminary assessment of how severe we judge the issue +- a proposal for how we can coordinate responsible disclosure (e.g. how we ship the bugfix, if we need to coordinate with distribution maintainers, when you can release a blog post if you want to etc.) + +For purely *safety* related issues where the impact is severe by direct user action instead of malicious input or third parties, feel free to open a regular issue. If we deem that there may be an additional *security* risk on a *safety* issue we may continue discussions in a restricted forum. diff --git a/nushell/assets/icons/nushell-original.png b/nushell/assets/icons/nushell-original.png new file mode 100644 index 0000000000000000000000000000000000000000..14501a3c75105f00e8f97c996797bdb57cf9121a GIT binary patch literal 3711 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

+j&@!zrF?CY=Atyg}DKaY9M6__XDf)bocV zcPZ!s>!fMo$RYX#15X%clF${n*^pBR1msV1x#1sP>a)Ey%YinOX{#D9(m=v)Ggy-` z$!vSDAtgY(a=Oluz(|qD5q99)&cq2*XxpN8rm7VFA5@a{FN4SrRyq;Ie zIA=c?>g4&a{O2TkFKp*zA=>k;y=HK8pe6*KfzAoYT?8VOz=k(ESr+aNmRs0T@d{1b zAQC{psF-9gl~nTBN#VelwI|_YR_8-cfFvr@$^FVf8-rZf6*rrqn!##HB4g_u3@Uy* zB;mxtu8WK-2%Sd*ml_ZP99T8y*V+|46(c)1wq($Zw=r4Dwu^Ocx%q-934P;x{vW=fGyD8Ad9vA4bOY+!c^@fS0>$PK zdX=OShF|6C2*b4MFNLb?Dh8x%N2siBpaY@)O+H6?3O;(C1sm!}N&p+c3)_~;=WI~{ z$E9^@D9=q|7JG#rw=|eS4cCP{jYiD>umPUVM2xjizgG`5Pj5jJsO$g1PJN+qMr}1} z<_~U=_LMzloIwjY@Zdh}KXLoyKpRjvf_`1gnjN|soyN`6Xr}{_w;x-dZ*0pU3s!Xx zDR94AeEkfVV^LZ-l8Q(5}>fDrZ;2We>n;moh+oo4S zQ-{6p)O7yktIDRz?L&w)U;TeJ>;G6nukw*dOqQ9KS&jSlDF+IW2P=OlmofhDe*n6_ B*OUMN literal 0 HcmV?d00001 diff --git a/nushell/assets/nushell-autocomplete6.gif b/nushell/assets/nushell-autocomplete6.gif new file mode 100644 index 0000000000000000000000000000000000000000..d5afd9d4bde79d67f842dfa639ec6bc03a260f77 GIT binary patch literal 1260827 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�M>#&jm*G5_?PlI#81!W;hTz2_^D0j1IQ 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

q*0z!dyzP;PDoBv2AqY70x^ge-^R(nx&dcpd! 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 Sq;u^jhmUQ?=x*YT_4 zwY%sd%PzN=@U)a(M75~^rhUL+FPO+V7h~=UxM5UVxly=+rp+;g!ZnimivR-)!KIx< zA0a~%S-H&NSX18<<~^4qUmkNsIam}36#@soMGWd`8jH-PFR>fVLN-iT3p-4mWtNm< zyAwkkYk>8?mubwDc(DL>NMKcj!opQdPBfs&n#gbMjU%=OwkRSk^bSq=qZv>;g(`Hb zCW=0mu8EaUd?Bo=Py!HP2*5HG-NQgNwH}n7!lB#Caa)cg>UBCJ{8MTn)MvPqVdQ91 zs*8K_9X$x^jT4OPbg%+Xb?*CG1&VbOQ<2iwxQIN57O)t;W3L;R6P4@jBcRmutzzqPv&nQX(yig1; z0J_s5Ex$Qdj};JoqO6#8#_Sfr<@Xu|TX=3EpTX|_&9|f;EQ?j4jLFB%!(-ekp}>=> z5ByH95>M;P!B{45K;Wf7=E}Tl#5dy6Gdd8%$wl1Ao@NjOjb7~fW`7mHknM$wk0=Hd zz~>V4PBYEarUyqkChA z#O`x%NJ0Vl%%u~N`a@L<;?w0VlotT@BOi=!8>|J2AD{Nu&TeBY@F4+Q{!K!g>g2aa#`v08ihdKTerZ(zTB z?tI&!0Erqrx#S=LodQ8}xrhTju^~TIp#oqz#RWZAspR>#aZhz{c1j7X8`}%&(9}thy9+hfJKx%xX4x2kE)b ze#-B@#LIsEx{|_%o}(s zXay`vSl%Wpe`I(5`Hr2<>Th^w?`fbr@iy`9U+KC5q{C9k@_{MhJUgtJnWsWULUGJc z7Xes(8QQ*VJ)lS!NGEs6n3=naYqmZJL2o7rYU8lyHy*4J*N-N^9yPq3YC_>(3Fq80 zrC82EkYsqoMo}G*zS5Ovi_S_A+j`cUFrETCYG14^LvTQ%**wH*>jVD|; zr#y8W(bWYs1BI?rV1t~bhFG>&2q3SGG26$t1PvxcvZ9@YJT4LfBNqxy|i5F z@y~2dKX0sJkKU$}x!SzB57>Y_w8-Apx#AwUjcO|K=kjrJhq0J`tn|D6Rq)RxQVoA) zO-Z21m!?ZKf@-JtrAYIwor}*|+H}+0eXUW48`4ieVB=n^HN_$6r^mo(H0P~Yh*1vVupmCg3mLdXJTDU;dK3Jo@qW*)3H-iq z*6{1X=Pu_R=^dbPcnUJ$q<|XPF|mmbd=u0jBh)w=(tcK5fQMfJ=iTL##iKvf zE}n4HAod%ZsZ%rL-{s^H<07W(KtZj~+XhIRg!0AhmG?4#Pf`BUVc;AplfId0B%kpZK7hi+^Cw?M9hyJi)IayT z(_>k>mWUL^RR$(xVnOlg5s(*7@}>jpv)t>o0MZdBt&xB8!H;#a{{+C1 zHW7`1DZT8m{eOvqd1EwkU~_3eV<-j#G1}*KXl^NfHbgFfPL44+Hb50aZYah#C3=t( z=8j3$_7;~Y1I+)(Iz0SIyS1Y@NDL{YF_3CUB8=LtKiz9NO!8ZznbO<{AtrSI&J@ENYWi1+|8_ z@Q1n}49`-6+Pb< z_FPrM2yd2og~?oNJRO*!c$27F7%a4t3bP4N@d?FGZh=U5!7eN}!YRt0 z4ff)S389QRKfMV=XsBW%YWu5Qhxx|#T#NMz3 zpo3XCVIZM^NbyV19}}9mQnrMl>PDy8RsF255sOks<019)pA>in?09d_mbZgniDT!$|Yk=U}#W+XfobHlpGW{>mfq67zt4<5=wL^X3X6i@VP+z=rg5lYDM#0 zKZgLow1?g`Nga#e;9RJ6+~bh2SPVxj4=wA-wJR2#sV1DwrV#0W!Z8dZUbRqP`Dd=b zTRK2*3(TU^@=Gy%yIu0{idC5@F^4=U&q-XH=~=OsScA(=sjo(0W_9=v*gHAF{grw)eR;X~LO-(YH4wu)5%_ z4l=S2eC&~23`_Qz0WY-He!4XFuUV(Yq>yam|AsObDMbi0X5YOEcd3ud@|Bv|qd&LC zzlY)ff#WBoChl$0FaV@2hd^*{D9hDahrpK*1CtF9wrws~nTKiR0?dM!_8gpp9+(0i zWExU6QBgImurQsFOFw8%CZxz3TsLiZZf(RhyVl#}u-nuM+U&^8?2>9s`?n#dZrW2} zmR4xC$tHE0HvH_T@Ltj+{b;klA$6pJk2@X%_qm^gGY&>UZbJ?{37`u7okv$Qne1Uc zk-1e*B@$97I*c19Vcs9{R(j;0*=Pvy7zvT!zo@{4QY@bWZ&7uF4e-WfOv54yQU_5> z3F-GtOv0;1$uVUtoCbfXuz1_FozAxPRSkimU;$2S_#DEp7Q(e&7~8A?Yc+`nXal&a zBV-U5X4(+~3u==mIrcfpWdWGnr=&vC{aIx!`V&e-&JaiWD*8IQB8<_d3FPAuqcMTW`>4hDiy*Fq zJYkUB^Q%~dC`?TS9ql(NK}CXBIjV{rdDL@F+H=IVWDJuz>26!40BVc$q|f%pgfW@R zc{|A|@T+&RzZd}Ipi$(6i^Y4Zl64W91ee%yj@f1)%;e7XY?8i4ZH|gI>kvKY$lN5f;_zVMLQNPtY-QaD%7%T) zkC+L?n0Y1ad1drCv!%Psio>)Glk)%cqS8OfZmXIzy@n_1_|qySv>&Q_jeg-PDKW+* zs!-BiMFXzG8g1rwgiNta)C{uGu?OqL0;=6*Wru6>Q%XfBKu1+ZO8y&-2L z>&hI39-}yYk&8J!Cr9(yhK33Ro1QF~&D|`CICL1D^uJLY*0f;6 zR`GTg^A?_nMwtm5V=y~q1nBC_3zE)#flFMz_@p{{VWTR8_JJ^Jc1xeu><$WEFD^gU z&fFvQAmtRuiiH@e{sa~$Y9zt*zw?z8Kloxk^1aYycyS{J_!XG`hsnm<&B=B1O`5a4 zz1i#ElHUkcc>}Vh-yd3*HA2dhSu6Uhsv={mxeVU!6_BhK5!zBC|2VX@y%i>8VE7AU zh)vld_bJ9@nS?17#3lZb&8&thSE?nf}}Eix>+hA1l6`VXIJ(whP4!$13B zN{Q~2B4FGdVrpc8M>)ESsW&N{5hH5hDObCot2ld-#MicJl^&&%joFT@L2h$~!j!4ELP)>bTnKgrVLcOM4Tl zU2&Dj8_nJC6YNcmSH9HsIXQFMfJkjXgK@E*=>Qg&D+c$GF8_K$h^ZbFftEwKn_F9x zPgzB|$M#{04J~wE^_!kwzasSf7gY0`>rjk{*g?+JXM|spY=tL^jCo)a0u0|u=?QAd%XlKc)%EG8i|(A~zO z0Dpdg1MjpY`&7yq`@6QQd8Ie=e$iDXJn>N3Pc&!Vs#Mw(-ne5CWWDVABQS=q0Bq&m zz}gdlHGEm+);_C~F1kw>&n^1~Axhg~!8}xrT@{-cjfiie%d+{1IWm!1D_WcLq+K8}-998Thbul25&Oz?E>!S>*R%%^|9$fHI6%fMO? znNaX>*!?CrxAQ|ILS$mt=y8OHIwZZZi|k|XdEn$L{u@(&xyr}ejo>-5&PbYn=eQwD z{;A7Wd!CkFeI#zHMj?h&qFEmys;~aFQQacHd<;IlNaLZnyZXH~5n|lCo4k*|ZCh(} zaPzR{uikI|nkd~v@hGIZ%uT#G{pndAwPD+IoXpHM=guSzr77H-ZhDn2^hV}glJ<;C zK)AHV@^Oe|y2}1B{+_{&>Y0?(56!((j93r|gOJPVl5Qvxi;UmpSh0MO}b#O}pJ z0!T!>sB`wRdr`*^DR}9$p~U|Us6bc0e8|*PvUe(g#DxJg$npnIo&=KuXV$!#6XJnJ z@m?7G7;|C^CtLA+;`>$)-u$S)E&6V!&*usYsFK+xea^m`g z#LWCG=>RLt;JLFkB5CG-;5sBi=Z{!P02VfRU)O9)MgRva{c8_SLO}&|xcPHeE9XQA z_9D?i2d~{7gE=Jt1uY!#0|G6uAi!XT9Z*R!3Vf1GOaYjH&nfCP(oH^hG&BGfBPcN1 zXCR75;zI)PkPjJ25%ge$6S9?CR&_O4TVP-rreltG^{AC@KfVSSk6rNyBtbah*rQaz zCHEwhQA#-_m1@~Ti2(ovaDzRCm^45Z|MlQfha~5`x7PtMSQ3v=aZuBXKqKB0iW+eY z^WH=P#DGN=$GrDqBlgUq#wPGQXFvcDoRf|)LTE732rv!i05$*Y)80SvFxTK-0hA=E zL;+mUp#czllSDnId?wR~o)r{8tE4rQ+6V@9`e|D<25F>^g8ev~fVC}YTW?|sTiCC_ z-nQeBKJwaRmC;H&Ew$AeM@=$01vQjFloFGZiY&rszyyK#!;TP->7pg2*=Ff!g&KWy z=1v%(^DO`aG;$9adnx*!00ZRF&lABOfCa*AV8O;2S>BkJ0Alca03p3#0FN#cI0P$- z1aa)DLm#*l01wLzr>n8cCd-ts|HnS1mCHo}hcd5z5muJ3Le>m3&$uB=o3%j;Jv7lp z8?+{Kk3CnwmiZJi0n`wr^U6*F5tL?7J~34SkYId6IZ2rz0PS_ZHJ)&)R- z&bnrcL9oLD)*UQWV`-HKzYv7;#Kpa=s?f)>?iB0b2?@L$$tDX&v(LN5Y_rNtQm&)k zmHXyoR`aV-0fED(XxtIgEua7l{BWT43pObFQ+(f%2Y44}yfNahmfw(by+4EdFVM83uNZE(O+yr|Do6D+UL&dtaJTJ_cNfau7CzSAOagg0BSq~0ePs5?D7!_ zC{U1sEHFv$^1u%v+-)lXgMl8Hfe&D0$#}?TiFS z>7TQZbUCc}FIi+6Vgl2s#x+_iDD1GnF~GBv8(>HPo${E~Hn>Ft2mmq5!OHP|@h2^v z&1o=MTic*V6&T*_E(c54!W!1d``yebAHYX9lEKGO-N8i#PyiIJL&T05v4{f!r6>iW zFWO=1JMfu{6l>PG|IWdtidme9Eh{-Q{N-RXxA+_QX-*-rWFs<@sZ6=7Egy_< zM^qKfX6Hk zF_poJ1%BZVb=1myq&(a|3y{x!_Ok#2=s*RbV2OU5K?nk99~ygUKb28#iZ>I|=xpSb zV$w3Ayy4$33G=>*VzH!Cj9gPZy3Ccbw53sb3_2hXxN^iI3)lFki&HR zVGirOYefF2ol8#H9el1ym2p7S=$3Q;9-tTOaLaQBt$)YA*&J9&UUIY z0Cj7JHJvB`y3$Qt@0=)vlWjJ$JL8J{9BWxELiVF&G-fU1>A&G_?^&AtEPnH=UynJr zAO^@uNd_xeo%}a2Ow$NoUUf%-2$*Ss`R`OTa+RduFDy2)=n$ELK~FL5EGF^fftknP zq%3&E|D!Dci2VyixEvG1UD;7b(R-v9zYoSEWs>QjqEQQ%w2L^-5sr09%arc7$VPT) ziyv3sBS$I8|6{W1BuhXjQ@P5kbF!6<>||W>GRxEQv0c0@<}p(X%VhqnnazA=@?u%d zYko7Fi5zD!yLryath1f-tY-u7naX(Xa{~Vi=t0wY$%MYMp?7xZCxLm&i+(hr1#PWH z_c_U>L(2gYkqiMOF4LP{F_}Hh>0ilNjiLrMq*JXHNtan=3yg;bs3Ft2prjs|cxAO3 zu#8hUnpk*o3k0|Ur-KB0*bS-mt-CA`UGusk4KT(libUy=HrmImV4Pcn$c( zz;O>}a47EYhVy&o6_MWVph9nZQv=`YesjE=%--J^MI!!5r}N5OTtN% z3lq}xXxfTPRCjNp(MJtAVrJ_|ABfT=WkjpLO5+=cdfag7-d%E3bEX;G#*LLkvOlC# z3w+McWApa8Ox-wPXUpF=f^)PK9VuV;v!Pp-v(5DwjKZvCY8LZbkTV?tAgsk_|4N*q z8yGS+Xita$IA4gohraVzZ_C-}Hn`O9Zg2sxydE%b#J$|6^rQEf*=dG$UuK)5KOP9{ zLG1g!ILY>Tm&x6aAC=c%e)U&Sy9L=YN`V<*_R3g8cg1&h?H;^3N0X) zKZJva7}V_igFt|w41OSnypn#fL7@nb6zGI_kjDmspL40lAJhXagh$>;|Af*^KuI-W z-aKFgPGAMD2d3bOSK;6(zz5W|Abr3fRTP{I5)9L@V0ZW+AqQqe#AqSQN!?>)OML9Xbi^NX{ndW- z$A842KuF;}NFW8STN8TB8phxJnFJt;7Ir}*JV>I(+@N-C;Y=;y{kez+9-{KS$OUQ# z%e^7_8BRi2AqEnJe(;BX00=>NUp*iLA<&H~!D0hShMB+zI;qe%380M3Su4y*o!rSQ z1%;pxilKbU`N5Euq{*7J$(!s%37kVaghCwTf)A-un2br8(2K9o{}3zT(8|o7ryxp% zkt3VLgPZgMe1M6VkjXR3%P(Mq5DY*Rw8IwIkwNWApZv)wT_c^?$)5xOLal*4h=K*} zgg=_2K(38FWWuLd9SV}l3ZBC{d;=S}iO*>y6mX?QN0#9^MAr|f06OrK zNyy1XY9lTMKm#1ZKit#JgiDJ6AquTXiv-3;C?rEVBt+`TQ(+-a&ZJJ-;p@Q97<;JNnQ>aO0p9%AthD8(e`uU_%U8f@chfRFYUo0_2-y z#2~^@oLFQwW@Jv*(L#~@sx<~-T zB|EyK6fjL;1|&3IW@ZklANZw8$ zB)u?AyO8IqgkG2YoPoxtx-8pxl9o_R6+xsR87!xwc*6zd(GxHahTdL5wCK7)-7^S) z1VoG>&CrKxNeKl8#neMDaN5m~O(h8_QFTd{K&aXr|Aru?2k=>4jGkzUYS4|G?$i~=T_;<@??fC2mtI9f&}EjP}Gf(3Ko1K=zIc~?2sXj zx(m}>sFPB}WIjWTLd{N4$}@1`ztpI};3-Om=Jpi?*$~8+KEZwF=Z4ZL?%?Mt;%K2Z zX@(ZWf;weJR44|09bb%-dEU!Fs%I_EUT7{U^H?dO>JHOfh~R)|b$)7p{#QOJ#xDrv z;gQ)de2w80QZ(%a+o;O!q2)wm5Y}i7*Fasi_=V^}%>+nIv=!G>Op`JEHCA~sPcn#P9S*RQmsN_h~xTwU69;if2Ist$JpsU255T{-pXX--0G7^<4 zW((sS!0+8nC^peYb_NW^H0@mMS#d280pYspq8!}6j*(H%h`fc0R{ z4^Tk9F-;=^=RiCLIAGA*;0{{yk;IU}xpK?cnI2C%BE0gfvmON0eulx$(Gra-)vznr z{OV4aDzP4z%oc#rUe6C$kJ5@*AWdkZz|EcRj@5Js(^RRrRx7y%?u9^uJ9HA;j@j=N zz-c8#3NerKBrDD>tJMhCL|jtZO+_MB|JUtwDd^_O(f&XI{DAh5+_PLo24QaJY8UQ= z%k3G3tmJL@_0I1E&+vGX^zE!NdW`59fXGn7Vt$}|AWCBP?(Pyq^73TdNCrHNr0)RF z<8rBEAqF*#l=c2rR2q_!24<*u>`CbC!Fmd8PZOow+wE%Wv*gLagJsCGOz3B4$@9|7+lC5C=urg>3GCZ07_e)CD~rj@Hl(Nt}J1lF z-PmXpSI`9+0Hr7-0;Gh(dd#{S6kGu@35}i8y$Tni3OcQHx92?Ov7xNDsGX&3(AV<&_ThPGbavN_<3NH^4 z3*;yDvcmi_8oO%9O7MEn|FR8xaYEVTXCx&&;B2b#ksqlWu_BnvQm%W>vNpv8C{tL4 z(9tQ}XT)BXdZ@F2HnL&~2|+We0{fJ0?mXP9tOq-M z#HQjciExNuov~B!Gf9sZ0B$V4eTGv2^>xg~Mt5{A)QTm$Dpr^@ zdkSnPvnTsLuTZ1Xjsn0zJ51G}%^}Gwn!b+H+^obAwZ$c|9?7!*igZ8Q^g(=B5;g5x zsW6Q~?K@X3(;PK*BsHW0W-4*qaqcWi&y-wC09~{7*kN>nsdZ1sM<{{UIH^zPA(E;H z7K&-G4EwRbn6uy_|Mt&qOBI}h*B+V+&>lFYWjXPbdNQv`l(yw6u~i&TEAWF9XoLVv z00vD{QCpK(iOoBK)LC4XSr;_BPy;oYgf&%UGF$`_(XNPb(_xji5w#AMz_Aj;D-Ybm zGYRjjq+lll8 z7(s^x+7)3j9ls2Md1_aM=Z|ZmAboi@4_-q^0ga>y)usBju!!|R` zcuNy;S5ss<|2MswID_jGKiP^5pY}JUHaUm%3}1A!1qGhswsA)$NuI(14l~xJFN3eqwSU@GfLpXhtPXU!siJeBP<1FX_ESPJ))YMJo)J|dR%JAWC zhpu|ec~A}2A^SN_>6BR#z%R4|AOJ!gctQBt@l!<=6in5Yhi)wm_4qyqvjaC%Su zRHFYJrF6ra8bk>+gIjsGT`$`)jC!df3a#5Zrz?s|U==*P2ci_!QGGf^YRLjErDeo~ z8zuY896$juDH5keoW5FDHjJrKGUA*{oXYPGd$>+IK_;MZV$F6M1v ziV$@^C++-N^xH zH*k7D9(_Vwvu^)>^XY`?dms26JS}n7+P~@!yXHjW&a%fEldLh5R&!}R);2?kJJ6i- zE;0z~Q;oC6=7SHz%pSb3IRh6f(I)4%6Hu|mnCp!((y{^!MdS1XPJ#{v|IQPL;zRSWLMtWHQ9A7$;nGe?E!EUhQB74<*fd==%}g_ORj(`T!G(=F;((>8 z%497-0X>en=MG9a6--cFG%OaeCU z_14^T(M{J|W!1$LR`O&$l$(8KY95wCA6JW;N)ci7q;5osCZVT%;S0P3flr^Eff4p|0BMtNm3Kfe~nq+G(tR zrus~&!A?3>#l$XK?X}k~w1H)u`m+IQh(WpIv{5C1ns_vzh8>NrlGh)1guzqkv|od{ zU9w9)yW^J~$BJ>R8ZhRSuU}?c^HT*U-0;H$$RZmdXzsl5&BrV>tg+;#+wL|m4uF7P z=FwXot`%x8pIOw4&E zCte|>_F3v5NrR$8CU=}C4g+|^|0f?ZG&>+Bc-oODE9t4X-Z1&Oq2K=NkM|JmT_$+L zquKh}_dd;7U=!#7Nhb7HK;prRdj`y109UdF1|d*<3M@_cF2fq^32=GDS)Ic)rnn*D zuNl=lO!J=SEAtI5eFGT)2AiS5r?et`OCjG^Sm;6tc8!4!GzSE~H$(KrP)b3J;8#GX zkP#-Ygi^G^Ipm?T0&s9C9xMR={P!am(oA=}^Id722$-_OB_U<(-R}wmKJk(7hRDmI zW58IyC<&&H54q$0U@^TG>Q9b7{G9x-sKr8FGpz%klk2sB^CDa3w5dNz0(r;Z~_^#d{DUfGFSt8EU9RQ@nG_T<)@$h0!KA zy$Q~*{L-4#LDK<73AolMfSS})B{mD7fnVGs6lj1&J>u3Hc#=|61AT#g1|WudAOjF` zpawtCvKe|-^PWNgia~D^0ConmI$t><;#5dET!#tIP;Y$m1aU0+R%qa z)K|t#rZSm15OI>UoY#xzRrJYEe*(0XEsbU^{{gd8a-ztfr95RjI|@Wu_yZnU1jMk}_+JPbjM=LHRv>mi;pDB1uIr*c5Lu^S0xj&Cw1(p zkp++>QU@bRtRR2|dJ(|fz+n;$q(c`rDa$>`u)k3XVMkhIt!rWH7}W-jPodG`Y-`IM zG2qrRHtFOuOw!3a1pou*_?u7T!CML)M!H<9?sW_B+Z_d0A;Y~7ew=#@=+4R>g;>s> zz^kpK(rq#_XoCds`vG|L;zz@Iu5jrV{~PhXmKw43s8}#(7^)3ayILd+a&5cZ+-{M! z5oWFd?2BIs=$F4iDQsNJJr=u+U-;G6~19S_2cExWgx!NskQP9Fp;1)>n-H z=VglMk9Fh_NFQx002;6jMKA*&!mt85+>wdSZc6|ZXu$z~fPfaTpjw1EKqZo)fKMbN zI&*u51SWtYJ;Q^~KiMk}ym+$z{|;n2VC4?3;dc^18!^rlp~hI0<+uPvQP-Fgkn!V(DY+t$d z^(;Xjy@=s`lEF-~AJm$8!_P7JU5^1^yP2_B8!tc^cw@+u8hHOWJ#&uAN?H<>J?P|t z5mdm&;nDHjSz*t8Ha4_{2jx7 zY69R28V&-!AqfB~Elgnj+K-#0fIT|z^Foi7{z3ptf&dNh6bL2&wyyxZFSP1!F#hk0 zjOhg=ga@dDHvTVh|59+XQUd}Cpl(iMHL&kKQV>D_F#bAFP*#EsLJzzSU=L;iSB62D zz6c0~kO-#_0!2^#*w6hY?#P0)dZ2$TXE5c%u?vIJSA_1F_0Tp5frDz08 z@C2{03j4%{9#?{XB3DhXe=b?*f~;0o%27CIvUDk3;+ zFW^3^0G#Z`|8zkB60i^?AP+KvP&DfRl8FtlfDO(dluQi@s(>1#0SchN1#+qvCt~0_ zL)v&i-=J(C+F@WML;z^u98L)quz_@f@d>(v76Y&z)}a{KKn~8KPr`{B>=7TC51i%^ z=xWLxkVhB*hdcJMAOF!mR-@NgB-f_^ zCSWz@<{?o;9_djbK=LcvqaP+Lp{T>(c+x{Q<0#Jy_e_uyY%n!??YxdMS#t6oVMI{C zVFUz#C@CQ=CP06faqT2y7Of{eD&o}!!X0rD*qA9L5mF%;^7UfTCJ0g=`EeHf5g;}4 zF7vW$|Ma3M9m^sg0wYhtEmtxwhYqYJ5-9UPC~Zg#igGVG5+DmeE#a{sRT3_rM=8t8 zA@9+oRuS=h(ksY9!e|m6PEs#65-&UQddv|W)sY=-!Z0<{CbX>=IHVCC@rzzF9oI3Z zkYX-pF{~^>Fx|q-76LH$4Yy7+HNWyC&T^0TLYOe~Em^Xeit{3oGc*+`I|oyqY(!Iz zg)*GXm-3+yzH$Nz;&KGV8QDaVwh0)<12gL69wdSrZw~-+Z*Gt!0q>wJ;-Rx1Co}$p zE?o^ddgBJpGda@5)(1BWU_@mSFg0o* z7}Oy2(?`hwNQHF22;~4$G#@O~=pM91DKa5;^famq8>FBE{s0{o6aZLsBH1HLBQ!ob zY5&e^NAv7K3jj^egi0yYN_%5>&KOHr}(J+w3-zBEk7bU`KcMk94lm-H3Bf>TRWInT5w zQS?r)6c0rcyGW2MoD@ojv_BjbRr_NW4^%f=6;V4CFmn+v0%RHubnOsyQETZ%|G`mH znZ;7GX;*`^SFs{cxAhp@^iUI3Ii)p5XVfvc^P=`3Q_FQA@BvxG6O#5VF3Q6B{-Iql z;{)vVapp!D(4kLUgF71HA7}#N^7GO76987=Jacgy3FUDFfB}90)F77B)P&F$LJa7& zU6Je=xZ?_BH7z7S#nO@*KIw+Ip&cR$Us>lWp5=W+H9STnWLp8e4)j?*HZtIejhb-; zOcrGc#wE{z7_P!c?;sEArY0w#WseL4U{)G47FlvpSd4ayQ1d1wE&ybfW}Ve$w=^w- z7D8U)is%I!0zp_dwqxnBW<3_@T*H}!l1I4+1!P4wKRNLn|IktZWFQxG zLMr~$Zvht`1UH*7wtX~KX7)}vsj@nHS4 zEcAf{6X#!v?;`eLACNCiFw5cit$ytn3h)=#&=Uc~0G}o!7vmx*|B1&Y)<H zGr|Hl9Rn8|6D=6-gF|?$Mpys~0ZY$fI8yjbo&~pP<_Zd+3Qo@in&RIY4k2C`Au@P_ zIT#lO(1;rliMcI45F!tX!-FRPghklIT+A}4R0@#dx@x$KZ@2^()Qh)jH3k387iPE1a#l<=8kY^V|F)gOGZ z@T#|_7&ZVBZjzxZISfGBc#Sl#VgN$grNd_+F2bXwa}y71q)R$IW=9;f2mn5y0J2s8l3Jmi8U&tzv4FVHK>Q0pXH+w+K8juho(KH%i**vcRl!>RUFksKIKbog%Ei8agP0!zLoJ54*tnnp!lPGypp)ExWBhx}`(f zokdf2?8L#ETBuvLBo3>APhzoe?6fmuw85#agSnnN6SoCho?j=nO`@#Nnr2@6sd@XZ z4>@-l`?w)Pw*yKch+DPQmzx{z75Sk7^&-{|jCJHUEcXupSPKC6WVZKB zlR9oXch|GR(EmccO`_5f;?iwM(pBUu|7tzMuj|ff*v1Bc*#V^2pFlE@y#SOw*17Zt zEWH&fcpuwg7W4oXn2Vm}*XXVQADRIW^k5j`G62Zk+|iv3*gG;R0-H3d9*RMiDgpXh zqfXdC3M`-!;32<{4FDE6gdO-cCP%=dc&2x1dx zWdH!J_YOVXhJ)u<{Oo&PKW_jY{}`$c^!^MK?)CoWHRztV0HEUw0Ov>kJI;an5&<40 zC8?1C3*vwo&;j`zAMz!?g0tS@yT0A4e&%cbE9(8+FYM@(9{CJ_^iv-B1mN!Te($Z~ z=YxLei+)yO-t!e?O60y;*d7+#o;Xe)$B;htfiCm89(SnT>T5pmIo=X(p6p59=wN^i zs^Aymftp@`kdhoLydLcR3iXv<*r}WIk$)^L;1}+(11bR>*ywqqgyqX!^m7aL0YT`A zzA;uG?*T#Y>);IVWcvX^4J>=70u%^v10OOhahRctC!~OY8}N_;s)O;&hyoI?D6B&V zA210AX{2ig2oNlMuM8L{|1basn<~HJ)nW5uLIIN~RkCy`vBWTV^}0 ziGj~Ikt8MAc>!|N|5$ROEjB;0w~rkgpC=XZG+ZQ#%{ZmL7UmMNtOE;y!9&U>9yI}do5_q z!V8*N`RYq>WB~A6fKL9F3+{Q~K1Sk)>t^Sfd1VUxAG$!z`&q^19{ke5h)rg1djmh# z0gNX@Od4bcHk@L$AWjUkwTfN)U&QTwcdfI98YExKJj*9?yaIa$pumwW`!Bxx<_oQ> z+|nzV!p%x|v03k)oHD{u+pDozNN1O-)+C<{Ex==M8!gF2vc~Yw2p60+*!LY&wq$cN zovzgqVC^lt^SXL>cHat3vAY4A{g~f?7a6Umj;rf#<(6MQbGVmp&Uxpae-3)+oomiH zh@zj4|N7~3r_TE5rn}yH?4S!8`|7gaj(hI9Pp9VYt<&x~@CHxpJG+?|k9_jVS5Ero ziy63l^wLlNy64SLkA3#qZ_j=A)D!8}re{PNFFzx&>| zUw{6{pRa%a{@ee*019w`1iT&p3W&h}9Wa3mtlt6~2*C(SP<;=apar*A!O6_*f*c&) z%>dZJ5Q=bwxXU03PbfPRx@?0elpqUB_r4a&aE2&Mi~zEb4Ixl%G6bMTJTyQJwa{>g zlyjeVVpzWF?e2Ky`XKX|s6qT0Pl`_@q7|>$K^sCvDq)(!TaZNwq-p0D^XQ>GMzBLH z|B_IJ5Tj!JlxRLES}t=obECT8=)nxyv0ZFbqaXiBK>$1@DhIiNJ7&QKG_=AVlz>bE zej$$p977(q1LOt!$QUO&P?K?_BjyZ5ygjb)g?B`v2S0~NOR92}%hMtuOT_|-2w*JW zC=>t^&%O)Rda&nG)bmk~cSwvQ9 zbDP?;z$Va94`dLcQ_&*8F`i+|15_dz3iw1aat2CK5;K|eeCF{ySx-Qwl9Tl`razh3 zPftekh}Qfk91Yq$gjUa*+2p1}A6mRc&O!~9*vBigg8&#*q8(EBnS7EGPl8Uf|CAe~ z=R5^!(q#H^pPCCOK2dtomqL@86-?_3#3n?43e?WwqZclz&_zE*jeWG^ z4bZZwJ)bC3fW}m(3T0>wecDF+RW+m~<*G05xzkVTF_{i)2L^hHVus2I`oUN+}|FQnNt+4bDt|2ehA@1gEZ~Z1dxYLN$j_*|AlQ=mFv=k zg4MCC{Oo1XI@R97Q@NIvtXLH*MdRYsv#hP{x@O8p+(LK1th@&qs#V>|7}dJ2ZLBoc z`&HV~*JZOMEP`zt!agpSpXb%&ce&f%1iu%)*OTvrfy>pk>Q=uH=C6r~2&lvypb>-= zfDGP%nFbs~9ULk!hVxrk2j4WR;}tFumx){o$CJJWE^;xo>RW8$7sth=>X0*RS)OK6 z%29^hiLd*C{d0gwAb^Pa;_Swo`Qy*I~)4(;CpYIFMHV)6% zqpa^hQAavYm-@gUuCIGX3_?~*`;R4NomHp(Nzg$W+sNK_Te%JHA746m*A91cQE6;* zcU#x8R=2y?IPMab``yA0UA5^w?|RdF-xj?0y5o&+fb)BN{vNo&yI1goM=#+DS02L~ z4)NqYywCwaKno7=g9%6=jSG)=XCppEb`KlmB;Vw1^Ig6HSYjU+S}pf@J#lP*{MaS0 z`5Og^LmhhWhB@T;9icrL0Ysr5nTXW-0-*ACuz?L;NEO1z{|!q0dE45bX1AVmy5VTs zeCziUqoLm9v9PU5|Ur<^4cVGx>RBhbpA6Eq8tUee>S~yxn`uXAlA2)RUGi z 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 z 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 pN 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

SIfsHWC5D|7w2a6biP~A@^lKS+3^c49 z7*tBmtDQ;dYpM*f5is8CQqLHBKh4VLQAv>=kxE4sTFb+_&4ZxgWvxM!$&XCCJ-O>W z<0P*_!-dOWPh?k4o9)zAX_JG$;`BnuYZ^YcMkKT)*XX`9 z@b1|~8>Lz|TTOD~VXo8M>0|nT5Zo#vD{+E{?1*D_52&LUZ=D$7qS#*&;m=2Nr%u9g zSYg%=!WXP&7vC5tE_&eOScObYs7jTSPTzr5RMgU~ETc!~H z19OB_f+#7aMkyidm6!<)BH0Z&-zQUkyx*7^oXk8OwEv-wvAJmG!}e7k>m!DbRw;WP zF{yv1eti9qUyckK3wf~Ybte^3+^gmw6?V8A^Or{2?w-1Py?WG=x*t;G{uqh2>RP?6 zx`V_grsLG61rmh?g1Z2$0|X#%nC&7fH_Z0(S)SBh&CCLaZ=cp14%d$q=4j3&{G+sE zGa_1-wL6hIk4<%+7Utp+msTb|dY%(8X zpi&uW72Q8(`_xk&w)DKTn_FcL89g^0+zkeE@A%VbGESPz`K&4RnLB%!YSIAOL>e-i zrr<8)dI3|_LJbWr=cWyB@WybSBd|w1;V5SAS{UjSyeC1D?;C}D`+GB*$kLnMIw{f8 z1ZJDVWwmT-_3)8R>9|!hS7Mx+Wvae4L8SGRSvHFvSqIns0Ck&X2b=zJop7bdbVbKZ zMO$_|Tk8N@bLpJf9oqp%U{S*EEz#T+SF-&4H?{R89NBkf8^el$yoOiNO@Eh4t(%|! zsKhgHO>FE$KYp<^EYJ&Gxoh^%`0nbbXXXyFZXpW0F-H&?N=e6(6DW0xBjc01q??W$ zkv~mxf65hVfUaM+IPNvgI^ErHlK;5(o4iuKV~Q$j1QOt)^~6P?*v;sPTVx=CMUg9Y zm#f{mD^)^*%aa86a~CoL*FUxHevnx*wtGQt_nt>uMNG6rPb6X?M{$xz2_ZS<74E(h z?pLSoy4Q~i+&qfazsKv2eU?(4y0!KJ-5h5Vt*?0Zt-!bq{Dz)Z`G+j;FxmcG%?r%> zUHR3I-u)ed^Ozszz+;XKl^X061elq)I|pe6Fc02HrvH=Ry+^S(Fyrk|{WkmX<#nYz zo)F}_C8_oGV6P9lKdI0AmLIrWfnA3r3_XZ)0{l6o{E05YJMxG-bR+aG{duJV*k2=P zlLM3v5W|yUEw=*MH3E-Z0{iI#N;_>e4+7O-o#OZIOJB^AY<|=Fe$oKzo?V+|bj_0# z?3o$*{?C;tfO&}I%7eI95KT~H*_}mij@^1hY zNl{8xt7kOM0VL6}`66Nss%f+}4mV>Cpzofx%}`K(5ce2JkqrJ@^U*AK)c=Npc+8b=9HO~1)H83}sjo3_NnAgF=pdS*Cyj35a~+JD@8h`$Y$ej(n9}%d7@OZQPO)QH3;MV zv`82O8cQP}4joD2W=3V_sOP0N5E8q)v`%8#-JTL>Dr=)*f@6lGBqY+@3@ilhM{4aZ zs=SSa){7d-%eDlEaH$egp(nIk#UAiK(2k^l_T^!6tcM!zDPc|p=dhqyhnSjn? z9f@D3V)`O@vDw*v7$>#3DDhmY+&dSQRFHla{|(^N*dt3y-!Lp8k?a~9^z;uzi71yu z-+veYkgm&%y6sFZg_73vN-qvNOx|*+ynG`nW@_eYc0(=p-=?JF7CFoPw8f-WD9F2i zBW5NPaZ;q^27GD$A;2~7ob%tF8O&_d=j#&UN0)h7#T0eXBg8D#6J?Ze4f2`;)S= zUw_=I>-Hzc=RJ=&zzU%60Fk$;IY_M^+yfDwALwxYI54RMiQj+d}C{d%Z zJeR=4s(&vb%F!PAkQuz{xTnBI8tt){NzSKquW<<3HCE|#un^Dm;Acv|aEjMWb6ucC zI;kQpi60yCF<@2U8r=Vy2Z>QuLSw(SzO+BD%*p+KQfO>JsYnWy0D*O|{gd|Fxj%I* zRLH&tnu{-F_}=yaJ3>lUl;#qCdgy#(SWa_OQamH^;2uOleAJ~$np{C~8-%>HM??c! zo-}v!v*^5Ut|!u4$v#bNfN$|A%MuyD)HTXieIhllr zHR?x@(I{o0OPmicf*tYlseTAx4ki9iJ#{dGl^hC?vs)sC?wqz0l5D_?T1W=gkF!Gu zaUB0k82wL3RhbGyk_5Ub1#?i5$)$j)V##9);%UR>Q`kQ*X(EU)1YPem6cTcYejGgt zjc|Z)m9Zrrmk9Gxl48Nuo7rmrMsKmk*K-DkX|>XC6qb*v)7z2gSS}Vh}}4 z@hI&#ZB7aM%`PaoU0f)krrPC_i>8A_pJy%qiOA?k3z1$9b3)@L;BiBm=B!Z zR$WfE07-*&3MBEcQYi#2YL&Lwp^o-PS2(${tAPUfwyMU@x42FPrha**{15K4ki zPwYS?i*b>p04lgW`zjfAUEJ=b+01YQ=u&A}CJF1)GSiz*7B8r2pSbZ&xg*S3ZqpGG z%~bv3Y*Lb=uPmQGb60)^Cuw~nUfBTYs$|=oPojNY_qCuiHc?*)Jt3f}b-v zKzQ7T$&&m@kDAxw)TM=~yOfe7+BOYEaTKl&AVO*{Y69JjtZL11iW?HIl4Iy7Q%EeK zF7r6jz-j!V@38u`tn|t5yGgu)9?+8J{PO!{KgGYJ?A&q}sKGl=9XGL*g<5scZ`CQb z;Ff?+d8%$InVDG8vI+pv!UvqOo;#h`LG39k!%i0k9xFKceHCp)vj6OYT}BKGFz zWnNF8om8DL?{iXHF9hvAHh_o_xov+Tw^t0Rm-5Qb)a9TCBk(4*XP)j_qt9k5AQDb0 z3gV{>j+AkTG4_;=jnXh_`1xpctD}NvRh$>clyrQIhk~at8X)WP7q9oJ^)UD~FkK}X zQZG~S<;C`-FM2($tHRvVovENNLp!9M8i`dg*7)#WOx<-@)8YF*{P)H-HabSv=( z-CatTbSNP>y1PT9B_#yuZj}@PQIM9FQbAFEe7^NO|L(sX$Bz5nabM^4I`PQS>7&a2A%&a1ci$`Po(s|16e=Y-FK;1iql9XS_B0Ncl*_{@6yU0sidls_U0;=(?h z)p&O4&(#_|*ApLd9vfJr!r4KMqq;G#n#eJ2&;HCZV$b7eSME{X#3-KTLuuyb z5@BVkTq+C9lEi0Gd8@KYM(0FRM|_7x68g>b#1erW^pmImNK3PF8Wwr)0zpcj4lLxa z7t(N7|Eu!~y{(Tvirb{Lg(bnGbS@QtlNR^mDGy$`5SHOEhB*Fcd=_@B!aB}h8bb0= zYk)QgfXg?n!Q3(8sPZiHkf)}Gz4+_Y7 zX(+65DU(yTZE-tq%G;-y&$XHbd}Y#r#Q)Hyl&sH)aH8TXJ^kXm4Y~i1HZ79s2&jh^ zaSi{6ZQ=oNS0Dj3*p4Vj*(GiXii8k>7Xu`^q_+_ICaBn>(p(jTf`$Ww;|GLEiinhi zL`E!s{|{|Ctn@srOa?tPKy)#Hjn_BZ(_14*9rqdaUJ6}u(5u}mQ^3iHqsXY+Mp_HX zhV3*!d62sKgiNKFDPnR~#m40zf)%K*I_{Kt)md{|_>a&5D2V ze~>A?Mm)*&^Z$ZOu{nwIw-dVVA=A*2YJcsCKo7NSBDNias7=L!{z*d0n&@z(*dA9k zlo|&VAMryn_Fm)$Vbp>v)k3x5qyG6Z$&zu|#CF|r`ub54l&~~yIG4q!Xo5`mg|Kn< zDClXY?)%=JVdd$N=I1+8HU2MyFS-jMDwW!r)qk37zkp-TK*|wgOX*|u)HJ&K&|qKL zG^IQE-wldlb z1ZArQabT4KkF|t4lhnhyu}-^ViIzF*A$U6lTD z2SNP_C%gidssWF)APP#4U71QpDyAVWNDYu>)xs)o}^*aLl)wcP*7FF9i7C8^kosscggLTa+84ugCrr-w|#Gq^Wh{ znY&^2FKQm5=enb3doVd2GL3h=Z$H5?P|6sSbg*$7b!RAvLrBb*tX3Ix23Ad!Nkuxb zU^9ZF+e{r!aG-QWoS~==CsoMsvzRAONs#er%Z7I^ALA|=M5#{3VGH#lf<}hgGRq|r z^FrnoZBQ0Hak8=Rm7~+! zy}+U_7A<21kIL-POQHD>H?&CNJ_L20CgQKkfIznG)kM@Bp@T*$m=|Lqb05TpE(1+D zg-N(6xVsWa95OxJk6JX!guHd+^(>mOsGh4&J)xaZ93K-vzwh9J`5pFK@!4G_MF3)f z2b1Ze1}B#C2tiPF4fIdK5kVx6eJW`XI1QPGnaS~%HkH=A8g=`Wc^laFe+^^iD#10C z;wxNu5^>(PQM?>f6+7}(Ruz{>Qi&6d7mmwu^{9{#>dR!afL(U+oDWsFHR!QrW>VuB zA>+Rdj2bQX%VxAhDTy}9MGtuNAt#U+KUE_XvoQ*)wz_B#qyPEZ*mYFn$VbaevN5VE z2Yfb5r1KHL?TRA-?(u*U{fq{nJHaRMZ{OM@oQV8zqr zi#GNP9+l#3qbu!BxiCGMj9GwYCC(}JMOKdaEq>ac!DgAo-N}?nR9a6#su{xKG|1c% zQP%FG&r`-|vlDG_R+9~FKHpAY)Sf3RAi^L>xHpMH@6RsFf@p~hBlV1MyNu^C8T`+Q zmzD9aKWA|MAf6SiXXMOe)*xBnF=dY+c_s*O&8NR&(1X7tEV!Pk;7wvPgh3S`r>(N9mSjlTfyn7-5?{Wb^Gdk8sJBhN{3{mWtVg ziiC>vr7v!vDCtfPpPI~i*sfIhe8IP{!MBgrbI+HVo!8Hm#g3kCmEzf-+OYFR(sUtc z`b@0PrD!;fibj2lgiZ>ZK5cbt6eEp9+gFPEZN`2~pBI@>LVt5Kec%0R z)zFlD)ACP=?xO30n1_lWbCBzN}D84g?Mj}=CW zHt4^D7|t1Ato&uYGGO@W%fNwQP^o^Qs(J^%ooD!$L9a_t`n;3~OA!UloO<9%RPSot zo?rT}-M$@a{`9cB?Z*sT|I3rn55_ink_F2WVT=KZMyFiPctVRqLyUA=Wq)}VRY2t` zl=^DC<;P$PW~?u#uROY6F1)!;pJ2%AMHeGWfb&YoRcWuqZTBvBy45+cuDqP9UT8HwldFTduJtz;<3Vd5tmiYY z&hYxkx(7EXsJ?THyP|XVsVL}m+wDaa()5Fg|FTu8xuR+IV71CL>5QEJLesl^=Jh`#j`Z4ygYi=- z+*T}(W~``Jhp?4D|BgS&Ik(8(9d=I(Q-rqQ9W@i;wp6mUP$>zLMd3VpfCtg@`DNm) zk@bBPcBX{e%E+9J|IG{Z-6wS6^u!c>{l<%=Lm*}nuCOK^GJhB+u|-(d&@SrfKzdG+ z*XH!ucX98Wi(dHT_Tb#3`MXy)O1_Q3>_Wl8*E6e^-P^CS#7|V|f}_b#ChNP(qc*j7 z7mN&LnmujWm)_gmesj{7{7tP5{&>!k?Z#H3eVOf@rk908J67*RM_>8NzDC^h1N`5; z<-T6Npbt1v^%wAcgJ|mv?0yp)=6pMIRz$SpRrFnOMBGp770(rRpo2Kbr$c+gJ}q55 zgw*CmXFwP?NBE_9*H&&(@1651U%)JZ4^z{n$S~3o%RNG7E+b9+jP`x{`Gr9zREZKp|K9L3_aR z-ybxC(tX>~*aZVAh+ak}8L6)ZHPi9E97_fBUl^RJ&C;$;O@2LTHR{m$bwTfG6?X-E z=-)SzRj`#Ufy;fmM6AA+{c_p2#{KPUR`3cI>z1(GPEx|5gWOlr=!MU6gkLtX1^ZOa zqG*XAK0Cq7m%&?@5P8fU^A-@LqA&U(${)nhe;a5la2DmKDkUWU`~vGLnsBp7e<0U$ z;Ft97_3LX!LERLy>zSYMc6RocN1M;Sif}$b*T^-XWrJxMeD4)zK+B(2y9GzN5%)b3 zzu20<`1dkc0m!}G6HwrnV#0D5LNc3}XAjaU7hyD;eq2CGh!jXf;IN?V*0QwdApZMS z0fcf)qhqd&SALzcMTnZv&FM9GUy+4{RiJl7CV7~%VVL_VT<1v~@6-6LyWz6y5g{2R zi{1OGStUDvr59Pg5iJlYo)RoY{@ULz#q-D|5DE2}nXYmd^RIu{5~+V;(mWrpYWW zGdAl%PBKm=vsZ!;zG?A^w@PKx&< z2Ye*lXDBvBsb*c9Qc`5^eWADty`up9BQrUB>f`da8ti&6(732(;Y4H(tr`OrAW#O) zH?B2}IT+E@jKHhV*4UK9s*WD^5OsFsJo_p?3%S=&Rqmri|Er-k75#r2DmZ}me>7AD zKA+NzJ_~oTp-|^R!2M%`%}9T3sfnLx&d(pA!$JUretzqYZc9mWgC+yQ)fu5E>Dr%8cpD`f}k*jwLyNQ#=(q% zh9-s(+d;gnJ^>=Iwxo)FhT%yd6(=+18wFF0EX5%3G#P4WA_wN&vGj;YzXwxqDOvOZ zqy^@IxRX;N5gZN-Kjb-f8MXJksv>>p-EN0|SP^i;l>9sxR_MAhG&d>x1nD>kiMSp~ zC4$gaB%ulPm9(9~XX%7gOYIBK0T4t0@k+FH0h+G50X)#g|6N zt3^QcPurzxC_5dXLbj-m1x51he{%;RZp&%B%Tg^5Yim!JzY4FNQXDtKkViH^Ia`*6 z*)F~#06SB^jLPkuH%G^C6~-GRvv1Zg4@tIOmnVz1iZl=MuxT5r@(EcIk04Z@8YCbc zlI@0AO}?CKnyBo4NSEGna?)p=<}Bb+^r=D`JwO^eJrA%SH?dEPj|Uj)+Z0&Sm@B$0 z0J%~{O=pfG9ua+zHS8@@B#+P(2k#x?!++G&s9Z2*1dhIz?3mGmxdbl9}U$;;m&8K2Z8VzTepEW4}amuMTxIH-u@dTm-~++wuOsMKZ-hKM=7C; zu1gBkx*Hx`_~y&$OYyJaSnH)PV+fVIcEPr%Hg5*LkRo~!jEAF=cQsk}zqhNRg#lhE zZKgz&^gww`k!-KbrFiO!fZ7z+F;NO_RE_V|hPeCBOUj(Db~zHIU2Pemh(I%A4aH#f zG~to2{Scrb!3CsM=I5#u^advd?x=gnT@Y_bf@#7>NCjqo`0KGG@`9r}vbNdMtbZxt zTiZ9(Q+K1RR%Nm1K)5FlF@SgfI-wcE=e3rR7dnb5xw^$-DCHW&_NYmpP^hu`k*H%v z|7#dVH%M|jc=!B7=n2WbI@y2>zdj%nXCvjKv|>4W=km^-kFSg^G=PWrb>q# z&2BEv11I!nO=nnlEd2OIkGOU!hh;036-Km0TIfXLNUT(1{3VyHsX)h5F`~$dhl2Pn z#a!p{j29p*c+qd<>F_B3Yqq;c5uUoRK zFv2!YNxJ?8VhA!a*7^l~@7C%TI!ExdCCWNvf~d(Nkf^Q(ufqI*(dpHWBxN%;>&8zB z_u&(m|0A+DFd>O=>X$yDNo3pm6UZHVHOw z2cyk>NwQJjjf>=>H$GwSzHKFWzAsOkBa_1VPqQ17Ps+w$#5z;o^$TVSkJK#v7kMh_D_c+Yxi>noc1V2wRFI z&c3f9KenJTyfKETeneSVK$$qwqw+=*dfqynW^l~KRdk{Ivrvk!Ma+R-UMB2uywwXfOtrOl^T}fI+mC@kxINAO4vX*sjV= zrFE$NVO?YpxAvyer;XY3h(rC-Sx$)BGDy8rfy5qs7428gA(0+WRer;Cl4i`8P*Q(xHAf=7VapqemH7H3zZq-9e! zc1gX70LE#PwxQ%K)gmx5HBKDvjMx+8~QxkK)HBuP4H!TXrpO+vvpEe8z6oCAJOjX0R>(BdNCYOPE#Hms*xPRWII; zQuaK}ao;=j!wVG$s7RHC#1o~RY~VLR{lQ5l+x_Y4FU9$iPp{xomtK3fm&FM0=L zV#|o_pKwhXtzSUp|8G!2o+>T+z|P^jUHmoY!#^=X;d0S2);rS^opF5O7a8A)s}}BD zeY)QJrYtYD*R`);Jb8?s^Jv^|-ic$(iHFHz_e$~PS7u?V!5puQqoe%s?o_odir?)} z0Y3+f&ETVVzH|QS)@HUE-z8q;$!fX=#MiDwaa?Bsx!AvLG@X6)ALwkP!3UwI6TN8D z*T$tTLz+aNvNWPgZw|g9O-zq=$$k^t!b((~rg0JfCe6k)Z>V&!--E0Z7*a(bmFcrN zvJ6+843jmcKMIN`LE5=t@OK4^%Dt8otS?CTqLF)Fy`5;^QQ2t-U{Km%%2-B9Ch#9j z^73Nz3w;3YI!3b-Pmx$gnaTL2Mz3Uz7%Gw=;AH*zxiZ*8ZOexd1!Ec#cprSvuHKfo z9y8K=mZ8M9en~K0^_rgFA@XtsnOJ_#G9Ftj5RVrJXxF$gX`{;H;-9k($H>kbPCrk( zYlzg@x5Ii2H}gp4c)-NFv^7{dPIxsP$HDaLV>$m}JS*4NAF_l9sJ(#H76cO`#8>fH z5W|oS!ZkNdwbdk$Shd$yq*ULCW7!rG+QxClFrXqur1T#0fXP^Fwa>Q@)f@b8D#*oV z>vUr4VzFl;h&e{x_Z-jqJ9NLjH3&KxR($gl%TAC-NjaYBN)7-YdL%2Hc` zxuZ%y9h4tb-T*ADd=EV|SQP9ly(22sbM;hGD>eAG)N<#zLmq0DR0_VS)EamEH|6+f zzEbDys^)s7t|g1c-QJFt&W`SqgFb=N1+kMlW!18B%Hl?fc5bDCoRfiEno&QMwqljO zWtA?N6|DT@b|>Q zeWvmU?RLfGLd1wBN%`cX{sTn%4PnwZzeUPhUPJf0+>+E zeYcgDsHb+7Q+7ZNM^bqtEjc>+=S%b?dl*SXBG>At>q?EFLrmRH%^_Ucd8Zffn7tgY47nr=`04&Da4O>~aF9;Cd{s=W$3ma8KD>r@ zogSGnsg{ey>aNr&W;+6?89GV;@>GdrG0OJbjvHy^Sjh9Xj^`a4TT>m|WDdUToo2l$ zJ*!rTOOEctX4C8oyhp*NRRvTFJ!*-t)vC zJ=j{w8$fiL%YkFo*0@Z~we&lA>1U103PCh2z<8zDw?7Q28O0W0CmekKIYD9ff!Chb z>GU4!C7f$OzxYF>+XxZ2FPTFglimCU&+Auv!H?4{&v|m~(k#oY=Y>uJHBbHm9v?gL z^Z*=A$LS^4sSmUqA8pe?8+%9{Zw}2YOoEPYP{D^v@S?iT)oRQ~b(OU{aDs^jMoT~T zM0b=;*46A9vcPkCuBmeCZmHAzeR`#7CgA%o-RbiO(--de%PYr+x~I+xXbG7iLe@RI znA|ALD~)JUFt>mV-n)bHR~{ev+)ciC@YS;@Hm)ZkCvs?Wm`*&nj=+44*{S-4R7ZOD z+(X6*w=DcCM5P(70eY`!M@TT?J!; z1;uDN8iJ0~TyJK}tObi4Tg++S5`CwFMSO(){aQ!uQ?;WYn{%p>J(Fe)g5*I6*CMDt z;L5n3Lce;kyjh05aGuTlhArH9Z0UBHE|8xq09SgnKz*TRdi45kcnO#EJ8Oy}n~f*G ziZAcIxO%ei8|3>Vq}34mL4Yjlq`aJWGxPq#g#akYlNg{KM0u-6`Y>%s)i-_A8)(LJ z#AI@0EMU$rIC%NFN21wY3iYN7f?m_r%SAsl0r?^^h~jk(iOF?s035I2%IYjE?=RA1 zP9N$+zniO|zo=p3gkoZ5a+vw2XlMAS zsb`bI0-JU`FPfrlQy|^KB(}{`87&;GFiw&>o_~> zHr{}hIx$0}oRLgHz7CBS0E;mZB8)cL(-&tMk)CSkz2g9o@mr0y86k^r(fe0C3vD`o zK2D8a9SmFi42DSJ^1~`B^Qj)r!ML#r7d#^TB?z|-XZN#F?ux{a;_OL~CZVLknp=_l zU;`SC#y-npy&9o{4=J|3dGv5eu<|iC&w=>ee4_FrhNx(xqjSke4^5)Ze&-4^d==JK zAY3fmyUwiWdVdi1f>$Ubxe-tP2jP$#JV}XNp=-F0*$Ze_Q*4 zezcA=ww`!8`18Sl+;eWdJf4?ps`)lWuvLFJKu{`vcNUXhDPoknYp|J8AHT}B9&ME@ zURPV`nvWy55lKC$7B8(iG)U@E2ChrD~Y6u7pm!%-Xw;?R~< z5WwW<-Fz%zT-Euds@%04Q)i~pHux&Do)W+0_HvRDn7y$!+(9#F7qT~FY`h2OS=YEW zI7__i7Uqlc^==+JZLu+lPAyH-J620Nf)RHx(fdDBQiYUa75NoPA;COTAQmYZo{);3 zppZIYghofkvk>jZ*FSczlaGRYu`5vDgEXK2b`^TzAtf${Rj&N5BGHE^^(g{m+C&wa zOJx<`XE{m+4kcJ%NLq0Rk#sB!FXD<#;yRZubu!#ey#Td+{S&Bi`!=WobADXc_T zKqpSM`u6Xt(#euPRmP@Wp;D&u+MysjSL@{2iyisMuY_D3mwh1>0%gAP_W5I>Eu@V% z5>Eywg!0Y4_FPCrgzi@ zncdx^>enHJ%lt0%H^abL4FhjAel^RT(eHNqUh`%qT}jFCq=vwz=-D*7Ilaq5SNmKD z8g9<@H1ADJ{ZsvM8HLK*45hH_SGVuCy|Clln5CFS#9j^=J4u!>M?xKEU%BT0 z{q(XgPQOBQ-C8VMLo{+&bmp&?LEp!Yip6(VLKQpfak5J;veTsfeOTq_pXHrVp^eg8 z^+YJef0NMu(hp4^zhcX&|Ll9*EwlHFOPM-6xV%73v1;#0czl=~*{bnr(`7e`)o@85S)`5C5XwIBNVVFMTPkR$m4 zmY;Q2UhI{7y;o{gu2S+=Lh?525-E57&wl>tixb$BoK&iOG8%Xtklq@7Q}Jx~>v3+~ z+KkuVqZd036(PRz;sLYr_ui#B##SK;o0!eGGu=)pj*yX$mNJ7$C4z#Vd^EmgYc!ET zAr>i_SvmRajte%2ddDCWOoE3tw&kQJFEWo;hi~Y!YUK%N!N{bL`QWF3R;J<$Y}H*O;mq;H%UO&W{CX(n2ReAeO z!jvTb;Zi0AC;s+AS6*b=gwIrvCc-TUG%-goo8R(UCQURsE zn4{S@&HpZOBq$w@r$vbiib|mZ-MAHmrqKc@fR=u$ERNsMKn4C&)wdM`IL8yR!G5D- zvgyYqMter*lG5Nf$LhPp2y11{dQoggVHL5@Pkl#Y2`V`NnAsx^5nt7ng9>TRVxzgO z^v`;z>YytkH5DaVk-JL#K*(7KSs#;uuDWc%YgHOD8(|&QsZ9S?AX(ihM~tXBYVr)s z;TieO^n6$y0#m5MM;OvUGxE{sF(l*gh=LaR{6AyTvl@)xkgO!9t2M_7WaKATQBg73OHy~E1S`w#U&JkHvC(C@Y-m3rp7k9mD zuUV~D6R+=T1YxzAcuX3zXg>u+-w%SdBej_{tZK1~-}O_miWE^|o>J`X zTzR$~5Iw24yi+3j6_&j~h(9B_(V)<-J{D>7G`RKU6w^nCNt}2DrcEeTZ#xoAIhIY~ zOsUe(Iq_&o{mRsWP?qWCXoQ8!9rW7cQQ52DW14~fRiW&E%6UwaEE1&|;U%_GWmUXQ zc_&33g(nQ8wd=+U3tt!cJr`T{3RTkIzM4Ll;9NF1YQzug{q@1OsY|p&x{Oks%Lr7J zLT-6xxRmeukrK}afn#f7Xp6J4bCjrZJ2_@xCj2H88ZGs6@?Bh*%X_1RUM4I^C({eX z&YZ7*6%zQZ0+&FpJ(?$aPlkmb&X5N(*S9}2vt5wmt`Su%OgJcvK zSeO9&0Q`5J4N(y^kn3s@tcQI70N($+KK!flyvxJjwbECt&A|ROC!C1W?N3VTPwo?) zcJ{cn59Lnv%NWVeQ3@;@#lP9bYBycoaqwnHhaNYI%+EX^KQ8>lWi~d^()5(Obqhjf zKGaN1$V1tHcY%s3>Kl!NlJ0+AI}^h>y-h*kZH#i!3r65Ox<$ohm2FwS>EXrU2}}84 zH`K5@UjH|p{Wo(wG<=gV@O>N#`x^9xWG*pCrWTdI$ij}hrOac=kyu+~PZe{?^SaS6 zIYY()h=*M`UW}>M(OA1pQH}0G@H$xBeSZiE13)?5OMEGAGg`#t>p3tQpwN5Tl|87kh(qh)M;+lFLjV0_3njaA zH~DqjMl`Y1o_i0sQiyIbRh;n7h5V)2aL|Pg8rC*p zqWm_-e&!7fyi18p%c@h+-*kEBCZJASTm*K>A6ch+8@pS-LJ+4p+K~L+Gxg5~NmG4G zxv*!vnhX=sM9?S^+hj6nuRZlhXTbd-Kweg}&Au8mK|bu80oC4N&WfH?XM1&*bRO8h_=x<7yN! zhch+Wss1{~`5i=(_nH;MJAJ6TjKeY_qNBG$ zTIxO^iu6w0eZ5KJxhL1yWKn!XexO++hVx|gK(^6g{_ zG-VSZct_RVdy_>+s|!pM+{WVg4HCbPM)}1c7t`pUX9IjLI|lSO=8JPihRWgt|f}ytjHcvCYM*33XqC`#^k&7sTSOsdM1o#xH zc^r0Jdf2n0SE*dL9bWsoP%|i=pPtiwwT(!3)rH}Oewf@_+@iBFo>4npRuj`I*>ETb zg7R)_0+5Dq$^}M?(l0f&3zH7ZZ54NfWh(6uTi|-bI9kamUBzOOor!(H`wijc;-f`s zCV&WlQE$?pZlLgN!Qdf=6$N;vE(LrTRAcvJKMwmM0xzV646OzjKLYC#W6jz9knv>; z@#>LGAAI0N2*ow|UV{kI<2X@FDEBvK!HzYG^WZcr2GG}O9bs2LnAXZg}hEu#T%~DOm(jV-kTMQ1U zb!8t3S**TZK4m1~;_)IHL|nOv6sNnB`{SylA{aglNhMXTq~c8IUSAQ1k@&}nWj$P~ zVTjYqQ-!2@JaX(!leWxqG+oq?Q6~&DBD~uoN>xb?_|S%@!Iz%sWZI^Y_(7t5jFn0e zum$ifBiO!QNXq;C%$%=#+6u@44CUD?7pQNyjsntx78j)&N|Pi=F4@mUY;tjUOf7&h z|K8aLy^Rx%Pjz>iZs~`HZqSj%%gicBY#DHTf**^IHM2>xVv7s0?Ju4#KRn0%ZXm=W zf)c#U)jebwniD!`dCWnIQfkA!aj$|HW@uk2Zm3I)$00p7K9|0P+A8`g=NOl{ypgNv zRfpYHLriJC-Gw}fa0O$7vY+Y)8mk4G%x2G_8%&sRvHYf6OR^XeM^PKR3`~r?&vT&3 zkoR@Q7EJ+MxM;2UXsrygvwaZ@SwbclK+viC6Un5L#Re<|{LKGo@qxs$#dlNaNUOs{ zyH8MdO@lBW#DFPN92WZKtQAaKqdz}2-aM`NsOF?|&ww$o+>m`t?9wjk;JR~eOT@%T z-V0ISeJ4ZSqKHP3Ep9XM5du=Cj&LSun6cc>Ft&{I@@N_}p`!R_Tc*bWv2%`&EftP& zI_loZ>QrE%!={8(QT3NQuveO#HchCD1M(s)89iT_mO7bBz@o?js0(E8|HvpePalwC zO{)0A+*@-Y&^3v?qp$|{gcqnG*E;yYy{!r;PA%dM19S5~m^6Oj<=n?bY=2Y*Qoc6) z7^^>^Zs?0>dx|iUBTad*BcF}41J0A&v6sQoW9C3(p+cCDuU+YoEC7erBfezpb^ay&8(0&gf>}!EQ|8-uzwU%+tglO#CEl;i+Fo|SZDRW6g- z*y@99p+`9=xs7n4`aH-RPFSlDg|_c}>d=l;zF)2HU80d5p1oQ?6+uTLAGz;yO`!=6 zgEXapJdK)S4NhZj?>fEe049J%qI!l!Ho}q2D^Xg#!$HimdVhidt&n!6#foq19NGr( zJKou8(q|I! zao33h^CTCHNPrR9Dw@>MnY7y|byP-)2f9D2sSKL_t>+bU)!CD2dn@c5leha6;8@k@ zH^cKXL_R$Eohw8pnfZFg*Y0hM3m0>*8j&gp$!7O`t2$dxGRH;uzW_!B(SqpMFK4*4 z5mDY%fZy1k8jYB#33Z{tYy&DmTZveO$hBy4j(RTo_f@E?1sq3Dy);wcEWmmgq`<5M z;%laLjmXNsVJVi(F$RI9=>_t!9t5X@1KVz6mOUpp-rhI@x$O%SF_C})0kEtF-b zpqnKgVk;d``TdC^UB_5vYzw@6tn`z*arY0tM_~1eHxg=rYcp*yCYQjY{EQps;RSl- zAsZ_xA_)h{812H#6lrMwDSW&Fk3HSJe?xL+ra>SmFcKx~(>}r@*T3D5RHt zyLZiMp%UExC#3J4bU&h~|_X@W7ua%d17Ze7}T%U6O2Fg(HSOO&bRJi4T+Zd%YFN>$4 z51w1g(sPPFY3`fyMXYNDd?{lh->_?B3E$%EzuV&dw^i@%A{f3c*}p9qt}ZLLqY}QO z(Z8efZ^uAx*Cc$`qGU_7WcRNEF$B#{kYh{re9W$IpsxAzKyybxc=>F?H(|>ZN9%R@ zKVr=QHBU{|@EXdoAecOF_8m+Y2f54jS4Y30*%ASTE(A zjgkIUi0WSoYskXqwx^>Xj||<2=-YU7TX9DIja2OT=x-~h1;!oUvj0lT%Fe0w`kP+Uu-x+AeB*}7r{(FxvfAJ@5 z-{S6y^z$!r(~SILZ>l>Xg|^(x+YiA!mo0R6-~Ic4K6`jB{^BY|0Ogp$2na4Y01TEYM!|_mv{%k-72>c-b)#1VDpV7( zg!yjaLY0#lELw#!2|`tGb9k(}chrT-ClYCyO_A^qthz~3I(wtRmz%0NG@c7G-B~W$ zRZP!vv)xFUm1BjUEI8sA){Q2a)k~dpogHbm*y?5S(il1zHn@K74#O3H^`(pd(?VeA z&sXbxrZ=gLIA$j%1IF`vyP-i|27}Qw(s$u_k{6SsnMJFO$v576X^~|7)wI__2J_Jh z6E?k)?S~&5rZc^4DBm16G_ev^C9OX8e9`lxkic_(-{U!$4ey2Y(BOH`fQ9%&f}5^~ znlZ^|)CR}Qh80oB!T z!gO#jtC3i`PqM~pSZ^hg(LT6#%D;1XOjSl&w3E4;i7`^&W5qukgn{6@uKH|@b0n!!rf&<{&jFw(xmPz-(EX6683q;$pV_}=@B5Qu+r9|ayWYl(m6aEQqt{b~7#nkrJ*{EACdX@=X%z z`@5W|FMwJ<%Zg7OT!W7E#o{Cy>ZOlHM|A52kL7EE1DY`~(C0^)(3{jTehrtGbOJ+m zD!Y8PT`A8Ode|7XQ){$y9o`Yb2YocemF$HT!?9RV?`pJil@JP`no`;@!n>(cXt(I&1}+Mtm)U+PJ_q6;<} z-&!+Gv350RH=IwB&f1djV{>0dS&3~zgb#S$ZT?()_984wkx+KO{Zp<%34wtXZs1~4 zqI%#*oXz?sG^q1$AoiV29EM~(8=p0+5ZMpeqi5J8^pZTJP{)B|un5w*2!bg-{S>2m ztTXp8fiiPASA^gpEsCHg9#RwQm})bs7}FCJ1xr5fo-$wp_te<&X`2yP(qeF1@?&sC ze3I@-m^j&6J0dsn5$e;eSpDCzM3x(X!=M+K=z3PXQXt|JZ-U8!?GVToNQ&=sr&+_~ zG+lJ|H%$U#^1lb634^z z(O@d&EL;kXc(4r7G_}4hYMBLuSAGydE-}Xnjt8*YOff-y{@`&=T_9$g2y)H;jL%?j z_4IL52QjOc*7a9eEj&@&gOLli4VXh(iWS$~K~4Qybhv<&%V{Q@e-qC6CeS>vW(=q@|m^>8S@ zqN1MeXmM{;4?{MCWc5l#kTzQK5MNf@>?{VX=v+9Yi7Q)x1(zr}=ttI*WC&1z^Fp-rUk{fc7nM6nKrk zc27eOJKd;O zH*4OWDMtxOmyf0Kqz){^H8E}HX}&Uqsm-?@N_dK$kB+oWNXI>DF!$Ac9xT@Z~I>>7pzF|XHarCgW4VvBp$!)ENEnJ`Tzb0Yrl}>G2*;%ud@-3;hG}-1RFKoxVdUS+|TL z^;l8YZKTOl8;Qx%IB{hKnx=e3wz^K0+CvaYxoc!z$L|+H<8@DqZ`Z`y?C@OCN-oIX z_v1PnN{(b`AQC8gNs91i2f1Jkz&0!8NkZ7wFcd@z}jaD zqJO9aS`-o?x&M#1_Y7;Q>$Zk>DrsQo9Yg3v2nYx$5_*S#^dg}nf`q1E4I%X2iwL1e zR{{cpHBaTLh=0 zD5no8gqtj`4f^OW_LG;ezXbaZoFI%#@ck@2yCrI(CM@MF&6_B_JdU;)JnhD?KS`FJ zS@1Vi_v0XN81J+O0cL!9>TwJkfbq`W2uvpMwzq z&=N5w(VHkmELS*@qZA8zwBT#vAhQS{N12!zEaVbP(OVXG_N~*Y)ia(?ImgMc3j&fB zISBe`Hnk}Aa`(a0u(R=Rg3csDs~%XiV_jux(nNjJ zs6#FiysrIJxhK_WMwbAzGxc(c+Vj zgEa2RU6?iWsCEj4s$DW7LrZu7A>h*L)GrPAb2VMtX zdb?M|gIe=~a08H`OF=#)4GsWABnuKLXo4-63VM}@1se6S3ppDxUN1FxkV!;tom`YF z83s^?id4C&;5>D&4iNAwk_J;SkjOo?p$QTh&;7IFts|L_A@Ei%ifF&}K`kbjOh%ch zbF~tIn>n27o5|Xm$5tsQZb~8vQLxI^2c;ly<50Zge){sTrsaaeMTMn)4)!{QPH}~} z9h8^}*DMZ7!Py%!;UnX~7#32wiQ-;}ws*qKk& z+7pMe5uSsEnwF=R^m=!3{lPGA;)SlO7n=hCyM8=@2k0xd9E&~Q5}@-~5Z}{vl4s!@ zt}kS+8vo1%@5r=$WqyfB+>d2Khn#@74H9$0myR%@R^uL{uuD=o9&=~1cZ#!B)X2a} zHugI&XdDEURsH@PyI~3j1HgW5g#&9j90}nq)2C(=vA>*ozG`B5Ner%dhS-T*c)Y4K z2_#9%lT6MNmX72o+8+T>a*_?V^IdmQ z7GF^IIrdUH$0VeoZWP7UO%%~l+6-=Ne@Lg4QfrQ{HQpPQHeH2|GdQOx(X9zZmvT78 zu_)8;C{8lQTvytWhbx3&x=hmc`dS<-h?~m^rpKYjsT_BJz`Y3bVE?lg<3T3^VA*uD zlzKgts8lo$>|)c2%KEa#Mwj!?f~x$3hYejDQ(RhxY=GjIr+swK_@?JkDSy8xrQ(648zsF; z?jizVSWL+C%0EWryroR+dl1j%gjA4-jt~!gq1NGnG%E)v0U-UrF+Byk5wgyDk`reY zSZ{A+OC!^t#lbUa9dg=2CH%cl$+0qA|Xwmf(4(VjfBs@@R(zO(Ox`8KL;A6 z%g%r5s)Lp8P&vF6apM%zIV0u%b~UMkFz-RVI}5QPS1~?l%hM)iEkb4IIvcWPf@){u zQf_f|mcZhl*15MgNIk$QR*QKxvQV$wvmbm{(?aZq=Lw_A{^WEyM$duxxznv&*FtLmm!t zHP;~qY=Sm3$cJFXZ)oOl`sA#Sa(hjAAqqS|?f}0Vw!0ZCguKo(LPaj#k@#*0=O)8$ zw#q6nb!m3H^juN<+zoy}dWL_?5R5M7duNpsYa}e(+_vA~q_~x@^`wbDqh@(CD))xJ zKw-2!o~~AR?B003Esr5bM&ex}%Xl00fU}zz zI8Wm0!$MMXoI-w_QTv<{%Wwo&b1G-ZCRlbxXmFgV#g)Ydsu(pS{s;;^>E^be7j@h9 zQUTO(Be+6P`Q%=Dnk@m76#z>mU{VJy?h{;n2Ay*Q25ZmsUl9mONNqkgI}%S0_nhzek+Ei>(JgYNzpELq2Kw|o41o)?qC!TiJYJfDxLIM}V?$?5 zK^PL)jB@d1&z1FtmM?-Wf7Des*Ru(;cfpHxZhqVx1lylM_c;8;5R$-}t`OmEBw`_6 ztT!Cd7O}}^SNte{*2-4Oi~<`S`BA4SUJ|iY`>-e;EAPfDSU`LCPV0T=sm*~=&bEl} z{*0cCh(_zNqFzyLBoE`{eT`9R7yk~^fFis4M9*P*H3f)fIIObJc?Xm2H5BI-(BjM} z>yXE5d)CsM%1`1N9&h}De>|d-$S^VVb+lXM^hv>l5CaL%dd(w?dx(8i|jd?^tw4$Mq=6} zit8mOy^4V48qAp3Q^R%kh_X3H7NM^w;IEv(!hdvQ5fsP@(u=q`{5a{^sEikkm9vcWvLv5sM?ZgvYME`i`#Db& z3R2iBy7r3~EHJM5tDed~3J~0=+VSi^@+k~fi+f^392=f{1_dRVW15Fsc0rvjGqt=0wc$k$3Bf{y`1+`C#23kE>2HGS_I{pbAQ1Z>2w zk=$Or7lQMm+vx^A_V>+J3~ca*XR+v%@%#b^$mV;39ra?21(%m2tc;2d2eg-Q7-bTy zjryu>VVo2bGp{GT6838S+N-^Zmv1;my(uN4n;qy#xPl& zZ>U{vtR7cZP=Cl}ZSGBR>xQF+mHw4#VL< zqdvE$bw`epZ+B~wk%zoa-57yJ9GBL$1rdM)9Nri*=uFjN5zClL~i+ayJ^v>oagPnk-ceA+MDx?YbK=V2PWn$idXk5(1iugOjplk{kk^fDC_L;z!OkYa*#CvM{;fsd3pRc{ zAmG-!C2g?%+qKdx|KF7|Pj2tf?+NO7{Sf9^=V(wQF_)JQ#5{Z8Qg@6f(9Ca|J`FHEy54kcco{0`zO;y^8(XzTpvm^7lv|DVesNuX{JXOHahxy4QHw{kR(bV@pNt z$MuOT?%%{8%fxZ-r=JH5H8S=IOrbn-B6jj$^DMp6 zKaqd@QkLLGo&u-8zUQJ~)qZ2oOFw2?f7f~A1P`dW4}Q9-`e)hh&xz@j?vVpN49MuW zpC43J{IUdAr?nrpeaEo8L}V!z+2R)`zB@s%Y<)|d>-d5J9m%hVAsF;CLsz72Yh5Rn zOfrNuPp!;MESu#B-prJ?X!jV&m$SOAF=FMwE3FprxYljzjZL{u%*U14ske3v13&lg zlQLuWwHAdc0dv#q#~SRfDt<5w=re3_Lks2L4BopiefBz0d_Og*Q~(BUIWYeW=XNs! zd2!fmsM+&Q+{3=7?@x!(1Lublr9EdheFjoT+WcS4Y<1~b&~58HXSV|$<@X3(nVbC_ zG+uF=x#l5K1vfFol>8Yj{_>uA-AAeRP63IX$!67y5lc@OsfQ%e=73$sq&3>t9Myo-z(O;t#!d7msa8gWp`_Jzt-_fGCdxn zE5F!7zaL4pONuu&vB(B!FshzDEIdn>l_#`lCnkK)rcBJn@-UesOo zxMeS^v!@b8D|VolwU5f@4%05j2rYgxU^mD`U2zaI?n@;+Q06tboF_!meSGAg9~7dc z&8>l#Ey1Pm9>75yDy^bfR81Z)6G`~9z1V0k;gajf+Ienhh9jgT3Rz{zwJqgebS|C+KWQ|@0>6}!8iTB zjD@G3OY1^WK*IcFJA1VRPFo^ODsLE`bl6h(EIC1-oN8xL)t7u!W3Z;AmyK2W^0n>q z=}W@AeBwM;xbOgH?1G6j8RWsjw=(5{s2|{$Ye(KPb@Sx1Z}j+`G=KXbHRdt7?y&fP z)^pt>0(m(8{NX{3ZBF%Zvhdyt3y!v=-iyH0IlZKK^Vt^VM%1n2LzQd3}?NuDuwU?)e1vTWa;!yvM5*v%`IWGe~+Ds~P(-9;_*(=~MB!WPE{*5*lLL9vW+n#%U$v%6+^*9)*)_y)l&vz{3K3^R3 zF1;|yqc8-osD3-cd>J@(z)bogsogHmPi%yxWHKt527a{YUsX#-6?JfL3y-x{uTjYd zCr9pRIUv$Ln6uGCnyoFgYwQ0uy?+-Vb+b8(#V&GQEJd0__aqg zb#0-EvW>3tchbqyK<|zcXe~RX-11_%69v%mUE-b{7I=(bkd_S@xf8^*$BE&>|hdx zuI7?XufZlc)eTmV0fe;!o~{{s;`I-j@_C*jvOttchgzn2$|w9RG0I;JJn|Rdw{h70 z?||QooPOXx06)W%SKY?`Je96;nNQNn0C5Iur^^Afr08PNLf!wdW{g<=_)yMnX)4 z@E>OUXV1r+;g66u9hyk@;nGDHdM21KC*0D1eF35v2%p275P@hS*V>KY0$o2q#<9?8$|~^zFKx9&*yzTU#Tt^5_E3< zb!0VXC@wxqbrlA~-Rx?(!1sGD^{U8)n}$mVp5ob+0QrSJn4;LyNW2U{G#O?oFa?rh z7r^NniVz7|GcE$KT%@?-qW9Pdm+)@bPw&3rfbN!cXXQwA^ft@%&$G;oWqxS4iIzX{ zw1BJ3eceRF0$YVDg~Ue1yXjuoL?lBwjZ#_Eh-mc_37AQ=Ub{M($GZBy$E903au_a2 zg^ai-_yj#rX|uwb?y!kAb-yYmHTd2KX9aZ3r2AY~#krD$N;p5C8+ z9o*yWIrwF{_?uDtZbEl<&HbGB#Ski_H9-k_KGElFqCBIP8%vz!rYUP@M8?8&jLNJT z6ot=? zhIL=ROgS9Pf*da~84V`1oMR8?DDUbq=4^TPL-D*{#@Ou#MiI9a@}EhA1ofG zwkY?8RzDo2VqspCHIQ(~qG6)BYFk(D9{oF^&7?gTd`4{ zsz+;p#R=V;9U5mHUPo5Y|E){~rn*N$ckj(*WYP^s6 z)t`rT_WoQp&0I^myCG3qmB_WJ+&`{=C$wS^nrhk3y>SD`AA!RfpzKPU#XHy^qmChL zk^-(GmzcEQoEA6TE2f-!R;;gU8Fqy9ppcqm-YmfO|AY1xDv*t&b3~8hG)u?FMBMK{ z)9$2bB(GZ1w%k=zjBN=S^)c9f<>C7GX;~}MtvmR;n&%rLE$_dI#jXxwg&YPmjdoPbk& z>w(6;FE^Epf9p}pK^<>zxj*fu{^i)iP7SN?`9j$V4?9KL+d|UaJFJo$B+`MQbVlXg ze)*w@67~Fv7V~%QIodtmK=JZpf0>AoL4jAbk7w$a!YH|EYER7?Wlr-DaXXwc5x&jbxurseIC53fa+Nr0dvg1G>Alkqe2Ey|+FKW5PBQxy+%h z`8{!0QX+!k13T@=^THRuJg-uq@8%-Nma^d_U4K%-$3-Ri3kC{fiAtP_O-K$`T=I#T z2h-74pSEaN5T;6oXPjTq0;+w;Gm0SsJw9OE}u?qv1t#mM1dE82)ua{SyK z{av|(VmZqz*-G7VryW#Y6x7E=&fR8973R86OXU=7V2F}-*Pc%AtaL@*M*BYPuMtx4 zeagFC`^2#0NtGii0-4S(g-FQr$-2^nbAU2D->pP3L5kG1g{OOo2&(9fVsRw^M5Ur| zApWQ(ZwO9x)%GOmP@8vW0}3)7FKgY?ZYu7xa$HuYQ~0qn0z5msMUo>U1KHEN5Hn7Gl`;M57x>_?z_Xv2E6R{P2xH{8dKw{z8>JmD_{Lq3WE_d~ zFtkoM7Lzs*=h0Ro%q>(P#RPR=wGRjt;1{U-rk;9flGaZapeRk9=IK?6iuJedbqG;~ z&lS{ID$>S%&D0cYEz`$eHo5I6PCDH`3Z8f*?v<5piOBK=pg8j|v>}zk^-?hAD z$DFatOR9v76}rAgLn{`a(gPMI#X`pzv2Ksd!MCjp%YqGOn^teyXMK;!IsPYL6&fhC zy{gLnM&w<9w?SawRFy?xKJQVn;Grz-9@V{@SfIH*uv0tbx^{Mb#?kf5zW4QN;CBlY z0ulGathyJTrCfgaJl15aQ0R2heT^b#XR(yCw#`Pq`UdW$yjN24jQHa| zwO6&6Y&hygXnsS|yT*%Im!ucD;@%X$3Te_tm3~}LV4gVo;{;RUW&6?hZEtcJ*DEe* zh1|UOzSS=^w^PJ5Fy!{VlXpz-26AN*#^d*{th_6><=$`lzK7zw$vV+@{O!Q;jgXhQ zj3h*N*2eH@?*iAnUlFPGk57)h+K`Xn-7oLM;tJz#Olz|VZA;=Du-%vr4DCA}*0Y<= z3JxBr2>VWa_rulk@#C| z>lGi@A9u4dNvn@Pvb{9QPNjd|{kR2$Kf{JU`*`ZZ(eNGH@Gr;1zuF?+T?~JJD*Sr| zo8%q-^IrI`$Kk(UeM*cCf0q^hhl>K*PXVh^Ao>)je)!(?k0)&?9G57FYznfHf_m@? zR(uL*rEtEcaD8Gs9#XI_Dd@dq%)SU-{fJ>cy9j>oh(3ueo}dV!>k7cH1JtkrPgla+f0Ivm+IrY@si0Dcp}#eiC`W zEJ8MX`M_QzVPBM*+@^~DvKm|K!7fTOXhZ$m3(ZSW+SyS$mpH|qZ^>3h9eEO^_xdv} zI4W#4inuS@;CZBe@v?z_w6Wcev}!cBQ?%KoX!Gm{)1Z&$tt_m7djY14+dC6Y=`wUF^hjXtT%a%wExp#T^h++ zesozo>fMWx8}(1v4(lj!ksGoTHRkz>UZWk2Q}v`8kxa|Zrl-xWH$qHCu0C{5@p7Hn z(fQKMHdvo>elgT_ZT==@x$AC+oCS|`?B{ncAKq+zeV+p8b4*P@MFew01d z5u6LY`}1KyXvZb}o`-K9bDO+38@sP>2TMJF@bM|AK=495LUwpA95eKE?7&O;V=hsX zPKXlTI|Y$qNh0n-t^zMw`pqL|NAe!0zAvDO^VpW8RHyO%aFXD8+Y>Z|fQJ%aXXSFM z^+F9c8{7m>P>L!qR(-Eu$x{Vs+iIaq6;=xzUp-qW4AYyjp*s@~Z_VpwK+)$}OcKhOH~I|U2dJSj%l>dZC-Oz@nvIXSZs%pxL(_teQ@t0Y4bpx9!W zrPUp)X29XJndhN%7f%61F5hv^lCK|Pa(MJR;Mpv^4(F4A2GjX{$F0Xhd!IeqM>ZU*!JRod&Hnnz3z~v`FWb*O)dx$1XGARItsnM{i^~ScOH96Y6L{NO3u$Sk;b5480<<+?rewga$LfZ(T z$DHTo;<)Fx2ZUbZ;sLSB%|0s?-j5G659c}dbuW+E*MEbx;g*vhCYmoqcpDFbORu)_Q)YFzk`qMa+d? zv%?F?pGXZYnU?d1{KuIXof#&{aAq0P9dIbfOid|ldAjU<)3^L7>-LvIX7kUOowFGU z2RwcZ@tz_uB0BbQtsuy%$~g23#P~lTs9nMT3xZmCoPO%p(3!2cj8%;_nejUT+Ep z1byUCkQ=^yTjT+0M2nr8dJSXzY2ECE%0Vm}gSr?^GqZnV+NzHDEb9zFb|{G4s+vi{8obNmu#_R^CUU18!cRq7B7CU zp`+HEFJHG$FQ_K0%6T2T?-o~+cMtFZ1suz=ZeU!zwvH3zA|WHCjUeHqUhUKCB5=)R zp266DkrjBAa&FCW^}IQ>SG<_kQX<9F*ifLrUgyw9Sh?W}{x8m%&tIG~vhNj!yoms( z^}jf0d#SOJZFbdG$?A?l)qj!BzGc++I^P`7idXY_rBR}@FR^rfeGQh{k&)|wO#)-` zP_UAH|0bOYYZ?jD#)UUtegqqoRDf(L!XK{I=OW@(q|b;P-F9o&8rYQ9^2cRZ_sNPS zx~?KkzCa;F@`VFA~cTLc;weJc^ zOu(FtHR9{oN>lK!4n1jAC4rMnlO=slbW6*5xw8sI+$D()QQ;cDG)mqQA(elW2RHII zQ^^{=DMx?x`-vv2-XlG04_Fb*SX;N#olUIp5OXDzyH*@X3MSRsfK!I->y`G5w{%13 zYsawyw=dZgREu~OWVsUJO)TNrUTbTxTYy8E;gI>v$wz1~aacoM5qNa+dIXzWa#_W= z{s?Dly`sfKw_AZ?ymw$;H^%R2vf!cv^s#m>Lh|QlO%Q#u0mlkfYliLs5~a&r@T*|~ z!9cJ*{}7tYJ`-Dmdb_qvTmFgITnzfZ5SuuU&zJv$*Z}<@w+21EM0|a2(pd)#`cbIg zRy;iMPppVFe6hnOgs>=iR`8Ifo$?^{U=e7y8kJnLfaudSjlA*nE;Q)1m_g_DCPjkznFM-_2APV`_8z zR;E^nLGpn@DIP*jVYu(^(#d;qL*psWIm3l)#UG^W9I>5>p}WrB(*Supmq6}D4u6z9 zJl$c3`CR(xk(6%qD7HA0`65n9N(bqtYLEN%8g)JV zyb*WBmgAM9cC{vPx)Tfb1;!N`*&M1>aj9e9j|>RH>tz>!qgn`BHi`nyjM`Wd_f|2V zhfEq2Ek2H^I8|lF+A260vYL-fc(nL*rS8-CEa)N+OtTQ9;_YKs6Y1crflA_tb5T!E zBA%qwp9xbtvpOUwMB@njCNNHLtuT=skvJ;bMH|G(FyEd_E7Hq1fbr&-={TK#;F9Pb?=br9SjU8xJ}YV&>)6g?y?(>-cKq=g zsO3GviQ5J)K2A#96lc@`QGV(#qKw`R^bHm`b)54ZK)y={Tr~}RQVb)iILE1Ihhxrv z5oI<-U+fJD%#q~wXdIH#XYyPnQ=j{XsdFUe3z`hsL{`V9zm5ITW$H#C$RJEJr96-U zan1sPA2dvza}fO`Lf{VC&ELqNgVf#aUOsG^lqaaQb~cOK97Hy|3pp33bLQ2c~(~QXSIA;EV(>ksHy^I<_TvGmI%5rWG{a{SZ;*pkCfGZL#0dF zwzVZRi=2QJtf|je4zF6uqpkSC2$&Nczqv!@ID@x2LHJ%|Y%d(a=X-X|NBT)g;V6RM z66Doip8#$vjF&Fb-_A(tQkyB!>y%QEn96)DR7{FbTpkvAbVyXOhNF#&SaDLqVnbTK zLU}eFuTN+>F_7Jx@G5n#J{H&si_Q^73&$CvG)g?3lu#s%8$>AVM6n?Nappy-;vkdB z`m-$Xr3I1DV9X>|vsKa(6qie}=gQaNOk*HIn8;-YW_w2Th1MDRBD;kRs(~w%=#%`I z1l_K49i{4i%#-{USd2rX_6QisNzR7P)H!ba3Mr1S zq~blZ;-FB5Rxo@`GDvGOfz1YK7j!V@f!{I$$t_fRtb_XxVGF=)WFqta&EV|CqVVr( zk-}9`3Rx@WN_8~FrlsuH;a=YoloJQosg%lN2YHCDYa+_axpWr81sUuyd!tloZ zae{8Qt}c#TbuZJEUb=cc|7w_F-Kjva{@6-%h+3$kwANGmGH@}EZoS3CMdzTSPI;nI zT1w44M1c+&dssuOGj0na+5)vq2ob#-L5$q{<{}f9sv9k|d+lV>Z&di z>cM>J4?CLE^6?h)(Ws|yoOF|AE6+Udh9GE+$;s?$6}jC;4{pY^r^7|t@rT>bMq%cz_CmNk<7`MiWxGp)fu^;XEVa7;^tv+Z-abHuI_&+O@>pe+7&4IN7wK z=8w$B6J4!=lWjzBxuyWF1WRPh-BvBV12Z(B&4Ib=Py*K7Z>R_{*BujV)iusb^7}l6 zX?`>SD&u?HG&N>xNhbIyo}}iK`bd};GmRm*;64Bs)-7wbnSsRrTIav!D*2DO{wp;H zsO-6dcONjT`Y*wx6w7y+z5_G_%y^R`=`)xthzvZx;FItmo72b^N}w82^W`N)jtBt; z$p~4OKI0Q413HSR7YlIXSX2(85_RT#869LkSz|FU{!Q~m@hHZ^u3?xy6+ zOJ_u}|Fu%b|FbJH{;`d)|7}-@#gcpJ?A4d$6T;CrP~4glD?;&*;SBs9l0~Yz`Vb91 zrsB_HK+|9v9HUSy*>EIZ_gLO9AqQ!Td=pJBn8-2tCzTd5T#2cZ4J;^oK2&Z)szE*Y zz>$UpNhqz=841TO@LzLCF_`LmiM-k9nG*ee6vI|W`ZxS?;y(kl`hO1apW7C406!p4 zS~kdn>(O?)bEHOc@iuh>u?|;F3sk+_={m>ijLQy%9i7(6eQQ#QfPnw&`O*J*e#8I% zd@=cjfnpQyJBaC65)MpgWJ}tupMZ`ef+!64FY*rr%~E9VK#4x2CNs9~KZDSR8v)R! z*YYMe> zXps*$<9a+203&j+3{{JiL^Fw@-~z?vTYQp6=Y{|F_AdQr@Kt{wJcQ_zR4NF^U>(iX zSTy#pL*>owtKwnh)<}h5rj#LoJD8^t$5Y$5-}~3DBv0n8E=U$V!4Z4-uuc=j7z+|>>Z=q%QR{|)^6ALDW%dvgB{J%7bzEHR!P zdIbI*dIT6iU>;v0djHW3R{{VrYw99Tcjqp%z!NwP-q2v)6SVpC&1_feNXO2H^Ex&{kbAa=g9&r;38+N9hH0694*t55!Y z7m}@2FE~``rD(GEL36FSb&q2!x`*A03aF(O=JY0`&g7A)t@aRM(?%Z8@wZK?jn0xy z!5kS5~56kEsJ3H`EPfZrHH_13p-|>F+;M4KF zKTBLsgI-^Bh5c<=oB#LK`&Z!R<##?Gn@b*|i;ABX+vWBdPJ&|q^5$T6r4}z#fQ%b{ zl3s97ATgJcSH;4Vldg(bhR}Oq<*rCI5@6P3d*s~pjf6DEY_()($ubhqI0*)wK9YHs z-C5{ZM+XSh8pZVM7Kv1Tbm!aq%tmtyQmIdYV$bo_rEBvCsoahgU*W`CmZ%r42_s3E z1*z7hdre{-6^Ealq6!Cl16YDzL8D+c>?hHrTNz^8EMYT4{4(+Cd2<)v451;)2c&Jv zDPHyr2R>XwwBh;qQyL9`B6r+iqrB-Q9KzJ9duvvobHETGJV}h|AHStgT2`PtNgheu zFuRxR-SzwY?GG=D2g3L6zWnds_UylZ?-;%8P4_P-8U~n`n{%`7v!Uoe=NdpJDco2i zo{fe0ffN8_ENe|#M4$_iN~6=}Q<7i_>#S~bH!KKNK;YCBiu9+)GvJ_L+%4V{25Cp_ zZEG7R7U}#tGGgLF3;jGe-Y#9v1)Q9DJrsf^D*_*gsb2S!u2}L*8N#Gx&51fb-~=XI zp8z^Z3>^osDHSmuI3lF_fDoFlRKf(M#(WUKG7RVfd`3y~>)d2&5MQMfnvVhQ$ir9m zehkyb(So=R$ks+PR}dBlx?yaK7FGg+Pg5SV-<55vRB$o|j>Rq>L?AN{hzaHzv7TiS zZQJ)u)r?rN6HNQz$LHIqCuA*?2*O}Co&s@MIq2q_fU}kT334qkLh-2$@K|lUg@ECh ztH$TSP0lQb9~U}Z<2huz2WW8R7$}TKTFW>Vj*}IkCU6$G+5-q`{=PTA1sQGvZ7wX5 z*$e@I>a04mpfEbYky}eykjR04K@h^A2~=?-a0_uiQay!W%#|tgOccXS*D?aZ$p|_| zT}&Ht+TPY}wJ_7ct!<*X2>wd4;4!^kt@23b6A<51b*fJQ?lE!Z39JGa)F;~eTZ<}03V z(}O`L4@mCEW?rrR&;~%M2DYkO&eKp8^(`e}+|tS=5QaESKYo&PV*d>eE^AT%U&h06 zjx=$)l=+vwH9QS?cL>)H5$WJdBdEBjVv9k5LAc6!-A~X9@Nt#CMDEM86u1CrF6At@ z=KvCAM{MjvUwt=epmdMk-a5QZz~`Ieg`1wJ3iDmbvr_h8*;orL$^k;y!9M7n>d;S5 zbM42>0ls@vo065YGtu_2o=Q03Z+j}7j+j*v#`!cqERT5Go zU@({MI_R~8@|IC<9amU>7&*KVwz9^psZ6Dwf@^y0&L6!=AwrKTLRlcVM4JHzH&(}U z{I2`mcPV@XQeSdHyY2M*HbLZj?z)>2v(SJOX)Fh;17t)Y#;{?ij z_rQ1#Cwr0+Y&9S#VV63ZjPpU+aLAqC2d*l-gX6qQPH&V&FnGL|e*8(W%&7#u;G=#V zLxT>D@24&$iDUSE&U>TXz5zS@NPk;AjDSspL-3e&Gh}YMBS>*m?|^5}DfmQIa27eQ zCi;WPaG%S@nx7$e6A7uTF-kAt$)&~zfDy68N9{u0BAmhTM~Nh!3`018&S4%E@V5)o z-ppI&+mL@_F+%xKP55liP{p3G@?j?Q27S4DAU_^`4}&*_Qm_&t~m1ID7*7uS49EA8({Br}M(bC0IrM2d@x%?xZ_qEIozB+B^ zvqk-_)lW!48(75Fi9QU#JL-I^U9zUu{0*SPO}w{V)SY3W?B(3$`D44d=taOAcDvqx z&U%mjb1<;|-wy^D>I7pbQCy!kAm3hNmMLqM^s6Lq)v`eKfJll$gsesJA)hxLGY)bl zg@(DYvwL%Rf!CI0Zi>g6Xj=1z)4$jO?CT2hVW70b?$$#U0gAurQ3So{|Z zQAbu4NyMU1L-4R8G5NConLbktANJ~TStJ+lueoneULS<`q03B~yLe5X0@pu0#t@;$I|Lh9W*ptgIqQ_Blt z#UJuyQx>Cl_6)o8dh*JxM|XNYzs;2Mc!a!rcI-0f)C(!zg}R{8BdPj(KC!nY)QOP| zTT&kgK)m0`ii+u`k)cl#Xqy)}wQ$d13+qGPC-aQ|uZkgUfQriw-Avqn5esq!p?_?F z$p@8rlAz)?rn9u{@=da^ajhc}5M5bF#$Ajxz{1GN?FeozlzI(O{^**SkP2dx52nMM z8G@Sj%1dQ>&zKw2j`#%8j=j=>9*?cgyqN=1?~v>*+RvIwr*LW#In~HK1(laReE5bb zqd6fb^2O8?-j+w>y8*cxMxLc&b4z<7@k~3O4gwZ(Eak+`mP}o#+32ZP;1Qv+a9P`_ z!%#VOin(Hga-N)GlX=7vCR6v8r6{jDv9YF>nX_JZ<>H=5$Q89!X`IY->i2!x;?lG% z{Q+xjDt|+dpOw8S3Da2?O2Qey7Cbb!Q@V-*7vK8F`%crhY)fg(-+8O3^Q7hD0MBfbr!7bfNRZjm;IR{%KA##c@MXav zS^Divvoj!5K4mK(u`-#}023Qe(Q6L_Kk@#3VsEVTIXV3rQ7N|Be&lG41+-VES8E64 zz4Nv3lo@znVP5Skj|MOsSaVG)D+I0;yO=C@oVDOU&kc>2jiUk^ zKXTIK#H0F9S$HXT;)w37iU|PE2^mHENg!CiOG9K^Ab10gORnxumHJXy?Nd_>hs^a8+1 zVnI+3^jKT_*v_fceX<`3)4MKadpRyx2pN!=-0ekpBJRuTZl&&Pd-=ey>o5{v`QgwN z{DOp3m9r5%z6#U_(7bs2249jKkA0qYTiT(P=Cif2@xXECg6d3P{``drI+&2)NcH8` zDx(X(76i0MbF+>m;Mr1+ROes)60KMuW~Pwie0d+h(a@jQo}X=Ky^uc=H<&8$t#!|{ zDqjx8LMiJQgB-W>NQZn7@l$k?e!-gFRw@6+|Q+u8iYbl(-@t6v9hN2A^u4=Di| zAA=PSEe#{|Aej5|(7hz5BOkb}YL|46MGT#LbFA`JOBvfjGRb)+Jny>LbI$>wXLu1p zh3&FT_AQNm;CqweTT^RnC*As`09MAuK8%gz49BN5Mi99JeGHG;pAF-S{^jOkaSe() zT}T$%BaMlERls7(mqkNoXsJA-({+ZJ@}(EPIx)1z;F*Oc*G>@kwE7TG5W)Z8y_Edi zI8DGf{H)PHkemQS2#2h;Pa&5MhK_@86=}LBKB_+^)n^Ve2Oy^<9fRaY_G#F50J)?p zU$^nfJhCGpZZp{aE?uxsq^Pz?UU`*dDWQ!?u|dZv*hffD<-d_?OG^a%Mck6T5-5<_ zrA!6j07P$(0NKwHvI5)34m_zaxIp?71+|HrWsH54%}GDEl;4BXYa z$IUN>#?%GNQ%mB&1YC~rOBA4*5O}DY6I9C0LFa#Hnp#riPrfLBL;GH-#lb6{^NOl& z50CIYvu@1|4HazHIrjqAfr?XL**d!KRv6w3j@);i#YY8PC@f!YBG?@yKoes5yf7e~ zHM91;j=6aSGE1{%+qo~srQpu=sjyA^l5>$jmU0Qu*m82bGb<646-!6UGC`IR))g0s zFa=Mb*1|aC0>^1P+V7d9dYgRm&@$D-_Zux}kioT-4QJ z4|f_}WeCT@%tsI5QAf=IkvjoiXJ@S+p0_;x%JUG`{RE&#yCJhuKJm-)JKMV)<;Yf0 zfDT~zXv(ZnOSpWD^C+K@l2pBAV%n-O(dmyTOnxa%%HbOCbdaIG0I!U8kBkE9Uwhfn0Pf7Vk|>ZDu)0bGXq1p zu!|E}hob-T&QmaiQXsMA^<0~>qek1-SP*L=a)Y#(xS1FlaBzP1n>|%#n;S)>SGO;# zeCwIADchK?5lSK&$^2Tp75~C=pyzS-kay%#yfP76zPl{w{KnVhB{KWWo+mv$1PL}M z>kBx&N%z!PmES;}h0sW)3V6qoKmH5XN+cZ2g73*)J}D+w213U|g?eJ|Fb?_(7kSV} zjX}ROG#43l_I%81k>iFc>Y=)yDSQAY%Xj}5tf{~>Tfghs&i?I&z+jHxy58?nk=dTM z)7J=J0`J79`l_7^Vg4Tgk3ew0aiRQ}9qno_PS)gr8h@B$Uj-4MVm40s%FhHRW4VdB zpiZ5VOt##;UAw}{BmJ_P%nTE%wa$+wY>lM$KR5y zWMz!xw@LyIhsyNJom@JRqzfCgAK#6ux| zPzEfpdp<17>g`;b(swG!*|Ag9fn_O%W$PID}9%gWmyly7pcL@jYb{01Ge* z*&~8p(P24=6oZi#Yta^O5f^h&7k7~td(jv6wQgsDg@%C`lShPV2tU$sgh)6LomUX( z(<&ZzC*%`?vbP!C@rDWUVp7tE5g{H^a~i3!8aenHu`wI9F%Y-WK@R^h0KM@W!J!a> z*dEEDcWao5vJ;1YI3;k%i2@N`q|k%<*MT^Z9UjGpQ|5;Yp@9&AVQnV{=7ApSVKDgN zFY;j!^f64kghPKJVz8(Xx1x!}SReoZA`Su}PgWr~m?0Zt6fbs+3?d>6SR&YwA}i7& zrw9UzpfalfNQI{qsM=BS2(ALk9nZK%BWi4fH?}l$aEx7TbwI z-nl~_WN3lN10>WCCWJyN#6oMM77bPa;7LH^c|&TVLnXmOJ~SRcBt$0?7)FFd#KwWW z8KFJ#n^Pn*<20Njb46bSMw7ra?({JLP)27oL}~wOeAkps>hPixnx;QNmf<9vQ$fXG97fRzb?g&kOSSpp#jh?QEZ)mV>O5RnzB z1prc&RjqgV>|W+I+3wvv;`E<1LUQU z9gC**cZyHKQi9cAS%!oH#AN{BWje8EtsrLI;XOuiX5FD?WMHWOWhOrhXYxrNbrwlY zJ9iQkQ}S9Eeby0wrc4tiXop*9rh{lEA}@^g0gm>xqI-EKW<{3fM}o8`aax?7HV~ku z6QUN99cgOvV+RpAiX6+VY)gNq$ZMqGYjyK&!}e?facl+PZ_V~>0T6BNFm2T~xYu?! zv!HF<_G`g5ypo%6=7w%;_aE){Zt?#Hc42alb8&A~a18kd1^aev$+m3C8*l?xa0hoH z+PiRycLNU>aTB+i;rdyl`@b*|waWEzA-4!$PynlYmTV+Q-{=L@+Hw*Lb23+Q3;+fN z5OkRGr&V;0d8l+y$8_}Kbe*9S!%_hLAXFz(7FSmfSyz)>_bXmE0-XWE|KN1%Qg&yT zc57#g>DmZy7k4eivnOJAcxMlK*F$`F!hQ#M1|WF#KzPh`csi_j2f%pn;CPTn5Rx~r z0Nlk4;fZ3wps44Lpl1-tLV5*IO`7+K2@!z>m>Kj*drxtDX>1U{H$HCw#&h zdks<@7x=#K3;%@ftV25|rxks8y$uI-A5vOycRfg8H< zh>-{!Y+H$jaft^#(<}dxH46=pIRPXrv@RE*${Y=8*r6SfdeJtK(XOZvN8Qn&nGo6G z4zs`p4OO3pfs0{O5W6VQ`oSN-h^`1Rj5Ph#4FMt|QUD}kA~&Has^GvM!XnM6A&HVB zf=~dHz$tO{T;M1OBq@yzQjVF|hWM9&5rd9#+lfi2(MWCBO5G5DMtVePkB@sCjk^%| zIviYm5dR3)n4J(1DG;duDJx3>3k@C~LnwwKJP(Zuc#20uG66TkC-yWvjAD=lfRG~` zjeiZ;bz&>*MHxG(lEOkPF1arqqAbkfEYPxbT39X70sy_uEgdnH1mn^1XaMhVnfTEz zE}fL}5;^?ql*0eLrKMC5&<&IVVU-HA1-z)6gPYmxT@Yxgmcj!vn&KyZ`lje)J6#!$niS5MRvJ15F*=?}o6_P?x7j*PxRvew zvL3aK_0;Hf7D11khL;(fln2kjtI!J_~J!e(lNv=gyL<$5HGmjt;IDr6s za4IW$MrAopTh8TxI41xQqjm;SuY^fQdZovdOvrH#|B@B>RS2oHUzzSoHmXUP;iXH; zXbRzNYS0Mzz^=R0OF1;9>*BLHicC9dx#3+F$Zktvs&xk;DcGb<`%LM?T&J8cEAn#) zx5Mcbx-#KKKF0{)s8VvK-bO2$@arYJDOA)L!z4Sk5#HTV)3Z@Lsqw{e%Go;l~gZi z?gszOrof6F^L^wGTcHTdAqH*=Ij3Y}SL&xOwkGqY`<{SC=Ojv?;&Tk9g+{A;i@_=ne*9#}So8OS7e4L>k6nhA$ROOV4-z z%H$+tG`4BfH3+D1DJS3pMnSbu*J2fUDlISq18&u)-Ucvc^c#$Sp7&mn59?G0w^#q> zUm&_Jb*rLy3o>DLJeg5u0RXrFAh>jH`IIqedKYJ=&rve)2Ex$*$8e@WOuixingHQ| znzs=K3Ls!nKw*IZ1db(>U{GOz8~9EsJkY4$6NLj@2*7A*<3fcW@)Zg|QsqjPEnU8Z z8B^v=nl)|S#Fd^v=h%^;o2h^xks8)e8^`bygRzd&-z)`@HgrRlZB(T)SC%VBI5Az<`2A_GSU9gbx_l0tf#fOQsya zaR3Xy+P&#e2_0jY3M|mNE#`A>& z6bdYF-@t`4rdY3-AvBfzfumjkgFQ-?5&s7;Kmi9Nus{P3L=Z6midu!MRTl9Au)YxZ z!jT5sAZ&pGI00pmFH-rcsSWH{MIpBqLck8TkU}ah1L(2~uT=I5tS|`;tI@{35=^i! z0j|);uE7NQr^t9-a7-Zs2C#w~f9h%GjR155K!6g4fv28uA|XkEM9}f499l*oj7TGq z+${hNVA-c0VX`3ZrPcOe=E-KH$PcFIrXwi;1zPc^$Rh2zNHr#%gi`-X{|s0&OKiNG za?Lj1gzo@3n1RP1b8IO{C4pX%h(}RJCACyjPenD=mS7CPputG8%7Eu~bTvr6YKsx@(5c zMc8Yx$0oaMn$nHBrvN61_1dt_hC6P#=cc=EyYI$3Z@u^CyKle$20U=V2PeF6!(YO2 zC1gjXU~>ilz@0$5;_y3)Qpb=6mAy>*yu)O>T2 zKp2ITgjS;6_Mcwl#1tW12R?Y=hnHM1mSmqjm7Bw+dHJ7WCO&%Ur>FjB1_XITA*YD| zsQ?PVSj4Oiz7WK$8Y##@5I@>rn;{Suam4CH%7^s*_#dR-0H_whP$8`R@Ip+AVu~Mp z!4G~Qg1XSBKK2RZInPPFF=7GO!Hgsj$Z#%VoPZ=D_8&lj8S6 zy0m-taTP!;06W!bQc~EU1wL&-3kGR`kDimLwL2#Q2B9%9i~3(1dnCk)Z6J}IAc;=L1sEuzf)p-5-y{;~ zRX=Wl0zDvtV`+E9)224AD*`D|s>u+O(x|ha4ee<6db4jHQL?`UZg7X9MUpJVF^RPr zC=k(?DSg$0QY_a&>|iqneG{43UuAnr8PVvz`3?}f zxUm}d*vCK43G_-eLbtpX$VWzUl2!lGw5OpiK`B}U6;`ZdDpz^KXiL?Jt-NI}ciGEd z26LFjJZ3VNxhIJe)&2xgJ|g4|!zlTM!V1|&2`L%Jr0hV$!oWNA{DdO+99UIDh( zz3+vO2;*ZjNes9?XU+_M^2=Y17%*%0y-ENl_=1N5NRnM2@W3iLgeoGWEFCdB&}fEp zpiMn(Y6FFXF8p8!W)Vnjh!hjKs41!Rpz=nLB&>v2Dmzq&g*|w)BmsZ| zogTHM-;CyFE34Z72DnYMNDBWhdJ!yP9HZ6Dh(-oPkrX``gQFV@M>!I3kH>X5#3ep~ zyU0J)a+;@%g`(jc+6!^$iJ>NFzd8hDeZ7d5a7@*29Trf z>>JC?_1t&%4Z6j$`-p&1fQLr6O97HzBLt}YM*Th(ru#i}u6La<8#*N_{V0TS;e4Ap z=%xYksp4^6Q%JB>cYRUHb^y3N0I9rbeF3xfLAu>3BV5I@ukM(|K|9pO0=3r_|8IpZ zB%mpDie?-0(7gnfK~iW6+->I<%10!iH=UVEji*D;Uw%T#X3EM{pKs(P3&)$2_Tpu4 z>Y5S}^LNoH=PT*?Yu^9H0)RZs_9FA z)Ghx%>=QsjQz$870m}jrl+!G~V1SHygbA=L=-RB+GA-2NxCT@#2#lh)GOsZ*1u8f# zJ7@#Gz`zHL!0ahIrMj>QH~|;XJHkVr{zE)}GrR$`K{+F?g)puGTdD$hi{;u40l)$9 zDuAP#5Ia~1b$f~-OgG=@rTAGQmSRF3jJmtnD^xg&Dbm0Hn?9^dyc+~VF=G%1fv@8t zq425-WeI>B=!5^a@B|j%IAifItuQd7xeGRQLpUV1F93xPYO;yILr{3bIHbA?xe&0} zLjDUttOGz948upPvJR^+)i8)!QHfSr4=VA$N)(v8D1b~fF{613@0y5DbRgDq46B&3 zWMM^`kewQY#8^bK8}m0)nU~|K#RG9UN0h~0{4pUr97goTVLUP>gBr@&I$~5tAH%ZB zvA$)5#%PqrX{5$#w8m>Ro7ls~Z6roKI}A+Y#&DEHWco&46vuNEz;r4{b415>?6LqD zp92bmkI)|@;GYQr0|0W0c=UsL^cP#ZpZQq?wrUFWQHTce9x!->8CV1}D4_MR448Ar zi3GC;>LC9z`V|Avp>>)JBSw$tqK- z0_cPu=mD)@3bFg6yGXH!P{Et*0X|GUJgPW4vZJOrFGr%70Xu{X`zDQvipG-2nY2nJ zOF3WBAER*~Tf!w>3M?Y~6#?j+`qDfW_={p%rB*^TcM<|~5~ehK#;c^u9|HhJx*8XB zm4|AlLzt_(RFS;&u%U~)@B=4-{3o}BOZtMz0IbW$q%o8PgCeq;M*t1MQ1BPWu9;G4cctOTWGV0kpb30H`bC z90B9pzg$$#^NcJ2Xrf1O0SH_=WBDp|+e}AbPxn+L?kug=;<(!atsD?70}xO096a+x z&jKAQi%bd~+yZd1w-zdZUD}OEBDWS<&?8K@n`y2US%|j^P{y1~0|imBf=5A!A5%ae z-58irV!oT(01_?26a5PU3o!e-I|!>o0QJkaJWUV%!VvXQgbFOxz(h^Fxu2AX-4L;T zG8QFaQt1PhCsmSn8H@oX&>yu@n8Gm~d#Nks(tsl}#S)z^6;n!sGAZ-3F-223)3X0G zWz#lw(>I0FIF(ZXp@1)VoTyPVHbc%i<w56L4ZB88c*xfM2#tO5&a`=!4gA{NmY$DoT0VI~woJvE%Dnkj&uJXei{*}BQRqLRCcZG)hCSA%F+ zh4QV4#aG%=o~;V17Ele0joG73DD=xK9~q;sFfT`2*p3tuxmqdwOTD;C3Ke2bV2MG1 zMcS_wo2H<^(*mQ3v7HHsq>=3*DH;I=5DR!?2o-Fs7BmR{%&o!fQLxoprLoXvC6hjC zixu(Jq9BP>U||s>slqk)nU~+P#%rpxMl0Kya_Qx z1LKPa)2|za+{sm4t;sz9Yf^5J6~vR3fC)5-pbi&9n7m!x-7U04tWy8p1zyV$#^5F1 z)G^xPMP6jo-Q;E7=5^lZgm>Dx@rs(C~n+P3tWSEJ0G?%cU>^#%% zMPFBn+=sD97ikF@`6Bd{-LLkUK=6_ zUtJ*wRfx@FNp3?SDUh$R@SvB335#?KGOEKHHlZ2@ql9Y<9-D}so1yqsVHKWMi*td% zPzW_*$~QtdGFmtxXh5j6nm3qA0b_|yY9_pcv?^A(Ga@^9l&b%w>L0}71kbX8F(@P@ zUg7{=*S=6o1n5_x!?}<&B`nU-+!;^$dWk^7P_PuGoaI!O9J|OK1rrz z6|UpESXpdyS-xx=_59-&(sFr}`HIC+O$tP;AX71fi$0#his+EVL zu+9ADK%OF%2rP6FfR%lam11WKV+mL`;<+P}TBhfEhTi|NwLtH2xc>Z4?}MoN>d=68 z38f0j78n69_T{%>Xp*q008*lemT2cqkqHHb7{JxK)uE za*+V2Qx5SEeQIj-{beU*2u_p;D1DU{vqYG z;mK2<4vOl%UZh#=HcRa|)w8KM)D)fx@g3o#scrv0!|mDj(M7X?Mtij1?(6PT8sR2x zM5UesAc<+{j|v9vXyUZu-iiBt4*lg{-riK}t{#eThgo0)G-w6>_}%H=B$Q0HiA|yi zvI>R_gDG3H48AayV#x9l;lV&PejKftSRh)1B=@#83StOSHB|tDDurZ7hcqAx9x&_y zwpAmx^=66xM#$Bntav}-aK&z;_npuU$Vo8d6Ne-$R5God{T?rb0p+vi!-7Elyc!m$h(v%Z%z-ZWM z<_j>M0KD57{gtYxd}b;yB!Z)W>7wc1T}uCNeWUiJq)wg)9JtmV$X2o=GDL_x9L4JqGk>1rf2_wc|mFBqtVcEBkpFQ|K+a+0kkUDopgNU_Q=V3YCNXf`ol3RCiRjb0CRDvBMOnv2z{U zP=iLuhyJ+r=*jhDsk$TL^+vby@%kXUNakU0;TvMGmhzWxo`lkX~Ax6V9Zj6k3G;`!{&vf6dGcVTkc zg6?S{k#}ca7LiwLm?*4;IIN#utW=n|Xx=AN7xmYxgci27)H> z?aLQYNdZPuJz`OS0to+3tKMkT>(?(}x>&X1t!()+=FFNmbMEZf^X~2YH}K%XhZ7e$!3Of=$z90qXkbDPJD^gnniPgb zbBV{5D`!rZfuAxgniel_{yh5h>esWs9ALs&s@aP}H9)>S{`~s)^Y8EfKY#%WI3R%q z8h9Xr2`acCgAF?P;9P<&B8VW15JAyTJtYKQ7$e*VA&4Q0I3kH9QWO9Je4s+wDqG0b zl21P|Bp7vDTs8p(5?q9%jwbr}BalG~8BqW&*wDivEvm*-j4(13zzn09^1^&?fiMaw zhE;TBmP3wo07C!MP;!))Wtw?rZvh;Tq>Bp4co35YQILZRJuY=YY$eTEXGE>RR;5CI z=85J;0o>ruENr0BianHQNGPO{O4=4dqN(CVPXOrU2bBiQP(T<|0btV?6i#v)U;@lA z;e<9Gq}L-GeBp;5MBwHSsivZ85UI3=;eu4GE#e4utWvqu208d4h#y`YBrLJ37z^m6 zJ|VyY08uqS4LH= zNMw|#tis|X^}=h~DmqEvgKMZvxe@|{AdJWaNil4i!^evIP)jQjaLh9si##&P28}9O zi%jY^>JIY!FtdkU|6nb`WM~Ls-Eqvyufwj7ldx^za2J zu2Rqf4i5j&0-sCa@JJ3l;H%Y2Q&(-u)mfMPBmyv0(vB2oyZtty1R-E9j4KDwvb#|F z>>&bnjDkp2_6?vSV+R?%1yl@sLi9pd zH{Sm`wq}Y!lr5!dF@h$3KO`3m zai^70`G9E>fJ)0)vu`@kKIHvXbYi$6=jr1{Lxm48-sSib;&ZAfimsisVRyf(Sr5Nfa0;ri8~L1(@!w3H~h#uSJ< zNZ(8Yn*wCuok={+!=@*+*Nnh*3b2GdictqWaKjyUu%|XNs!_b~1OZ=g1igB+06}m9 z6pQ$R%TTfbJ3LTe52Ic`sYF0m^06T+ZRsi=W)m99uvQ;xASlLJFUx^|oTlKK9X!#{ zSAij@1-s+h44{BLFvB19Xof&ixY4b0l`bbqNtJpMlbP`9CY9^TSbhkovHt&{tT@q$ zeZ=xcg`_nsyo$ndOa+rPa$<}ZO6Okoa_7-U|=F@>E3B50IY#DGt* zmc1-yM?#z0+=e8qsmLZ*+10YPwGi13caYb$ z)(JW+rH*xS>)PQGx43h8Pkh1{667K!uc9?BbfYWX=~B14*1axvv#VX!a!7*P{VsUJ z`w<%bOT6YiFM1&YuY{(zz3xSC&9wO5`O>$#s$!KOTs7EO&8k+o5kU7&>a6+_xWJaY zR|b#QFY1(6Y4|#gHW+|U)wZthW*e3o;N%)(sd?_LgKgs7 za%Z-_A$E6wE$n48yV=fuHngKH?P*iH+OLxkh4dMc?xxxz8M6O2xRZ<`6|tyI6*;p( z$g5wCd^_Ck#&MC3#3s?s4k7E+7`y9@T`(O)OtpSDz=^b`q+y6Bd+O1sE`VipSJzO8 zQWT>c74V76&r-I#-KILVs!*vbS9?KKwpLZ4{PF}=vZ9r(05vLEEusKNByq-7vT;!X zU{1^$YC$Zx2n)%oLPQWisa82XFf_|`^TU?5xTS20Lt9-nXJJ9owXT%HOJD^6ZoTd` zuQ%|7U+G*$%G8V6R2amN29P?t+@&rCNbEJ(TH$FH5ieAPSuj`v%Vfk1w~iIyV783Y7FNZ%}+3^#GTY zr3@}-a5~(JYr2sAy`U*%=b7+{pFe_f!W2S4fB?9pr2q^jVSUpIiUv`+{tM_(f%DoC!hrWy%7|dRE3ZekS)bv z*icOLfQNLGyNCwtwU7CrkNR|*{7oADaSZ(cUqPUY;oS}5>5mNQ&H|at|1p-`c$onj z0V*ucO6nrU3PPeoWIzF| z0wT-_CwyK3#G?Jo;y_S99~guS%*iCA90eYsYFr6v4AiwjlQdD2HMQR=iW)cJU^@L; zo<$KkUEKmI4Y?VFw5(GB6k0jKlRVWRqc#5oR6LjvnqfJPQ#rNEQb?Jv=?L2m%qoDw z9a2EsDc|cnR76cwMP1Z4zFSLp6i5|J7>-m)om5H{z)jgkPEiR=nFglyVm&^|j6%kQ}TC73FVG)L5P!?k~#G4G( zV?mZexRNN91qB?F0F5PHj!3VSMrV!0XQh^WEkwKZ4^H~pt;i*ybp++Cf`{d$V~z;2 zEyq_fL~Th2a9xMWwPgWBrfjiA0A&AwA0UDVc0}JS0u|WaW2PqiAlFy$AxkjaL`;PM zw8dVjrfuFPZsumN4JKD>vcT`P_j7Ct&gBZ;}v?FvN0t+aHnylPv{4)yQNL z2b1tvXZR*`4yJaFi*X93zOiL^CMWEO-}EJ#b3W&G4raU|3Be7>0ayVyz(YGkLSn|H z3S`3*jHW`w=X}=ZeR?NsHc5AiCwGn~cowKqs;7WrCwack_ykI5og0FR1ahj$ylKS2 zEyRXuh5$qXJ|Ke{RDwO60)HaJ0W?B95RpWDXo!wziJoXAGU#iD_Xf06v@o0HkO)O1m4 zK9Ipqq!0=P0Jw@PxtjlL7-m^?%1;VP>ZG>YcP{9gXlHcZtG;$Bh%A8TrK9Sxp6h`P z^_1S}fzx47jn!byKpaK^j7`}{Q$Y=&S4JoG6oBcW-bzp&hw;+JKBDiegmw;|vNAv) zXkibGL6VS|;xS&*)GX4pNyCOL#3n3@EUXZ?W<~_S6_~35K)^R7K|P#;(=izUfRH*6 z>vh^F(Hbq%D(xxkYjED{re-REep|oNpKk^%rS2=i21(m^ij<7dsFYtDoZoK9jQ4?` zd8WkX#EIsR9=5cEnyBBOv7f&tgv?A&_?43Y+K2!s&Kn`X%l>WTWD3K9jeqZ5s2?bKe+u8w@jf4P*!99?{0T4njU;sSmLd68^2gE23 z=mQ;TEt9Nn>%MO6&Tj46s1#Nzr}`i9=4&pJtr^)Xjy_7+o-K$BA4;5T$5r49T%d5A+a5kfm%PNsr#VuLK4X`T0!tc1>W8S01!31cbvA$ZjvFEb$IN9_VfW z(t(kf;OmweywKmtH9P<3%hG~_N(-gh|#o7+fw6B^o~LR zS@>oN-roPM3j;tBzCaf7?{of@34s!lo%7A8#nE!unQ>^Knr*>6^V-4{)v-}vKGk=Db?ZM z;BdX+fI+Y!8;0`PM&>F7P`_JwxKLf zqa3z{02FN%unhp1K#8)jz41T+6v6}`fEehmCOfD!>z*}>>m=)OBEN8gs%Im6=_5a{ zR+ay)4pTCSsLI-2FKWm#6M4CD7M81;6pbggXI+M9keR| zC;${_Q6%ldKkW2Q`vWo5YfazuOAtg$zjRESYf{WGJjd{kdhI%|Gb@kn?11f=@g{Q8 zvx98j1~el}#vx4~#>jm-Q_F;2z1K z%#ems1waxTXZqEtD{_)znATS3vjND`Ekc!In-WybwOB)=GyRgZU8tT5fT4{ z1^j|PL@i8o02GWi6j(w(oPiJsKudJ?XG^U?Ts9eGb_i{@zQu{Y&NIg_TstSR3?r`- zE9DjkH&#DLKiSW<5~M-$EkN>RW6I6wmEAx&w?Ij4%?*M<0FH)GE%_ouK6~LN7eE1` zNHga0MSmMqh$CtIngHN{rJ=DpHfuXh54ow+KfbkXH0D53he1L!58wkXr~xd*s0>2D zIs5}ZJb_Cv1yp=+YUe9~8#scepaAsue+RgUvT#)6whX6pRXc4BFLkaWXCe>xfK*5I zEQ0OaBy&4mQhX*&J{1RRN>kP3qyiOwM$q)JG+OLdBik3vntB2M;YNf5;W?7@7RLnchC3@QL2)PpY| zWlgLuAb%B_t2xbqxtPNPnVUK9miJX3xjOsyhR3xdhq$13xKoojf#?QTL?u+xRb16o z$1I7WvxHa9=%YB^T1aKS?gVffIaD)xUOh`*{To}kRpl@xsl%06)D>60g?${wbNIFY zjn0nBpiiL0SGPEs;5n^hWsRCGL=^h3?|3|CxNa}6^0Ke5_qL%o2mvh|uq#AeR*wLc zWnbK3u-6}9xtc~uR$4CB8w5b~7{+N;mS^<2CGGjL8%VQ%#E27Sh!OwIUf#FRVnn>> z@7La_(D%ICB>lI<=Q+p&YC41hw1Q6aG@(v}(?dP5^|{gG z>pLGWhI>6z6R6T>6VHoF0BC?L_yas>y+k}zJYa#`V*wG&Rr9Dl+q?bH2Yc6ddX9p9 zp2zTr1Af`7htB;eaoU8kFw4bdDL`?l$uPh{)Jsd4Tz^Sp;D`UXZ%48u56QN)0~@r0 z-b2LHcjKo=#OH_p=#%`|XMXGZxsOulr4Byf7ruGGT>)^bDbCHrpi%+U>Qd!h^>Tu| z7zAt->w*F6u@5?+Gk@)a$N*r$2u%Ix=jua2{cbZ!^iRL&iwcI{FxUSzurqIMyK{Jw z|JT31?Wc#&QU}o5$JTTWN+nN^fA2n}tjm&K0m!T{Rt!Ka;FO9K5ejw+JSqTyVMB)n z7CL+wQDQ}l3?XLJxRGN=j~_vX6giS)NsR#%w2~*m0K|(83#1e`B7j7S6AsgmW( zhc8X$#3<6|O_&*r8r=xg=tQ9af<~1(m1NJvSRT~6$SP3a$ zAbM6 z)x0^Z&Xg-#KD8Osk~?Pb>Ir*+5op7mpjlsR>XamHkVRu3oqcq)Xqz~PBDKhwcyZ&$ zktbKaocY24V@bUbkfX;4zX48s`Qm5Psy8|X7(vxZLR?l-bnYP7Gs7rVY8MXb z>`%lINi5OC6ZsQsJOfzts{jhX=q{BRy^9cpQB41NVTMsi89_zK*b-k}U|2_-QH_I4eQGx>+>E{UsgTvA@o*=|ew5Lq6@HXAVY*Mx};q35D z0mGEi&O7nUQ_tp9>;%I9W=I8;Hd<&wF1q}(%exp6`42KuSPGy$RfsfFz9j40jm{09 zWNOb7U8^!QGet8%fGhGTM9omi%uP4o*bGU{HDfgs%F6I_YR=g{?bX*`feqFp6(8w| zApyWhg}eX`kn1~$!b8QAK`4bPfEfZ?t$-bKRE(1&1Hg32g*3eh#Nax;PuTv(1T8-W zps;S!Q}ek4OaS1O_ofG3RTtJer<^rlfNlRBu1!wmRF~9+*KOG0haonuPZk>rk02H% z*s;cpZk(}4jW}6Fp#u6q1tJ41MN&x(H|;lFf+IezN-Qn-#UFJ>KJRQ#OSg{6N_StFgHLe*`LFEw$9Rpz! z93RQS4o`9}z_GC?wJd-f`d9@NPcZ+6DCKZhPMz1+W3N4{l>X_ydwfoz7+*r_@x{sl z5U64p)TYTq02dchfPC}I-sVnb8!Mz^?>=gbry52MOaq%S-?~5)gpD7NS4n%`hS@ z%E=AIWG<%pM`60Mn!z-fA04`iBTWvk&k^8;Q~8@ zM?VgdkcBklArYBKMJ|$&jdcIyBOw_{NlucIQ49bG%;1Fygl7?g5X2&ga4rV;Aq+HO zQYBHDN>#3sjah<>Ck%i9KA?g|Td?4<#)$zDjYR7a#@cLiVoCk|tSF$~0|I*E%eAM#Bb z*x(STcmoR=A`pTY#12#y<4@rlSGgikEMzeYTGWz(0+<4Q0=Q91Gr$SKAi%FYVnH+6 zW&j^ZYe@`2KulpmLIDhb4`qSLVjA<9mCcp2o%L+Y>KdKtROecPQt0pAQ(90cv;giA zg2g;h&j2hoQ&v5cn`CKIsKh5doBix>fg9XAK4(QO>McptmRj|2&QgIA)<*u$Cl|q5$bduM3mqC$^}EJpcJBLoFgp zv!WGm;1U;j0UZBe0e6L1#)1k6)J7zR)UzcBK95Tn9Nix2WU=*qCuFJS*vhuyvf8B{ zcLy9|5s&yb#FZ~hC{Qv|xB#A$n5Y3#d>9tzz{M=OQ9(ueHVX&9E~r4n1Ww?Bd*v3p zyY=vYNt|RQllW_4a~|1ra>=yK=xhohVaIT%yCpey6~BW>SC9A60#LOj0IO!` zqU^{80P&LH9OvNPZbrH*6I(JMh*5xI67)Qwr1Z>ZKa-FGU*N=Q0V)}XAm9s*=yG0o zoK)npZF-oJ^QAHU*#)97BUL;ZMXR{!2a>P=Z(#`sT|&`=p)Q4)cJ-@a9cx+7n%1?p z^{sK8YhC~En%BMd^{;^)Y+(9Zi|I2kv6S(Zw&8L4~9O3*9q#*mf?}d{%fC)=D zFWvN;0iGP?nBmn2>89xsxB6(>${Tn)Tx zvRS#TB$O_xh1}m$H@V6UCUJ+;G3i)$63`#s^bk?Ky#;_rH;4X913;qyu@FE>XukA; zhh6{dFZ*BCo&F*IVVpuh_xj(J5_KSsG3G4m7tAxvCY&3M?kvwp0AjHZwx?a1btu3; zVnKnUbKUEK_dDVfzjCR!yxx5?pvCi^dVpQsKIYx0mDveMnao1C;}CopoGO@BjYKl8qdr1`OQjc7!y#0V3TUI!ZwSNhxEaJ4TldNdc9X z5=SVll!PLVQowj4qGIyp^Z5P#JAa<@$9;IJ2_kun&JpjjAe!CdVuCoPs%fWiXpT*-cS8#sw{XUixld8#{S3%;2-htF}hr zKav9Ca3W7y_~Xw)cu5EZfwo#FYUeL}5OU&Y%Za~VPW(_7XabOkRvgDZj#~xK7m62b z#f$9Y@hW1Hp<=RVBn?0|QP_HL9Gb1-di&xe6^XN<$CPIYi+zbRt!$GFk=HUC&$z8l z<4%myvEn8mUMeI=WT*#=bOFMJ6#+CbjigG?NCY$QIB}TqOx^;*j)Kv6@h^ zJSN(GfK|y>tZ`qiEmTf$7O9RGxUC|0VitMY6GI0nN)F(r(26fr#8_;_ZT7{d=+?Gm zr7yD*6Abw0fH&xjXtL+r{Tid7{wLM0<+Sy`(@$2Zo*ZJHB_9~gkYt zEd$y{k{};#oaXeGSB=>kQQ2%Nz;TproL zcg}!MMXrp2EXIpOeH9CFaEgBE$US@Z0`JM(Hb9-uK5N4gb)XrUe-6|pesn8;wfPI; zT#H3YJ7qcyA|Y*7)($CDgG#liwhpE>A@sI*}%E_j{b z^W?iGfLV}vLPEGQKpB_?Q*u@iD;0%U;y7mwPbN@4vlHPR_ZaT=## z8*T>>!c-oA9#=UIPrb&)s=^vY65J#6B;f@lsG1f0LeKWOlJJ-mRpdJ+PZU)klzQn> zf$$0mE$4Z;u~U9PC7^rODUX57!fW=T<+cigPSBjw`6Q2g+W{p84Ce)=w@FMf;Fc6t z_Q;cg6c?>l_83N=B{^7!#yZ^ylhELpWWX#LA#S)(D;3w8Q_5s(X$2zGng|VLe!}TP ztdD`(jPP!{&MAG6E+hO31*{SmVFJL-7a^{6v->Z_p*XN6VB)IGn`4!N>QroxC)Vd0huk;mFHX097Qy}$VKo&Skx+f6s&&9ppBT=fvX^MN_Z;XC`^nV;47u$PK2w; z=byF7ODZcAzGY!40!$zXh66`?pG_USFj7?q-%9%Dg%#s6q24qU?&D! z?7L`%y1wB9ClQgw%p58`3P(ZaGjh0oB7jJ|8X1wq%qha<;=OXYqVw>AJB-in(|l55 z6rGt}JSRDSEDv&9O?q7)qqaO{zp7;rOM90e3aMuR!+K$>LTvV5?;hE!)axaVitt;7ovwDVM3 zAx<1ORvmqlX!&W8k_WoY;lQg+=4Ae$IN&bDhx!P2-2PANcEs!*5r;cJf67eYdF&ZC z!ffNZnSdM>OCv#6iLhsDw<23r%hu3oYa9y28_P$nr5aJI7brv$geRn zz$fSF6#L5Qzs|JG?`iQ7HOSD~%r=SNj#_;0L*HmB+v1K}dBNcnR)Bu;9updlV-KKb zOD?jH;}A!V8==0ufD#U&vItl*vq6Gku&?3@6dIKd7}9gX7-?Ag@iR;+8WGIg=A|Q& z0E7<_o@oMaCGA!3`zQ@Lm8h2jK@E>ER$TS`tl8;)T84Wr95?MomrVrdkw;vx^xr528dV zKMO83^Xl2Um>(ExLc)m`mq6;(z@k7e8}so-Y=6~nyPhBAi8KsTP}qlvStyYnsziM+ zi62`N?uUX$1*AEIsv=d6iLGoOod!541Gj7kWmhQgf6&hsvM&&YElIvdBB!vUM6OjF zYx^2sEsn=tT}IED3rFHD1*)x_PeeGXC7ue>i4bldIR2LknIGUA(L!l4_spoyc}$+T zN@Q18(h+0y9>1e+!C1vgt#_MK<`TBB)SxnSqAJQMo|=-!Al`~O`)H-kGYqSJz?v1M zFx1t^g?8@f!C!in@g~YhxwhG0KeLy3|0JDlC8l{tMR`)2<2)VMFE;Y`3TCNzp@$A< z(~|%*AxTU`lK~J!Y5$O#lMQ%-8Bk-luevv&`2rB7<#`bb66bQ<70Xi0U|GGy#m#+T zy-kW9M=&A2FVv52Q-dVkot39Rz3zg0Q~{%(9bdLUuVN#P=E9$m| zGR{etZ8DN03N4H)m7XB+a*{d2_bEC|7H2wSlj##3db|WcxUSn=|D+{vuYXvy6zE?& z(J%9uWcdg$r~vTK7y0fm`RsAnRSKsH9$ZYKM}*1_fzbJ$g3WmNKf0)QF?H8I}$-9RWh+D(GCko=IY85M_uz}G6*WG*n3=B!{Zv%voIFS-&V+8l&;)4x~dk5(SS z{@&M_4H?}e8J0vx zv;#2vJ1+|~4sJ+%_4VjTo+r7#K2;pOc&8TM{(}Iam-L1mS3^g_0Em4FKJ~J+hDMCr!~3_Kmg?v%Ie)O~SfNFMFK|cq!plBV`L$EGn0<%a!=aYpy_(a?Eiq z$uldFXuP_ypE(#PBHo!WTjI^;Oz<4~pA(R%B+?UM!_6XEUcI+Axifn|eZ@uDO?q;n zz)QF=yk{Hfft9NBKGXo^cy-|fvO7Na3qAOFCYiAoR)Qv|-Z2h?7>+Q@>XKnn#<=-+cV0(68Ah8E zl!qzjGEe~20E?i+njhkhDA#8#5R4dJSD7~;t^|T7AVed2hVR0r2Oy%l)+Cr9bb1vc zfv`TFv~AWTL9y1T3b1g4#sCCs-h3O*7r;25Ya~VY%GLXa+021KQB)QI%so+>ggpwJ zZXeXW%JMTOSG34ptb~*cBIkIO%AN;&0Dk&53Blg{UaCAaE%nmvn9to?pkSYB8+9!X z9~$gY9~!2$l+pa`EaZOvQ#y^+{<*x+ikOX7iTmz$HQayP-?HHRuB_JD${JMdmAPFC zEBF0_bLt`qVnZqq)yU>`60$GtG%u@lOlfxhX@)=4Q{KwAeRch%>*Ytpc$Sl6`@HM{ zp^|t99utc1(NocY4*taRWDhe3-tI$(2VJ*3I+re{dO8-XSorC@l4=g;&+v`Y8d$zq zY7)mH3T)tC`i&HS|Kx0moh-fL=_2gNqgh;6!9hZSHjxY)cekK7_&RKuY&B>#$TzCo zBlx6sok-jkRa$h!KVRcK#xp3D5o!8ug@ZLBWRB1Nq9oMsMc?e7;Ad zeMC|s^J3=$f8_Ehkk?_V`}b}akyXwU-}=t(Y=GIr8N_$If8LOwQbEnvGAeF~YH!xw z=|8FgRnsK4s~Hj$B>PZ?cqTX%JI@BPC@{6vczA1HR#C)$Fm`XqY&RCnh)v_TWd$ct zVds3Sh>~@k#37Y#Z@GIdI!M(-WnKJN1N7W}T2t!aX`5k6n$TlcSUBzJMzzzilvUM+)I<{5-TY55Dc!r2gk#)_C(=>*wpzy7DW| z!Sw_XB*h;rPvL^GqbPg|AcR#o@rKc!gsklhaH5_Iwy6$+Hl6cR@SBdkPN6g%Ii%># zXaSG~XJCh&e9pBoH(x3k4?XlV0_Ci{0yFO_&M2P6I?trwf~&q6-V5Fh5ibA}rBv~u zVY@EXF$zo#anDdlSUznB8>y;CQpropN1yO)mlVmRhws`*%Gt-hqS;v`1Zw@Gq!mg zo4=OU0JW#sYvFo-B^J+ii6LDuco^4chP!dxUGe-PgC8}-XPOs}FiCi4v7{No$R96} zfnYG{^%PxZg-Pa!l_%ZskG7JhDO9k(=taD2-DpUuz^~GAP-!?w-^v(;N_<1m1MO$6;V9fAF=VPStXMp6A#4$4Z4zo!+7zQu z=IkKFAM=5P&J7QDIZZ`}me=q|k?4{jiB2HLBinb;?)3|}Qej`BB=41Y*0F`VO?e)=CnmlY6%Wal@SoU3>j}oQ+Y|6&Bw@j zS|?p8mqo^Hj5Qd5Su84^*QAn`UT?syy{kGk2)TFQ7T9N?4_f{2GXq$ED} z9(e0Tt6F()sX=<@@n7uwGVF(-AHBUg_dVb4A8kD?HCdGlk~1=&q7e;*Mdgy<-ocTI(Jo;Eqb>(*L4Bvre;-GVTX0rL%2(;2pK;r zI+~aI^a=@}KN8$2Qdagm-vU}q5*C2jmIN&S?&k^%$PsEwE z8Gq|M*HL+#546R@p{GKr$^&SG6_UY zem%c4I?i@ZMRvX#*G_LGSRoQOTa-s_oT3NC((Uls$tRqkdXX0;Vk9YWy5Y^Ul=^BT zcUvb4L@WdvB{oP&Zxgkko{n z#?oniH#41+7t~R2t6hr{IE%oLHoS87TV=gRL_q&;MTGm9fI_GQwv3`604J8!gy2-u1Y5WunBE#MGxdk4w!;iuKo-Lj%FAH`{~-pjHL8@M{<4(pBxV@#732X>`^p)p4% zGG)reqcfkHluqo>xwL7WVYC^OO1{e>bE$EociG!ZD)_F2wH#IkmcY1PR(zCYQ%)iT zu0f@Rgz))Ru(mRmlKhe4JCCT!JbQWL&Y~tp<=$S7@L6zO-YNcd&Ff+}WNDyhE)sfa zNfu+$rmU4Vay40qtM2}lPOg=h(n^aN4jUVSNU7DW;EGRGXZ%UGW%8k3+VO$WUXrh@ zL0?(WFVFl+Ukf^NN*kXaG=K@{e0?N{dH&s5qj=<~7e55uapmviPjPIa;Lw_2)2n!;$@$f2xrb;gyt#OFXY|S_L`n2pZm8=|EzcW+1#< zSdbF@?rzpwV6UiV`9+8{5mwN9N4@!>?=(bx8Z4btCEQ_{|(j1;eKPr`E~-lrbC@2 zgF2@{cbXs9fniCl981$6H=_A}DRH9=xI6I{9G*88deq^#SEIPdx7S_xd4m;PeI_Th zf?a_~!F%5x5JDt)`8RmeNa2p>26Pq(Hq&0Yo}5txr7V11pRrKnZf(qEzAQ6kgb7HU zK#@k(Z{!N2_3^Sp;C*}&eEQBb-uHJ}q#cilmu9z>B=$k0bn|QQjap}02^`E8s>cw! zxo`@wt~L`o?!j#_^1304yP4E!#L56&(+7dApIyqh;UCa4!Zz|uz7_0QBZTK*3DzlE5uSvl*+1K}+0!N71HyU-q7 zj=-6ui)vhAFS2I8YOTu!~CjuV8WwK*Rg7v;f7$-Q0P_(2J^hceKiUpsaFdteg< z)#Os}Xp1m&#?C$%tc`-J6U@%|!+lXu-~1}KLM(~g17~8bU`0Twv?cpfn6;xB@wiAI z!nbz6ZGxiSU5$4i&7*Ogw6;|F3sti~H=>aSW+U1+9`lgkSLhsd07zNU zJZ2AW15oU8kY-a)4iea7fFtDHX{bZ2g2#BJ*BZv%H1ruEjK{&#hZHvE&Wf57_!??w zyvL%p*trN62>QgIIv`YPL*k0?US6>c07axy>tZZyRtTKMA+V&D`}?Ir;+uD0MNh=; zJ{mAA6yV{+VI8G~qkx&uSUuFm zY^$RapN4Gq2DF<@+lfD{6H`$U6OS{Qcvl2^b5H#KijDS2u5-gX-n@r7u&Fk<5S62( ziF+yn2n$9%d<8ng0E^&QHj=n8_42Q#-Uxqz#?~}Sdam|ua6D<}7$bw4QIB~^ED!16 zmuFc@P@qZc1{ur|XAYfxg2JJ^$5Nj`*0o`|{Y6uOvqgujJ$W1*`fuLfVC5#RCfK5p zEhvsJsNBA*d@b%ZuAKN{{FeG;z`HSL*7 zD7z(R!P=3KGk(o&hR>rV`??LkMlt`DUH)KDSVV|GbS2})K)N*N2I?CrXJDW}`J;v- z<~B%3l|Q29%hGVuR7P+5)iGt!A>sazWf41U>0h50B)n;a@S@F&l^I`ar9|F%(IfXQ ze?O2e4rgY4$z*eyH}01nDHVblU86gw0T|?e<5%>O3>h-SI;+95@Hte)Y}iii7pu8|p2Du`E^T z4NHDC1)W}Ru zt&)LG;1uxn#ticdwR2)O|7H#>iK%@eV3sv&>=dCA4$pipE`EPrX~38_$g8Xl8eYK zP*AS8TcNvpoBxEV_ZM;2?vP>hsF0I7R#52m{O2v52a78`!8c@$hZlog10N0-ifDB0 zt+n4g<@d@Vnm^s}&AjZPy%JBH!cE0#y}qe~ow--^wO@uoZd#to=*rr_p4az-+B=j@ zY0$B&%z->+w?k~?f6TFhljqQ9ORA;D@+Oygu4kz@F)9p-L=#_YubLogR2PqQSlc2V z(0n|N`b}tGyCv>lefaTlqRwV}$*^X0cpPQ_}M%7Z#Aukh|9nz{is4$`I)t ztvPP+ZRufLWs;ECdL6GeuQG?KQ87K80CdsW`FB|(C2S_4gT7E6YZ>2z_9G#nKKRl|6t2;xfp>(kuhOltG}c2g$uc^RqZY{%o~ zvH-N0C=FfB_oJ|AQdA|fwl{I|Dv$TSS`i_9;nw;tDmcp1S$($FtJOGiQ}Ab*0n9Vn zT2tBMaqcZZ8!X<4Jr8Dk&%u&$&rJA&w(;;>yV}$N@tBS7igfS_E()VQbmjUKYhxA$@oh`=X=KPFTd_QWl{E%;G>l89=cYu z5+-e!rFAW@*HBP?mFF{$?`Ga6`h0%w&_LwIQ&j(dgBuSYN%)YG%fHX!A3i$6drebh zPifeSnHbv}SC+ikl1=_1x_UT}CGxLpkS+cSI2p&M5}ye6G1sa@TbYME<+n1fVn=Gm zZ-`KB#G2yh;SXIUDP+O6r3QT-_f=fegOCKz$~0%MY?$j~zZ?4D zvuA1yK}udFi3m2b=bMNn-@3oeA+4TkTy5w%2F4#<+@auG_r7s?(eI8C_u2U+AFQwb z)0<^Mc6rqvc_gV~c+O1Z38ZwCtZ(=ByHS{sU$ea6&7VaOOy4SdlZGV)Hk=P)3o7#$cM7UZU z7#K@rNp(SulY!E1W8D8!GQgreldwy6$Rk*i6!k7gHO|-$F=wyBS71(uh;_|!2jGAl zLn51#9QgPYMQhPh&cMpPULGv$OocLJ`1Xhh1{{FyC1m31fb}t{6roE8^D!CV(<*hk zpIfqT>6R~HBaIEEY;$jF+iyOfmA|mO&Vrx}NCv}-u9j1yuZQr7h{gYZO~TLxZAYQk zpdlT<=WBJlwM@k55cg4j7t4}y`hB#@hBd$c=%Cs21DeAulijD8<+QK86n}3@g;b&P z>DSD6ZY$Auf)^Yt4kYp1zj~yCOUa3>fngWcLs27$+S6gRU-fo$t##gvS+cgwmA(ro zO2k&)VXYuCA@2Rli2-+Pj+gv+p)AHZXbtY} z`SP;&a>2`I`U@@CuP1!#Osz(;I^r()t)2NHJJgZn*pBct#vHhEcdt4Gx{+4=J$}0` zJy2Be4)OO4jCDI&dDq#z^p)SsKTJ5-M7?cDGAJZ7c4fmAapy8eJZBuibvsSn-#k6= z@_SdOg;KT7*IS=GT(mRBb{zXQB(DaIEWTbj_}|0d6w8~5|n1}7?Fu}Yh&PlVqE3-vHm z8vKad`jl<_eH~_9JO5Mpi!DyaQV@K^`58yjUi`_*2W;=1M|Ap|_*7OrabaC-@>S!h zT*$?~2MZ69|D4OK__KMd-FZCSo+5Vfy01dnqi4yIBZ^&P&Z2Gd$f6~({Rfkae1nU~ zveBoSQ%zVd&LfCW=;;%|>$;cx=3Uy(!0QEFr{hpC7en7>68&76nwZ(s(Oa_st3F^b z62X8-Fl~(48aBZzn+Tj`%QZe0Uu!Fu`7Cksz_#m`?MK2Vl0Oxy1Y_U*czX4wYe7U} z8>%_%nJYi1TQU{9ncyMcv`8+r96S8@0xbv}hg=XDQhO@~Yzd>q=i8l7gbwlRnP$OF zRW(&KbtM=Bgb^goHM2bpbCZ3&nzikSnhtEF2#r_OMy@*wtlGbKdwbC(!mjrvM^p%E z;oF~~qO~7Ne)(6*$4&GH1eD&UZoO)ZVho*_uDTs+yRyE6zs4#O{!#GuOPnu3t*z)H zAg*6za3o*Vd21wUroo&HGuMnWNJdk*j!lz4kJW0QT7+S|T;<+#GS0RJYSz_j%4sfk z7dD9fC%x#lOLY~|GQUwAI^0St8aC?2_b7}8b5=cSl~n4(J(b%NtKA~#fH^5i7VW0I zc^Lzu=55zZ5e#J0raKU~)!3)AMq9jcS?eM-$shmyEfD#YQL>TX9m#WN!LN zZ^Sgyg3e?Lwxrxp$nuJt$uKz1bhwA<*aJ2u zfRGZBe(aPKe8}^J3UR?V1TFwNs%YD^dHR@1Wz3fJdFLMX%umTI*7*wEh`q?OVLk&# zk(TlT$sUGYe>Mp$s&9^x-nYyW%F~Iy*E}Cs&8!2D%M#hJ(ZxR7fZh_UE$?>g9y=Q) z!J`=lHI5tb=EeI_ZMBG|#Q=hkX;eaa;?3{pl`chvJ(fDiUhKDUVgQLBf7i9*TMbJ?_kJ zRZR(Q0Zr$U}gRtf>a}abkqw z3buanfhzq?3jd)vi*uZKj+!FVuv#8~?E&0Gst}!$Ha%?fak!e$^N<@*)CZx0>w#v9 z{qd|OPzCl=!!dJ>4XJ{fGA3BCX}clQ`%&s%zZBaUzu~lossd=6b{|e8fJ`-^ruR%2 z2KnX7)Ejj%%iRWe9sQHKdSyGE<5@nky*_*<-33}0Gtva)W^!O9G&oyxBIhAAEQ433 znX=AE;#`XBBh=RF!_}E!3)_douL`-_!PF}P@LZ@~`oqHz*l3IZ^2!O#4Or$pXT})j zLK#MS8^ii5KG!grMH~NL6eb1#_^UN09FfzspPeo)EqydP_M@e4lc~?WEX~?XrE5`X zY~!I24Zm1DAW8-zqjhJdWU04=+d4HFJ(NEtU8q`pxwjsK0!dlN-4~2Ag;J546!|3~ zDQB>-GZIu>+E7_4PEpHsRfOSEC7t6s4nR->CBzQgl0U&ejg+@Bt7tS$?J|>`nUG|f zL98`cQ5EvYX9gjsC7GqHtKN{0jzLL2zn)NKEjW_(%=s4IHF{oz7DcCnw zB*9{G$Q8a+oMK?|c4;g;D$9bB7)0TuP%%!wgNWKv(b%t`_n zPeOI8MS+^;rB}?Tyd{7LE`?YX$1_bOG=rKc2C6dgIL2e`6>dHxSTz^~X)bA+H?^G8 zE2?Vj5z>$s0uc0WOT!vY1T{oHt}~&O^LPN6cpBpjzzMV-`?4my89E0fH%`qCK5d;q zMRd^`QxP-(ESLk5>=w$J6_Q<>#qZ7DZ9Kgz95<-|uoatQ=wgzi)aqc$OgZpk_^x!O zEv|T0PSWC%p@ores{c`b`T1P79tK;+E@DE0l+QH87?mi6 zv6{yWIC*PIGcs4E;ogiB$8~jPqbDGlakkc#5{C(7zqqEftTUr0L=H{_^DVwTJaJ(o z`#0m%Q9|~2=bTk0{b)cl(t|4qlf2gj-VasGO#Wh)>)WtOcT=tscP4A z5&Lr}GOI`NrMexZNh$zb6A1wG8BsilAFg^^Q z_GkivoCLkn5KMvkI>Q4}sAtHh{4YCF@{9@Tj)Bo5K@|9{dv$?50)8?u-O)s{an=V) z!WFcWbeC=*-vg$Hz>9RJyp`-Ukb0rHrV(Xei;sSWJm#6B3XEm5gn$)3N<~*p&mXC( za@@e*yu74mXj+o%%=404y`9Q5dn+)ylzSTuuQ~J8Z`ELr&v?SkzUr%cV9Zh+Cn%&uRqtw6L-ou3GSDKIZSX$ zp{yvg`^_e~(jkFV3k;pjPwviJF_tK0)#b#bhEj+L!Dns%PD4*l;E`!p^6!PW4p~?A z!Sc;_-WL}c2Mzq=rCXdY{+yUt>N7@su$m^wm2%I-lZ~sK_kxbN^LO{f_?k@)B&}H1 zCLiLG;9MeFBFHZbh-8jumyX95zZEC>#l*78q?a`8ujY_HzSQ%E-^`aTMEZ*n(POuTGGKTu9h1*Y;pArQb>0`IG8k@@QB zi(7eVvwfcPx_~C*-hO(96Kd2cD*XYE*BE!40+fqB$ z#qBdFtYKj17X>D_;!V|4yrtw`x@L5C2{5S6aXHdoKcl_T2Zmb4w=7qjZ z(q?8EjYj|XGJ(A_n5`?v-l{u2e*W{5y_#o7qiat>Z@19TSl;K0Ua2`>%>KJKV{$3u z`C-QNHtg#=%Qw!M3sIR%#hHH=GWY7G*9lqnCm!76=iF`P{5YNU9;IYkxL5AO^&`jW zC!MRQ5cd~FKSJbyWOE=PaZr~WxQmldc8>28>ktmr6~Q{M21cbL$`>#4959y16q);UX<|H!XNL2MhUt{?iy=37kL}smR^=^7^ho zv_C1PMd12c?OW^Lw@QNJlrae*#sB;;#TmtJ(#7dx#hG}Fonvt}5|`}~+xZOj=%#aF zNQq!tN$+RhvH`&go7CGs1uNFB{r>dD_d`x-q}YQ$Hj~fW<=09jBBP!fK9fXEkXI1V zC;#@D_XlyNX>*t{py1@oYYl$_`UCQ6_@_GK581~>54WMc+MFRf_Nu&q^|8z9a zPZhwlC80cG>ej>3jUShU9i#V-K7_4*E*S4FpY#uU{sr5Q5OI)XnfsioE7^k@EuHy zS8&irhX=!L*Qk@Nl(gzgTeK&IRwwCrGV1oPXl>Wx`Fe5`t znq8I*%XH<8=4iPx7^33dI&BCGUXp^pCTvO;3z1}fS={%$w)CekgM(0!;TDM^r%(wq zeb&sp4Dg*J-k5s*Sq1HSeL~_eO{MoE+N`$4ua&(9llsE<+vjY{o?R_S ztSrxXPLlSHfL(WE0NlZhxI}~@VHmBB!BKia&ZF<3@L?88?_&#q5xSqKv)%_cM!o5O z2^*~hn7grV0BBae0yu(CV*6O!E;0IGxNgETg)AAyFbqmm4*LNQZpqfX8&Ewi-?q{^ zagxQQmBw~sqrO^WL*d>OhpdmUh7OmurA7?ved!lk>Bs|h!}OA`b-2gSJawyh(>(R_ zN6V!R3vNX*sS?$p6?u!~WRIri!OJ(kTh^(6mutx4ehKA#=~%dYF?^%q(Q3ZOglqN+ z>z@sf6FYSX3dUK-#i>)UC$kSibtU=;ZY)6GE6(MIIXPUZDp~pQqCMMHy$Wq~3$cox z-Nv@no(~VLOglcdPRwUo1Qk`pF8REF-uwAh$JDju?p;y!m0XJ?4Zq0$-t>JP78FRz zrm$!Yu&jh!x;<8%XIU{`8us7M%$2+g{XeVAEG?&++urv7{%`1?nnjzP;#~dHjXO{N z{r>v)*5@qQD_1?INvPYG7?6K(t+`lB=FJ3v&*vQSQ^~;h=jXbAUbnjNp65=c!u9}H z+!4xHMHs%zyfnyj7j^R+57OeDMsLvG`jvlWc#bQ6L&Cp?kE!6RpxAALo{Ed$Gk0$z z61&Q27D@@GE8K_1BLhN;%4xQ`C;G&uGXep{MAsEDfm8ZVPTF4Pav8!4PWTzA-dsz* z?C#xei>iWMyOI{_?!t5K$1rwEIXlM3B_1>V^bEK)Jpe0#XY)5!*A6n;VNNWmD7I5%%GogR+cQzCu7YpXl*TQmsnENGU?_`sEqqV;|!v^kVL+il^m@O zGPBENs~vY$%Ga^dTImwh^Pi{KJ)IYP=f|F35N&1mod&Tbm1sn&u$|gg^HIs%v~d2% zQ?|TfbNrqyRL+m;FcH!wRA_oUWbPdI-&*wv|Cw~JgS+BOmsYDIC!a_0-fmDc(EG-3 zd$DA#B0j(m{#VP!w%?wHcsZl*viUg8agL6zkm6Bhk+@^4R;4c@XA>Cx{2l&%Rgp=9 zv7L!+?0V)siyC$_k6l~(Aa5i1th2dY)m(yOe&c!HZL40^1>dBIy0aegZm;E@hP}e6 zNk?76$PhrR#8VvhDOUYb%`YB{rdVKoGd;ds7L31*;|PHf&sRCX1%kK1@ij-_WSM5G z>FF@=f|``C3J+9lDdNE=g?pEFV;1|s>cqGXcJAQ3rRUb)A7H-)1e~PXs}6sAAgy`P zL8oLP=(1ATIQQp%iPy{g&ga_lWDSB3YJ`P(b6CS}1b}V}zuD;lyg|k!!D}0FMy1bS zTFy#rm;GH->+M)3Hg@GNRIMI7D6)WAK*Bm;z{cz&*j3%DLi0aGIM6?u`Xl72Yysq% zZ||Vm^p7wFgJm83T{s|gX-Nv|Cb2aBSE6Qs>A2n5gpn(qL)q(E>iX#n1HkKM1* zAA(#8izd-O!h47bYd-LYyXA~FnXmRQf)9^;SPZti=Gi3|^a76ea*hKRa`rH>A874HuJT@ z3uiKjpHOrwmT6a|{Zd6}AVD_Pe42Qw^y6eV$St>GXq#Dp!6o@B}KjXP3u{fuZ>3l5PGy$IcchA(d_6m^+=fc;gm%%;aLzz zsg72_tHu7S1}9%PYfQc_mkf6J^d&p?Pkja7&+-paq2su^t7fMt<2Fh{d13j8lb0;+ z>s1A;TVHb--KlBuy}#&lmDla&WA=8^WlHvbQk5*%wTA`eVF94NHd5W>oa|Td^Yic( z-irF-r<1{jD&JQT8|GKuOl`!fs*k9jj*aea6cqdkKlN8i|N7<9QZ+(5>6GM;H(#GS z$0t4RdxVdDV&|qcQw(awY-*l5vFmFWue(oM+&+Ev!J;`oac2&`^G?3aNn9nl>Zy-* z+g%s0hTqRL7vDusn>~N`rd)StD(K_ZhX~=R#XgmntHHZEI^n;LEIl5+`bQ|c=2oIO z*E+wtsreRpaxAX!(cVKBoj$uE;kF^2Ps%if7^?VohrE5=uH*-2F4p-kiz0i|BOF7p z+er&a>3?DNbyv{pmyHZ=mgT)YbEGWv`|gJVKlfr?!R6V4g_(iE3mo*MmW6=n%pGnP zKgINq-`sZ}i|#qBYPIkH+DkKvWKb)1=ac9ajyoTbuP<<1xMV}RR++a@!1q=0MDcRj zqzU@h)Ef_*J4@Xn-zzI#r#cI?!(ks^{}^*W{4{c?ocu<)G$P}IWrgssH%b1}xaBP~ z#Wnb2cgmMj*ni)S)f%qZAzG{v*Jz09n@2ibmL0YUlEsO^3PMZ)k$lzQX>S9b>`zc2T$Mffir;qH*$`5 zUB1m@eyyKOnr+^30AcMertpX4uYeXxm1&~fnz%Q83{}@8WdDVhwY96;l>}3!FKRtc z#M@u+|9Cs6=*Yrv+gEHm>DabA>Daby+p5@B#kOtR>ab%Q9dsw%T{r)8$9=iuJe>P- zpX*`Q+GCILt#7V1=dZ-t;~2pz_v-H+5h?*f!vv)m1@B+=QV9H`6wQ$kBArz#Wa0)! z!d%+#1Y2|~lprLkcmno9#C}buwRn^F6%VQIq$T}CHgpqO;MnE>#o0gv?P7?B1!Pr@ z-?3}T+D)<~`>8|#n`EG)k2y~0R-Bd*mkYFqgu)adJN=Nl+LzWlvn)t5p3Vzj*7TCy8gISlC0$*eRLYvdDuSso+lNG#%%) z9ui180`MHfG<6`ey2i=GGNjmpvS4l3o%(dbhRU}c&Cs?L?QWzL5k*CCiy6%b7iBlJ z>8ZF0@QU+8lwhLmmNvZXR6M=bJ@+CXF?8)7cNtLetq?ClLKid$=-R1{fVh}XFd5F> zlp(gO3hZ$GOh%(rUnEfGCaBVNZl?xK=tidC&s?b_BvS)Da|X!H+(cG%^r`~4NPn>z z>0(^OuT;&@*|ZmFC!X2Z6QXnPT@Zc}YpjyBB=-ynY)uVUNycp^zuTk<*e3m{YHO;D zl{+S+wn?v1O`fUx)_(qvxnwOO^_cxKE!7reR&Bn#WuucFL4XN%>OKTrC1fU6YsMVH zv<>BVgyeUKcty~sIN5?A?b1dri!iSsrmOW}?5JXFRDq^N0yV6-c4cx5yI*P;g=%WJ zugdKhz@7wD5s8(k)71UQ7b&P!91NCD3{sYMH7zxh^;c<>sUxcN+bSoH1;2A?$=nTw6kuz+QtdUz*F5ORSq@=g+C)+rmb=ze zG0r~N)5w|*K_YaeUb!JVoM7K{2-Hb>GX92%G1Nq!7&8P%>(%96GAi*G56`HXjZ@5) z*$?nUkJ~teIPIpsuGQ?3PA#ZT8{NQl*Ttusy{X*9&((RZ-Hbjt@JTu(Zyz1OOxg0O z|Co zSokF11xgxE5Z9kRR35VDp&Oo*?e1D?Fit73m^J8-DoMGsv-loPczJF_wO>5jI##sY zxcJty*r@|NoLqnJoL(W_IyT%a7MCX@9w1KgBs)d^y?H{wuZpW<*s6aia=JxN}z)T|VrM zqF4Ml5vP;}r9N!_zHM6e=>i zr#mKVusJ{$V@&H8nl@t)xFQ7O(aX8wySRYyxt0>U>Oz_Cpn0dd{x!y@vtt&z4)UKF zG`l8~<)DNR;>0&%b8h14H{)-xU0CLTiV5PFT+!JlN#Wdx7FmG|xBY z85A&+phkh{#OYMX4Tf*wsBsN^4I5Qj>P0p028#(`f69+9%bV>svVX_Pr>;Xq&M{;O8@oO`KyI~u#>O3yJEKH%_T`>A&d_NI#G-Aw<|WFu)tsx#dDf8I z-$T=5Fu+mX4J9KrKo( zt3??lZGUT*4Pg)2tZfcvSk_L91JB_|>dxbr+kio1tXrhtxcg~{!}q&qw2?xw{=$

j9bnyn+-Y6n@D+85d36kwpQnTJMZ8!OqMT8<%MCdV>DPU9+Er{sr3bR-Y51?`B>MrfIWc0#sQX>8))qP@a#(4d4y=>M z(^~9mvuWqGQ=OF%6pwD)ucWjZ;p0w*l`eF#76WhIuX~Q%qi#1&Sx5(>&+2|Zy zzDRq%e%PTjEMFB?{;WlKFs@y3CX(Ks-tRPZaz#b9IQ7>F3sVmazJ%0tX;$eW#~<0X z4=%r%CCHz35?{MByrgGK8r|^1F(@(O+nvujrC^;rsk9vbENja zquP7O4?3?N-jANKCz;Z$;Zo_Iv1EQARmqddvEPDt3A9i%G{!O88#v8B`7gHTc zQY>fuRy6GcHeQ8=KF1IO`**YI>R9xZ&jD;Fw-{$=cJ(MuLtne~@S#P!bKir8I@}@1 z{h(!-BOZ3y1-o1(zyyp@PEC(8>XS^2tHZo9;dml&VR8K%jBd*3tElPYoP8K51qlev zo(g@BEPc4MGL5aj%Sw;@41b$peFzsa^}g^gXn)Ld-gsK~#zX%JJ=GoNUFutmUgGV| z)S@b9Hdw5sZb9qCkUf!DbSJeJ`lEN!+xTIb7-_tBh~a9S!L0)R=NyNI+8 z!~R46kPG3=7;6e-SXU6A4~}p{vprrlDCz1|IhGMIBqEDWYF+VP%sdyMH@o6;x{XL%is0Me@|F} zKarkER$t#Pzd!u+ex%%fq&>@EKD((LI2~*u6sHM}`fE9G?w6{GFreBk>MW+485pPM z^zdUGN&*511Hk5j7de0-ww+VqH?<0f0Ai_m$f{37LdU?+=y;eOjE!R;^rC}Q*kB}p za0o3_J{0hyY%H)>Y@=o-G7L~y6I@tUp`YueCNmzuCIC#FEsGtOPw|N?fS$6XO($|H zf=mpZu&n8!61u>Ax`WBT<5V<@@q4P{Z0m(`4zyznTa|mA7D$wLBA;J{ezk%KNram| z`D!8-58UcR{GnN)(*{+nhOkm@x&(}Cw!=x?pj9c3q$P`#!FQbGA{Eahpl7QvsgMx4 zCno;xF*eN~m{}~=^>jKH&d>XgX(?ncj`T3HfRU}id9AlvyEBN`-|Kd#+xzVwae!Ab z3@wsmedZsLFz8uat_Q8Zeg(&;Xl37m>XuqBRy(C*|MY{KkkCI}fn;pLPjkmf%>NJ> z68hUH)*8NDYNcf65O_gEbHhLq1>;Y}5 zS`Hvk{$(9T5;wH(M^P7SGQ~0v{4$B>-pf8tpuEGk(EWxAvJjPKAvjIfM7=-BFk}I9 zZDd&{@|=Mj2MErAbR1#D`v=?X=SAK2y3_goQn%1W5fzyi<@rH+y8yMT;s`8`Bl-v~ zRL-YR?cdKmApnxA5@bBGa275^sxZBU6jIIaq6K9*Yl-q^eFiw?i=C zw$lAMO8FVePugyL`>E9r*NdK_l86W!Btd%y2bt~m2srPKGseT6gw+@tUgy%VGH8SO zWFsHY%c5nWp=`MqrkbQu`?K8>8bog2K;j4;JVO!Y_G>7YQzh|q^l{|J?S7VW^1za{ z;(J7^dSd?XyZ-$JuMjvr12%>Q*rJv++`;NO>3e~B>XHLx=de`774ix^4P-F*gCc(; z)uR_v=9hwma7Fh0w@V~_!-i6Hsdf>{Y{pSd;TDXlt|1y*^aP2Pj;h(=82DKJ`7$n@ z5M&l*2jNEo6OLb4?d|h^f71?;yIbi_^KT(p=tv@4DhA&pmUKR|*wIIdSjjOTRmq#> zH^juCQ8gnY4_tRHqF*G4a*{X%ZblxU*TkXzxR|O8N2B0Z5m zPz#AxV=vJ|7RTO5h6@xF7^cNYZI8YnV|0DjeI?{?!|#cR{kgIN&7uM(AU?7XPOn3! z86A?py|qg2IfPGgupZtc2%)g`F;wa)8tfZGND|YPITmokhYY1c={hM?!K|Lr?!e4T z;2Prgml(r#Btzlx9nQx07*rOvfF@ul{c{w9o*OU1$W#>{89<=K?nvtg(U+|9>m1h* z@gnY$Ym`IVL*NQqNt#?Cdi|h8p(PzLDZ037^H->lMW_o!7?*w#?xk{?SbfoH9aR~w zn_$_=tQXyHDp4~595vjbbb%rnQpc4 zQbF!IOq>5+*zJf^4*_k%L<~dG-Vk2@r*Fo-=6KCG)q)1QDPOZQv+uI|u0$V)MoE(+ zv#whts#s{pCYGb03&h=2ZMbC$gBc=X7VVlLYdC=GCfO72SqURzjgFkf-FqTYSJS^{ zg3;c{B#Wj9aAAg=#MF=CS!)v}7PZ~9lZL0httJUPBkr~n`&37mw2scuhrMWu5%K!@ zM=d-i-}DOppgS*o{x7#|@!V`hif5GDz%UAlxr6Z39D0D)s-OY8kgdnf4{GPMUW0y= zlPHtJ^}hbz+A>J-8LsSeDMf}VSjgPWF7_4l~$ z@X{1^V`DinYoQJ`xsc0I4I@;sPYjjZPgKmv%uT@5EX@P3(0vz5sGH&-*D>1~K6&5R zBQ8u|?t4ZtoW)I(5;Ff3#{&$*3}vZ5T$d!#CK+5~ahXNwdk%nZ44K7;e4VSSn@IkI zTvk|Ap48q5pOmm%n^@k#!o9oahoo`ST+EazEnqES$22@el+fuolubgsD89-D-~FE{oQ z5K4=RJNzmcqK$~8M4{CzM-?Q4*7(4QAhN5z7y>wT`LM%+0ymIb;v!NzF>*|UrucRH zQE7wX=W_+!ERhvegm=<~1npuzwU+!2?*M`l<6V2KDrK?P@F1s)F1Z2KK0?>hmj#!& z>sjfi~Ps_2X|+WA@kE>{x0|jkfr~YZ=mTKLg=(y>0P}suu2W>j|!Z< z&jvWA{^U&dh_G>{r4kM_G>d)Z@6j_VOZ9ex^W{9o;%!>Nz+;^|@DdApX7C&F!<@JF zwXyMEt}P*Hl|gjd_kzX|Tlf$a){r|!=;gbmC+Ly4%@*xo;_~M$}v%a927^Uc45N+?Nfjd=3^B`r6^>E`0cAR zQ<+t0=BUJgSPeb}=Rerfkuu$)@`|a+7(GT78Z@POT1R`0@m3$2h7Y#(#9S z*>Pk8_n;rqvzW=$sn)7v$&}dh!b>vK>vUxyVvthR(|Nbhj8rh1=sr3Rh+@gZoa-(^5#(BI*!=g=>aVwjNW*^R5Ju!`q)-dPc)Q?%cs z5h-j_=cZHr=+i_H^kOH;Smx_#T!vaMzfGysdLe@R;88ZhG94}R}iY1Ux6UWY$Xn!AsFQear2 zB=eP9`8P^z=(+-r6oObw;*BYI!$PWi^?iF%w9A>{pfc>M4Zgd4t%4Z3p`Fl|vWn0s z{GU_EQpq(2aPZD^6t3koaWEAfRY-#;bVT!nr6u%e95ofOEp;>2?}!o)a}2Ii{J-WR zZNxv;kC?GBDR2G7D7dcvM)YLkkVC8kxTQ=j{%qS=n zTL+|Sbnj3|l+n0;a|r)Sv!oA;LPBAo=%agZirQ3Xj+r9dVWGsJU#B={aFhO1?k0P_JJ* zGO72-DJIWV&UQQvU5#SFJ(ru+j0Dw+jUS0#D8DIOH0ac~8gPzz95nEWeId1w;Jk65 zswP`M=T?|Q0%{l!fgRVJFhvU2#F3vxu&_lf>k#c7LjEyLYOJt_>(cm6$vi z5|j6C$SUpT(W51oDH%RS753*~-^F}q=8zW@=mgB-rBEfi)g*J-ob2S{u~D7JuxVmt zD7K^BMm(sekZJDLh;Z6r@Y|^enCA56Rp;wUv0azolgUOr6sV6`cG^f)mk=t`Qn`aFjjpeBEd3>hsKPtjNbBvgA+Rby4)gjTHLdsg*K`W#E zUXtIpq5E^hUnGVp-$Wfd$~n`bS3M(?ZoZxjsZR{$nCuvFH=;$EP9y(a=ND_08nv%=mj`N`aG|>Tok$9jNjAy4 zF(HdZNvm+vYU_>?6k2dwAo3?G+=Fkoo$s=K|2bSXIf+tkeJ@qQPD_TYqe}U2+fPI# zk{3-2@Y4Yuj3z##Y%43a6wq_zOJfc(UT*z!a8PXuRNYwJu7t_A(&Zt%M8@TfbCmwRWX)>+k(@FEOVlE=q{M=n(<%f<@_uO*wjR*13$tCf?hH$&~H z7eVCfP?-03XO5swu$i_OQj(XdRD&J0x9Eme!G^cL#@QEddA}@yoVUVcUf)ioH=SfE z12QRU9;7lBn*dhGtQsiDK_%%Xn?M&^CVkI<W?zXee)UKy_?{&qRdEO+cx9eJDCKPASW&R50f+ zTAe!o?glhwY3U!ImjgE-p&0oW#8%h@p44+n?2JsKuG~+c0XsgDycy+@O`_YBL=b+| zGdMcQMLenlM8Q_jCh$$ zWge)MB2D||TdaerOHbdHotUVDwdIifBimt*H=^IWvgi@mJO!ZRgN29$>R6D+!WX0- zw<8kRkWvCNWJGlzSDWkv8e&p0y6J1Gxv=3=jVYmF)ct5DVk_0sT5U7_F=x0Uq@#d{ z$gNG2WpVhEbI&_%i}~;NL$Q zK(!X#>FTAK;xp9KMJX3*xf|1v?@-(CG~h(~GgNL8|HTl8Hkz4MLTX@63z?5R z7r9sx^s+n_lsfL_6slQu*IMZsWSRDD5Sf`7zaGO^!oZcMNYtZ`wTue;?FwhYN=nNL zdgeNnZOU#gHKm+#RkNTadjBiye7Tn*s%^-$9lfHW8RYW?K>+Qw2j)wg-T6+j1n|w3=#cd_XQy42qJ|Y;X zn~UVvvlv$AKI*4UwCo3$=0VVn1{(D+hnf+oq@#x~X&ty{VWJ%owS^KBs!I%-6obj5 zMfRny*XL!M%QzFFW}oxfteg0 z6c)c!4shbA$xzoMWTtfpaMuC@6WvxOFIxW()%3yjcu!x)kCz zQZ@D7vQ(qzmm}y6lENY=pz1@phbJ{zSQxnYHaaN-S5-^PTf#KM7zGZpIWhmTyLdVZ z^z-;7NU-E{42_VJ7%oLD5ScnsZr=9WkNGY07^m#Is{Y;VwN}oS+wwm4Je4q#ftG=t z*z&d5f}zvKpl%anrTiV5xWH++BZcf=9V*c=r_nKQ!Li`p z@i(Jmyn>@r_!IfP6J?T9b)!@5f>ZsyQ)v=&lYh>H3rDj5PMt~4Apmz@pnKi+&VxxV zJZUc|%g>?KEG-Jo({cSa#}Vwkenpa8eKU$%N&KdwZ77ddRcdtI8KiFYblgv(pjHIv zMcaXot=^Prf?+Y;6d))Jtb)+mOgV$rN*h;6DRnd5j=6vT=*c)%Ie-CJ6rI0O!A`) z{<3m0xM%$cXWxp8^fg1ThLz8Bw-j1GYe8D3$zG$Mh_)<^*`^bi_{WH`c>2fvJ* zfq)m9o}yAzI+;X58=I$NQZ}7NrTXc3Z?T-s_}rM5AV{@RNaI%S37AeUpGo9#-n;2u zt(+_2PdI|M`$@Y}sZuI8U)@sky;i5yZg-}=b{&jhSXIQuMjkDZf<3~4O=o%%!@`Q} zlP}-du-ohN(~9^?^Fle&HU_Yn92o(`CW4uP`Qr7s-C|82X=o!N4Z;86LR!)`W zd{ckv#XLJNE#_QQkWF{~+*2)%&5V7&pUPHHuDzSDTSmvtgo5H;Y1IAdW-!KY=-Oefr*XqVCRzOwr%uNQL(v+pC zBG~9D%MwoOXF%Lpktqq#BUpr+oOvH*Tj*Kl$xZNgWJ2KOg`h_wi@u40Jl17tQZ#L& zh~px zeLGpZ>?#JE^P0TFt?wW@7&efsLxv|vhP-C_s-f@dw8rs|YBf>eegs@dJS9{5nM}(b z9YGTE@2)EOt=n;`OexzM?2vS~p8DW=+3L%RR-im{Sy2%GU8k`UpOOY^f+ zDSU!ynfk?El`~V?@}qoD!1C+Q10!L_Us~AsyQcccc z?eR5*%)R-{gMVyJ{A>Kn8Kmw9pZ1W70B|xQ?HI{cZy%)l=u-n=eid`H_#)_4%^^g+ zhft+bk~Q?ML4>1;FcPR@XgsgI4-DC ze2lhnj-1E%gWREvB^Vmk#K#1e_)pim&ICdoEedWo3GrKY7LwOiT|F6VGsHCpoRxL2Jxt*Teh zDqz?IFU1A97&Ct-{m~*5j|@|qY(zy#G&}=C2FGtbedloGaVcZ|u6h`c$-BTQyWlX? z4yjUHMiD^|K1Nkf4#O59M}-<1KqSLYvPrN>dxV#mY2uvKh_8kfh1U?|&}e`;tkP=7 z&|-C4mcN?xBD$?IK-p5inycaHw5#4K`>xguFCn!YK9%sW-Bx2F(S&w*rudsdXU36aHR;-h9Z-Gyy?7b#;a#g;>mN%y zJ*9>#|2La63KAf|au5vx-($f{UQ0QvrdZF#5tF?lb(s4gU8)O!SeEQzZLJ*@DVI#7HMJ6zY&%6~f`z^CKK(8G_m;>tbyfR^H}-QdxluJ7<$uvN*)?FhU>@hCZzZL{)>9Hi z>=F9A#t*C7=G3p_VR6shQ`9CuiyfM-satP?)HLn*;WB$s80)59P>`e(H8s``Oc$(! z#!wKv;Ekq)mJcyU@>a9Qf45-y;Eq9B4gGZH-YUU6_J+e+Dkmx7McC%1?vupZCp=fz0mx?=X5I ze{hipVF*!$EquWrXCFGhJ&#C^iowe)uY12YD;Zxp7yr&{umiWy23@rG|2~Nu|M?b4 z^4{+J@3ptkQ4;zaDmQ7h@wR^YwKe#oT?|Mj(-2Bu#9t*%!KbbcHHG8+80`NnK5`<} z>mEo51>`?BmP`$fZVNUbHv-5gj+{f%L>U=~LNFKkn6E4Ua>F~BWMFv~1AmS5u3iZR zNd$jT2jj{}6op$CrYi7iip*Nkx{2Z{W#PEB5YtA7;z5(+=)~a^Nel>4fz~ z0SRPGzD@!A)L8W~C?vaRQpV*W!@VEQ87$HT1!?HVkHvrB09ENCF0F&mzboBSDe6kW zcvFQ4nR6|Ms~mVqZ;s)^nNm6rd)Z<{t9rZrZc{=_Wi1>(E3^Q z3fP+BCWj-46-77AKwnVBV3kyBC{=@mQ`BwNG~`ZDdvV^N!`tslIGUmn(Db4xj?k^t zI>#|%DKe-%wq<)l#~5aMrgI^SP85_hQ;QTPgeIc5`DP#XRj5;63O?Q*i@R?#a-2_G zLxv=?JzmL6+hT%mUrRBoTo?H#F_0ZU!WEwg<1_a^4XITZ%3B*Gi61o1)>Vng*saI> zTiXhdCPh_=G??a}8CPV;WIH^}0vqYlSwtC5XTaW);|WD$ z-g{#D^J4_c3h1~q67s1dUYNX5JgzxMe8wHo4TQv zXPomXpr}l8rg3ysL}qC19DjC8Ra{Gp82VGlRF|JQVAyowdV=_J*%Z?5f|pBgmB=uo zW;@?g8)zxeFPw1d%;KbJO6HMt=p5VH_Ox&sy!q;)iL=rQ__7$-V(83}QYcy`JiDBi zFIPB>hOecGAe+N##yk2FvYHax>d42^0$i=!F{oU-8TaBeZ%6u4PDDRfTPNfcHN*}3 z)eZ|tIL+B&y>Peu$r3t9zr5phOIcWAFl|gEcY4@WWh5eKJQY8@#|=wB;CdqUZz?P- zJthWJL4;jaiLK9Khv5QlDRpTM0fF43ZH_H`WlK(Gja{&3jfkr)B@eobw7TL4tZJYg z2D6I$UpF`UsOktr7i8O{^cptk8g7U^v0a+Gc+#Ae?Li^ml1hLpTBP2S%6BVa<~5m%lEQy<%*XW-Ec2!y7u8}Zmjhj! z0+AaI#n`mT-b8;yM?jsso*I7T9fxWkUtK1);vK>wYgsA57{?w+Y1&~A{9@yeX>X5{ zJlSE%Xln2lyjm&k*ee7_=VOxFR&X4egX2>&*d{wcDQ~s)jRlK}ytP27xBZnM%frGi zxwq4>Ic!fo#WU5nBZZKCDufKXt7E#0{iMrA!=DE?dswu4*Sy>E$nROVG7hPSg1*Pv zBVf!sK-ivK0MLq$AEtZVQ;5_%Mb)eS+`hitvD?`_1l`w&)K|>dw@@1}cOBkO)SqA5 z^BqrW&AyUrs-TMjSd!X*Kr|qXhYkRc|AvM^1i%28SfSJ*Apj5n06a7R2^#wU?+;E8 z(GbA^qR)rt0FdwjDn&)ZVenWC22)MNqfzLTauV<%2V-&goOVCpn<*xf$i!pIY+OI@ z<#Yso3ezp8QyDDgGa5S06^hxM?q_||>XnP2ug?FzY;#m8mdGd*)`Qw?r^@;A<@({< zPu6NNYRz`HF&H))8Tvzs{Z$yZTCEln6>DD^cRKXyD7HHNc1*IOMf$20kHKbij{FI?5zcsK43hP=F@D0DTMHiw}x z8qML`9!(@u$|wHzX*r$E=GI!6>ux;{&;1rhlEBY(xmtyjt2E!!ZqnFbKD*cJ*KxaJ zVt>3hPjsaV_>a7x)W`P#fQV-_Ug+!odA?NoDK7~5++X9=+V3y)_rBd9B$$IqS=r$+ zpbl4Sl}X8Da^5tSD!(m9O!*z1{1mMFRxA*Ki-k{C=mLh}I|zgq@CG6gd0^~&z#!@v zAljlY8;1feDvQPbXnKngvf{s)M&oC8eer`;I3V++WRV_@pmw4&7bR}l97ke9lqOB2 zd9BKe)!3Xecg1|=J5GV&%MK;54L3b-rR}nw2pdxUwU_a#=}VnC0)uWzsE#Tlil+!! z1eGQ#>>@jWG3;`&N>hg9t;jbFBCvANasp9* z;#m-k69H4x7WpF(S7NAHEg}a+R^g&R=pk}`bG+gXk;1g6K$(adR3oqq5D6Qz*(9ZP z-S0Z2VMGol-afK8ESH-D&W3!~2epLPs*qHGKmtFw!^;X{4!t`c6)Dk(vR5S>7(m95)E!%Pl4*ATHh&u?C`LPO+U^b{vE>Nj* zV-l=89RXxJkWOP|-`FBr#wU9QKCv^u43C=DbB}5fRl4Jks)A)YwuU5`_fv_l9U_s^ zY3kc1oWE^WmGTafy{_>&_fuyL=U?)SEITycCkn(T^q)6|QGdaJ1 z!P9!nbEnIDTR)dcS{RV1fd_X2+}dei{}n#_cAjMm%lh@$?d{EU7&1)XcNYw`@K1)D zzeG~nbIe!Q1u)s)-hS&CU%L2XDvI}?B8%5Jg2+$-9OvS&vNx1K&H{=BbjIh09@AWS0UI1Mh`1}8q)@Wex}H+DhGMqs%*0VFt>M_A%}Q$%{s;RzRC!_sf` zaP&TvKgiUi*4_2tC(Bw$bYq?85yP;mX2sb(50XSDChpt{>jeGq6ZXRhYW4y@s!CRi zIIu-@+c{U$^+HDAAeQ}|?Q>dqe7*!w&%#0-nGucS=i$^~BwSJ)hnjd)XuqiX$LAg) zsCh#2Bp}5dUy2nBtw}_F(u%)c?{1vI&}g+^r6*9S=kEQ=%jk|$3eqz~oC>e|WW@rR zkU~2kxj1^Yq1gN$-leZmdV-+#vXLp9hM^5dg{pMv+WNeP zNsFA+W&fGeZC(;$$Ujp!=Np_}aBbiec$!P*@jV8Y-YXnP0{+snV?YlC5o#2EjLnO7 za?)%pBP3kYUx+27t3)WZ3EiTv6nXw}=T z4@AZ`2A)<&Th?}*h6CR0a3OQN6^4qLyif4Yf%QB+p{n0m5m9v4!_@PgGXMp zLmYR;rO?BVTAnIP-p`M(+IJA!Gvxk)00#S5hKOGqI&8a`b#~SbHihwoqtiCL_J8iI zTTO^LWEA-_ z9MV;#4kPr(x51nj$7KIl<}O^F%$FHQ@#|9(Bu#lqkJQx+n%Yeat{GV^p)bfp9{jUU z>oeLTEs>*>$DcaM%m9pgaFoIE?1ck(hQDKpc{F7EudvsYNaBrB*cyzk8bP<|K=a+^ z31lJo&h<$#7KdEgFq>Z|`17dk zoX(GPMq1a;Q!cNqvB`D2^_WUC^aJ08YEV6G4D;3PS$BH0c3-Y#6o4ET@$gz|cb#uv#r!f%Czz78&6KZu zj3f94vwpsw&du9XC7D3|TG>r1WxkzY>and>GBO>joVeN9x zwR60(caGWQYtQJWl(!vP+1Z!|Yk5x^OYe|>LYm@i(Gq{xIOlN$9DbYdRS`wKh9&B* zH|+x8GoG~T*L*o7NxFu=2vfHoziOe~SKG-Zc~X<_U){g!9y0WH&lZn_`5C(r;3&zu zahf&q4Cw&$M30Obz6&whXG~o|aogqS_AHkcy_q^|RaIj8hlAQ2J(d};@F6sHj zgYLu98FOQ~$vc^{uv>kY0U6cFvQuvXXymL=27d+W3`5Hf;UY^y=D7OdEbe`${X1Ao z`nPPY*9riSrC*NwHWPT&D;H?1ws7+>fFTVr>Hg;3>{)Rq=KT^hstajI4g4gP`p z2>JzO1-8O7^Wf1=p$&reVSeUd0%QmNJr53Q4nfBUVrIjBrm^_31M#zgJK8|pXuOLP zY*HEQi!mS$dnh4BD6tIz1jPTKRRsXLKco4W|En*9`0x5M{AR%a>C28K;-J;TK_&-> zF)R}Bu<)rB)ETKz+8qi%F-v7qNk02Bg0yn^Y)Da51yd_%l}P#(bdbpB{0PO+jwg`t zrAnei%GZusrWi)HRv$|sf`Qvcw9W)a%|xK742YnL)Dt03O}X8quUzH}>^%I@1s#Fd zcfBN{2k^k4>Ck<4F;1X0ZVK#kc^rbo_Q+<(lKKe`#O^6WfD++U1VVVsm2vo*T=c*h z%g^<7yDtN=qATd3hybQQJQYazJBldKE)xkX-|&jU)c2KIfwG`7n_Ua z@}yBPjnfz3Ic!UbELYQP#)DbWJmaP1a)p;e0f8)AU~2v9K^cLCt|*iMHYv`}@7lW_ z@Sj9mqk#M(aXGxQVI!9X#s4%SG6%^<8f`9W9$~kZ01b&D2_TXz#-WBkB#_QbBW=Et zG*}*GLo$-ci|#X}=XogHz*C~}^rD#u2x?f`i}lg9@6 zu&pX{$E{&5PEWmyV0`Fh>7ds$X(=vCpt)iwyL)aaSImqf5!BsZZ5|sY+Ot#;jtG7$ z&B}Q!uPpWRdK}TOjikDCGX^27I(K~@dnV4P*LFV9dY06g(pGvm70A974q6hsaQPyl zDi}E^lBaM6!Sz<{Dry_;>ANB|{TAN~tjlXzM3o2;(?AXwJo{E9DRk(mrtck0S_sQ9 zTEJB)jm9BeUBNpwtP^h_0gK15SSR(NeuH^R&%sDAOWSLHP3QJi?Ic;Jl#3`KXPzsb zX_v^beLY0LzOz7bfC_+%(4%f~h2^Aab{+Kf%EU5H1r{KRPHsOtMp2f9L{gE#>2ZJc z-VmWln$DT0m?Gb1tw2y`D=OR2>tZWFG}bzZKpOr~`w92E@9+};L~08(fxRrzH5zm7 zTM!~}Bcs5W;bzOyzSDcEk(7x#qQ*qf++{B-Uv4X4TUV~k%db^G4dpoz7YF@<>yqgWXlPD%-KASYKMtu6r^^ocfUxe@{2}=o_!Gv{ zWgeyKD(|Pdzzaxst8~?BkH_(#M!SV-(06ZUPoH$dreDl~Pc zE8P{a#3)IBa=d>l(Uce8F{GEOG_cZE&Rq(!6lP+MyTo??CA717xN1^T6g~9sMO2pr z^%xrh7yP7JmDuFaRJigs0x~%yHr9d)3$Me}FZdC$89FOwk-Q;2uwNAxIU#$r#PjFe zCtB3^7S=(|!nkL9V(fF+L-yH@;OZxj<8m#<8m^h)4f=e}eb`m`pUDZ+Y$kYmKIc9^ zVzJI;CIz-16Mg2)rnU8er7zORj!^lw1fcmD3F%+xikW?ar zGs%T-#^}5Y%*d-QQgR7jtmIt;2=iN{xFn`P&@23DZ1_X8jEYy{M0(Pe0b z-&yllP6XjsPL*fT^H4FkL9`eZYLkRYZakV5S2OdJaiI-$3*q%FkMsr($=HoEaqwzX zwMGfk8Ug~EMr+IH;+HZjN_IHK8iolOI%I^Uu)`qo{AnZFTDjJDoO%`psN`q5K^aLl zqf%dMeTu8Fkj5+-4^lKFQt|>YpW&|U5v*3SpnEk&iH2}aOMB;yU{Gpoy z|0A#bZ&?C{(C)`n^RZa`r@WF!=OTv4`ROEM7kQAtqaZP#ao}sIn2!ZO=G`nGg`*%q ztCx{;n9__OSxS9Tv|}4W;53}+q7!(KNKQAU1K{|yUMm8ydg{1D*2!RMq>x~jRIO_D zI-F`_9gEGYMDlH`HeEpJ% zr{r)r%6VNb4eR!tSzH76sM+xjN47oPHgQq)RP zil?1{?rC?!ciE(}iAQRqF8%gZLk&6a|k+V%@g|AwS{baA{hpvaUi;^)M0E`AhH zPd%vmx3#&A;6vhhrLbZ?MrjOE=0bl;4@uJ~0h3+OiwCbg7Zg+RE*V`UX^9c`(7JDH zZ(#9qtJZ)t#Z}J-P`(s(32a+3Nkbo&v`nnGin7Rwfi!e}iiS%T4uRT0LLQHv4x5#! zdk>`^lle|UvcWu-UMiS|HQh?9hZPu*z}E)XPvZ`!C>QG0(Kd0LSh6JNUc84_;yg9@ zK@tTqc4zT?Qj@VI$I4f36k6|2FsFr4u5aMi^v8Yi17Ez-j^u<7#L>dW>T!?$j7g<> z<4f-qLo%BbkD?Y_)GMO4xW)}9ob5&gXS-mzAyIn)yMlAuHMHrZi|>k4vlUF{aM}Z7 ztvc<+6*)R}fjr?l>nGNAIO`)wl?&D(hBcP>l0C42<`ZHZ*bIMj;*uOHPCs%TrZ`EL zA{S>HORFbg4gSz;m6VTx^Qf?@PEjy%{$f(nkect+0tIgJl;d#+?<>X7akm~VoKC?h zDb^~10e#PG!Ub@ssw;)oY~v+NyM6i6#j#Vh-}Ff=@~b{wPWoJvcIG|a4NP)e0;P=S zxp=+k_=0Z^EgE9MGv0r@2Mw9OY{)_!({!J|z9Rr|*vieInTk=@IPI2_FJe(%(tl1T+#7x4K zK2__t7cKX{`FB4L8AH#T>3I0B$0#>^ceW{AI`0pveYtdHw=Wq4G+aTm((|+xHS0XF3TMNpD z5mkY-i>#g1!o}~y;%+%FvW;if(jTVr)wzd>K;i2m7%d7Pd`X#dPi4}_Z3jn4=HFyH zpqLC7>nC@X@?v(B$|hNsr))Ll+}gx#Wkp6c>RR6y(&Lp6;Hq z%0&NvMh1TarvH1W`!}hLLz<>gx78o^7pXm5#|Vg|$AM+V^{P+`XyL-2Ob3Szp@;)o zqR7$YX(sziQYJgXVpN96%(frJ=Z8oDvu}f_nKY<}*e*pv1VUJ&Hce+S9 z6Exh`_-d$t1gNrMpLeVsKwP5f$bOTrgz>7}izaR1*cjl|>LaU60D$zsR=!trXj`mz zf*u@7+ z6NbxQwgJgl33S!jZoN43t_d;ErV!Z0!i$#yMnvGVOfV}i>y$ObXbPmOuR%|10;ME= zK~A>pN#}!+EGT6e&^VCez(^qie}#-s8pOdf9?ZZYi__b(1d9#L`xxVv=>+2tT6eo_ zMfY1oQx#29MdI_#=Tk72^(T0~VArRPW;I}j`wMW->Nt^RD5SeGkLbLhIB>L1OFhNY zSGQ${w3=A}yvhi*?qnf!8Brs_1=2>}gLd>fJ6V#9j=VjSP-=W$EXn>EkgeBrEQ+a! z*MsRHIK0+vbUBGJ%(K#O*GFva(1&=G+$)80RJ}I2q9Vs2nzDfv&^gjF z)c`wVRj(hKC+WBCR+L#Rz_bcA(J6oUgVE=Vr~kMnse~W|ud(<>A59SFooZ`iSq0+H zW8duNV?FA~QRkVpmZRu~=!EogxA0C?zFSWEqVf&DpSE$!!(iX1DcRo4_FMUo0o+){ zlT&I?PVS8l4Tmn206mbG`C!cEIa2{m!%A1{r*W%H$~kTn@YB$h04h6*|Gosf2IF~j zJ%72huVxD&vLyQ z1ba<1s-2SDRUC}x-EJO>_f&@Ue)<8jz_kZLb<1_w=nP((QT}r+N4QvPtY)(&ZD{05DBAv zd_mi1*ZM#MYNq?ek4Bfv~0!wPc%Gg-djcQ;c}ohtg+Fnz$$s{*rgSBHp z&YgA!`<4Je3d1cZ5bRV&(BR*E-cxPR?(h97SLmeMG1!syM%n9IL7m>JH zjIDeVziAb*<8dopSt;S$Yg?SC@%UY^cKEuvUDh?y0|WGbKym$tw*mm*Cwd#=`VY7- z22x&LhJTq!menH2IH;u~s1^Cmko0z%ntX^U#^D5Bc}-is9>7={{87u|=~)RPRW#84 zN&HUmR45m_KNsw>Y$lYot)uL=VKbIT1&YXy_8DUxd^^;o59YD!1x!g^Tdmbuoq=F+1-RS% zJPw3@tJk}qtHZlI_8)Ib#qkq@@k?Gy%0CClMCVLNim2MwRvGtsC?qLGmZ2~y{mqc9 z@tMR%)?%+_)RcIT-+z`lH`PiQ2RW3C_LqR>`% zf>J1I#DP_tm#~B=c)!L$tzn2r2w$2uxp5F`{pFU1Y>`0*y7>aG^~5?5wN@@%U}(&5 zNp8;WEeqG>v|_W8^gZ7%MI`0ht{K_yjAT<-BT`lorq)&%x}nQUY(|M?k2)GOr#de8_+`gg1nm=Y*9{JNdM;}afy|@qFECw2puHori3Iv29 zJJ~XA;kG$cN%_*IgwRbXhohQ`DGO^&rMNdvBqX{q<1sor>7;7V?KZoLQO$ywWQB6S zlFrM;0mv7bbk`;!9oigCy9!t7kYKYu6YF}Jd@z*WC^5on*;E?8aq!89AW>(Xl``V2 z*5k2(*4k7GD@%4mxb>|=pXxc5;foPa@l`sW>^m%dTbcMQzS=d~23<;P+{bVv21zr| zOA>=-j}@L%KXQkg?0eNB!(0urAh_A|686 zpP#2>8;@|%!(u|+!_rw{%dmly`+I;9?aH2Rhr+i<%n2G_%y8k|Q1MznjH)lda55+c z8!t1iUmjG1trLcQqAs)fVovU~wXuAg<)oJmQ+K#`+gsh;icK1>2bb!HA3m0FSvJcf zO*>($4MwbP;LL>H1W+D0g9*1^fbNod=*7?8NfXoJY2O6EG^PN?8+6dz;elIO4fhw@ zM7AF-rTV!D_*9PyD2Hxjp9T|zXbn^S!GF<%Q^FAaYW(Zfa#)%OeypBB6fP-7xV!}A zXK(g1M)K&gXZ>&ncUS{`F23RjzDF=N`Bfy1+^hyyY# zOr`=zGN4{mbtvc-{dkTpca7v^?@ko#uubmH%HvIkjho_Mqy=-8(8hYJSk)w;O-v;m z`RpooItdv>4J^$6Rb-3;GJ*#GcWMnz&?1Z;?FK>9BGiiYf2mIXQfr()9E#z#7$v@| z-;s;Fe|@le=Ug(GiwMM~Sw1b6!DEw(615eyz`V*c}hxK$gi6(0%k+*Hy)Xqe7{TEeh1`>>)t{2>f6H_CU1j1||lBQvno!3?z|k3yRt$`^+f_=1@$lRTBv$1VcJKLUb(B^ z5G26q&V{8o&fNYevtA=^!w9%XuTQBZ2qS`sr^Sa*m~C^w-4>MOf)IY!#CvT=O}?6T zZ)wc>0PqfXV<3?mT3C{S;76;&DQVPI*h#TLRcy$Gn21^t3 z2HIzza|Gh1P!72OW#iNl{X`e@bniOwagY!@5HJu1VTyQbo8x~_B|(6~bLcO7 zK`pFb?Xk(?zLio{4kA+lqW7jJZcoAvtlmPngn&>;SbA}>H&v~tDIT#)5N=L{m@$wJ z22KND5MiRM9zV!GN^y$U%B z0i^M~BV762YZvgUmOU)>eaJ|$kV)S|&L8QValaU%n(sKgji{zu34kfI*fK_142H;4 z02tY0$aT5)6-HF{tnJenkCGoER6s>G)ZSQ z8-9$s1%o7k5a^=|0vOb%fg}(f6ZHg60|Ipi_LFd#0y95RHkv1|6PubU?UzhGd**Ww5O zSk{Cvkm5p@`SER!u2aY}WtU7zFQy()mO21V3=2HHDvI9t>?ntYz>V!jc9WoFZl&=PNPcImHL_(XH9`H zFG5(K-u+|0<2ndtSa)ZXZ4!pp0gP%70sg@pXKp7DBezE}?j;L^CINJ%1j@Dv+td}0 zOP@iHAAJ1P6huK!AEMkX>2O2Vr@<8{bMGXsm^S7mv4jtc!BrsR)>bZMwyT9URXY}*qhH|4?<8MmOa zdvHj+xbpm|n~s5O`Jkvlg}$Tf8_rXWQz6f{-K2MI1o(Cg8VK?dfJKQ9sq4v zN!(7L12oOm%+a`e$0q#T%5jo)^wULrX(R;M-egvF2HkxX3mucr_%qt|jm$^II zKU?}Sj~Hy!^~a+&t88;hs(PJ_6*1^cn7PC&_G#+#QJ$q?`^+!H>-weOqkfg2D|WLU zMQ2>cYSQiflO}@Z?KDnSFR5l>OGzC)*^Va7KiA4kn%g(=%Dg8-*8#EDA17!|d{b98 zI-MFmkU7cx0{k2f91$p8`0T)N{J!LmoS-{t&6z!B=vUB?*D&2$V~JMBCjC8TWWVaC zGkKz4&qzyKhB;}E8Ck~{TNzqMAII2d67B84=^D!ppS+3cqugVC z`@@r8hY?;kb>sfaY`LdT$vP%f-+O)ChWs9cmZo35JKg%ScCxGE9-&Kl3-$YLgZ#eh z6O-x>Y4JQ3LH-c-D7EpP2}L@Q`8AN*oeH~T>7phFQ4XGOaL7HWSdr`2E?q;;zvq$g zVNX8Hx9Y6k9D7f~ZBW9ZsLy0?i54BSHy_`yzI(vumfCN37)tKtVfQr6Lz+BjdI)*l z6eLgX3|R=?xYQwDS!89*nxXFAZyz3$|wn zKP!D48WvU!4Ih&ax9Rcm*b7g&eaDm^j!FrOvJGYq3+udiM@i;&%^I;CDw|biS7R${ zBWlnXMp!NyNnqwIff-5mI{bxb)TV1>vUQY`mr}QAL@Aryo1sV*(O~O^s4tQ}{Am&W zEpJ(EQ4%bn+k??GVc|2L(U;9$vtgtsaxqUZV}$f#N){t2JW(sKh#K+$MYq6G1)o1Q zF<8T~Up!)I7Ri@}gMRDzJrs3}3ysa+jiDX(7$15!wHVF?3luDkgWtxvV#dPAVvbwf zMsHBk-h~6eGoVCh75BcS%}$DH`Fad7df1 z6p~*oCHKk4Rp@%nvn2|qg>Mn0+cXEAV8(xJa$LNQ3ieLohXrofq@u8pitH%?nD&5& z>Ex|p6$&Z8*`fu*JwopMO4&VU%Tgu76Jr!ni=ol6t(kSOgp)Le7|gUT(R6)SmTP(R zr=iq3RyT9e%z^ZbJh9j@_Sn+v4ARtO-Qmo)5QuQu+ zjy3sNYVtB`t}$8GQTkiBPwcH&bk~v}X-3{B`J|G?yqf*k1^Ik+th^1oTp`w5c1cX(TiF$=lg+}-+W^a|2 z4cwMx?GvVzdScw!G=wWT-iEL1g{`Kza%qH=i&xyTKes0jFSf7X467)jtUM{GsI%3o z@^Oe^tNdUPSGio-W?T6S>$y9Oc<7+gHLWa7ylPyWXrv-&RJ?lDpnBe?dNHGVxve_s zNB$~hMCM&}E;K$w$thB)=9PD~jc!d(M#-|c)AxhCR?1=?wwh(VfWr8id3!JG#q!`~ zZ?4grrP23y74K&c94;wyvS2>T@>$nyZ!?u@TK97ll;Zi=i(ih!5sQXUE7Tb)Wr8W) ziGI`;D<;xr#tnzZYh#zVV3)pa3qDk;i=s@$ZH;8Q|CxJ|UMqZ1KtPqu5>aqfkqnA> zLuON6Wb3=uQaa6E`_taey0uo#rzkf)1zkluR_3&_|Gu9z!^k%`*ZV`HeIBEoSN9Ju zL(0q~tN<5tEtDnfc~f z;MC8C`uB-}+OT(^f->%!tuBwu*REiq%P4C^6>W#6`mwMf2qg?_9Rc097jOA(F`e9J& zva!gnQ|u0+F=8_6R~)H5UgSMfqRp_5WbHJ9G0`4(_TDQ+yV{ms7Kbhv&fEH%SBK)B zv{WTRLiNPn?HpX${PuM%l?gu=+jt$`)1dv=WTt4_SrTSgATrdZFjYa zmH81_^@Ym$QIxsjRUhAFrn9vSCml6*rq?P_cj&J)^+yh-iVvl|swt?d^2}JE_2I4B{KWF}zZ=TqY{2%Z(o(MPeLV1Er2a`n z`*_s=kHTp2YLcc=(WHL+eOljE+XRxUuc#HJMLqiMt{ww-f?G*lA*!R@yHq-BjKL^E zfi11?S881OWV*G-WZP81uTkZZDLBnk-B?tc^3a-iFJbm{*7E4UZ40oYo4R`Xp>e%S z$H&SlI|hl*9LB*RT-62&ot!i?{1P*Q_r^2A$3)z3XT&?JN?%QLT~GHeeMTII^!epi z>V2kK>n+)yG5$rNFfluMl%#AttCl^p+0*kpYA)7jE}>*DxH8ROZq5!h%j7WEmQiAP zTs7h~oya!tRa(GgThcE-wC|N5)HbY+{fRYd63o$`JywdsoGkg3F;Vr&lRM)D&El_L z0ov`2Z`$5*=?xr3_4-9O4|2Azj@M`V*8BW!2z)gujVBy`G$t|PGRV64uo5+x)m9Xp zq~ut2zdTUYGPaXidhRo!Bi1OmP+{|A!TN1JBV~@QU9n$P{&&4aXWzj;t;z4JqiDIC zJG^|em-;SMh6{eqjsITd&Y17c?ufkip0HY(DDiGeugbIM%9xOttL?}Ls9c&o9(HOS z3QHd-jt*MD+{A`Il{y9LX@2*)FXvrih%F)`(qnls%u-=*Js9Bvwjt{ zNo+nG-TKtoAh14LEY=yr8Ice^g!?CDv_1cvW^=}I!AoLI9=D(LZhd&QKZJBiT={b& zO*1rSNmu1PyM9Lk&HPpN(via^bH=v1L5FYTqRLv>pS|gT&J7y;!Ta%@KdYs#6Ki&& zV?S|by6|QshpXZbY7#44(B|2*dqbB-xv~$XZ4$8ZKiEC&oiof8yKYMRpw*qUr=OV5 zDl+~1bJ3{$@!PwnpQkAgPRXZ1*?VQ{2Q~gtK(a%P-v6s5*blnH{Jp?eJgz;D1zMay0VkaQtc6w9^u4x{dYG!4%K8eASuBn8SvgV^xX$ z)%9cCjP)zS#v0?ql$x&X^~3i($l%VcFMp0CA0L#&B&MZr9;)>mKRxR9?>c=NP}zC{ z`0^bfa?)HnDyCMD?{wN9b2_|~i{bqJ^6>OQ>@k!gWmEO+g7fGPZQ+Si9AGgGe9}wW z^=YW4aYpTcwd;uU{@iW(T>KvYg5lA{w#tR5a~*%~#gi}V!p|-w=q{z6UCQK!%F+?7 zte@WdUuOM2r=Gk#={$cvdHLeeXXeSSeTA6X%slIi`lGQ)i%)GvlpBoBCn$w;g!qzP z&C=GV>PX`qw)JMqM>l#MEiZUB7h;auqZf3akIxxx`qE9jG)i`)PIET8YU3J9#aSP4 zT*Yg>|B@JFF*EtM{g9p=ST9%cw&k}JF_MS?v8)ft^Evp z7W#cHrN3+ALzRE_WcrfP4evcqzqS9^Gu*on!-TajX`7Qpw7EYp4kv_s*JENSWC%H~_opW^E9Hp4{R5`d+EXu(ji!|~h_e|j zQq6uEOsRdKRq>R}pejTAP^ZSY(;q^mbEH>qHIXBmsdH@52hCdNoy$8L5T+-gOkFFtr!4H|e?2liFXL9p&8#7#(f1qM{kfXrN&ortM4g{AZLC-{7ZqXn)URb}qg5KT zhL(vxKR((K)c6E=Kh8J7ZIPKIeesY)r~~dgk*uk&3L&l1)`)hU$+0iydo1WVd!@Om z2dVAg!D2qwvoJFj)N>qrJ;BH=+4)Jj9eO4F{FqHky+P$dP-NA0?TT;Bakp4k&(2D` z!Q}0Y)s%R~`8N?$lo=P{mzS7wqMNO41B%MQbk_Xz|CL$je>f!l&%b~HiU#5UNYTRs z8o<9}Dc~2RM_WB3{x1nS|Lu=c1Mac@U7zVz?>{?M7l6?~k-t~l{r4MAU!wkDuvKS3 zq7|SZHif$Ufk+%?`yxGF2AL>&0{f)l_`IQ523a{Rv2(K#6h5%%345aTSSslGrv|$> zOlpCQ7WPjT6Ks`JMWYLj!q06{g$gh0t41`-)hnLo|0(h&;nXc*O4K<%5IU5uC1_S- zK6EetoN4~Wn!3%SVzR{=ZE><&_%2r`d!Yp8ynR30YxAW|8<(WOAS#?&Q)1=z>{C+m znF%!g?sO+ETiJiGO8a6jB>KNL@lilOhK#=-!$0|R3H}%k*KT$N{X+=*P!fQaWP#N+ z3I~GlrP0BIXBJYiEH9LpTH_0lFj^i{!7xp8g-|B#hYsZzmU0nXujGhNyZb`YF@V(Q zXNOSC6rngj@^n-XQGS@1XdT-q+&c8ca%`5;#OfmFM=jma{ zY#=+Z81&r^Q zSwuKd*=D^n0HW*bd-rO1?MC{inKzdHAKm%~$ZuaiIYolcL96aWRWZH==NHFfHk9^a zjh6Ioc6SZhz%8?)ZVZN&lw7^@HOvI>s&aV~a`v|I8e@9h-wUcpL8=|hRQLhm<(=!c@+@vl%z8Q`NHfAk}51|7|7_3%v3C< zd^6AdVPjr^BqYz!I%8so_-&r-d@ds08x8{b<6koSOl~$ZrDbtk?`!3JEFlm7aR&v2 zr>MqJAxqdz#hIdPj=hTWf|BQ$(=g1LEhKFo9%zHJtcVRg(tp@bzq6+qNeLkBv9ZI% zvE@yVn0#nw(zNPv$Z3Mx&9vlb=FJKJuv4O}Z66^nThNx_gmcnC$1V3h^?beZQHCVs z|7QdJe~4dh=>PbCz!der2UCAZzyD{X_zyqnzwrfk^rA@q{u!42ZIeIE?Foe46By~y z=cCG!6?ANh~M3F0)qg47B%%T=r*!hq4x=OqtiEm4J9*-YKP zJT;S(08r~F{wwocMI9-yHF>d8n1-4H4tS6Ko82rxSyyoh^TJjWC>8!x_9|>3*=m=93$4JMPr|83WK zhh9AC--}QE`-#H4yU<~$<9ft$0fT{1QWtaP zegJ^FTs-{=7J^wB0QBh3DzDp7Vi0v7eRB8c+hpG3@E;xN0_>`ph)jG5yQK05S}%P0 zHyZ45ka&Sv*D?SWk}}0Y&G1Gx7Zkl(9_d?s&UjOWR0=zD!7{SK&z=kh%!X);2*$p`Y4_!tO4g*)>?I0#}3&xZ`eF(~tdT=QNO zXKOlFog|!vXmcpgC&4`heqz9*ZS?>O>V>>_#h zFNH`f$VTX`et*agfQEEc9mfKQfkpefNC$`VSFkitk6i@iUZ9U|kY?(pmxl0H;1p8+ooL{5=yz&!J`T>+#&o-$GPPL0UF%w-G94BuGgWE?jjc@ zbk}JNWP2niu|d|-iohQaNRiLRLisXMvomcfg9dnyL`4y~j26a9t4&FQb)cjgK93Ku z4vZnVd90qY06q&zLwxZmFt=vjfm9YWj|NV>I6{eY)+%NRAOg4`lNTs>X_|9>AiEP; zX*K#luqoTA6m~*EAhfE{1p!v#X;>x{;8ou!6$I^@04TpxAfd8x-2e~-KffIKDx`6v z)bF!ScX*F?C^ymt)C6|Qo@O$4TB(*j4xE%MCCrl5OJ8wca=oEe7Z~sYxA{=UpBcLw zES(QA(3OITqKWNv;l{MGFLv82rHYav>;0TGi}Le+azX``vu};bUKog z2n<^BZ`W>p^X=zZeJRf`$=!bj{k(rg3HARqO7yd-f0c}ZN>Fa>oqbV=Vt%fvqWIYY znL;U<;urpzStXKRVkgS`#gE~7902UFTqQK>Xx8a^YKi8|2=5kyQKl0T%ydPL*7>M7Y12o^P+$j z?R05I!g1-_I{`rY?cb{+m$skF6Vb^fs~ZQXY9MTiUTWhXU_>v4gMGs7fPJry0{If0 zq+0#tR*(vT5gYL=T4HY>c>RS&aWy@Go`hWE-?|Cq)r%pR+%R>7+tB{(Y9L%rbny*N z(;y9z5^hgFd>6&rgD!B_0H8%E>Mwwx+5vDl=fS|D56G;nKf;1eHI}_)1p-Hpb*<;qPiSAQE)X0a)Ce?7a(cKtum#D$*`dv6s`%G>H&%D zLHj_sStQ0lO3-uwbYYV|6C+2c$pQ$~qlaTbhSgDqAOMmK#Vg~oh8y2FpZ8o-j$^-w zOhUIfw(YE>+g(g0L>ok%<3bt%+D@T;Io+cTz##&g1~?Hb+yf+mJfz)y@F&oz?l>_) z762p|gtSO);_3P7uSzSwUq3D!8CR^dne>oIjvjyn$>PQb29N}ZTT2q9nNnB}WS7l` zLHeQSk#fB$8;Vhd*Rf{N9PSZjU!^H$#lfnQ< zYH29rEnRd|(9C)&2JdY%V_9ky#e>nb%hyJHh57u*eB?+Y6X)n5WPCR}tbo;_^a zNgJDtDcb3qp))}g=gHSQ&Yi22cyGz|_XK0Cuf#5Y-NX_GQ?5kJL+cArv&zydA5^NK z<|u65eCg3qMC08;u&Km!#a{Bu8}w=4o@fgOZtlt;(e6X}vrnDr-Pw~Msxlo2|U zsS1Sy@e%j{n7UTDf_A;1qO2VT0TOV}grJIYb+X@&$U_8$kpLSw0G;ee@I#^jw`n;^ zT$4v2|{_wEcYXSqgER`)8 zF|sJV&-Bo=0u|wXlILxog8}{2oEXyaf{W)VE#p=^FGt2^X6sT(r;B-mvCt0LH=513 zePB0U6=PZfCDuI<0Sn=T-P1R0b44YB0tqT;#c`@NOq$HYTNSIA9#4jxS>{vvr`OQn z>;pg86Nc9T^hFF=IQ_*GgX#BUyu{r(E!0JiUr3|8q>Az|@UW#=>!(7%8(CVll7eHk zsn#AudCkPOQpy)&fhrpy);uXm@ivX*IASAu5_Us08{y7 z^+C;^y13*jd^SVq*nQInK#`DRn>ZEKRD?$*&y<6t`cJL76jY;OumjLVF}R22BDZz6 z%v`=#JN}%d+`O|!J=|*vMQ#ep=2j4VnKyG5n-k)Sju#zDt$V+SZPQ4pxZ*hz=L zPiqfK+{=09@_I63cGAsl@Rw>I&J)lUFFn~P)5qg*x>aT7#IzBKPtMM@Mo4G1yNc}2 z*DdTHR!GW zTwu3BW$cb?DQ3ojHr?`EQ;d+Lwd&#rO_jyg>kpZQezsyaA3kkAxl-I%Ik0NZD8OoM zlngx8dJUmk5Z@8Zd8v2|68*9Ky%DD#((Aa4tGNh7Wwa${yT2lpuhb8G_*h;n zVeY2#-e}>gfAM6nePCXp`<{+XGf%w90T`ohf8MXHUSoCMQf(uJSfW%`VDwGmMs%@5 z)bIccd}3IRX2hA!a+QJqrtQP!LzCva<&)LxnI~EsAa=)1vP@7v8RCq&4(NC(;nn-- z4=)sHi(}vdvTg&kran{Lv1+^fRJwT)|J?qYE5(n`zuaa&P*2YBa*FPdLaOUqkYd8DCR7uswTk5`s zM$#$gaEbAwQ{^Cr=u|m@wTT?*NMRfw^x4d!wZLTJhyDJ1tp$+|cYD)uwk2?HeWKm- zWJP!ehEA1hIr}<{KASlKTGYQx9Fi&v#HPEd9F9{-N)xIvt+6ltH|4W~~- zf=SJrvx9^fhE1I>I(d7XsdHo)g00jUHo}*a^%4X7()mDv?Bw!6PCOaI>tG`F+5#7T z%8ficMu2*ui^!-=7KLyvuX*eRLn~EOUoxL0Te$C!Cpt%t+5FFOXDs5JprqB})-q za<-%VV?R|Y4iBA75-Muara@`7C`L^{%r;632rtlWv;75c8We2{SB zA!B$fNfu!+Qq??aSLsy!$iXG6qu3*}qIj=>siyV?p|W`wu~7S?975jql8T#kgPr_I z%Fsv6bKjLu74HKm3tGv@vaG7d2r->spO^4e0wvbd9czd`*tibST8(FR@-$Fzj1$CX zoR(w09INebF4+tSeD?lm?-S3v$O}3C+$Bi1@V5GPtMcO@%OW>9B_j&qBHa*IBz7A* zSf=bpZ<^WO>D7ExjPZ5T4-R7?xsLKqQ)j~xGdc1*_hhkVsX6a}%dZFvZ&l}lxW~JZ>n2*=RH>|oA6Y`RJnD`EG{HDxnAjdy$Z%iYcv}M$=ck|Mtrjt_*r<@^CIa5&zny#&!Lcaw2(UuUg4uDd99Y#Pc{!a zE;n>{n{Tkh=xFXRg5UeU{#tnAua*8WR}%sFzj7h_4{@a*PzWRjlKrcnix(-00fliG zmBG>c6PyvB3-Qkxljxh8hl=#Sx)#tK79c{4(JaNp{NcYdCd+4v|8gyq1nIxnLgyVt z;6KSoVwwCaWAcj4jhO^nvZAClLz`2nK#8J6LE2JkvCb-6&3LToSoJ+yIbbSZn`bT0 z%!oYArQlUYkQsv}FO`>zMspYuCl7$EIGx9Y4l~(TN%=0UE46p}TKRbj1wp@;ZP!_J zH?2y)5IW}3Slw(HWwxg-hoeB?fx<}#%1?nMr&xNhtXdFLK_nbW`fu)&8GwMb;^1IbTY?)08xX)I+f(3@gJ58F)~=R}!KBNg>FYWyBq*C{_U8Rx~5uAdAcR zy~h~cA}i0T^wtA1qo)I!D)K#yzgop2@?)7w2Y<7+Lf1c(!AoWsAbL*UI_(ZT4AJMv z+}ikH21PT#eb{bZIn>7@kC{es8#Yi*`7$oS`KNXyPBPEp;;<^<) z9+ENdvrXZ0&=fgWp-<5`=Ut}M=D$mZqgtTF6Wu`>@hTG4>&9i8ZXC&7kLy@&>TEn^ zol}&{Qs&SZ6koyJ3~QF1Z((Wj;Z!~>K?ehskBV3N6B3K?C=LQ!Y$+e%Ub0C#$Pptl zupRUC-{59*Wh1~imM*=5&$Z7gUPb);u1HWiZSxjZLVV^=`E~hBkylY{szdq2hJO@% zB~K^ALr2D(dP8e;G5^>KYbC4YX@}+{Pge5>Md{|TvzCTNB|?o+jcHK8&!?Vw6g=v@ z$8N;ezaKN08K#&8;&FT3ntd_*g(omC@a9-l?RXPvkqeYV5SADr4&aJK_@?F^!*PcqsFhM{7i%1-wv`HIT z8iXe}n1ae;A&M{xUpC&1PT>rTmNGsl=q(KAEuxZEsQmbBPwtXPXhB zb87W=2E&MSvXbLGO_2|jkt)1^)C0vfo5X`FoVrJLsK2t;==rYf!&n1~_=rLRz^G7n zVf2Zj*}1NifPpumKbYMsdIxCrP@0P+2Q?&!lTCzsQS7^Qjk>#AKM&4oar_ zn_&{gL^DjQ*H%Dxv4sHW?WU;_FdxX<04MCkz<|KeJ!N$P={4#wz;PZ&W5U#VQ?2s%?gsYr4=aRAM>9^XW?cpVQS-O4vME$^)wd9z1!~wiJBO zZ!kg-JYaxuH0XbBAQ?z}3OFFz1_Rw&f0;O(uiq~6loR>`$q=KAfO;UbA1znLjvp2* zOBp-_{iD!67@~t>|8@iTKvCmO`*3 zMB8$R3wf@fJfF9ew5oT8O@NuTEg;2G5otsh&>sTAJL?> z8<_hq%(Vg4SmAzSaYe{|G(;G;b&xv}$xvO!PQ2bj`pIW5kRvxmNc15GXdu|cT9@MW z)s`pdkla%k8uH=Dj<$7jwat%EYM~1`NMw>o?kTXN4`k17x&d3URV@+@8o-c+Jj{aF zk(emNk}dI`IXLe;%ko{SAQH*h-XMW+5MWB}%hWgGjstPkJ~YS*o(53ehn?Ye+7M_y z1H4DcKgXJ3155Pl)TibUVbb}8ZjZ0U5(E4~(0!tEu!DqM#gXzF1$}yVeM=aiR4lk+@!r<3P)_Dyin7$ASQ^J^fast#IIdW^QkaKZ z@gW&4USKzuGouliUI*c|fX9%LY5p`k39k?~qQNsPOYNe$by0Bk)RO25Z*4^`dRI&q ziW7Y#^^q+Wo!yTJ*W`eMr?a2GOh}*D^OmA6V*rKU9yWma9Tb>y8*HRSC3FLVbGA~I z^D_}6f0{wb#0xcI2o#r(PcrF~SU%mRWN z03IfA(9~^%9wo84LbUo$pQ=0<0$Vgp-p8n|$sTJnPM}y?VH`BY6Co7{8 z*w-Tg%6l|qUE#MQP0957CTC3k6L><+>6Oz~Mb?$k>WKvL21|QvHxZLbDW0KK4{5Bg zSEm|;d9vnfaX5Rrp2n?oTNDd=ZTP>O4Xg|_<(<_g3;ZFOhW?y>_dCzBOM7WR!UQLE zH{OnyOlY9Ej=Q9i{IIDudQLa+qP$7eUiC%Jry%SfDXcDs99F^%*G92#X2@;D7=@SL znR+IXusd?wk&aY|^C_$1k?ZSSEWfhw*&z=&HY9uZ+2-7*-bd`fY&S=w{@Ypcjp*qi z!Jn0t58lm%8}_yh(#yTNUR4C5mX=0ji>s;vU99;BuJ6d`x6k7{LpJt2P~WXe>UMmv z!g90O{j)(ABY<{5amMrY>w5UNjt>~@Zfr=R^c+UKrHt%nxS_e561tt;Bn6$quh+TW z9r31q#P?Y6BcIeU)J-Y*;I<{7kb;7OgoW6qf#;Kr&%tW{>sEKTu7@zI!C}o zd`T$fK&BA#|1X8~-+t78WZC~oA^m@6!aZXUMqd0Lmv?_Y^r*xFo(t({TZPZE>}iAi z`Oq_8DrGU5-g#4mf=?}rzmHaA{-0)g@DjaF0c^;ZLg}AEI&#KrxO^MczqbF@apvIX zbQd%fch0?WND{3N&GRS~L~;NXjcoRpkKIa>iz=ri|ApMjMYj6ixn8hKJ43#M9^+8eI9$$t+$m(7wpLIlZhs*sa# zG)&%;zx`#cA&d1cFP<;~#cn5;Xv}ls#stN0L+3D%qo0M^Hg^z)#D&8;5MTLg$BYq3{|{^_5*0_LqfyZ51;iK6Q_Q7c)89OeHh(16$stfxM)#J!rq7aS+AJ` z0H|-NsL|Ng|8en*|8?;InyP5;84Ch)P252Q;P-Y=%V+}k5R71xWRz5C+%JVeAls__ zOlBN?8!ISx@i0^wvxyplNA5lX1#>oqV@aR`i11t&j=(;AC+ zGWDY?v1!->Wd!vl{1xLJ>@dI;x?9N1@Dy1RZGZs)Y=RF(0SMbG+5m*hidhKoASeKE zx$o0eE=lcV)^T+mwl|E3W3R}8gst-nIOC5AGk(@MLk*jZ>FC&hyg_63R^eymcKMuL z()m}pdHDK40B{*Wi;2S~IAk{*q02%* zbjW!chjavu#I|WwCw2jdcAX&32sodWoBFeI$w; zrg@2^%>$x*@A5$y-=S-|XmEef6bRC95*2(Vrw3$Hh6bZ;prOKmZ~ie8BT(i5r9#fn zX5s?~YTu^&O5-q2!tj_Iu$eI_spI0tGJuSScZ4%mKq#?-aqsd(E?fR4i!FJol>~6* z-|KS)8sRiExY9nKaqqu-z;IiB1 z;TPmgyFQ^XI#Xz{>cux^#?Ku5G5XGKdTk-j1v@Ab07iJ^Pg_4mH`yy7!kOciUayT6 z$KEdIB@Exa*R&~7&h_#4q{`zq@;U{K0*JAu?l9+O%eFa>&lFQxsgg0qTO@d|bs_6c zA&Eu>05t+$;I|>uPxtd$@~8nFiF$jn+}=uflE4)CK%MmLjDb?qXbYF2L^`i9zpzT& zatk))`MnTztx3 zA>?=qxjwUP#+Vh9=cKM$K%c=3a(knUi-}6o-uDB)|DAu0CXg_bOa1Q*fYvykbai}i zwQ~-0Gfl0cD1EqL_%t#Y(^|u`GZ%!pFE3e9kSv#yVTDJ*#C)P50|VP1O{37y48jDk)VdxMVEUW{zk>`Fj8?0p7q9S| zsanl*b>l47T#*6)SY4o8%k29#;sfH^QC6@>KHIyIkSQKLcw4c`n2P){felm5@WsZY zITBgxmYQO(qi&lXKm@b}4@Z;2=yeQBW+!0dy+s%w2;;o!^I_B{hvcJpig4GZ^A3_k zgIS&jUvb#f9(SnG4TIZ3h%^leh+eTh5s;k?0U>t}i9@IA;lPc}c(aUIA*ll(3y`HM zA|0P3W`J&%Sx}Ahm=ejevK%}C``fBD32<7!47M1yW_HcEjGY_ibuRqq99N0HUuaJQ zN(UnifB+!S&k8g`7gh<$5{X!T0iN$wh&LswR&_lDKtXoE*0XObo@Sb0a^NLBsFf;e z`8q6sv2Xf)LMnpv%FUt_<*O3~=iJ!%$6TAqv-~ zWB6tt8^!j;z8wr?8Q+Qg<)1<#LI^gP&5^4+Z8Y)ir2^nv)F-=Bi9TZ>Rt4kiEiJ9rl8 zW#T1>ONrdiCnvU+F{(I-@!T(X`3%&t%p9qDb%!_H@)8UlIEY#a(=s2flvtD=Ymv!- zav6Bt17Z#gvhF{JbNtJISQ!__Y#rrEwS4cSXSN5&fweceaf2)|?%g{3cv?MFTwrRS zzJwM0ET}O)WY3Ece{!&7X}oAAF0yV!4S2^{gXPzmd94 zaLedlLqVpCZ(WuGI;){^wr2NN$V{t7ya)h+U)0OUK`wbvNUgsptmIRm*R1cPe1RVm zR|)WiQbA#2pr+6~SmMWWOTO??N;e3n_nGOjlwygR&oemut+xPE?KDNbZ7%$&E=ANiy2Pm6)2h z(bQt6AJJx${+J|pUBPuUC)sPn+utO4DQ?>w{@$c+Kks|W|6UDRMTt)4Bos9I^h-gX z*cnj0ULd+$@q>@jf415bciWHdm7qHV;B8Vv@ArU%hD`&RUw#+&;OLHk0mfHA=Uuzj zewO#72=pe(&fxD-mDBZ|j$uRo$U3cxD}&<8;N*lxD{>wHBCinTu=0-x^WlKu`+3J%-XmUUVaEf|Q4*vUNV!)4An}3D{0-fGJzRUlVe~v@~+%ecU6t(QJ8mMsb zV+f`c06obG3`EfRANU2!>I_7BwK2Za{p`Hl!KKyAN*CqwQ0a+M$@0i(3}G^68Mb4C zzRL||#)bRgbh2dJk)gotCM5$mtz=1;_!ox)B0WUef~{DQScKpxB5+Vm`RnO1_i&z9 zQA0{vCHB^1(6KN&{uNR_dqDxgARdVC5Dj$GBj^_+^q?ZN1N0tB>~zF$Ge8p_O$+r#QvQlWJcdsew2kxNOXkoR zOOWw03lSct5rf*qWxEB!T#i7Qk0R-0k!FHg3x?Xs$D`Q;FbSMWe+CEsjCwoD5~YuV zedj^&%bU29J2x_coXL3rVoU>x>dJ^llNb0vmymE6Hx=zgJ!IBN5RjS@v#lGUni^4v z2+L;z{uqyu^fN@G^=;NNn zlgLOr!RT0dKVpBo__6r+&xtl)&(?~BB}nj)XTpc*gaN|nF$6aYo?ob6v_C^4^HXP} zXNx;~w3jxNyCapYr8TbY)(D8^foGLe0#7QAetAQTq77yN7|1r<8mZ_fV|rvDIiza~ zr9-YLWUsw(m{V5$qL%IAM<9u$2GLvNp)?bA3xZLdp+@o1QOliCbR7;scuv<0(Jua( zK{07w%*M7y(Qm(`z4;#85W$9yMn)GN(_9>*xEiKVm83cWL%R#qj>$lENJpQ~ZvF*t zJ$&Eq4K=b)DJ4!}?F_Gvc**=GlCU%7{CkcYGa0d<{VVs}Hx&upI{wTGiI6m(8i&+3 z4DguBpth>WX#3D!W-@mB#3%))oYc^X&^SH$94sph<<%J4#{56>5p~oVCr?e;_5|63 z(Y}}|$_LC52Au_z7WoiVaSfjgD+2&>I!G9x(-cKVw#CUYr^LeO-|(A^jjE`1wD1wF zC}zx$g~y)N3n*5EG+bpwZHL5UpJhp$M>l5nyGr1NpC|T>Cq{PB0KXVYtXIhMFnJMo zD?b_hO|b|`ejr2++scr)lC4i0MNB>5dPQ4pALpAwb_-XwCYR*vRWe(u1akuceTNin z0_!(kYA^sib?uo!fgvcrK=o#5X z?-%PbX$ipYVh)gwWlr{~0GDN~rf-l`um4sw7%P(8dJme&sFGx5+{#8T_NaGEFKuHk zRJ6#h_8H$JQ-8Z>k}XCk>W4nX9ywQfY(;| z*KX<7CNcPaJFfF#ahRE?+o-7XM)f#Ubg#Ur;e*vjpw!%yv zx%ACzRy!C*yey7*D;=(YkuQUtcpb58bCZ(Vf|BqF-IISg-c@TV47i-y#KzU8ZzN@m zQ6~Uw*NMZmB8#uo$L(y2b9hJUgdt?;1igS++-Sxscy^o_;CRIm(hdvA3?Tf-GXC->S1Ye2O3xJE8I zz)T>jHN5vDGHJ6>x{_e;2hHAH>TrW7o2{^(CtzRe6Nq%Gr+l`C2uAcl-!HRVv(NZV z-vJTnT20jeq6a$Qb5i3tM)c7zD%Oudj^n0!#;z9~r#HfawH>4PuTrJDp3TKqs5>fo z2w(4AoU~p?pX1kPIU=2dnwA%AZ;mPhu-N>ev|RW;Ivt07GU0=mR|6+@ockRC5mQ!? z)b#3}+N@hY{TsneISbwbCyAzmf_7eLpyiFYX{z%mvg>(KrAe_Ld8S2E^H1{&Km`jf z7Zkp~Bls?h^x=!Y3A2ee77>sJ(%nAE4X6hzy@FEgH;k@Yj9%^h9z3rF3fkD@;YpP3 z--n8rnNqLI$f4P^7W}xsj9B}WWFPQ1I)j*;`6?}XJ(b44~p$?Q)x8l`**cVEJrgu(J`FLZe+gc(9Tre{r!$BfqNKiQ|_Pmz72Va=n>Z%Itf`GjBRy zyP2PmUGkn(&tycOV_(`7Mdxv3EN@GreqS7W+aysgdt#t90h;UIVrm*&sj;p)3so>h zQF>h1_1Lk0{Nx(Aj^UBR@-$R{Z*$=OxWAH3Y*k;2!YL4=`sKE3znc2+>&7HbaY60h z!`d?(vPP$eyGV@>2N>J3Y%NL!c6*f`qNb;FOxn^m1v&4&g%dnZf=Z5C6Jx-bN(~(2 z<{!rU0@d5=zx@t5VRT)=>gq76J}t&Naf~~S<3Ij=Bmjf%hfuC55}&;M@a_6&@Dxq? z6J?JcW?@-$L`%WBxj>;`8Mm5n<@J1$_75vdo2}(tFB2cq-`{lj8y&UK%MUEdW%Wl1 z$_0BjRs&4m{~X||Yn{e@4H2GmG~N-Qz>vvj@?5&$M`7Iq6kZ9nsZYW%ls9=br52tC^_tHnS?| zSWeSaj_HCL&gx6LjHj=E+3M@8Ya)!A|1N%9{r;4(m((?VoH+RIF}d~eTM*8Xo7t5a z&eGcBT*G6fMe|L>BS1r9OX9hZPALsnw-`XfCl&X$H{X_yMWZ%N*Z=<%(jl*eB ziD>W?bwz)3?oK6eX>k~@rhZo~AZ7Mez|*$R;ii47`5>fiKVSN9A^nGgX1R32cW>s5 zYRw8w3|ERZ9ctYM8#z<^ly>kMA;&bKb#CT!K+fmv+XyT7`C6+t^PxKz&+)e|KeRg; zbbWWzQ6#MCfN8AcqV z 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 QQo3(XF5(b3cy8MKA3IX~!T` e.g. `cargo bench -- parse` \ No newline at end of file diff --git a/nushell/benches/benchmarks.rs b/nushell/benches/benchmarks.rs new file mode 100644 index 0000000..a6fd2cf --- /dev/null +++ b/nushell/benches/benchmarks.rs @@ -0,0 +1,541 @@ +use nu_cli::{eval_source, evaluate_commands}; +use nu_plugin_core::{Encoder, EncodingType}; +use nu_plugin_protocol::{PluginCallResponse, PluginOutput}; +use nu_protocol::{ + PipelineData, Signals, Span, Spanned, Value, + engine::{EngineState, Stack}, +}; +use nu_std::load_standard_library; +use nu_utils::{get_default_config, get_default_env}; +use std::{ + fmt::Write, + hint::black_box, + rc::Rc, + sync::{Arc, atomic::AtomicBool}, +}; +use tango_bench::{IntoBenchmarks, benchmark_fn, tango_benchmarks, tango_main}; + +fn load_bench_commands() -> EngineState { + nu_command::add_shell_command_context(nu_cmd_lang::create_default_context()) +} + +fn setup_engine() -> EngineState { + let mut engine_state = load_bench_commands(); + let cwd = std::env::current_dir() + .unwrap() + .into_os_string() + .into_string() + .unwrap(); + + // parsing config.nu breaks without PWD set, so set a valid path + engine_state.add_env_var("PWD".into(), Value::string(cwd, Span::test_data())); + + engine_state.generate_nu_constant(); + + engine_state +} + +fn setup_stack_and_engine_from_command(command: &str) -> (Stack, EngineState) { + let mut engine = setup_engine(); + let commands = Spanned { + span: Span::unknown(), + item: command.to_string(), + }; + + let mut stack = Stack::new(); + + evaluate_commands( + &commands, + &mut engine, + &mut stack, + PipelineData::empty(), + Default::default(), + ) + .unwrap(); + + (stack, engine) +} + +// generate a new table data with `row_cnt` rows, `col_cnt` columns. +fn encoding_test_data(row_cnt: usize, col_cnt: usize) -> Value { + let record = Value::test_record( + (0..col_cnt) + .map(|x| (format!("col_{x}"), Value::test_int(x as i64))) + .collect(), + ); + + Value::list(vec![record; row_cnt], Span::test_data()) +} + +fn bench_command( + name: impl Into, + command: impl Into + Clone, + stack: Stack, + engine: EngineState, +) -> impl IntoBenchmarks { + let commands = Spanned { + span: Span::unknown(), + item: command.into(), + }; + [benchmark_fn(name, move |b| { + let commands = commands.clone(); + let stack = stack.clone(); + let engine = engine.clone(); + b.iter(move || { + let mut stack = stack.clone(); + let mut engine = engine.clone(); + #[allow(clippy::unit_arg)] + black_box( + evaluate_commands( + &commands, + &mut engine, + &mut stack, + PipelineData::empty(), + Default::default(), + ) + .unwrap(), + ); + }) + })] +} + +fn bench_eval_source( + name: &str, + fname: String, + source: Vec, + stack: Stack, + engine: EngineState, +) -> impl IntoBenchmarks { + [benchmark_fn(name, move |b| { + let stack = stack.clone(); + let engine = engine.clone(); + let fname = fname.clone(); + let source = source.clone(); + b.iter(move || { + let mut stack = stack.clone(); + let mut engine = engine.clone(); + let fname: &str = &fname.clone(); + let source: &[u8] = &source.clone(); + black_box(eval_source( + &mut engine, + &mut stack, + source, + fname, + PipelineData::empty(), + false, + )); + }) + })] +} + +/// Load the standard library into the engine. +fn bench_load_standard_lib() -> impl IntoBenchmarks { + [benchmark_fn("load_standard_lib", move |b| { + let engine = setup_engine(); + b.iter(move || { + let mut engine = engine.clone(); + load_standard_library(&mut engine) + }) + })] +} + +fn create_flat_record_string(n: usize) -> String { + let mut s = String::from("let record = { "); + for i in 0..n { + write!(s, "col_{i}: {i}, ").unwrap(); + } + s.push('}'); + s +} + +fn create_nested_record_string(depth: usize) -> String { + let mut s = String::from("let record = {"); + for _ in 0..depth { + s.push_str("col: {"); + } + s.push_str("col_final: 0"); + for _ in 0..depth { + s.push('}'); + } + s.push('}'); + s +} + +fn create_example_table_nrows(n: usize) -> String { + let mut s = String::from("let table = [[foo bar baz]; "); + for i in 0..n { + s.push_str(&format!("[0, 1, {i}]")); + if i < n - 1 { + s.push_str(", "); + } + } + s.push(']'); + s +} + +fn bench_record_create(n: usize) -> impl IntoBenchmarks { + bench_command( + format!("record_create_{n}"), + create_flat_record_string(n), + Stack::new(), + setup_engine(), + ) +} + +fn bench_record_flat_access(n: usize) -> impl IntoBenchmarks { + let setup_command = create_flat_record_string(n); + let (stack, engine) = setup_stack_and_engine_from_command(&setup_command); + bench_command( + format!("record_flat_access_{n}"), + "$record.col_0 | ignore", + stack, + engine, + ) +} + +fn bench_record_nested_access(n: usize) -> impl IntoBenchmarks { + let setup_command = create_nested_record_string(n); + let (stack, engine) = setup_stack_and_engine_from_command(&setup_command); + let nested_access = ".col".repeat(n); + bench_command( + format!("record_nested_access_{n}"), + format!("$record{} | ignore", nested_access), + stack, + engine, + ) +} + +fn bench_record_insert(n: usize, m: usize) -> impl IntoBenchmarks { + let setup_command = create_flat_record_string(n); + let (stack, engine) = setup_stack_and_engine_from_command(&setup_command); + let mut insert = String::from("$record"); + for i in n..(n + m) { + write!(insert, " | insert col_{i} {i}").unwrap(); + } + insert.push_str(" | ignore"); + bench_command(format!("record_insert_{n}_{m}"), insert, stack, engine) +} + +fn bench_table_create(n: usize) -> impl IntoBenchmarks { + bench_command( + format!("table_create_{n}"), + create_example_table_nrows(n), + Stack::new(), + setup_engine(), + ) +} + +fn bench_table_get(n: usize) -> impl IntoBenchmarks { + let setup_command = create_example_table_nrows(n); + let (stack, engine) = setup_stack_and_engine_from_command(&setup_command); + bench_command( + format!("table_get_{n}"), + "$table | get bar | math sum | ignore", + stack, + engine, + ) +} + +fn bench_table_select(n: usize) -> impl IntoBenchmarks { + let setup_command = create_example_table_nrows(n); + let (stack, engine) = setup_stack_and_engine_from_command(&setup_command); + bench_command( + format!("table_select_{n}"), + "$table | select foo baz | ignore", + stack, + engine, + ) +} + +fn bench_table_insert_row(n: usize, m: usize) -> impl IntoBenchmarks { + let setup_command = create_example_table_nrows(n); + let (stack, engine) = setup_stack_and_engine_from_command(&setup_command); + let mut insert = String::from("$table"); + for i in n..(n + m) { + write!(insert, " | insert {i} {{ foo: 0, bar: 1, baz: {i} }}").unwrap(); + } + insert.push_str(" | ignore"); + bench_command(format!("table_insert_row_{n}_{m}"), insert, stack, engine) +} + +fn bench_table_insert_col(n: usize, m: usize) -> impl IntoBenchmarks { + let setup_command = create_example_table_nrows(n); + let (stack, engine) = setup_stack_and_engine_from_command(&setup_command); + let mut insert = String::from("$table"); + for i in 0..m { + write!(insert, " | insert col_{i} {i}").unwrap(); + } + insert.push_str(" | ignore"); + bench_command(format!("table_insert_col_{n}_{m}"), insert, stack, engine) +} + +fn bench_eval_interleave(n: usize) -> impl IntoBenchmarks { + let engine = setup_engine(); + let stack = Stack::new(); + bench_command( + format!("eval_interleave_{n}"), + format!("seq 1 {n} | wrap a | interleave {{ seq 1 {n} | wrap b }} | ignore"), + stack, + engine, + ) +} + +fn bench_eval_interleave_with_interrupt(n: usize) -> impl IntoBenchmarks { + let mut engine = setup_engine(); + engine.set_signals(Signals::new(Arc::new(AtomicBool::new(false)))); + let stack = Stack::new(); + bench_command( + format!("eval_interleave_with_interrupt_{n}"), + format!("seq 1 {n} | wrap a | interleave {{ seq 1 {n} | wrap b }} | ignore"), + stack, + engine, + ) +} + +fn bench_eval_for(n: usize) -> impl IntoBenchmarks { + let engine = setup_engine(); + let stack = Stack::new(); + bench_command( + format!("eval_for_{n}"), + format!("(for $x in (1..{n}) {{ 1 }}) | ignore"), + stack, + engine, + ) +} + +fn bench_eval_each(n: usize) -> impl IntoBenchmarks { + let engine = setup_engine(); + let stack = Stack::new(); + bench_command( + format!("eval_each_{n}"), + format!("(1..{n}) | each {{|_| 1 }} | ignore"), + stack, + engine, + ) +} + +fn bench_eval_par_each(n: usize) -> impl IntoBenchmarks { + let engine = setup_engine(); + let stack = Stack::new(); + bench_command( + format!("eval_par_each_{n}"), + format!("(1..{}) | par-each -t 2 {{|_| 1 }} | ignore", n), + stack, + engine, + ) +} + +fn bench_eval_default_config() -> impl IntoBenchmarks { + let default_env = get_default_config().as_bytes().to_vec(); + let fname = "default_config.nu".to_string(); + bench_eval_source( + "eval_default_config", + fname, + default_env, + Stack::new(), + setup_engine(), + ) +} + +fn bench_eval_default_env() -> impl IntoBenchmarks { + let default_env = get_default_env().as_bytes().to_vec(); + let fname = "default_env.nu".to_string(); + bench_eval_source( + "eval_default_env", + fname, + default_env, + Stack::new(), + setup_engine(), + ) +} + +fn encode_json(row_cnt: usize, col_cnt: usize) -> impl IntoBenchmarks { + let test_data = Rc::new(PluginOutput::CallResponse( + 0, + PluginCallResponse::value(encoding_test_data(row_cnt, col_cnt)), + )); + let encoder = Rc::new(EncodingType::try_from_bytes(b"json").unwrap()); + + [benchmark_fn( + format!("encode_json_{}_{}", row_cnt, col_cnt), + move |b| { + let encoder = encoder.clone(); + let test_data = test_data.clone(); + b.iter(move || { + let mut res = Vec::new(); + encoder.encode(&*test_data, &mut res).unwrap(); + }) + }, + )] +} + +fn encode_msgpack(row_cnt: usize, col_cnt: usize) -> impl IntoBenchmarks { + let test_data = Rc::new(PluginOutput::CallResponse( + 0, + PluginCallResponse::value(encoding_test_data(row_cnt, col_cnt)), + )); + let encoder = Rc::new(EncodingType::try_from_bytes(b"msgpack").unwrap()); + + [benchmark_fn( + format!("encode_msgpack_{}_{}", row_cnt, col_cnt), + move |b| { + let encoder = encoder.clone(); + let test_data = test_data.clone(); + b.iter(move || { + let mut res = Vec::new(); + encoder.encode(&*test_data, &mut res).unwrap(); + }) + }, + )] +} + +fn decode_json(row_cnt: usize, col_cnt: usize) -> impl IntoBenchmarks { + let test_data = PluginOutput::CallResponse( + 0, + PluginCallResponse::value(encoding_test_data(row_cnt, col_cnt)), + ); + let encoder = EncodingType::try_from_bytes(b"json").unwrap(); + let mut res = vec![]; + encoder.encode(&test_data, &mut res).unwrap(); + + [benchmark_fn( + format!("decode_json_{}_{}", row_cnt, col_cnt), + move |b| { + let res = res.clone(); + b.iter(move || { + let mut binary_data = std::io::Cursor::new(res.clone()); + binary_data.set_position(0); + let _: Result, _> = + black_box(encoder.decode(&mut binary_data)); + }) + }, + )] +} + +fn decode_msgpack(row_cnt: usize, col_cnt: usize) -> impl IntoBenchmarks { + let test_data = PluginOutput::CallResponse( + 0, + PluginCallResponse::value(encoding_test_data(row_cnt, col_cnt)), + ); + let encoder = EncodingType::try_from_bytes(b"msgpack").unwrap(); + let mut res = vec![]; + encoder.encode(&test_data, &mut res).unwrap(); + + [benchmark_fn( + format!("decode_msgpack_{}_{}", row_cnt, col_cnt), + move |b| { + let res = res.clone(); + b.iter(move || { + let mut binary_data = std::io::Cursor::new(res.clone()); + binary_data.set_position(0); + let _: Result, _> = + black_box(encoder.decode(&mut binary_data)); + }) + }, + )] +} + +tango_benchmarks!( + bench_load_standard_lib(), + // Data types + // Record + bench_record_create(1), + bench_record_create(10), + bench_record_create(100), + bench_record_create(1_000), + bench_record_flat_access(1), + bench_record_flat_access(10), + bench_record_flat_access(100), + bench_record_flat_access(1_000), + bench_record_nested_access(1), + bench_record_nested_access(2), + bench_record_nested_access(4), + bench_record_nested_access(8), + bench_record_nested_access(16), + bench_record_nested_access(32), + bench_record_nested_access(64), + bench_record_nested_access(128), + bench_record_insert(1, 1), + bench_record_insert(10, 1), + bench_record_insert(100, 1), + bench_record_insert(1000, 1), + bench_record_insert(1, 10), + bench_record_insert(10, 10), + bench_record_insert(100, 10), + bench_record_insert(1000, 10), + // Table + bench_table_create(1), + bench_table_create(10), + bench_table_create(100), + bench_table_create(1_000), + bench_table_get(1), + bench_table_get(10), + bench_table_get(100), + bench_table_get(1_000), + bench_table_select(1), + bench_table_select(10), + bench_table_select(100), + bench_table_select(1_000), + bench_table_insert_row(1, 1), + bench_table_insert_row(10, 1), + bench_table_insert_row(100, 1), + bench_table_insert_row(1000, 1), + bench_table_insert_row(1, 10), + bench_table_insert_row(10, 10), + bench_table_insert_row(100, 10), + bench_table_insert_row(1000, 10), + bench_table_insert_col(1, 1), + bench_table_insert_col(10, 1), + bench_table_insert_col(100, 1), + bench_table_insert_col(1000, 1), + bench_table_insert_col(1, 10), + bench_table_insert_col(10, 10), + bench_table_insert_col(100, 10), + bench_table_insert_col(1000, 10), + // Eval + // Interleave + bench_eval_interleave(100), + bench_eval_interleave(1_000), + bench_eval_interleave(10_000), + bench_eval_interleave_with_interrupt(100), + bench_eval_interleave_with_interrupt(1_000), + bench_eval_interleave_with_interrupt(10_000), + // For + bench_eval_for(1), + bench_eval_for(10), + bench_eval_for(100), + bench_eval_for(1_000), + bench_eval_for(10_000), + // Each + bench_eval_each(1), + bench_eval_each(10), + bench_eval_each(100), + bench_eval_each(1_000), + bench_eval_each(10_000), + // Par-Each + bench_eval_par_each(1), + bench_eval_par_each(10), + bench_eval_par_each(100), + bench_eval_par_each(1_000), + bench_eval_par_each(10_000), + // Config + bench_eval_default_config(), + // Env + bench_eval_default_env(), + // Encode + // Json + encode_json(100, 5), + encode_json(10000, 15), + // MsgPack + encode_msgpack(100, 5), + encode_msgpack(10000, 15), + // Decode + // Json + decode_json(100, 5), + decode_json(10000, 15), + // MsgPack + decode_msgpack(100, 5), + decode_msgpack(10000, 15) +); + +tango_main!(); diff --git a/nushell/clippy/wasm/clippy.toml b/nushell/clippy/wasm/clippy.toml new file mode 100644 index 0000000..d1092af --- /dev/null +++ b/nushell/clippy/wasm/clippy.toml @@ -0,0 +1,3 @@ +[[disallowed-types]] +path = "std::time::Instant" +reason = "WASM panics if used, use `web_time::Instant` instead" diff --git a/nushell/crates/README.md b/nushell/crates/README.md new file mode 100644 index 0000000..ca1e44b --- /dev/null +++ b/nushell/crates/README.md @@ -0,0 +1,13 @@ +# Nushell core libraries and plugins + +These sub-crates form both the foundation for Nu and a set of plugins which extend Nu with additional functionality. + +Foundational libraries are split into two kinds of crates: + +* Core crates - those crates that work together to build the Nushell language engine +* Support crates - a set of crates that support the engine with additional features like JSON support, ANSI support, and more. + +Plugins are likewise also split into two types: + +* Core plugins - plugins that provide part of the default experience of Nu, including access to the system properties, processes, and web-connectivity features. +* Extra plugins - these plugins run a wide range of different capabilities like working with different file types, charting, viewing binary data, and more. diff --git a/nushell/crates/nu-cli/Cargo.toml b/nushell/crates/nu-cli/Cargo.toml new file mode 100644 index 0000000..a6c5d9d --- /dev/null +++ b/nushell/crates/nu-cli/Cargo.toml @@ -0,0 +1,54 @@ +[package] +authors = ["The Nushell Project Developers"] +description = "CLI-related functionality for Nushell" +repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cli" +edition = "2024" +license = "MIT" +name = "nu-cli" +version = "0.105.2" + +[lib] +bench = false + +[dev-dependencies] +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.105.2" } +nu-command = { path = "../nu-command", version = "0.105.2" } +nu-std = { path = "../nu-std", version = "0.105.2" } +nu-test-support = { path = "../nu-test-support", version = "0.105.2" } +rstest = { workspace = true, default-features = false } +tempfile = { workspace = true } + +[dependencies] +nu-cmd-base = { path = "../nu-cmd-base", version = "0.105.2" } +nu-engine = { path = "../nu-engine", version = "0.105.2", features = ["os"] } +nu-glob = { path = "../nu-glob", version = "0.105.2" } +nu-path = { path = "../nu-path", version = "0.105.2" } +nu-parser = { path = "../nu-parser", version = "0.105.2" } +nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.105.2", optional = true } +nu-protocol = { path = "../nu-protocol", version = "0.105.2", features = ["os"] } +nu-utils = { path = "../nu-utils", version = "0.105.2" } +nu-color-config = { path = "../nu-color-config", version = "0.105.2" } +nu-ansi-term = { workspace = true } +reedline = { workspace = true, features = ["bashisms", "sqlite"] } + +chrono = { default-features = false, features = ["std"], workspace = true } +crossterm = { workspace = true } +fancy-regex = { workspace = true } +is_executable = { workspace = true } +log = { workspace = true } +lscolors = { workspace = true, default-features = false, features = ["nu-ansi-term"] } +miette = { workspace = true, features = ["fancy-no-backtrace"] } +nucleo-matcher = { workspace = true } +percent-encoding = { workspace = true } +sysinfo = { workspace = true } +strum = { workspace = true } +unicode-segmentation = { workspace = true } +uuid = { workspace = true, features = ["v4"] } +which = { workspace = true } + +[features] +plugin = ["nu-plugin-engine"] +system-clipboard = ["reedline/system_clipboard"] + +[lints] +workspace = true diff --git a/nushell/crates/nu-cli/LICENSE b/nushell/crates/nu-cli/LICENSE new file mode 100644 index 0000000..ae174e8 --- /dev/null +++ b/nushell/crates/nu-cli/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 - 2023 The Nushell Project Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/nushell/crates/nu-cli/README.md b/nushell/crates/nu-cli/README.md new file mode 100644 index 0000000..e0eca3c --- /dev/null +++ b/nushell/crates/nu-cli/README.md @@ -0,0 +1,7 @@ +This crate implements the core functionality of the interactive Nushell REPL and interfaces with `reedline`. +Currently implements the syntax highlighting and completions logic. +Furthermore includes a few commands that are specific to `reedline` + +## Internal Nushell crate + +This crate implements components of Nushell and is not designed to support plugin authors or other users directly. diff --git a/nushell/crates/nu-cli/src/commands/commandline/commandline_.rs b/nushell/crates/nu-cli/src/commands/commandline/commandline_.rs new file mode 100644 index 0000000..909c2cc --- /dev/null +++ b/nushell/crates/nu-cli/src/commands/commandline/commandline_.rs @@ -0,0 +1,35 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct Commandline; + +impl Command for Commandline { + fn name(&self) -> &str { + "commandline" + } + + fn signature(&self) -> Signature { + Signature::build("commandline") + .input_output_types(vec![(Type::Nothing, Type::String)]) + .category(Category::Core) + } + + fn description(&self) -> &str { + "View the current command line input buffer." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["repl", "interactive"] + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let repl = engine_state.repl_state.lock().expect("repl state mutex"); + Ok(Value::string(repl.buffer.clone(), call.head).into_pipeline_data()) + } +} diff --git a/nushell/crates/nu-cli/src/commands/commandline/edit.rs b/nushell/crates/nu-cli/src/commands/commandline/edit.rs new file mode 100644 index 0000000..7b51ba0 --- /dev/null +++ b/nushell/crates/nu-cli/src/commands/commandline/edit.rs @@ -0,0 +1,66 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct CommandlineEdit; + +impl Command for CommandlineEdit { + fn name(&self) -> &str { + "commandline edit" + } + + fn signature(&self) -> Signature { + Signature::build(self.name()) + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .switch( + "append", + "appends the string to the end of the buffer", + Some('a'), + ) + .switch( + "insert", + "inserts the string into the buffer at the cursor position", + Some('i'), + ) + .switch( + "replace", + "replaces the current contents of the buffer (default)", + Some('r'), + ) + .required( + "str", + SyntaxShape::String, + "The string to perform the operation with.", + ) + .category(Category::Core) + } + + fn description(&self) -> &str { + "Modify the current command line input buffer." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["repl", "interactive"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let str: String = call.req(engine_state, stack, 0)?; + let mut repl = engine_state.repl_state.lock().expect("repl state mutex"); + if call.has_flag(engine_state, stack, "append")? { + repl.buffer.push_str(&str); + } else if call.has_flag(engine_state, stack, "insert")? { + let cursor_pos = repl.cursor_pos; + repl.buffer.insert_str(cursor_pos, &str); + repl.cursor_pos += str.len(); + } else { + repl.buffer = str; + repl.cursor_pos = repl.buffer.len(); + } + Ok(Value::nothing(call.head).into_pipeline_data()) + } +} diff --git a/nushell/crates/nu-cli/src/commands/commandline/get_cursor.rs b/nushell/crates/nu-cli/src/commands/commandline/get_cursor.rs new file mode 100644 index 0000000..61050f6 --- /dev/null +++ b/nushell/crates/nu-cli/src/commands/commandline/get_cursor.rs @@ -0,0 +1,52 @@ +use nu_engine::command_prelude::*; +use unicode_segmentation::UnicodeSegmentation; + +#[derive(Clone)] +pub struct CommandlineGetCursor; + +impl Command for CommandlineGetCursor { + fn name(&self) -> &str { + "commandline get-cursor" + } + + fn signature(&self) -> Signature { + Signature::build(self.name()) + .input_output_types(vec![(Type::Nothing, Type::Int)]) + .allow_variants_without_examples(true) + .category(Category::Core) + } + + fn description(&self) -> &str { + "Get the current cursor position." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["repl", "interactive"] + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let repl = engine_state.repl_state.lock().expect("repl state mutex"); + let char_pos = repl + .buffer + .grapheme_indices(true) + .chain(std::iter::once((repl.buffer.len(), ""))) + .position(|(i, _c)| i == repl.cursor_pos) + .expect("Cursor position isn't on a grapheme boundary"); + match i64::try_from(char_pos) { + Ok(pos) => Ok(Value::int(pos, call.head).into_pipeline_data()), + Err(e) => Err(ShellError::GenericError { + error: "Failed to convert cursor position to int".to_string(), + msg: e.to_string(), + span: None, + help: None, + inner: vec![], + }), + } + } +} diff --git a/nushell/crates/nu-cli/src/commands/commandline/mod.rs b/nushell/crates/nu-cli/src/commands/commandline/mod.rs new file mode 100644 index 0000000..bb4c9b0 --- /dev/null +++ b/nushell/crates/nu-cli/src/commands/commandline/mod.rs @@ -0,0 +1,9 @@ +mod commandline_; +mod edit; +mod get_cursor; +mod set_cursor; + +pub use commandline_::Commandline; +pub use edit::CommandlineEdit; +pub use get_cursor::CommandlineGetCursor; +pub use set_cursor::CommandlineSetCursor; diff --git a/nushell/crates/nu-cli/src/commands/commandline/set_cursor.rs b/nushell/crates/nu-cli/src/commands/commandline/set_cursor.rs new file mode 100644 index 0000000..012bd8c --- /dev/null +++ b/nushell/crates/nu-cli/src/commands/commandline/set_cursor.rs @@ -0,0 +1,65 @@ +use nu_engine::command_prelude::*; + +use unicode_segmentation::UnicodeSegmentation; + +#[derive(Clone)] +pub struct CommandlineSetCursor; + +impl Command for CommandlineSetCursor { + fn name(&self) -> &str { + "commandline set-cursor" + } + + fn signature(&self) -> Signature { + Signature::build(self.name()) + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .switch( + "end", + "set the current cursor position to the end of the buffer", + Some('e'), + ) + .optional("pos", SyntaxShape::Int, "Cursor position to be set.") + .category(Category::Core) + } + + fn description(&self) -> &str { + "Set the current cursor position." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["repl", "interactive"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let mut repl = engine_state.repl_state.lock().expect("repl state mutex"); + if let Some(pos) = call.opt::(engine_state, stack, 0)? { + repl.cursor_pos = if pos <= 0 { + 0usize + } else { + repl.buffer + .grapheme_indices(true) + .map(|(i, _c)| i) + .nth(pos as usize) + .unwrap_or(repl.buffer.len()) + }; + Ok(Value::nothing(call.head).into_pipeline_data()) + } else if call.has_flag(engine_state, stack, "end")? { + repl.cursor_pos = repl.buffer.len(); + Ok(Value::nothing(call.head).into_pipeline_data()) + } else { + Err(ShellError::GenericError { + error: "Required a positional argument or a flag".to_string(), + msg: "".to_string(), + span: None, + help: None, + inner: vec![], + }) + } + } +} diff --git a/nushell/crates/nu-cli/src/commands/default_context.rs b/nushell/crates/nu-cli/src/commands/default_context.rs new file mode 100644 index 0000000..ad19f18 --- /dev/null +++ b/nushell/crates/nu-cli/src/commands/default_context.rs @@ -0,0 +1,36 @@ +use crate::commands::*; +use nu_protocol::engine::{EngineState, StateWorkingSet}; + +pub fn add_cli_context(mut engine_state: EngineState) -> EngineState { + let delta = { + let mut working_set = StateWorkingSet::new(&engine_state); + + macro_rules! bind_command { + ( $( $command:expr ),* $(,)? ) => { + $( working_set.add_decl(Box::new($command)); )* + }; + } + + bind_command! { + Commandline, + CommandlineEdit, + CommandlineGetCursor, + CommandlineSetCursor, + History, + HistoryImport, + HistorySession, + Keybindings, + KeybindingsDefault, + KeybindingsList, + KeybindingsListen, + }; + + working_set.render() + }; + + if let Err(err) = engine_state.merge_delta(delta) { + eprintln!("Error creating CLI command context: {err:?}"); + } + + engine_state +} diff --git a/nushell/crates/nu-cli/src/commands/history/fields.rs b/nushell/crates/nu-cli/src/commands/history/fields.rs new file mode 100644 index 0000000..a5b4422 --- /dev/null +++ b/nushell/crates/nu-cli/src/commands/history/fields.rs @@ -0,0 +1,9 @@ +// Each const is named after a HistoryItem field, and the value is the field name to be displayed to +// the user (or accept during import). +pub const COMMAND_LINE: &str = "command"; +pub const START_TIMESTAMP: &str = "start_timestamp"; +pub const HOSTNAME: &str = "hostname"; +pub const CWD: &str = "cwd"; +pub const EXIT_STATUS: &str = "exit_status"; +pub const DURATION: &str = "duration"; +pub const SESSION_ID: &str = "session_id"; diff --git a/nushell/crates/nu-cli/src/commands/history/history_.rs b/nushell/crates/nu-cli/src/commands/history/history_.rs new file mode 100644 index 0000000..10f0a21 --- /dev/null +++ b/nushell/crates/nu-cli/src/commands/history/history_.rs @@ -0,0 +1,206 @@ +use nu_engine::command_prelude::*; +use nu_protocol::{ + HistoryFileFormat, + shell_error::{self, io::IoError}, +}; +use reedline::{ + FileBackedHistory, History as ReedlineHistory, HistoryItem, SearchDirection, SearchQuery, + SqliteBackedHistory, +}; + +use super::fields; + +#[derive(Clone)] +pub struct History; + +impl Command for History { + fn name(&self) -> &str { + "history" + } + + fn description(&self) -> &str { + "Get the command history." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("history") + .input_output_types(vec![(Type::Nothing, Type::Any)]) + .allow_variants_without_examples(true) + .switch("clear", "Clears out the history entries", Some('c')) + .switch( + "long", + "Show long listing of entries for sqlite history", + Some('l'), + ) + .category(Category::History) + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let head = call.head; + + let Some(history) = engine_state.history_config() else { + return Ok(PipelineData::empty()); + }; + // todo for sqlite history this command should be an alias to `open ~/.config/nushell/history.sqlite3 | get history` + let Some(history_path) = history.file_path() else { + return Err(ShellError::ConfigDirNotFound { span: Some(head) }); + }; + + if call.has_flag(engine_state, stack, "clear")? { + let _ = std::fs::remove_file(history_path); + // TODO: FIXME also clear the auxiliary files when using sqlite + return Ok(PipelineData::empty()); + } + + let long = call.has_flag(engine_state, stack, "long")?; + let signals = engine_state.signals().clone(); + let history_reader: Option> = match history.file_format { + HistoryFileFormat::Sqlite => { + SqliteBackedHistory::with_file(history_path.clone(), None, None) + .map(|inner| { + let boxed: Box = Box::new(inner); + boxed + }) + .ok() + } + HistoryFileFormat::Plaintext => { + FileBackedHistory::with_file(history.max_size as usize, history_path.clone()) + .map(|inner| { + let boxed: Box = Box::new(inner); + boxed + }) + .ok() + } + }; + match history.file_format { + HistoryFileFormat::Plaintext => Ok(history_reader + .and_then(|h| { + h.search(SearchQuery::everything(SearchDirection::Forward, None)) + .ok() + }) + .map(move |entries| { + entries.into_iter().enumerate().map(move |(idx, entry)| { + Value::record( + record! { + fields::COMMAND_LINE => Value::string(entry.command_line, head), + // TODO: This name is inconsistent with create_history_record. + "index" => Value::int(idx as i64, head), + }, + head, + ) + }) + }) + .ok_or(IoError::new( + shell_error::io::ErrorKind::FileNotFound, + head, + history_path, + ))? + .into_pipeline_data(head, signals)), + HistoryFileFormat::Sqlite => Ok(history_reader + .and_then(|h| { + h.search(SearchQuery::everything(SearchDirection::Forward, None)) + .ok() + }) + .map(move |entries| { + entries.into_iter().enumerate().map(move |(idx, entry)| { + create_sqlite_history_record(idx, entry, long, head) + }) + }) + .ok_or(IoError::new( + shell_error::io::ErrorKind::FileNotFound, + head, + history_path, + ))? + .into_pipeline_data(head, signals)), + } + } + + fn examples(&self) -> Vec { + vec![ + Example { + example: "history | length", + description: "Get current history length", + result: None, + }, + Example { + example: "history | last 5", + description: "Show last 5 commands you have ran", + result: None, + }, + Example { + example: "history | where command =~ cargo | get command", + description: "Search all the commands from history that contains 'cargo'", + result: None, + }, + ] + } +} + +fn create_sqlite_history_record(idx: usize, entry: HistoryItem, long: bool, head: Span) -> Value { + //1. Format all the values + //2. Create a record of either short or long columns and values + + let item_id_value = Value::int( + entry + .id + .and_then(|id| id.to_string().parse::().ok()) + .unwrap_or_default(), + head, + ); + let start_timestamp_value = Value::date( + entry.start_timestamp.unwrap_or_default().fixed_offset(), + head, + ); + let command_value = Value::string(entry.command_line, head); + let session_id_value = Value::int( + entry + .session_id + .and_then(|id| id.to_string().parse::().ok()) + .unwrap_or_default(), + head, + ); + let hostname_value = Value::string(entry.hostname.unwrap_or_default(), head); + let cwd_value = Value::string(entry.cwd.unwrap_or_default(), head); + let duration_value = Value::duration( + entry + .duration + .and_then(|d| d.as_nanos().try_into().ok()) + .unwrap_or(0), + head, + ); + let exit_status_value = Value::int(entry.exit_status.unwrap_or(0), head); + let index_value = Value::int(idx as i64, head); + if long { + Value::record( + record! { + "item_id" => item_id_value, + fields::START_TIMESTAMP => start_timestamp_value, + fields::COMMAND_LINE => command_value, + fields::SESSION_ID => session_id_value, + fields::HOSTNAME => hostname_value, + fields::CWD => cwd_value, + fields::DURATION => duration_value, + fields::EXIT_STATUS => exit_status_value, + "idx" => index_value, + }, + head, + ) + } else { + Value::record( + record! { + fields::START_TIMESTAMP => start_timestamp_value, + fields::COMMAND_LINE => command_value, + fields::CWD => cwd_value, + fields::DURATION => duration_value, + fields::EXIT_STATUS => exit_status_value, + }, + head, + ) + } +} diff --git a/nushell/crates/nu-cli/src/commands/history/history_import.rs b/nushell/crates/nu-cli/src/commands/history/history_import.rs new file mode 100644 index 0000000..360273a --- /dev/null +++ b/nushell/crates/nu-cli/src/commands/history/history_import.rs @@ -0,0 +1,440 @@ +use std::path::{Path, PathBuf}; + +use nu_engine::command_prelude::*; +use nu_protocol::{ + HistoryFileFormat, + shell_error::{self, io::IoError}, +}; + +use reedline::{ + FileBackedHistory, History, HistoryItem, ReedlineError, SearchQuery, SqliteBackedHistory, +}; + +use super::fields; + +#[derive(Clone)] +pub struct HistoryImport; + +impl Command for HistoryImport { + fn name(&self) -> &str { + "history import" + } + + fn description(&self) -> &str { + "Import command line history." + } + + fn extra_description(&self) -> &str { + r#"Can import history from input, either successive command lines or more detailed records. If providing records, available fields are: + command, start_timestamp, hostname, cwd, duration, exit_status. + +If no input is provided, will import all history items from existing history in the other format: if current history is stored in sqlite, it will store it in plain text and vice versa. + +Note that history item IDs are ignored when importing from file."# + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("history import") + .category(Category::History) + .input_output_types(vec![ + (Type::Nothing, Type::Nothing), + (Type::String, Type::Nothing), + (Type::List(Box::new(Type::String)), Type::Nothing), + (Type::table(), Type::Nothing), + ]) + } + + fn examples(&self) -> Vec { + vec![ + Example { + example: "history import", + description: "Append all items from history in the other format to the current history", + result: None, + }, + Example { + example: "echo foo | history import", + description: "Append `foo` to the current history", + result: None, + }, + Example { + example: "[[ command_line cwd ]; [ foo /home ]] | history import", + description: "Append `foo` ran from `/home` to the current history", + result: None, + }, + ] + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let span = call.head; + let ok = Ok(Value::nothing(call.head).into_pipeline_data()); + + let Some(history) = engine_state.history_config() else { + return ok; + }; + let Some(current_history_path) = history.file_path() else { + return Err(ShellError::ConfigDirNotFound { span: span.into() }); + }; + if let Some(bak_path) = backup(¤t_history_path, span)? { + println!("Backed history to {}", bak_path.display()); + } + match input { + PipelineData::Empty => { + let other_format = match history.file_format { + HistoryFileFormat::Sqlite => HistoryFileFormat::Plaintext, + HistoryFileFormat::Plaintext => HistoryFileFormat::Sqlite, + }; + let src = new_backend(other_format, None)?; + let mut dst = new_backend(history.file_format, Some(current_history_path))?; + let items = src + .search(SearchQuery::everything( + reedline::SearchDirection::Forward, + None, + )) + .map_err(error_from_reedline)? + .into_iter() + .map(Ok); + import(dst.as_mut(), items) + } + _ => { + let input = input.into_iter().map(item_from_value); + import( + new_backend(history.file_format, Some(current_history_path))?.as_mut(), + input, + ) + } + }?; + + ok + } +} + +fn new_backend( + format: HistoryFileFormat, + path: Option, +) -> Result, ShellError> { + let path = match path { + Some(path) => path, + None => { + let Some(mut path) = nu_path::nu_config_dir() else { + return Err(ShellError::ConfigDirNotFound { span: None }); + }; + path.push(format.default_file_name()); + path.into_std_path_buf() + } + }; + + fn map( + result: Result, + ) -> Result, ShellError> { + result + .map(|x| Box::new(x) as Box) + .map_err(error_from_reedline) + } + match format { + // Use a reasonably large value for maximum capacity. + HistoryFileFormat::Plaintext => map(FileBackedHistory::with_file(0xfffffff, path)), + HistoryFileFormat::Sqlite => map(SqliteBackedHistory::with_file(path, None, None)), + } +} + +fn import( + dst: &mut dyn History, + src: impl Iterator>, +) -> Result<(), ShellError> { + for item in src { + let mut item = item?; + item.id = None; + dst.save(item).map_err(error_from_reedline)?; + } + Ok(()) +} + +fn error_from_reedline(e: ReedlineError) -> ShellError { + // TODO: Should we add a new ShellError variant? + ShellError::GenericError { + error: "Reedline error".to_owned(), + msg: format!("{e}"), + span: None, + help: None, + inner: Vec::new(), + } +} + +fn item_from_value(v: Value) -> Result { + let span = v.span(); + match v { + Value::Record { val, .. } => item_from_record(val.into_owned(), span), + Value::String { val, .. } => Ok(HistoryItem { + command_line: val, + id: None, + start_timestamp: None, + session_id: None, + hostname: None, + cwd: None, + duration: None, + exit_status: None, + more_info: None, + }), + _ => Err(ShellError::UnsupportedInput { + msg: "Only list and record inputs are supported".to_owned(), + input: v.get_type().to_string(), + msg_span: span, + input_span: span, + }), + } +} + +fn item_from_record(mut rec: Record, span: Span) -> Result { + let cmd = match rec.remove(fields::COMMAND_LINE) { + Some(v) => v.as_str()?.to_owned(), + None => { + return Err(ShellError::TypeMismatch { + err_message: format!("missing column: {}", fields::COMMAND_LINE), + span, + }); + } + }; + + fn get( + rec: &mut Record, + field: &'static str, + f: impl FnOnce(Value) -> Result, + ) -> Result, ShellError> { + rec.remove(field).map(f).transpose() + } + + let rec = &mut rec; + let item = HistoryItem { + command_line: cmd, + id: None, + start_timestamp: get(rec, fields::START_TIMESTAMP, |v| Ok(v.as_date()?.to_utc()))?, + hostname: get(rec, fields::HOSTNAME, |v| Ok(v.as_str()?.to_owned()))?, + cwd: get(rec, fields::CWD, |v| Ok(v.as_str()?.to_owned()))?, + exit_status: get(rec, fields::EXIT_STATUS, |v| v.as_int())?, + duration: get(rec, fields::DURATION, |v| duration_from_value(v, span))?, + more_info: None, + // TODO: Currently reedline doesn't let you create session IDs. + session_id: None, + }; + + if !rec.is_empty() { + let cols = rec.columns().map(|s| s.as_str()).collect::>(); + return Err(ShellError::TypeMismatch { + err_message: format!("unsupported column names: {}", cols.join(", ")), + span, + }); + } + Ok(item) +} + +fn duration_from_value(v: Value, span: Span) -> Result { + chrono::Duration::nanoseconds(v.as_duration()?) + .to_std() + .map_err(|_| ShellError::NeedsPositiveValue { span }) +} + +fn find_backup_path(path: &Path, span: Span) -> Result { + let Ok(mut bak_path) = path.to_path_buf().into_os_string().into_string() else { + // This isn't fundamentally problem, but trying to work with OsString is a nightmare. + return Err(ShellError::GenericError { + error: "History path not UTF-8".to_string(), + msg: "History path must be representable as UTF-8".to_string(), + span: Some(span), + help: None, + inner: vec![], + }); + }; + bak_path.push_str(".bak"); + if !Path::new(&bak_path).exists() { + return Ok(bak_path.into()); + } + let base_len = bak_path.len(); + for i in 1..100 { + use std::fmt::Write; + bak_path.truncate(base_len); + write!(&mut bak_path, ".{i}").unwrap(); + if !Path::new(&bak_path).exists() { + return Ok(PathBuf::from(bak_path)); + } + } + Err(ShellError::GenericError { + error: "Too many backup files".to_string(), + msg: "Found too many existing backup files".to_string(), + span: Some(span), + help: None, + inner: vec![], + }) +} + +fn backup(path: &Path, span: Span) -> Result, ShellError> { + match path.metadata() { + Ok(md) if md.is_file() => (), + Ok(_) => { + return Err(IoError::new_with_additional_context( + shell_error::io::ErrorKind::NotAFile, + span, + PathBuf::from(path), + "history path exists but is not a file", + ) + .into()); + } + Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(None), + Err(e) => { + return Err(IoError::new_internal( + e, + "Could not get metadata", + nu_protocol::location!(), + ) + .into()); + } + } + let bak_path = find_backup_path(path, span)?; + std::fs::copy(path, &bak_path).map_err(|err| { + IoError::new_internal( + err.not_found_as(NotFound::File), + "Could not copy backup", + nu_protocol::location!(), + ) + })?; + Ok(Some(bak_path)) +} + +#[cfg(test)] +mod tests { + use chrono::DateTime; + use rstest::rstest; + + use super::*; + + #[test] + fn test_item_from_value_string() -> Result<(), ShellError> { + let item = item_from_value(Value::string("foo", Span::unknown()))?; + assert_eq!( + item, + HistoryItem { + command_line: "foo".to_string(), + id: None, + start_timestamp: None, + session_id: None, + hostname: None, + cwd: None, + duration: None, + exit_status: None, + more_info: None + } + ); + Ok(()) + } + + #[test] + fn test_item_from_value_record() { + let span = Span::unknown(); + let rec = new_record(&[ + ("command", Value::string("foo", span)), + ( + "start_timestamp", + Value::date( + DateTime::parse_from_rfc3339("1996-12-19T16:39:57-08:00").unwrap(), + span, + ), + ), + ("hostname", Value::string("localhost", span)), + ("cwd", Value::string("/home/test", span)), + ("duration", Value::duration(100_000_000, span)), + ("exit_status", Value::int(42, span)), + ]); + let item = item_from_value(rec).unwrap(); + assert_eq!( + item, + HistoryItem { + command_line: "foo".to_string(), + id: None, + start_timestamp: Some( + DateTime::parse_from_rfc3339("1996-12-19T16:39:57-08:00") + .unwrap() + .to_utc() + ), + hostname: Some("localhost".to_string()), + cwd: Some("/home/test".to_string()), + duration: Some(std::time::Duration::from_nanos(100_000_000)), + exit_status: Some(42), + + session_id: None, + more_info: None + } + ); + } + + #[test] + fn test_item_from_value_record_extra_field() { + let span = Span::unknown(); + let rec = new_record(&[ + ("command_line", Value::string("foo", span)), + ("id_nonexistent", Value::int(1, span)), + ]); + assert!(item_from_value(rec).is_err()); + } + + #[test] + fn test_item_from_value_record_bad_type() { + let span = Span::unknown(); + let rec = new_record(&[ + ("command_line", Value::string("foo", span)), + ("id", Value::string("one".to_string(), span)), + ]); + assert!(item_from_value(rec).is_err()); + } + + fn new_record(rec: &[(&'static str, Value)]) -> Value { + let span = Span::unknown(); + let rec = Record::from_raw_cols_vals( + rec.iter().map(|(col, _)| col.to_string()).collect(), + rec.iter().map(|(_, val)| val.clone()).collect(), + span, + span, + ) + .unwrap(); + Value::record(rec, span) + } + + #[rstest] + #[case::no_backup(&["history.dat"], "history.dat.bak")] + #[case::backup_exists(&["history.dat", "history.dat.bak"], "history.dat.bak.1")] + #[case::multiple_backups_exists( &["history.dat", "history.dat.bak", "history.dat.bak.1"], "history.dat.bak.2")] + fn test_find_backup_path(#[case] existing: &[&str], #[case] want: &str) { + let dir = tempfile::tempdir().unwrap(); + for name in existing { + std::fs::File::create_new(dir.path().join(name)).unwrap(); + } + let got = find_backup_path(&dir.path().join("history.dat"), Span::test_data()).unwrap(); + assert_eq!(got, dir.path().join(want)) + } + + #[test] + fn test_backup() { + let dir = tempfile::tempdir().unwrap(); + let mut history = std::fs::File::create_new(dir.path().join("history.dat")).unwrap(); + use std::io::Write; + write!(&mut history, "123").unwrap(); + let want_bak_path = dir.path().join("history.dat.bak"); + assert_eq!( + backup(&dir.path().join("history.dat"), Span::test_data()), + Ok(Some(want_bak_path.clone())) + ); + let got_data = String::from_utf8(std::fs::read(want_bak_path).unwrap()).unwrap(); + assert_eq!(got_data, "123"); + } + + #[test] + fn test_backup_no_file() { + let dir = tempfile::tempdir().unwrap(); + let bak_path = backup(&dir.path().join("history.dat"), Span::test_data()).unwrap(); + assert!(bak_path.is_none()); + } +} diff --git a/nushell/crates/nu-cli/src/commands/history/history_session.rs b/nushell/crates/nu-cli/src/commands/history/history_session.rs new file mode 100644 index 0000000..d6e0d0d --- /dev/null +++ b/nushell/crates/nu-cli/src/commands/history/history_session.rs @@ -0,0 +1,38 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct HistorySession; + +impl Command for HistorySession { + fn name(&self) -> &str { + "history session" + } + + fn description(&self) -> &str { + "Get the command history session." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("history session") + .category(Category::History) + .input_output_types(vec![(Type::Nothing, Type::Int)]) + } + + fn examples(&self) -> Vec { + vec![Example { + example: "history session", + description: "Get current history session", + result: None, + }] + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + Ok(Value::int(engine_state.history_session_id, call.head).into_pipeline_data()) + } +} diff --git a/nushell/crates/nu-cli/src/commands/history/mod.rs b/nushell/crates/nu-cli/src/commands/history/mod.rs new file mode 100644 index 0000000..c36b560 --- /dev/null +++ b/nushell/crates/nu-cli/src/commands/history/mod.rs @@ -0,0 +1,8 @@ +mod fields; +mod history_; +mod history_import; +mod history_session; + +pub use history_::History; +pub use history_import::HistoryImport; +pub use history_session::HistorySession; diff --git a/nushell/crates/nu-cli/src/commands/keybindings.rs b/nushell/crates/nu-cli/src/commands/keybindings.rs new file mode 100644 index 0000000..34ae0fa --- /dev/null +++ b/nushell/crates/nu-cli/src/commands/keybindings.rs @@ -0,0 +1,41 @@ +use nu_engine::{command_prelude::*, get_full_help}; + +#[derive(Clone)] +pub struct Keybindings; + +impl Command for Keybindings { + fn name(&self) -> &str { + "keybindings" + } + + fn signature(&self) -> Signature { + Signature::build(self.name()) + .category(Category::Platform) + .input_output_types(vec![(Type::Nothing, Type::String)]) + } + + fn description(&self) -> &str { + "Keybindings related commands." + } + + fn extra_description(&self) -> &str { + r#"You must use one of the following subcommands. Using this command as-is will only produce this help message. + +For more information on input and keybindings, check: + https://www.nushell.sh/book/line_editor.html"# + } + + fn search_terms(&self) -> Vec<&str> { + vec!["shortcut", "hotkey"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + Ok(Value::string(get_full_help(self, engine_state, stack), call.head).into_pipeline_data()) + } +} diff --git a/nushell/crates/nu-cli/src/commands/keybindings_default.rs b/nushell/crates/nu-cli/src/commands/keybindings_default.rs new file mode 100644 index 0000000..c5ca29d --- /dev/null +++ b/nushell/crates/nu-cli/src/commands/keybindings_default.rs @@ -0,0 +1,54 @@ +use nu_engine::command_prelude::*; +use reedline::get_reedline_default_keybindings; + +#[derive(Clone)] +pub struct KeybindingsDefault; + +impl Command for KeybindingsDefault { + fn name(&self) -> &str { + "keybindings default" + } + + fn signature(&self) -> Signature { + Signature::build(self.name()) + .category(Category::Platform) + .input_output_types(vec![(Type::Nothing, Type::table())]) + } + + fn description(&self) -> &str { + "List default keybindings." + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Get list with default keybindings", + example: "keybindings default", + result: None, + }] + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let records = get_reedline_default_keybindings() + .into_iter() + .map(|(mode, modifier, code, event)| { + Value::record( + record! { + "mode" => Value::string(mode, call.head), + "modifier" => Value::string(modifier, call.head), + "code" => Value::string(code, call.head), + "event" => Value::string(event, call.head), + }, + call.head, + ) + }) + .collect(); + + Ok(Value::list(records, call.head).into_pipeline_data()) + } +} diff --git a/nushell/crates/nu-cli/src/commands/keybindings_list.rs b/nushell/crates/nu-cli/src/commands/keybindings_list.rs new file mode 100644 index 0000000..6332ec3 --- /dev/null +++ b/nushell/crates/nu-cli/src/commands/keybindings_list.rs @@ -0,0 +1,117 @@ +use nu_engine::command_prelude::*; +use reedline::{ + get_reedline_edit_commands, get_reedline_keybinding_modifiers, get_reedline_keycodes, + get_reedline_prompt_edit_modes, get_reedline_reedline_events, +}; + +#[derive(Clone)] +pub struct KeybindingsList; + +impl Command for KeybindingsList { + fn name(&self) -> &str { + "keybindings list" + } + + fn signature(&self) -> Signature { + Signature::build(self.name()) + .input_output_types(vec![(Type::Nothing, Type::table())]) + .switch("modifiers", "list of modifiers", Some('m')) + .switch("keycodes", "list of keycodes", Some('k')) + .switch("modes", "list of edit modes", Some('o')) + .switch("events", "list of reedline event", Some('e')) + .switch("edits", "list of edit commands", Some('d')) + .category(Category::Platform) + } + + fn description(&self) -> &str { + "List available options that can be used to create keybindings." + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Get list of key modifiers", + example: "keybindings list --modifiers", + result: None, + }, + Example { + description: "Get list of reedline events and edit commands", + example: "keybindings list -e -d", + result: None, + }, + Example { + description: "Get list with all the available options", + example: "keybindings list", + result: None, + }, + ] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let all_options = ["modifiers", "keycodes", "edits", "modes", "events"]; + + let presence = all_options + .iter() + .map(|option| call.has_flag(engine_state, stack, option)) + .collect::, ShellError>>()?; + + let no_option_specified = presence.iter().all(|present| !*present); + + let records = all_options + .iter() + .zip(presence) + .filter(|(_, present)| no_option_specified || *present) + .flat_map(|(option, _)| get_records(option, call.head)) + .collect(); + + Ok(Value::list(records, call.head).into_pipeline_data()) + } +} + +fn get_records(entry_type: &str, span: Span) -> Vec { + let values = match entry_type { + "modifiers" => get_reedline_keybinding_modifiers().sorted(), + "keycodes" => get_reedline_keycodes().sorted(), + "edits" => get_reedline_edit_commands().sorted(), + "modes" => get_reedline_prompt_edit_modes().sorted(), + "events" => get_reedline_reedline_events().sorted(), + _ => Vec::new(), + }; + + values + .iter() + .map(|edit| edit.split('\n')) + .flat_map(|edit| edit.map(|edit| convert_to_record(edit, entry_type, span))) + .collect() +} + +fn convert_to_record(edit: &str, entry_type: &str, span: Span) -> Value { + Value::record( + record! { + "type" => Value::string(entry_type, span), + "name" => Value::string(edit, span), + }, + span, + ) +} + +// Helper to sort a vec and return a vec +trait SortedImpl { + fn sorted(self) -> Self; +} + +impl SortedImpl for Vec +where + E: std::cmp::Ord, +{ + fn sorted(mut self) -> Self { + self.sort(); + self + } +} diff --git a/nushell/crates/nu-cli/src/commands/keybindings_listen.rs b/nushell/crates/nu-cli/src/commands/keybindings_listen.rs new file mode 100644 index 0000000..2232b9d --- /dev/null +++ b/nushell/crates/nu-cli/src/commands/keybindings_listen.rs @@ -0,0 +1,200 @@ +use crossterm::{ + QueueableCommand, event::Event, event::KeyCode, event::KeyEvent, execute, terminal, +}; +use nu_engine::command_prelude::*; +use nu_protocol::shell_error::io::IoError; +use std::io::{Write, stdout}; + +#[derive(Clone)] +pub struct KeybindingsListen; + +impl Command for KeybindingsListen { + fn name(&self) -> &str { + "keybindings listen" + } + + fn description(&self) -> &str { + "Get input from the user." + } + + fn extra_description(&self) -> &str { + "This is an internal debugging tool. For better output, try `input listen --types [key]`" + } + + fn signature(&self) -> Signature { + Signature::build(self.name()) + .category(Category::Platform) + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .allow_variants_without_examples(true) + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + println!("Type any key combination to see key details. Press ESC to abort."); + + match print_events(engine_state) { + Ok(v) => Ok(v.into_pipeline_data()), + Err(e) => { + terminal::disable_raw_mode().map_err(|err| { + IoError::new_internal( + err, + "Could not disable raw mode", + nu_protocol::location!(), + ) + })?; + Err(ShellError::GenericError { + error: "Error with input".into(), + msg: "".into(), + span: None, + help: Some(e.to_string()), + inner: vec![], + }) + } + } + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Type and see key event codes", + example: "keybindings listen", + result: None, + }] + } +} + +pub fn print_events(engine_state: &EngineState) -> Result { + let config = engine_state.get_config(); + + stdout().flush().map_err(|err| { + IoError::new_internal(err, "Could not flush stdout", nu_protocol::location!()) + })?; + terminal::enable_raw_mode().map_err(|err| { + IoError::new_internal(err, "Could not enable raw mode", nu_protocol::location!()) + })?; + + if config.use_kitty_protocol { + if let Ok(false) = crossterm::terminal::supports_keyboard_enhancement() { + println!("WARN: The terminal doesn't support use_kitty_protocol config.\r"); + } + + // enable kitty protocol + // + // Note that, currently, only the following support this protocol: + // * [kitty terminal](https://sw.kovidgoyal.net/kitty/) + // * [foot terminal](https://codeberg.org/dnkl/foot/issues/319) + // * [WezTerm terminal](https://wezfurlong.org/wezterm/config/lua/config/enable_kitty_keyboard.html) + // * [notcurses library](https://github.com/dankamongmen/notcurses/issues/2131) + // * [neovim text editor](https://github.com/neovim/neovim/pull/18181) + // * [kakoune text editor](https://github.com/mawww/kakoune/issues/4103) + // * [dte text editor](https://gitlab.com/craigbarnes/dte/-/issues/138) + // + // Refer to https://sw.kovidgoyal.net/kitty/keyboard-protocol/ if you're curious. + let _ = execute!( + stdout(), + crossterm::event::PushKeyboardEnhancementFlags( + crossterm::event::KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES + ) + ); + } + + let mut stdout = std::io::BufWriter::new(std::io::stderr()); + + loop { + let event = crossterm::event::read().map_err(|err| { + IoError::new_internal(err, "Could not read event", nu_protocol::location!()) + })?; + if event == Event::Key(KeyCode::Esc.into()) { + break; + } + // stdout.queue(crossterm::style::Print(format!("event: {:?}", &event)))?; + // stdout.queue(crossterm::style::Print("\r\n"))?; + + // Get a record + let v = print_events_helper(event)?; + // Print out the record + let o = match v { + Value::Record { val, .. } => val + .iter() + .map(|(x, y)| format!("{}: {}", x, y.to_expanded_string("", config))) + .collect::>() + .join(", "), + + _ => "".to_string(), + }; + stdout.queue(crossterm::style::Print(o)).map_err(|err| { + IoError::new_internal( + err, + "Could not print output record", + nu_protocol::location!(), + ) + })?; + stdout + .queue(crossterm::style::Print("\r\n")) + .map_err(|err| { + IoError::new_internal(err, "Could not print linebreak", nu_protocol::location!()) + })?; + stdout.flush().map_err(|err| { + IoError::new_internal(err, "Could not flush", nu_protocol::location!()) + })?; + } + + if config.use_kitty_protocol { + let _ = execute!( + std::io::stdout(), + crossterm::event::PopKeyboardEnhancementFlags + ); + } + + terminal::disable_raw_mode().map_err(|err| { + IoError::new_internal(err, "Could not disable raw mode", nu_protocol::location!()) + })?; + + Ok(Value::nothing(Span::unknown())) +} + +// this fn is totally ripped off from crossterm's examples +// it's really a diagnostic routine to see if crossterm is +// even seeing the events. if you press a key and no events +// are printed, it's a good chance your terminal is eating +// those events. +fn print_events_helper(event: Event) -> Result { + if let Event::Key(KeyEvent { + code, + modifiers, + kind, + state, + }) = event + { + match code { + KeyCode::Char(c) => { + let record = record! { + "char" => Value::string(format!("{c}"), Span::unknown()), + "code" => Value::string(format!("{:#08x}", u32::from(c)), Span::unknown()), + "modifier" => Value::string(format!("{modifiers:?}"), Span::unknown()), + "flags" => Value::string(format!("{modifiers:#08b}"), Span::unknown()), + "kind" => Value::string(format!("{kind:?}"), Span::unknown()), + "state" => Value::string(format!("{state:?}"), Span::unknown()), + }; + Ok(Value::record(record, Span::unknown())) + } + _ => { + let record = record! { + "code" => Value::string(format!("{code:?}"), Span::unknown()), + "modifier" => Value::string(format!("{modifiers:?}"), Span::unknown()), + "flags" => Value::string(format!("{modifiers:#08b}"), Span::unknown()), + "kind" => Value::string(format!("{kind:?}"), Span::unknown()), + "state" => Value::string(format!("{state:?}"), Span::unknown()), + }; + Ok(Value::record(record, Span::unknown())) + } + } + } else { + let record = record! { "event" => Value::string(format!("{event:?}"), Span::unknown()) }; + Ok(Value::record(record, Span::unknown())) + } +} diff --git a/nushell/crates/nu-cli/src/commands/mod.rs b/nushell/crates/nu-cli/src/commands/mod.rs new file mode 100644 index 0000000..4a9dd9e --- /dev/null +++ b/nushell/crates/nu-cli/src/commands/mod.rs @@ -0,0 +1,16 @@ +mod commandline; +mod default_context; +mod history; +mod keybindings; +mod keybindings_default; +mod keybindings_list; +mod keybindings_listen; + +pub use commandline::{Commandline, CommandlineEdit, CommandlineGetCursor, CommandlineSetCursor}; +pub use history::{History, HistoryImport, HistorySession}; +pub use keybindings::Keybindings; +pub use keybindings_default::KeybindingsDefault; +pub use keybindings_list::KeybindingsList; +pub use keybindings_listen::KeybindingsListen; + +pub use default_context::add_cli_context; diff --git a/nushell/crates/nu-cli/src/completions/attribute_completions.rs b/nushell/crates/nu-cli/src/completions/attribute_completions.rs new file mode 100644 index 0000000..46ba1af --- /dev/null +++ b/nushell/crates/nu-cli/src/completions/attribute_completions.rs @@ -0,0 +1,85 @@ +use super::{SemanticSuggestion, completion_options::NuMatcher}; +use crate::{ + SuggestionKind, + completions::{Completer, CompletionOptions}, +}; +use nu_protocol::{ + Span, + engine::{Stack, StateWorkingSet}, +}; +use reedline::Suggestion; + +pub struct AttributeCompletion; +pub struct AttributableCompletion; + +impl Completer for AttributeCompletion { + fn fetch( + &mut self, + working_set: &StateWorkingSet, + _stack: &Stack, + prefix: impl AsRef, + span: Span, + offset: usize, + options: &CompletionOptions, + ) -> Vec { + let mut matcher = NuMatcher::new(prefix, options); + + let attr_commands = + working_set.find_commands_by_predicate(|s| s.starts_with(b"attr "), true); + + for (decl_id, name, desc, ty) in attr_commands { + let name = name.strip_prefix(b"attr ").unwrap_or(&name); + matcher.add_semantic_suggestion(SemanticSuggestion { + suggestion: Suggestion { + value: String::from_utf8_lossy(name).into_owned(), + description: desc, + span: reedline::Span { + start: span.start - offset, + end: span.end - offset, + }, + append_whitespace: false, + ..Default::default() + }, + kind: Some(SuggestionKind::Command(ty, Some(decl_id))), + }); + } + + matcher.results() + } +} + +impl Completer for AttributableCompletion { + fn fetch( + &mut self, + working_set: &StateWorkingSet, + _stack: &Stack, + prefix: impl AsRef, + span: Span, + offset: usize, + options: &CompletionOptions, + ) -> Vec { + let mut matcher = NuMatcher::new(prefix, options); + + for s in ["def", "extern", "export def", "export extern"] { + let decl_id = working_set + .find_decl(s.as_bytes()) + .expect("internal error, builtin declaration not found"); + let cmd = working_set.get_decl(decl_id); + matcher.add_semantic_suggestion(SemanticSuggestion { + suggestion: Suggestion { + value: cmd.name().into(), + description: Some(cmd.description().into()), + span: reedline::Span { + start: span.start - offset, + end: span.end - offset, + }, + append_whitespace: false, + ..Default::default() + }, + kind: Some(SuggestionKind::Command(cmd.command_type(), None)), + }); + } + + matcher.results() + } +} diff --git a/nushell/crates/nu-cli/src/completions/base.rs b/nushell/crates/nu-cli/src/completions/base.rs new file mode 100644 index 0000000..4e70d63 --- /dev/null +++ b/nushell/crates/nu-cli/src/completions/base.rs @@ -0,0 +1,49 @@ +use crate::completions::CompletionOptions; +use nu_protocol::{ + DeclId, Span, + engine::{Stack, StateWorkingSet}, +}; +use reedline::Suggestion; + +pub trait Completer { + /// Fetch, filter, and sort completions + #[allow(clippy::too_many_arguments)] + fn fetch( + &mut self, + working_set: &StateWorkingSet, + stack: &Stack, + prefix: impl AsRef, + span: Span, + offset: usize, + options: &CompletionOptions, + ) -> Vec; +} + +#[derive(Debug, Default, PartialEq)] +pub struct SemanticSuggestion { + pub suggestion: Suggestion, + pub kind: Option, +} + +// TODO: think about name: maybe suggestion context? +#[derive(Clone, Debug, PartialEq)] +pub enum SuggestionKind { + Command(nu_protocol::engine::CommandType, Option), + Value(nu_protocol::Type), + CellPath, + Directory, + File, + Flag, + Module, + Operator, + Variable, +} + +impl From for SemanticSuggestion { + fn from(suggestion: Suggestion) -> Self { + Self { + suggestion, + ..Default::default() + } + } +} diff --git a/nushell/crates/nu-cli/src/completions/cell_path_completions.rs b/nushell/crates/nu-cli/src/completions/cell_path_completions.rs new file mode 100644 index 0000000..51ca0b5 --- /dev/null +++ b/nushell/crates/nu-cli/src/completions/cell_path_completions.rs @@ -0,0 +1,153 @@ +use std::borrow::Cow; + +use crate::completions::{Completer, CompletionOptions, SemanticSuggestion, SuggestionKind}; +use nu_engine::{column::get_columns, eval_variable}; +use nu_protocol::{ + ShellError, Span, Value, + ast::{Expr, Expression, FullCellPath, PathMember}, + engine::{Stack, StateWorkingSet}, + eval_const::eval_constant, +}; +use reedline::Suggestion; + +use super::completion_options::NuMatcher; + +pub struct CellPathCompletion<'a> { + pub full_cell_path: &'a FullCellPath, + pub position: usize, +} + +fn prefix_from_path_member(member: &PathMember, pos: usize) -> (String, Span) { + let (prefix_str, start) = match member { + PathMember::String { val, span, .. } => (val, span.start), + PathMember::Int { val, span, .. } => (&val.to_string(), span.start), + }; + let prefix_str = prefix_str.get(..pos + 1 - start).unwrap_or(prefix_str); + // strip wrapping quotes + let quotations = ['"', '\'', '`']; + let prefix_str = prefix_str.strip_prefix(quotations).unwrap_or(prefix_str); + (prefix_str.to_string(), Span::new(start, pos + 1)) +} + +impl Completer for CellPathCompletion<'_> { + fn fetch( + &mut self, + working_set: &StateWorkingSet, + stack: &Stack, + _prefix: impl AsRef, + _span: Span, + offset: usize, + options: &CompletionOptions, + ) -> Vec { + let mut prefix_str = String::new(); + // position at dots, e.g. `$env.config.` + let mut span = Span::new(self.position + 1, self.position + 1); + let mut path_member_num_before_pos = 0; + for member in self.full_cell_path.tail.iter() { + if member.span().end <= self.position { + path_member_num_before_pos += 1; + } else if member.span().contains(self.position) { + (prefix_str, span) = prefix_from_path_member(member, self.position); + break; + } + } + + let current_span = reedline::Span { + start: span.start - offset, + end: span.end - offset, + }; + + let mut matcher = NuMatcher::new(prefix_str, options); + let path_members = self + .full_cell_path + .tail + .get(0..path_member_num_before_pos) + .unwrap_or_default(); + let value = eval_cell_path( + working_set, + stack, + &self.full_cell_path.head, + path_members, + span, + ) + .unwrap_or_default(); + + for suggestion in get_suggestions_by_value(&value, current_span) { + matcher.add_semantic_suggestion(suggestion); + } + matcher.results() + } +} + +/// Follow cell path to get the value +/// NOTE: This is a relatively lightweight implementation, +/// so it may fail to get the exact value when the expression is complicated. +/// One failing example would be `[$foo].0` +pub(crate) fn eval_cell_path( + working_set: &StateWorkingSet, + stack: &Stack, + head: &Expression, + path_members: &[PathMember], + span: Span, +) -> Result { + // evaluate the head expression to get its value + let head_value = if let Expr::Var(var_id) = head.expr { + working_set + .get_variable(var_id) + .const_val + .to_owned() + .map_or_else( + || eval_variable(working_set.permanent_state, stack, var_id, span), + Ok, + ) + } else { + eval_constant(working_set, head) + }?; + head_value + .follow_cell_path(path_members) + .map(Cow::into_owned) +} + +fn get_suggestions_by_value( + value: &Value, + current_span: reedline::Span, +) -> Vec { + let to_suggestion = |s: String, v: Option<&Value>| { + // Check if the string needs quoting + let value = if s.is_empty() + || s.chars() + .any(|c: char| !(c.is_ascii_alphabetic() || ['_', '-'].contains(&c))) + { + format!("{:?}", s) + } else { + s + }; + + SemanticSuggestion { + suggestion: Suggestion { + value, + span: current_span, + description: v.map(|v| v.get_type().to_string()), + ..Suggestion::default() + }, + kind: Some(SuggestionKind::CellPath), + } + }; + match value { + Value::Record { val, .. } => val + .columns() + .map(|s| to_suggestion(s.to_string(), val.get(s))) + .collect(), + Value::List { vals, .. } => get_columns(vals.as_slice()) + .into_iter() + .map(|s| { + let sub_val = vals + .first() + .and_then(|v| v.as_record().ok()) + .and_then(|rv| rv.get(&s)); + to_suggestion(s, sub_val) + }) + .collect(), + _ => vec![], + } +} diff --git a/nushell/crates/nu-cli/src/completions/command_completions.rs b/nushell/crates/nu-cli/src/completions/command_completions.rs new file mode 100644 index 0000000..ce74536 --- /dev/null +++ b/nushell/crates/nu-cli/src/completions/command_completions.rs @@ -0,0 +1,158 @@ +use std::collections::HashMap; + +use crate::{ + SuggestionKind, + completions::{Completer, CompletionOptions}, +}; +use nu_protocol::{ + Span, + engine::{CommandType, Stack, StateWorkingSet}, +}; +use reedline::Suggestion; + +use super::{SemanticSuggestion, completion_options::NuMatcher}; + +pub struct CommandCompletion { + /// Whether to include internal commands + pub internals: bool, + /// Whether to include external commands + pub externals: bool, +} + +impl CommandCompletion { + fn external_command_completion( + &self, + working_set: &StateWorkingSet, + sugg_span: reedline::Span, + matched_internal: impl Fn(&str) -> bool, + matcher: &mut NuMatcher, + ) -> HashMap { + let mut suggs = HashMap::new(); + + let paths = working_set.permanent_state.get_env_var_insensitive("path"); + + if let Some((_, paths)) = paths { + if let Ok(paths) = paths.as_list() { + for path in paths { + let path = path.coerce_str().unwrap_or_default(); + + if let Ok(mut contents) = std::fs::read_dir(path.as_ref()) { + while let Some(Ok(item)) = contents.next() { + if working_set + .permanent_state + .config + .completions + .external + .max_results + <= suggs.len() as i64 + { + break; + } + let Ok(name) = item.file_name().into_string() else { + continue; + }; + let value = if matched_internal(&name) { + format!("^{}", name) + } else { + name.clone() + }; + if suggs.contains_key(&value) { + continue; + } + // TODO: check name matching before a relative heavy IO involved + // `is_executable` for performance consideration, should avoid + // duplicated `match_aux` call for matched items in the future + if matcher.matches(&name) && is_executable::is_executable(item.path()) { + // If there's an internal command with the same name, adds ^cmd to the + // matcher so that both the internal and external command are included + matcher.add(&name, value.clone()); + suggs.insert( + value.clone(), + SemanticSuggestion { + suggestion: Suggestion { + value, + span: sugg_span, + append_whitespace: true, + ..Default::default() + }, + kind: Some(SuggestionKind::Command( + CommandType::External, + None, + )), + }, + ); + } + } + } + } + } + } + + suggs + } +} + +impl Completer for CommandCompletion { + fn fetch( + &mut self, + working_set: &StateWorkingSet, + _stack: &Stack, + prefix: impl AsRef, + span: Span, + offset: usize, + options: &CompletionOptions, + ) -> Vec { + let mut matcher = NuMatcher::new(prefix, options); + + let sugg_span = reedline::Span::new(span.start - offset, span.end - offset); + + let mut internal_suggs = HashMap::new(); + if self.internals { + let filtered_commands = working_set.find_commands_by_predicate( + |name| { + let name = String::from_utf8_lossy(name); + matcher.add(&name, name.to_string()) + }, + true, + ); + for (decl_id, name, description, typ) in filtered_commands { + let name = String::from_utf8_lossy(&name); + internal_suggs.insert( + name.to_string(), + SemanticSuggestion { + suggestion: Suggestion { + value: name.to_string(), + description, + span: sugg_span, + append_whitespace: true, + ..Suggestion::default() + }, + kind: Some(SuggestionKind::Command(typ, Some(decl_id))), + }, + ); + } + } + + let mut external_suggs = if self.externals { + self.external_command_completion( + working_set, + sugg_span, + |name| internal_suggs.contains_key(name), + &mut matcher, + ) + } else { + HashMap::new() + }; + + let mut res = Vec::new(); + for cmd_name in matcher.results() { + if let Some(sugg) = internal_suggs + .remove(&cmd_name) + .or_else(|| external_suggs.remove(&cmd_name)) + { + res.push(sugg); + } + } + res + } +} diff --git a/nushell/crates/nu-cli/src/completions/completer.rs b/nushell/crates/nu-cli/src/completions/completer.rs new file mode 100644 index 0000000..3de89fb --- /dev/null +++ b/nushell/crates/nu-cli/src/completions/completer.rs @@ -0,0 +1,873 @@ +use crate::completions::{ + AttributableCompletion, AttributeCompletion, CellPathCompletion, CommandCompletion, Completer, + CompletionOptions, CustomCompletion, DirectoryCompletion, DotNuCompletion, + ExportableCompletion, FileCompletion, FlagCompletion, OperatorCompletion, VariableCompletion, + base::{SemanticSuggestion, SuggestionKind}, +}; +use nu_color_config::{color_record_to_nustyle, lookup_ansi_color_style}; +use nu_engine::eval_block; +use nu_parser::{flatten_expression, parse, parse_module_file_or_dir}; +use nu_protocol::{ + PipelineData, Span, Type, Value, + ast::{Argument, Block, Expr, Expression, FindMapResult, ListItem, Traverse}, + debugger::WithoutDebug, + engine::{Closure, EngineState, Stack, StateWorkingSet}, +}; +use reedline::{Completer as ReedlineCompleter, Suggestion}; +use std::sync::Arc; + +/// Used as the function `f` in find_map Traverse +/// +/// returns the inner-most pipeline_element of interest +/// i.e. the one that contains given position and needs completion +fn find_pipeline_element_by_position<'a>( + expr: &'a Expression, + working_set: &'a StateWorkingSet, + pos: usize, +) -> FindMapResult<&'a Expression> { + // skip the entire expression if the position is not in it + if !expr.span.contains(pos) { + return FindMapResult::Stop; + } + let closure = |expr: &'a Expression| find_pipeline_element_by_position(expr, working_set, pos); + match &expr.expr { + Expr::Call(call) => call + .arguments + .iter() + .find_map(|arg| arg.expr().and_then(|e| e.find_map(working_set, &closure))) + // if no inner call/external_call found, then this is the inner-most one + .or(Some(expr)) + .map(FindMapResult::Found) + .unwrap_or_default(), + Expr::ExternalCall(head, arguments) => arguments + .iter() + .find_map(|arg| arg.expr().find_map(working_set, &closure)) + .or(head.as_ref().find_map(working_set, &closure)) + .or(Some(expr)) + .map(FindMapResult::Found) + .unwrap_or_default(), + // complete the operator + Expr::BinaryOp(lhs, _, rhs) => lhs + .find_map(working_set, &closure) + .or(rhs.find_map(working_set, &closure)) + .or(Some(expr)) + .map(FindMapResult::Found) + .unwrap_or_default(), + Expr::FullCellPath(fcp) => fcp + .head + .find_map(working_set, &closure) + .map(FindMapResult::Found) + // e.g. use std/util [ + .or_else(|| { + (fcp.head.span.contains(pos) && matches!(fcp.head.expr, Expr::List(_))) + .then_some(FindMapResult::Continue) + }) + .or(Some(FindMapResult::Found(expr))) + .unwrap_or_default(), + Expr::Var(_) => FindMapResult::Found(expr), + Expr::AttributeBlock(ab) => ab + .attributes + .iter() + .map(|attr| &attr.expr) + .chain(Some(ab.item.as_ref())) + .find_map(|expr| expr.find_map(working_set, &closure)) + .or(Some(expr)) + .map(FindMapResult::Found) + .unwrap_or_default(), + _ => FindMapResult::Continue, + } +} + +/// Before completion, an additional character `a` is added to the source as a placeholder for correct parsing results. +/// This function helps to strip it +fn strip_placeholder_if_any<'a>( + working_set: &'a StateWorkingSet, + span: &Span, + strip: bool, +) -> (Span, &'a [u8]) { + let new_span = if strip { + let new_end = std::cmp::max(span.end - 1, span.start); + Span::new(span.start, new_end) + } else { + span.to_owned() + }; + let prefix = working_set.get_span_contents(new_span); + (new_span, prefix) +} + +/// Given a span with noise, +/// 1. Call `rsplit` to get the last token +/// 2. Strip the last placeholder from the token +fn strip_placeholder_with_rsplit<'a>( + working_set: &'a StateWorkingSet, + span: &Span, + predicate: impl FnMut(&u8) -> bool, + strip: bool, +) -> (Span, &'a [u8]) { + let span_content = working_set.get_span_contents(*span); + let mut prefix = span_content + .rsplit(predicate) + .next() + .unwrap_or(span_content); + let start = span.end.saturating_sub(prefix.len()); + if strip && !prefix.is_empty() { + prefix = &prefix[..prefix.len() - 1]; + } + let end = start + prefix.len(); + (Span::new(start, end), prefix) +} + +#[derive(Clone)] +pub struct NuCompleter { + engine_state: Arc, + stack: Stack, +} + +/// Common arguments required for Completer +struct Context<'a> { + working_set: &'a StateWorkingSet<'a>, + span: Span, + prefix: &'a [u8], + offset: usize, +} + +/// For argument completion +struct PositionalArguments<'a> { + /// command name + command_head: &'a str, + /// indices of positional arguments + positional_arg_indices: Vec, + /// argument list + arguments: &'a [Argument], + /// expression of current argument + expr: &'a Expression, +} + +impl Context<'_> { + fn new<'a>( + working_set: &'a StateWorkingSet, + span: Span, + prefix: &'a [u8], + offset: usize, + ) -> Context<'a> { + Context { + working_set, + span, + prefix, + offset, + } + } +} + +impl NuCompleter { + pub fn new(engine_state: Arc, stack: Arc) -> Self { + Self { + engine_state, + stack: Stack::with_parent(stack).reset_out_dest().collect_value(), + } + } + + pub fn fetch_completions_at(&self, line: &str, pos: usize) -> Vec { + let mut working_set = StateWorkingSet::new(&self.engine_state); + let offset = working_set.next_span_start(); + // TODO: Callers should be trimming the line themselves + let line = if line.len() > pos { &line[..pos] } else { line }; + let block = parse( + &mut working_set, + Some("completer"), + // Add a placeholder `a` to the end + format!("{}a", line).as_bytes(), + false, + ); + self.fetch_completions_by_block(block, &working_set, pos, offset, line, true) + } + + /// For completion in LSP server. + /// We don't truncate the contents in order + /// to complete the definitions after the cursor. + /// + /// And we avoid the placeholder to reuse the parsed blocks + /// cached while handling other LSP requests, e.g. diagnostics + pub fn fetch_completions_within_file( + &self, + filename: &str, + pos: usize, + contents: &str, + ) -> Vec { + let mut working_set = StateWorkingSet::new(&self.engine_state); + let block = parse(&mut working_set, Some(filename), contents.as_bytes(), false); + let Some(file_span) = working_set.get_span_for_filename(filename) else { + return vec![]; + }; + let offset = file_span.start; + self.fetch_completions_by_block(block.clone(), &working_set, pos, offset, contents, false) + } + + fn fetch_completions_by_block( + &self, + block: Arc, + working_set: &StateWorkingSet, + pos: usize, + offset: usize, + contents: &str, + extra_placeholder: bool, + ) -> Vec { + // Adjust offset so that the spans of the suggestions will start at the right + // place even with `only_buffer_difference: true` + let mut pos_to_search = pos + offset; + if !extra_placeholder { + pos_to_search = pos_to_search.saturating_sub(1); + } + let Some(element_expression) = block.find_map(working_set, &|expr: &Expression| { + find_pipeline_element_by_position(expr, working_set, pos_to_search) + }) else { + return vec![]; + }; + + // text of element_expression + let start_offset = element_expression.span.start - offset; + let Some(text) = contents.get(start_offset..pos) else { + return vec![]; + }; + self.complete_by_expression( + working_set, + element_expression, + offset, + pos_to_search, + text, + extra_placeholder, + ) + } + + /// Complete given the expression of interest + /// Usually, the expression is get from `find_pipeline_element_by_position` + /// + /// # Arguments + /// * `offset` - start offset of current working_set span + /// * `pos` - cursor position, should be > offset + /// * `prefix_str` - all the text before the cursor, within the `element_expression` + /// * `strip` - whether to strip the extra placeholder from a span + fn complete_by_expression( + &self, + working_set: &StateWorkingSet, + element_expression: &Expression, + offset: usize, + pos: usize, + prefix_str: &str, + strip: bool, + ) -> Vec { + let mut suggestions: Vec = vec![]; + + match &element_expression.expr { + Expr::Var(_) => { + return self.variable_names_completion_helper( + working_set, + element_expression.span, + offset, + strip, + ); + } + Expr::FullCellPath(full_cell_path) => { + // e.g. `$e` parsed as FullCellPath + // but `$e.` without placeholder should be taken as cell_path + if full_cell_path.tail.is_empty() && !prefix_str.ends_with('.') { + return self.variable_names_completion_helper( + working_set, + element_expression.span, + offset, + strip, + ); + } else { + let mut cell_path_completer = CellPathCompletion { + full_cell_path, + position: if strip { pos - 1 } else { pos }, + }; + let ctx = Context::new(working_set, Span::unknown(), &[], offset); + return self.process_completion(&mut cell_path_completer, &ctx); + } + } + Expr::BinaryOp(lhs, op, _) => { + if op.span.contains(pos) { + let mut operator_completions = OperatorCompletion { + left_hand_side: lhs.as_ref(), + }; + let (new_span, prefix) = strip_placeholder_if_any(working_set, &op.span, strip); + let ctx = Context::new(working_set, new_span, prefix, offset); + let results = self.process_completion(&mut operator_completions, &ctx); + if !results.is_empty() { + return results; + } + } + } + Expr::AttributeBlock(ab) => { + if let Some(span) = ab.attributes.iter().find_map(|attr| { + let span = attr.expr.span; + span.contains(pos).then_some(span) + }) { + let (new_span, prefix) = strip_placeholder_if_any(working_set, &span, strip); + let ctx = Context::new(working_set, new_span, prefix, offset); + return self.process_completion(&mut AttributeCompletion, &ctx); + }; + let span = ab.item.span; + if span.contains(pos) { + let (new_span, prefix) = strip_placeholder_if_any(working_set, &span, strip); + let ctx = Context::new(working_set, new_span, prefix, offset); + return self.process_completion(&mut AttributableCompletion, &ctx); + } + } + + // NOTE: user defined internal commands can have any length + // e.g. `def "foo -f --ff bar"`, complete by line text + // instead of relying on the parsing result in that case + Expr::Call(_) | Expr::ExternalCall(_, _) => { + let need_externals = !prefix_str.contains(' '); + let need_internals = !prefix_str.starts_with('^'); + let mut span = element_expression.span; + if !need_internals { + span.start += 1; + }; + suggestions.extend(self.command_completion_helper( + working_set, + span, + offset, + need_internals, + need_externals, + strip, + )) + } + _ => (), + } + + // unfinished argument completion for commands + match &element_expression.expr { + Expr::Call(call) => { + // NOTE: the argument to complete is not necessarily the last one + // for lsp completion, we don't trim the text, + // so that `def`s after pos can be completed + let mut positional_arg_indices = Vec::new(); + for (arg_idx, arg) in call.arguments.iter().enumerate() { + let span = arg.span(); + if span.contains(pos) { + // if customized completion specified, it has highest priority + if let Some(decl_id) = arg.expr().and_then(|e| e.custom_completion) { + // for `--foo ` and `--foo=`, the arg span should be trimmed + let (new_span, prefix) = if matches!(arg, Argument::Named(_)) { + strip_placeholder_with_rsplit( + working_set, + &span, + |b| *b == b'=' || *b == b' ', + strip, + ) + } else { + strip_placeholder_if_any(working_set, &span, strip) + }; + let ctx = Context::new(working_set, new_span, prefix, offset); + + let mut completer = CustomCompletion::new( + decl_id, + prefix_str.into(), + pos - offset, + FileCompletion, + ); + + suggestions.extend(self.process_completion(&mut completer, &ctx)); + break; + } + + // normal arguments completion + let (new_span, prefix) = + strip_placeholder_if_any(working_set, &span, strip); + let ctx = Context::new(working_set, new_span, prefix, offset); + let flag_completion_helper = || { + let mut flag_completions = FlagCompletion { + decl_id: call.decl_id, + }; + self.process_completion(&mut flag_completions, &ctx) + }; + suggestions.extend(match arg { + // flags + Argument::Named(_) | Argument::Unknown(_) + if prefix.starts_with(b"-") => + { + flag_completion_helper() + } + // only when `strip` == false + Argument::Positional(_) if prefix == b"-" => flag_completion_helper(), + // complete according to expression type and command head + Argument::Positional(expr) => { + let command_head = working_set.get_decl(call.decl_id).name(); + positional_arg_indices.push(arg_idx); + self.argument_completion_helper( + PositionalArguments { + command_head, + positional_arg_indices, + arguments: &call.arguments, + expr, + }, + pos, + &ctx, + suggestions.is_empty(), + ) + } + _ => vec![], + }); + break; + } else if !matches!(arg, Argument::Named(_)) { + positional_arg_indices.push(arg_idx); + } + } + } + Expr::ExternalCall(head, arguments) => { + for (i, arg) in arguments.iter().enumerate() { + let span = arg.expr().span; + if span.contains(pos) { + // e.g. `sudo l` + // HACK: judge by index 0 is not accurate + if i == 0 { + let external_cmd = working_set.get_span_contents(head.span); + if external_cmd == b"sudo" || external_cmd == b"doas" { + let commands = self.command_completion_helper( + working_set, + span, + offset, + true, + true, + strip, + ); + // flags of sudo/doas can still be completed by external completer + if !commands.is_empty() { + return commands; + } + } + } + // resort to external completer set in config + let config = self.engine_state.get_config(); + if let Some(closure) = config.completions.external.completer.as_ref() { + let mut text_spans: Vec = + flatten_expression(working_set, element_expression) + .iter() + .map(|(span, _)| { + let bytes = working_set.get_span_contents(*span); + String::from_utf8_lossy(bytes).to_string() + }) + .collect(); + let mut new_span = span; + // strip the placeholder + if strip { + if let Some(last) = text_spans.last_mut() { + last.pop(); + new_span = Span::new(span.start, span.end.saturating_sub(1)); + } + } + if let Some(external_result) = + self.external_completion(closure, &text_spans, offset, new_span) + { + suggestions.extend(external_result); + return suggestions; + } + } + // for external path arguments with spaces, please check issue #15790 + if suggestions.is_empty() { + let (new_span, prefix) = + strip_placeholder_if_any(working_set, &span, strip); + let ctx = Context::new(working_set, new_span, prefix, offset); + suggestions.extend(self.process_completion(&mut FileCompletion, &ctx)); + return suggestions; + } + break; + } + } + } + _ => (), + } + + // if no suggestions yet, fallback to file completion + if suggestions.is_empty() { + let (new_span, prefix) = strip_placeholder_with_rsplit( + working_set, + &element_expression.span, + |c| *c == b' ', + strip, + ); + let ctx = Context::new(working_set, new_span, prefix, offset); + suggestions.extend(self.process_completion(&mut FileCompletion, &ctx)); + } + suggestions + } + + fn variable_names_completion_helper( + &self, + working_set: &StateWorkingSet, + span: Span, + offset: usize, + strip: bool, + ) -> Vec { + let (new_span, prefix) = strip_placeholder_if_any(working_set, &span, strip); + if !prefix.starts_with(b"$") { + return vec![]; + } + let ctx = Context::new(working_set, new_span, prefix, offset); + self.process_completion(&mut VariableCompletion, &ctx) + } + + fn command_completion_helper( + &self, + working_set: &StateWorkingSet, + span: Span, + offset: usize, + internals: bool, + externals: bool, + strip: bool, + ) -> Vec { + let config = self.engine_state.get_config(); + let mut command_completions = CommandCompletion { + internals, + externals: !internals || (externals && config.completions.external.enable), + }; + let (new_span, prefix) = strip_placeholder_if_any(working_set, &span, strip); + let ctx = Context::new(working_set, new_span, prefix, offset); + self.process_completion(&mut command_completions, &ctx) + } + + fn argument_completion_helper( + &self, + argument_info: PositionalArguments, + pos: usize, + ctx: &Context, + need_fallback: bool, + ) -> Vec { + let PositionalArguments { + command_head, + positional_arg_indices, + arguments, + expr, + } = argument_info; + // special commands + match command_head { + // complete module file/directory + "use" | "export use" | "overlay use" | "source-env" + if positional_arg_indices.len() == 1 => + { + return self.process_completion( + &mut DotNuCompletion { + std_virtual_path: command_head != "source-env", + }, + ctx, + ); + } + // NOTE: if module file already specified, + // should parse it to get modules/commands/consts to complete + "use" | "export use" => { + let Some(Argument::Positional(Expression { + expr: Expr::String(module_name), + span, + .. + })) = positional_arg_indices + .first() + .and_then(|i| arguments.get(*i)) + else { + return vec![]; + }; + let module_name = module_name.as_bytes(); + let (module_id, temp_working_set) = match ctx.working_set.find_module(module_name) { + Some(module_id) => (module_id, None), + None => { + let mut temp_working_set = + StateWorkingSet::new(ctx.working_set.permanent_state); + let Some(module_id) = parse_module_file_or_dir( + &mut temp_working_set, + module_name, + *span, + None, + ) else { + return vec![]; + }; + (module_id, Some(temp_working_set)) + } + }; + let mut exportable_completion = ExportableCompletion { + module_id, + temp_working_set, + }; + let mut complete_on_list_items = |items: &[ListItem]| -> Vec { + for item in items { + let span = item.expr().span; + if span.contains(pos) { + let offset = span.start.saturating_sub(ctx.span.start); + let end_offset = + ctx.prefix.len().min(pos.min(span.end) - ctx.span.start + 1); + let new_ctx = Context::new( + ctx.working_set, + Span::new(span.start, ctx.span.end.min(span.end)), + ctx.prefix.get(offset..end_offset).unwrap_or_default(), + ctx.offset, + ); + return self.process_completion(&mut exportable_completion, &new_ctx); + } + } + vec![] + }; + + match &expr.expr { + Expr::String(_) => { + return self.process_completion(&mut exportable_completion, ctx); + } + Expr::FullCellPath(fcp) => match &fcp.head.expr { + Expr::List(items) => { + return complete_on_list_items(items); + } + _ => return vec![], + }, + _ => return vec![], + } + } + "which" => { + let mut completer = CommandCompletion { + internals: true, + externals: true, + }; + return self.process_completion(&mut completer, ctx); + } + _ => (), + } + + // general positional arguments + let file_completion_helper = || self.process_completion(&mut FileCompletion, ctx); + match &expr.expr { + Expr::Directory(_, _) => self.process_completion(&mut DirectoryCompletion, ctx), + Expr::Filepath(_, _) | Expr::GlobPattern(_, _) => file_completion_helper(), + // fallback to file completion if necessary + _ if need_fallback => file_completion_helper(), + _ => vec![], + } + } + + // Process the completion for a given completer + fn process_completion( + &self, + completer: &mut T, + ctx: &Context, + ) -> Vec { + let config = self.engine_state.get_config(); + + let options = CompletionOptions { + case_sensitive: config.completions.case_sensitive, + match_algorithm: config.completions.algorithm.into(), + sort: config.completions.sort, + }; + + completer.fetch( + ctx.working_set, + &self.stack, + String::from_utf8_lossy(ctx.prefix), + ctx.span, + ctx.offset, + &options, + ) + } + + fn external_completion( + &self, + closure: &Closure, + spans: &[String], + offset: usize, + span: Span, + ) -> Option> { + let block = self.engine_state.get_block(closure.block_id); + let mut callee_stack = self + .stack + .captures_to_stack_preserve_out_dest(closure.captures.clone()); + + // Line + if let Some(pos_arg) = block.signature.required_positional.first() { + if let Some(var_id) = pos_arg.var_id { + callee_stack.add_var( + var_id, + Value::list( + spans + .iter() + .map(|it| Value::string(it, Span::unknown())) + .collect(), + Span::unknown(), + ), + ); + } + } + + let result = eval_block::( + &self.engine_state, + &mut callee_stack, + block, + PipelineData::empty(), + ); + + match result.and_then(|data| data.into_value(span)) { + Ok(Value::List { vals, .. }) => { + let result = + map_value_completions(vals.iter(), Span::new(span.start, span.end), offset); + Some(result) + } + Ok(Value::Nothing { .. }) => None, + Ok(value) => { + log::error!( + "External completer returned invalid value of type {}", + value.get_type().to_string() + ); + Some(vec![]) + } + Err(err) => { + log::error!("failed to eval completer block: {err}"); + Some(vec![]) + } + } + } +} + +impl ReedlineCompleter for NuCompleter { + fn complete(&mut self, line: &str, pos: usize) -> Vec { + self.fetch_completions_at(line, pos) + .into_iter() + .map(|s| s.suggestion) + .collect() + } +} + +pub fn map_value_completions<'a>( + list: impl Iterator, + span: Span, + offset: usize, +) -> Vec { + list.filter_map(move |x| { + // Match for string values + if let Ok(s) = x.coerce_string() { + return Some(SemanticSuggestion { + suggestion: Suggestion { + value: s, + span: reedline::Span { + start: span.start - offset, + end: span.end - offset, + }, + ..Suggestion::default() + }, + kind: Some(SuggestionKind::Value(x.get_type())), + }); + } + + // Match for record values + if let Ok(record) = x.as_record() { + let mut suggestion = Suggestion { + value: String::from(""), // Initialize with empty string + span: reedline::Span { + start: span.start - offset, + end: span.end - offset, + }, + ..Suggestion::default() + }; + let mut value_type = Type::String; + + // Iterate the cols looking for `value` and `description` + record.iter().for_each(|(key, value)| { + match key.as_str() { + "value" => { + value_type = value.get_type(); + // Convert the value to string + if let Ok(val_str) = value.coerce_string() { + // Update the suggestion value + suggestion.value = val_str; + } + } + "description" => { + // Convert the value to string + if let Ok(desc_str) = value.coerce_string() { + // Update the suggestion value + suggestion.description = Some(desc_str); + } + } + "style" => { + // Convert the value to string + suggestion.style = match value { + Value::String { val, .. } => Some(lookup_ansi_color_style(val)), + Value::Record { .. } => Some(color_record_to_nustyle(value)), + _ => None, + }; + } + _ => (), + } + }); + + return Some(SemanticSuggestion { + suggestion, + kind: Some(SuggestionKind::Value(value_type)), + }); + } + + None + }) + .collect() +} + +#[cfg(test)] +mod completer_tests { + use super::*; + + #[test] + fn test_completion_helper() { + let mut engine_state = + nu_command::add_shell_command_context(nu_cmd_lang::create_default_context()); + + // Custom additions + let delta = { + let working_set = nu_protocol::engine::StateWorkingSet::new(&engine_state); + working_set.render() + }; + + let result = engine_state.merge_delta(delta); + assert!( + result.is_ok(), + "Error merging delta: {:?}", + result.err().unwrap() + ); + + let completer = NuCompleter::new(engine_state.into(), Arc::new(Stack::new())); + let dataset = [ + ("1 bit-sh", true, "b", vec!["bit-shl", "bit-shr"]), + ("1.0 bit-sh", false, "b", vec![]), + ("1 m", true, "m", vec!["mod"]), + ("1.0 m", true, "m", vec!["mod"]), + ("\"a\" s", true, "s", vec!["starts-with"]), + ("sudo", false, "", Vec::new()), + ("sudo l", true, "l", vec!["ls", "let", "lines", "loop"]), + (" sudo", false, "", Vec::new()), + (" sudo le", true, "le", vec!["let", "length"]), + ( + "ls | c", + true, + "c", + vec!["cd", "config", "const", "cp", "cal"], + ), + ("ls | sudo m", true, "m", vec!["mv", "mut", "move"]), + ]; + for (line, has_result, begins_with, expected_values) in dataset { + let result = completer.fetch_completions_at(line, line.len()); + // Test whether the result is empty or not + assert_eq!(!result.is_empty(), has_result, "line: {}", line); + + // Test whether the result begins with the expected value + result + .iter() + .for_each(|x| assert!(x.suggestion.value.starts_with(begins_with))); + + // Test whether the result contains all the expected values + assert_eq!( + result + .iter() + .map(|x| expected_values.contains(&x.suggestion.value.as_str())) + .filter(|x| *x) + .count(), + expected_values.len(), + "line: {}", + line + ); + } + } +} diff --git a/nushell/crates/nu-cli/src/completions/completion_common.rs b/nushell/crates/nu-cli/src/completions/completion_common.rs new file mode 100644 index 0000000..41f6c0c --- /dev/null +++ b/nushell/crates/nu-cli/src/completions/completion_common.rs @@ -0,0 +1,401 @@ +use super::{MatchAlgorithm, completion_options::NuMatcher}; +use crate::completions::CompletionOptions; +use nu_ansi_term::Style; +use nu_engine::env_to_string; +use nu_path::dots::expand_ndots; +use nu_path::{expand_to_real_path, home_dir}; +use nu_protocol::{ + Span, + engine::{EngineState, Stack, StateWorkingSet}, +}; +use nu_utils::IgnoreCaseExt; +use nu_utils::get_ls_colors; +use std::path::{Component, MAIN_SEPARATOR as SEP, Path, PathBuf, is_separator}; + +#[derive(Clone, Default)] +pub struct PathBuiltFromString { + cwd: PathBuf, + parts: Vec, + isdir: bool, +} + +/// Recursively goes through paths that match a given `partial`. +/// built: State struct for a valid matching path built so far. +/// +/// `want_directory`: Whether we want only directories as completion matches. +/// Some commands like `cd` can only be run on directories whereas others +/// like `ls` can be run on regular files as well. +/// +/// `isdir`: whether the current partial path has a trailing slash. +/// Parsing a path string into a pathbuf loses that bit of information. +/// +/// `enable_exact_match`: Whether match algorithm is Prefix and all previous components +/// of the path matched a directory exactly. +fn complete_rec( + partial: &[&str], + built_paths: &[PathBuiltFromString], + options: &CompletionOptions, + want_directory: bool, + isdir: bool, + enable_exact_match: bool, +) -> Vec { + let has_more = !partial.is_empty() && (partial.len() > 1 || isdir); + + if let Some((&base, rest)) = partial.split_first() { + if base.chars().all(|c| c == '.') && has_more { + let built_paths: Vec<_> = built_paths + .iter() + .map(|built| { + let mut built = built.clone(); + built.parts.push(base.to_string()); + built.isdir = true; + built + }) + .collect(); + return complete_rec( + rest, + &built_paths, + options, + want_directory, + isdir, + enable_exact_match, + ); + } + } + + let prefix = partial.first().unwrap_or(&""); + let mut matcher = NuMatcher::new(prefix, options); + + let mut exact_match = None; + // Only relevant for case insensitive matching + let mut multiple_exact_matches = false; + for built in built_paths { + let mut path = built.cwd.clone(); + for part in &built.parts { + path.push(part); + } + + let Ok(result) = path.read_dir() else { + continue; + }; + + for entry in result.filter_map(|e| e.ok()) { + let entry_name = entry.file_name().to_string_lossy().into_owned(); + let entry_isdir = entry.path().is_dir(); + let mut built = built.clone(); + built.parts.push(entry_name.clone()); + // Symlinks to directories shouldn't have a trailing slash (#13275) + built.isdir = entry_isdir && !entry.path().is_symlink(); + + if !want_directory || entry_isdir { + if enable_exact_match && !multiple_exact_matches && has_more { + let matches = if options.case_sensitive { + entry_name.eq(prefix) + } else { + entry_name.eq_ignore_case(prefix) + }; + if matches { + if exact_match.is_none() { + exact_match = Some(built.clone()); + } else { + multiple_exact_matches = true; + } + } + } + + matcher.add(entry_name, built); + } + } + } + + // Don't show longer completions if we have a single exact match (#13204, #14794) + if !multiple_exact_matches { + if let Some(built) = exact_match { + return complete_rec( + &partial[1..], + &[built], + options, + want_directory, + isdir, + true, + ); + } + } + + if has_more { + let mut completions = vec![]; + for built in matcher.results() { + completions.extend(complete_rec( + &partial[1..], + &[built], + options, + want_directory, + isdir, + false, + )); + } + completions + } else { + matcher.results() + } +} + +#[derive(Debug)] +enum OriginalCwd { + None, + Home, + Prefix(String), +} + +impl OriginalCwd { + fn apply(&self, mut p: PathBuiltFromString, path_separator: char) -> String { + match self { + Self::None => {} + Self::Home => p.parts.insert(0, "~".to_string()), + Self::Prefix(s) => p.parts.insert(0, s.clone()), + }; + + let mut ret = p.parts.join(&path_separator.to_string()); + if p.isdir { + ret.push(path_separator); + } + ret + } +} + +pub fn surround_remove(partial: &str) -> String { + for c in ['`', '"', '\''] { + if partial.starts_with(c) { + let ret = partial.strip_prefix(c).unwrap_or(partial); + return match ret.split(c).collect::>()[..] { + [inside] => inside.to_string(), + [inside, outside] if inside.ends_with(is_separator) => format!("{inside}{outside}"), + _ => ret.to_string(), + }; + } + } + partial.to_string() +} + +pub struct FileSuggestion { + pub span: nu_protocol::Span, + pub path: String, + pub style: Option
foobar
12
"#, + )), + }, + Example { + description: "Optionally, only output the html for the content itself", + example: "[[foo bar]; [1 2]] | to html --partial", + result: Some(Value::test_string( + r#"

foobar
12
"#, + )), + }, + Example { + description: "Optionally, output the string with a dark background", + example: "[[foo bar]; [1 2]] | to html --dark", + result: Some(Value::test_string( + r#"
foobar
12
"#, + )), + }, + ] + } + + fn description(&self) -> &str { + "Convert table into simple HTML." + } + + fn extra_description(&self) -> &str { + "Screenshots of the themes can be browsed here: https://github.com/mbadolato/iTerm2-Color-Schemes." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + to_html(input, call, engine_state, stack) + } +} + +fn get_theme_from_asset_file( + is_dark: bool, + theme: Option<&Spanned>, +) -> Result, ShellError> { + let theme_name = match theme { + Some(s) => &s.item, + None => { + return Ok(convert_html_theme_to_hash_map( + is_dark, + &HtmlTheme::default(), + )); + } + }; + + let theme_span = theme.map(|s| s.span).unwrap_or(Span::unknown()); + + // 228 themes come from + // https://github.com/mbadolato/iTerm2-Color-Schemes/tree/master/windowsterminal + // we should find a hit on any name in there + let asset = get_html_themes("228_themes.json").unwrap_or_default(); + + // Find the theme by theme name + let th = asset + .themes + .into_iter() + .find(|n| n.name.eq_ignore_case(theme_name)); // case insensitive search + + let th = match th { + Some(t) => t, + None => { + return Err(ShellError::TypeMismatch { + err_message: format!("Unknown HTML theme '{}'", theme_name), + span: theme_span, + }); + } + }; + + Ok(convert_html_theme_to_hash_map(is_dark, &th)) +} + +fn convert_html_theme_to_hash_map( + is_dark: bool, + theme: &HtmlTheme, +) -> HashMap<&'static str, String> { + let mut hm: HashMap<&str, String> = HashMap::with_capacity(18); + + hm.insert("bold_black", theme.brightBlack[..].to_string()); + hm.insert("bold_red", theme.brightRed[..].to_string()); + hm.insert("bold_green", theme.brightGreen[..].to_string()); + hm.insert("bold_yellow", theme.brightYellow[..].to_string()); + hm.insert("bold_blue", theme.brightBlue[..].to_string()); + hm.insert("bold_magenta", theme.brightPurple[..].to_string()); + hm.insert("bold_cyan", theme.brightCyan[..].to_string()); + hm.insert("bold_white", theme.brightWhite[..].to_string()); + + hm.insert("black", theme.black[..].to_string()); + hm.insert("red", theme.red[..].to_string()); + hm.insert("green", theme.green[..].to_string()); + hm.insert("yellow", theme.yellow[..].to_string()); + hm.insert("blue", theme.blue[..].to_string()); + hm.insert("magenta", theme.purple[..].to_string()); + hm.insert("cyan", theme.cyan[..].to_string()); + hm.insert("white", theme.white[..].to_string()); + + // Try to make theme work with light or dark but + // flipping the foreground and background but leave + // the other colors the same. + if is_dark { + hm.insert("background", theme.black[..].to_string()); + hm.insert("foreground", theme.white[..].to_string()); + } else { + hm.insert("background", theme.white[..].to_string()); + hm.insert("foreground", theme.black[..].to_string()); + } + + hm +} + +fn get_html_themes(json_name: &str) -> Result> { + match Assets::get(json_name) { + Some(content) => Ok(nu_json::from_slice(&content.data)?), + None => Ok(HtmlThemes::default()), + } +} + +fn to_html( + input: PipelineData, + call: &Call, + engine_state: &EngineState, + stack: &mut Stack, +) -> Result { + let head = call.head; + let html_color = call.has_flag(engine_state, stack, "html-color")?; + let no_color = call.has_flag(engine_state, stack, "no-color")?; + let dark = call.has_flag(engine_state, stack, "dark")?; + let partial = call.has_flag(engine_state, stack, "partial")?; + let list = call.has_flag(engine_state, stack, "list")?; + let theme: Option> = call.get_flag(engine_state, stack, "theme")?; + let config = &stack.get_config(engine_state); + + let vec_of_values = input.into_iter().collect::>(); + let headers = merge_descriptors(&vec_of_values); + let headers = Some(headers) + .filter(|headers| !headers.is_empty() && (headers.len() > 1 || !headers[0].is_empty())); + let mut output_string = String::new(); + let mut regex_hm: HashMap = HashMap::with_capacity(17); + + if list { + // Being essentially a 'help' option, this can afford to be relatively unoptimised + return Ok(theme_demo(head)); + } + let theme_span = match &theme { + Some(v) => v.span, + None => head, + }; + + let color_hm = match get_theme_from_asset_file(dark, theme.as_ref()) { + Ok(c) => c, + Err(e) => match e { + ShellError::TypeMismatch { + err_message, + span: _, + } => { + return Err(ShellError::TypeMismatch { + err_message, + span: theme_span, + }); + } + _ => return Err(e), + }, + }; + + // change the color of the page + if !partial { + write!( + &mut output_string, + r"", + color_hm + .get("background") + .expect("Error getting background color"), + color_hm + .get("foreground") + .expect("Error getting foreground color") + ) + .unwrap(); + } else { + write!( + &mut output_string, + "
", + color_hm + .get("background") + .expect("Error getting background color"), + color_hm + .get("foreground") + .expect("Error getting foreground color") + ) + .unwrap(); + } + + let inner_value = match vec_of_values.len() { + 0 => String::default(), + 1 => match headers { + Some(headers) => html_table(vec_of_values, headers, config), + None => { + let value = &vec_of_values[0]; + html_value(value.clone(), config) + } + }, + _ => match headers { + Some(headers) => html_table(vec_of_values, headers, config), + None => html_list(vec_of_values, config), + }, + }; + + output_string.push_str(&inner_value); + + if !partial { + output_string.push_str(""); + } else { + output_string.push_str("
") + } + + // Check to see if we want to remove all color or change ansi to html colors + if html_color { + setup_html_color_regexes(&mut regex_hm, &color_hm); + output_string = run_regexes(®ex_hm, &output_string); + } else if no_color { + setup_no_color_regexes(&mut regex_hm); + output_string = run_regexes(®ex_hm, &output_string); + } + + let metadata = PipelineMetadata { + data_source: nu_protocol::DataSource::None, + content_type: Some(mime::TEXT_HTML_UTF_8.to_string()), + }; + + Ok(Value::string(output_string, head).into_pipeline_data_with_metadata(metadata)) +} + +fn theme_demo(span: Span) -> PipelineData { + // If asset doesn't work, make sure to return the default theme + let html_themes = get_html_themes("228_themes.json").unwrap_or_default(); + let result: Vec = html_themes + .themes + .into_iter() + .map(|n| { + Value::record( + record! { + "name" => Value::string(n.name, span), + "black" => Value::string(n.black, span), + "red" => Value::string(n.red, span), + "green" => Value::string(n.green, span), + "yellow" => Value::string(n.yellow, span), + "blue" => Value::string(n.blue, span), + "purple" => Value::string(n.purple, span), + "cyan" => Value::string(n.cyan, span), + "white" => Value::string(n.white, span), + "brightBlack" => Value::string(n.brightBlack, span), + "brightRed" => Value::string(n.brightRed, span), + "brightGreen" => Value::string(n.brightGreen, span), + "brightYellow" => Value::string(n.brightYellow, span), + "brightBlue" => Value::string(n.brightBlue, span), + "brightPurple" => Value::string(n.brightPurple, span), + "brightCyan" => Value::string(n.brightCyan, span), + "brightWhite" => Value::string(n.brightWhite, span), + "background" => Value::string(n.background, span), + "foreground" => Value::string(n.foreground, span), + }, + span, + ) + }) + .collect(); + Value::list(result, span).into_pipeline_data_with_metadata(PipelineMetadata { + data_source: DataSource::HtmlThemes, + content_type: None, + }) +} + +fn html_list(list: Vec, config: &Config) -> String { + let mut output_string = String::new(); + output_string.push_str("
    "); + for value in list { + output_string.push_str("
  1. "); + output_string.push_str(&html_value(value, config)); + output_string.push_str("
  2. "); + } + output_string.push_str("
"); + output_string +} + +fn html_table(table: Vec, headers: Vec, config: &Config) -> String { + let mut output_string = String::new(); + + output_string.push_str(""); + + output_string.push_str(""); + for header in &headers { + output_string.push_str(""); + } + output_string.push_str(""); + + for row in table { + let span = row.span(); + if let Value::Record { val: row, .. } = row { + output_string.push_str(""); + for header in &headers { + let data = row + .get(header) + .cloned() + .unwrap_or_else(|| Value::nothing(span)); + output_string.push_str(""); + } + output_string.push_str(""); + } + } + output_string.push_str("
"); + output_string.push_str(&v_htmlescape::escape(header).to_string()); + output_string.push_str("
"); + output_string.push_str(&html_value(data, config)); + output_string.push_str("
"); + + output_string +} + +fn html_value(value: Value, config: &Config) -> String { + let mut output_string = String::new(); + match value { + Value::Binary { val, .. } => { + let output = nu_pretty_hex::pretty_hex(&val); + output_string.push_str("
");
+            output_string.push_str(&output);
+            output_string.push_str("
"); + } + other => output_string.push_str( + &v_htmlescape::escape(&other.to_abbreviated_string(config)) + .to_string() + .replace('\n', "
"), + ), + } + output_string +} + +fn setup_html_color_regexes( + hash: &mut HashMap, + color_hm: &HashMap<&str, String>, +) { + // All the bold colors + hash.insert( + 0, + ( + r"(?P\[0m)(?P[[:alnum:][:space:][:punct:]]*)", + // Reset the text color, normal weight font + format!( + r"$word", + color_hm + .get("foreground") + .expect("Error getting reset text color") + ), + ), + ); + hash.insert( + 1, + ( + // Bold Black + r"(?P\[1;30m)(?P[[:alnum:][:space:][:punct:]]*)", + format!( + r"$word", + color_hm + .get("foreground") + .expect("Error getting bold black text color") + ), + ), + ); + hash.insert( + 2, + ( + // Bold Red + r"(?P
\[1;31m)(?P[[:alnum:][:space:][:punct:]]*)", + format!( + r"$word", + color_hm + .get("bold_red") + .expect("Error getting bold red text color"), + ), + ), + ); + hash.insert( + 3, + ( + // Bold Green + r"(?P\[1;32m)(?P[[:alnum:][:space:][:punct:]]*)", + format!( + r"$word", + color_hm + .get("bold_green") + .expect("Error getting bold green text color"), + ), + ), + ); + hash.insert( + 4, + ( + // Bold Yellow + r"(?P\[1;33m)(?P[[:alnum:][:space:][:punct:]]*)", + format!( + r"$word", + color_hm + .get("bold_yellow") + .expect("Error getting bold yellow text color"), + ), + ), + ); + hash.insert( + 5, + ( + // Bold Blue + r"(?P\[1;34m)(?P[[:alnum:][:space:][:punct:]]*)", + format!( + r"$word", + color_hm + .get("bold_blue") + .expect("Error getting bold blue text color"), + ), + ), + ); + hash.insert( + 6, + ( + // Bold Magenta + r"(?P\[1;35m)(?P[[:alnum:][:space:][:punct:]]*)", + format!( + r"$word", + color_hm + .get("bold_magenta") + .expect("Error getting bold magenta text color"), + ), + ), + ); + hash.insert( + 7, + ( + // Bold Cyan + r"(?P\[1;36m)(?P[[:alnum:][:space:][:punct:]]*)", + format!( + r"$word", + color_hm + .get("bold_cyan") + .expect("Error getting bold cyan text color"), + ), + ), + ); + hash.insert( + 8, + ( + // Bold White + // Let's change this to black since the html background + // is white. White on white = no bueno. + r"(?P\[1;37m)(?P[[:alnum:][:space:][:punct:]]*)", + format!( + r"$word", + color_hm + .get("foreground") + .expect("Error getting bold bold white text color"), + ), + ), + ); + // All the normal colors + hash.insert( + 9, + ( + // Black + r"(?P\[30m)(?P[[:alnum:][:space:][:punct:]]*)", + format!( + r"$word", + color_hm + .get("foreground") + .expect("Error getting black text color"), + ), + ), + ); + hash.insert( + 10, + ( + // Red + r"(?P\[31m)(?P[[:alnum:][:space:][:punct:]]*)", + format!( + r"$word", + color_hm.get("red").expect("Error getting red text color"), + ), + ), + ); + hash.insert( + 11, + ( + // Green + r"(?P\[32m)(?P[[:alnum:][:space:][:punct:]]*)", + format!( + r"$word", + color_hm + .get("green") + .expect("Error getting green text color"), + ), + ), + ); + hash.insert( + 12, + ( + // Yellow + r"(?P\[33m)(?P[[:alnum:][:space:][:punct:]]*)", + format!( + r"$word", + color_hm + .get("yellow") + .expect("Error getting yellow text color"), + ), + ), + ); + hash.insert( + 13, + ( + // Blue + r"(?P\[34m)(?P[[:alnum:][:space:][:punct:]]*)", + format!( + r"$word", + color_hm.get("blue").expect("Error getting blue text color"), + ), + ), + ); + hash.insert( + 14, + ( + // Magenta + r"(?P\[35m)(?P[[:alnum:][:space:][:punct:]]*)", + format!( + r"$word", + color_hm + .get("magenta") + .expect("Error getting magenta text color"), + ), + ), + ); + hash.insert( + 15, + ( + // Cyan + r"(?P\[36m)(?P[[:alnum:][:space:][:punct:]]*)", + format!( + r"$word", + color_hm.get("cyan").expect("Error getting cyan text color"), + ), + ), + ); + hash.insert( + 16, + ( + // White + // Let's change this to black since the html background + // is white. White on white = no bueno. + r"(?P\[37m)(?P[[:alnum:][:space:][:punct:]]*)", + format!( + r"$word", + color_hm + .get("foreground") + .expect("Error getting white text color"), + ), + ), + ); +} + +fn setup_no_color_regexes(hash: &mut HashMap) { + // We can just use one regex here because we're just removing ansi sequences + // and not replacing them with html colors. + // attribution: https://stackoverflow.com/questions/14693701/how-can-i-remove-the-ansi-escape-sequences-from-a-string-in-python + hash.insert( + 0, + ( + r"(?:\x1B[@-Z\\-_]|[\x80-\x9A\x9C-\x9F]|(?:\x1B\[|\x9B)[0-?]*[ -/]*[@-~])", + r"$name_group_doesnt_exist".to_string(), + ), + ); +} + +fn run_regexes(hash: &HashMap, contents: &str) -> String { + let mut working_string = contents.to_owned(); + let hash_count: u32 = hash.len() as u32; + for n in 0..hash_count { + let value = hash.get(&n).expect("error getting hash at index"); + let re = Regex::new(value.0).expect("problem with color regex"); + let after = re.replace_all(&working_string, &value.1[..]).to_string(); + working_string = after; + } + working_string +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(ToHtml {}) + } + + #[test] + fn get_theme_from_asset_file_returns_default() { + let result = super::get_theme_from_asset_file(false, None); + + assert!(result.is_ok(), "Expected Ok result for None theme"); + + let theme_map = result.unwrap(); + + assert_eq!( + theme_map.get("background").map(String::as_str), + Some("white"), + "Expected default background color to be white" + ); + + assert_eq!( + theme_map.get("foreground").map(String::as_str), + Some("black"), + "Expected default foreground color to be black" + ); + + assert!( + theme_map.contains_key("red"), + "Expected default theme to have a 'red' color" + ); + + assert!( + theme_map.contains_key("bold_green"), + "Expected default theme to have a 'bold_green' color" + ); + } + + #[test] + fn returns_a_valid_theme() { + let theme_name = "Dracula".to_string().into_spanned(Span::new(0, 7)); + let result = super::get_theme_from_asset_file(false, Some(&theme_name)); + + assert!(result.is_ok(), "Expected Ok result for valid theme"); + let theme_map = result.unwrap(); + let required_keys = [ + "background", + "foreground", + "red", + "green", + "blue", + "bold_red", + "bold_green", + "bold_blue", + ]; + + for key in required_keys { + assert!( + theme_map.contains_key(key), + "Expected theme to contain key '{}'", + key + ); + } + } + + #[test] + fn fails_with_unknown_theme_name() { + let result = super::get_theme_from_asset_file( + false, + Some(&"doesnt-exist".to_string().into_spanned(Span::new(0, 13))), + ); + + assert!(result.is_err(), "Expected error for invalid theme name"); + + if let Err(err) = result { + assert!( + matches!(err, ShellError::TypeMismatch { .. }), + "Expected TypeMismatch error, got: {:?}", + err + ); + + if let ShellError::TypeMismatch { err_message, span } = err { + assert!( + err_message.contains("doesnt-exist"), + "Error message should mention theme name, got: {}", + err_message + ); + assert_eq!(span.start, 0); + assert_eq!(span.end, 13); + } + } + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/formats/to/mod.rs b/nushell/crates/nu-cmd-extra/src/extra/formats/to/mod.rs new file mode 100644 index 0000000..558c29b --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/formats/to/mod.rs @@ -0,0 +1 @@ +pub(crate) mod html; diff --git a/nushell/crates/nu-cmd-extra/src/extra/math/arccos.rs b/nushell/crates/nu-cmd-extra/src/extra/math/arccos.rs new file mode 100644 index 0000000..bf7dd18 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/math/arccos.rs @@ -0,0 +1,119 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct MathArcCos; + +impl Command for MathArcCos { + fn name(&self) -> &str { + "math arccos" + } + + fn signature(&self) -> Signature { + Signature::build("math arccos") + .switch("degrees", "Return degrees instead of radians", Some('d')) + .input_output_types(vec![ + (Type::Number, Type::Float), + ( + Type::List(Box::new(Type::Number)), + Type::List(Box::new(Type::Float)), + ), + ]) + .allow_variants_without_examples(true) + .category(Category::Math) + } + + fn description(&self) -> &str { + "Returns the arccosine of the number." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["trigonometry", "inverse"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + let use_degrees = call.has_flag(engine_state, stack, "degrees")?; + // This doesn't match explicit nulls + if matches!(input, PipelineData::Empty) { + return Err(ShellError::PipelineEmpty { dst_span: head }); + } + input.map( + move |value| operate(value, head, use_degrees), + engine_state.signals(), + ) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Get the arccosine of 1", + example: "1 | math arccos", + result: Some(Value::test_float(0.0f64)), + }, + Example { + description: "Get the arccosine of -1 in degrees", + example: "-1 | math arccos --degrees", + result: Some(Value::test_float(180.0)), + }, + ] + } +} + +fn operate(value: Value, head: Span, use_degrees: bool) -> Value { + match value { + numeric @ (Value::Int { .. } | Value::Float { .. }) => { + let span = numeric.span(); + let (val, span) = match numeric { + Value::Int { val, .. } => (val as f64, span), + Value::Float { val, .. } => (val, span), + _ => unreachable!(), + }; + + if (-1.0..=1.0).contains(&val) { + let val = val.acos(); + let val = if use_degrees { val.to_degrees() } else { val }; + + Value::float(val, span) + } else { + Value::error( + ShellError::UnsupportedInput { + msg: "'arccos' undefined for values outside the closed interval [-1, 1]." + .into(), + input: "value originates from here".into(), + msg_span: head, + input_span: span, + }, + span, + ) + } + } + Value::Error { .. } => value, + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "numeric".into(), + wrong_type: other.get_type().to_string(), + dst_span: head, + src_span: other.span(), + }, + head, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(MathArcCos {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/math/arccosh.rs b/nushell/crates/nu-cmd-extra/src/extra/math/arccosh.rs new file mode 100644 index 0000000..5f8a5f6 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/math/arccosh.rs @@ -0,0 +1,105 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct MathArcCosH; + +impl Command for MathArcCosH { + fn name(&self) -> &str { + "math arccosh" + } + + fn signature(&self) -> Signature { + Signature::build("math arccosh") + .input_output_types(vec![ + (Type::Number, Type::Float), + ( + Type::List(Box::new(Type::Number)), + Type::List(Box::new(Type::Float)), + ), + ]) + .allow_variants_without_examples(true) + .category(Category::Math) + } + + fn description(&self) -> &str { + "Returns the inverse of the hyperbolic cosine function." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["trigonometry", "inverse", "hyperbolic"] + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + // This doesn't match explicit nulls + if matches!(input, PipelineData::Empty) { + return Err(ShellError::PipelineEmpty { dst_span: head }); + } + input.map(move |value| operate(value, head), engine_state.signals()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Get the arccosh of 1", + example: "1 | math arccosh", + result: Some(Value::test_float(0.0f64)), + }] + } +} + +fn operate(value: Value, head: Span) -> Value { + match value { + numeric @ (Value::Int { .. } | Value::Float { .. }) => { + let span = numeric.span(); + let (val, span) = match numeric { + Value::Int { val, .. } => (val as f64, span), + Value::Float { val, .. } => (val, span), + _ => unreachable!(), + }; + + if (1.0..).contains(&val) { + let val = val.acosh(); + + Value::float(val, span) + } else { + Value::error( + ShellError::UnsupportedInput { + msg: "'arccosh' undefined for values below 1.".into(), + input: "value originates from here".into(), + msg_span: head, + input_span: span, + }, + span, + ) + } + } + Value::Error { .. } => value, + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "numeric".into(), + wrong_type: other.get_type().to_string(), + dst_span: head, + src_span: other.span(), + }, + head, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(MathArcCosH {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/math/arcsin.rs b/nushell/crates/nu-cmd-extra/src/extra/math/arcsin.rs new file mode 100644 index 0000000..817438d --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/math/arcsin.rs @@ -0,0 +1,120 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct MathArcSin; + +impl Command for MathArcSin { + fn name(&self) -> &str { + "math arcsin" + } + + fn signature(&self) -> Signature { + Signature::build("math arcsin") + .switch("degrees", "Return degrees instead of radians", Some('d')) + .input_output_types(vec![ + (Type::Number, Type::Float), + ( + Type::List(Box::new(Type::Number)), + Type::List(Box::new(Type::Float)), + ), + ]) + .allow_variants_without_examples(true) + .category(Category::Math) + } + + fn description(&self) -> &str { + "Returns the arcsine of the number." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["trigonometry", "inverse"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + let use_degrees = call.has_flag(engine_state, stack, "degrees")?; + // This doesn't match explicit nulls + if matches!(input, PipelineData::Empty) { + return Err(ShellError::PipelineEmpty { dst_span: head }); + } + input.map( + move |value| operate(value, head, use_degrees), + engine_state.signals(), + ) + } + + fn examples(&self) -> Vec { + let pi = std::f64::consts::PI; + vec![ + Example { + description: "Get the arcsine of 1", + example: "1 | math arcsin", + result: Some(Value::test_float(pi / 2.0)), + }, + Example { + description: "Get the arcsine of 1 in degrees", + example: "1 | math arcsin --degrees", + result: Some(Value::test_float(90.0)), + }, + ] + } +} + +fn operate(value: Value, head: Span, use_degrees: bool) -> Value { + match value { + numeric @ (Value::Int { .. } | Value::Float { .. }) => { + let span = numeric.span(); + let (val, span) = match numeric { + Value::Int { val, .. } => (val as f64, span), + Value::Float { val, .. } => (val, span), + _ => unreachable!(), + }; + + if (-1.0..=1.0).contains(&val) { + let val = val.asin(); + let val = if use_degrees { val.to_degrees() } else { val }; + + Value::float(val, span) + } else { + Value::error( + ShellError::UnsupportedInput { + msg: "'arcsin' undefined for values outside the closed interval [-1, 1]." + .into(), + input: "value originates from here".into(), + msg_span: head, + input_span: span, + }, + span, + ) + } + } + Value::Error { .. } => value, + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "numeric".into(), + wrong_type: other.get_type().to_string(), + dst_span: head, + src_span: other.span(), + }, + head, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(MathArcSin {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/math/arcsinh.rs b/nushell/crates/nu-cmd-extra/src/extra/math/arcsinh.rs new file mode 100644 index 0000000..6faa2dd --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/math/arcsinh.rs @@ -0,0 +1,93 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct MathArcSinH; + +impl Command for MathArcSinH { + fn name(&self) -> &str { + "math arcsinh" + } + + fn signature(&self) -> Signature { + Signature::build("math arcsinh") + .input_output_types(vec![ + (Type::Number, Type::Float), + ( + Type::List(Box::new(Type::Number)), + Type::List(Box::new(Type::Float)), + ), + ]) + .allow_variants_without_examples(true) + .category(Category::Math) + } + + fn description(&self) -> &str { + "Returns the inverse of the hyperbolic sine function." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["trigonometry", "inverse", "hyperbolic"] + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + // This doesn't match explicit nulls + if matches!(input, PipelineData::Empty) { + return Err(ShellError::PipelineEmpty { dst_span: head }); + } + input.map(move |value| operate(value, head), engine_state.signals()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Get the arcsinh of 0", + example: "0 | math arcsinh", + result: Some(Value::test_float(0.0f64)), + }] + } +} + +fn operate(value: Value, head: Span) -> Value { + match value { + numeric @ (Value::Int { .. } | Value::Float { .. }) => { + let span = numeric.span(); + let (val, span) = match numeric { + Value::Int { val, .. } => (val as f64, span), + Value::Float { val, .. } => (val, span), + _ => unreachable!(), + }; + + let val = val.asinh(); + + Value::float(val, span) + } + Value::Error { .. } => value, + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "numeric".into(), + wrong_type: other.get_type().to_string(), + dst_span: head, + src_span: other.span(), + }, + head, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(MathArcSinH {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/math/arctan.rs b/nushell/crates/nu-cmd-extra/src/extra/math/arctan.rs new file mode 100644 index 0000000..17de98b --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/math/arctan.rs @@ -0,0 +1,107 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct MathArcTan; + +impl Command for MathArcTan { + fn name(&self) -> &str { + "math arctan" + } + + fn signature(&self) -> Signature { + Signature::build("math arctan") + .switch("degrees", "Return degrees instead of radians", Some('d')) + .input_output_types(vec![ + (Type::Number, Type::Float), + ( + Type::List(Box::new(Type::Number)), + Type::List(Box::new(Type::Float)), + ), + ]) + .allow_variants_without_examples(true) + .category(Category::Math) + } + + fn description(&self) -> &str { + "Returns the arctangent of the number." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["trigonometry", "inverse"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + let use_degrees = call.has_flag(engine_state, stack, "degrees")?; + // This doesn't match explicit nulls + if matches!(input, PipelineData::Empty) { + return Err(ShellError::PipelineEmpty { dst_span: head }); + } + input.map( + move |value| operate(value, head, use_degrees), + engine_state.signals(), + ) + } + + fn examples(&self) -> Vec { + let pi = std::f64::consts::PI; + vec![ + Example { + description: "Get the arctangent of 1", + example: "1 | math arctan", + result: Some(Value::test_float(pi / 4.0f64)), + }, + Example { + description: "Get the arctangent of -1 in degrees", + example: "-1 | math arctan --degrees", + result: Some(Value::test_float(-45.0)), + }, + ] + } +} + +fn operate(value: Value, head: Span, use_degrees: bool) -> Value { + match value { + numeric @ (Value::Int { .. } | Value::Float { .. }) => { + let span = numeric.span(); + let (val, span) = match numeric { + Value::Int { val, .. } => (val as f64, span), + Value::Float { val, .. } => (val, span), + _ => unreachable!(), + }; + + let val = val.atan(); + let val = if use_degrees { val.to_degrees() } else { val }; + + Value::float(val, span) + } + Value::Error { .. } => value, + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "numeric".into(), + wrong_type: other.get_type().to_string(), + dst_span: head, + src_span: other.span(), + }, + head, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(MathArcTan {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/math/arctanh.rs b/nushell/crates/nu-cmd-extra/src/extra/math/arctanh.rs new file mode 100644 index 0000000..97fb727 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/math/arctanh.rs @@ -0,0 +1,106 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct MathArcTanH; + +impl Command for MathArcTanH { + fn name(&self) -> &str { + "math arctanh" + } + + fn signature(&self) -> Signature { + Signature::build("math arctanh") + .input_output_types(vec![ + (Type::Number, Type::Float), + ( + Type::List(Box::new(Type::Number)), + Type::List(Box::new(Type::Float)), + ), + ]) + .allow_variants_without_examples(true) + .category(Category::Math) + } + + fn description(&self) -> &str { + "Returns the inverse of the hyperbolic tangent function." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["trigonometry", "inverse", "hyperbolic"] + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + // This doesn't match explicit nulls + if matches!(input, PipelineData::Empty) { + return Err(ShellError::PipelineEmpty { dst_span: head }); + } + input.map(move |value| operate(value, head), engine_state.signals()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Get the arctanh of 1", + example: "1 | math arctanh", + result: Some(Value::test_float(f64::INFINITY)), + }] + } +} + +fn operate(value: Value, head: Span) -> Value { + match value { + numeric @ (Value::Int { .. } | Value::Float { .. }) => { + let span = numeric.span(); + let (val, span) = match numeric { + Value::Int { val, .. } => (val as f64, span), + Value::Float { val, .. } => (val, span), + _ => unreachable!(), + }; + + if (-1.0..=1.0).contains(&val) { + let val = val.atanh(); + + Value::float(val, span) + } else { + Value::error( + ShellError::UnsupportedInput { + msg: "'arctanh' undefined for values outside the open interval (-1, 1)." + .into(), + input: "value originates from here".into(), + msg_span: head, + input_span: span, + }, + head, + ) + } + } + Value::Error { .. } => value, + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "numeric".into(), + wrong_type: other.get_type().to_string(), + dst_span: head, + src_span: other.span(), + }, + head, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(MathArcTanH {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/math/cos.rs b/nushell/crates/nu-cmd-extra/src/extra/math/cos.rs new file mode 100644 index 0000000..c5d7763 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/math/cos.rs @@ -0,0 +1,113 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct MathCos; + +impl Command for MathCos { + fn name(&self) -> &str { + "math cos" + } + + fn signature(&self) -> Signature { + Signature::build("math cos") + .switch("degrees", "Use degrees instead of radians", Some('d')) + .input_output_types(vec![ + (Type::Number, Type::Float), + ( + Type::List(Box::new(Type::Number)), + Type::List(Box::new(Type::Float)), + ), + ]) + .category(Category::Math) + } + + fn description(&self) -> &str { + "Returns the cosine of the number." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["trigonometry"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + let use_degrees = call.has_flag(engine_state, stack, "degrees")?; + // This doesn't match explicit nulls + if matches!(input, PipelineData::Empty) { + return Err(ShellError::PipelineEmpty { dst_span: head }); + } + input.map( + move |value| operate(value, head, use_degrees), + engine_state.signals(), + ) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Apply the cosine to π", + example: "3.141592 | math cos | math round --precision 4", + result: Some(Value::test_float(-1f64)), + }, + Example { + description: "Apply the cosine to a list of angles in degrees", + example: "[0 90 180 270 360] | math cos --degrees", + result: Some(Value::list( + vec![ + Value::test_float(1f64), + Value::test_float(0f64), + Value::test_float(-1f64), + Value::test_float(0f64), + Value::test_float(1f64), + ], + Span::test_data(), + )), + }, + ] + } +} + +fn operate(value: Value, head: Span, use_degrees: bool) -> Value { + match value { + numeric @ (Value::Int { .. } | Value::Float { .. }) => { + let span = numeric.span(); + let (val, span) = match numeric { + Value::Int { val, .. } => (val as f64, span), + Value::Float { val, .. } => (val, span), + _ => unreachable!(), + }; + + let val = if use_degrees { val.to_radians() } else { val }; + + Value::float(val.cos(), span) + } + Value::Error { .. } => value, + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "numeric".into(), + wrong_type: other.get_type().to_string(), + dst_span: head, + src_span: other.span(), + }, + head, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(MathCos {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/math/cosh.rs b/nushell/crates/nu-cmd-extra/src/extra/math/cosh.rs new file mode 100644 index 0000000..46ec992 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/math/cosh.rs @@ -0,0 +1,93 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct MathCosH; + +impl Command for MathCosH { + fn name(&self) -> &str { + "math cosh" + } + + fn signature(&self) -> Signature { + Signature::build("math cosh") + .input_output_types(vec![ + (Type::Number, Type::Float), + ( + Type::List(Box::new(Type::Number)), + Type::List(Box::new(Type::Float)), + ), + ]) + .allow_variants_without_examples(true) + .category(Category::Math) + } + + fn description(&self) -> &str { + "Returns the hyperbolic cosine of the number." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["trigonometry", "hyperbolic"] + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + // This doesn't match explicit nulls + if matches!(input, PipelineData::Empty) { + return Err(ShellError::PipelineEmpty { dst_span: head }); + } + input.map(move |value| operate(value, head), engine_state.signals()) + } + + fn examples(&self) -> Vec { + let e = std::f64::consts::E; + vec![Example { + description: "Apply the hyperbolic cosine to 1", + example: "1 | math cosh", + result: Some(Value::test_float(((e * e) + 1.0) / (2.0 * e))), + }] + } +} + +fn operate(value: Value, head: Span) -> Value { + match value { + numeric @ (Value::Int { .. } | Value::Float { .. }) => { + let span = numeric.span(); + + let (val, span) = match numeric { + Value::Int { val, .. } => (val as f64, span), + Value::Float { val, .. } => (val, span), + _ => unreachable!(), + }; + + Value::float(val.cosh(), span) + } + Value::Error { .. } => value, + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "numeric".into(), + wrong_type: other.get_type().to_string(), + dst_span: head, + src_span: other.span(), + }, + head, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(MathCosH {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/math/exp.rs b/nushell/crates/nu-cmd-extra/src/extra/math/exp.rs new file mode 100644 index 0000000..b8954bd --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/math/exp.rs @@ -0,0 +1,98 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct MathExp; + +impl Command for MathExp { + fn name(&self) -> &str { + "math exp" + } + + fn signature(&self) -> Signature { + Signature::build("math exp") + .input_output_types(vec![ + (Type::Number, Type::Float), + ( + Type::List(Box::new(Type::Number)), + Type::List(Box::new(Type::Float)), + ), + ]) + .allow_variants_without_examples(true) + .category(Category::Math) + } + + fn description(&self) -> &str { + "Returns e raised to the power of x." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["exponential", "exponentiation", "euler"] + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + // This doesn't match explicit nulls + if matches!(input, PipelineData::Empty) { + return Err(ShellError::PipelineEmpty { dst_span: head }); + } + input.map(move |value| operate(value, head), engine_state.signals()) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Get e raised to the power of zero", + example: "0 | math exp", + result: Some(Value::test_float(1.0f64)), + }, + Example { + description: "Get e (same as 'math e')", + example: "1 | math exp", + result: Some(Value::test_float(1.0f64.exp())), + }, + ] + } +} + +fn operate(value: Value, head: Span) -> Value { + match value { + numeric @ (Value::Int { .. } | Value::Float { .. }) => { + let span = numeric.span(); + let (val, span) = match numeric { + Value::Int { val, .. } => (val as f64, span), + Value::Float { val, .. } => (val, span), + _ => unreachable!(), + }; + + Value::float(val.exp(), span) + } + Value::Error { .. } => value, + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "numeric".into(), + wrong_type: other.get_type().to_string(), + dst_span: head, + src_span: other.span(), + }, + head, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(MathExp {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/math/ln.rs b/nushell/crates/nu-cmd-extra/src/extra/math/ln.rs new file mode 100644 index 0000000..60890fa --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/math/ln.rs @@ -0,0 +1,105 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct MathLn; + +impl Command for MathLn { + fn name(&self) -> &str { + "math ln" + } + + fn signature(&self) -> Signature { + Signature::build("math ln") + .input_output_types(vec![ + (Type::Number, Type::Float), + ( + Type::List(Box::new(Type::Number)), + Type::List(Box::new(Type::Float)), + ), + ]) + .allow_variants_without_examples(true) + .category(Category::Math) + } + + fn description(&self) -> &str { + "Returns the natural logarithm. Base: (math e)." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["natural", "logarithm", "inverse", "euler"] + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + // This doesn't match explicit nulls + if matches!(input, PipelineData::Empty) { + return Err(ShellError::PipelineEmpty { dst_span: head }); + } + input.map(move |value| operate(value, head), engine_state.signals()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Get the natural logarithm of e", + example: "2.7182818 | math ln | math round --precision 4", + result: Some(Value::test_float(1.0f64)), + }] + } +} + +fn operate(value: Value, head: Span) -> Value { + match value { + numeric @ (Value::Int { .. } | Value::Float { .. }) => { + let span = numeric.span(); + let (val, span) = match numeric { + Value::Int { val, .. } => (val as f64, span), + Value::Float { val, .. } => (val, span), + _ => unreachable!(), + }; + + if val > 0.0 { + let val = val.ln(); + + Value::float(val, span) + } else { + Value::error( + ShellError::UnsupportedInput { + msg: "'ln' undefined for values outside the open interval (0, Inf).".into(), + input: "value originates from here".into(), + msg_span: head, + input_span: span, + }, + span, + ) + } + } + Value::Error { .. } => value, + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "numeric".into(), + wrong_type: other.get_type().to_string(), + dst_span: head, + src_span: other.span(), + }, + head, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(MathLn {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/math/mod.rs b/nushell/crates/nu-cmd-extra/src/extra/math/mod.rs new file mode 100644 index 0000000..239a57d --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/math/mod.rs @@ -0,0 +1,33 @@ +mod cos; +mod cosh; +mod sin; +mod sinh; +mod tan; +mod tanh; + +mod exp; +mod ln; + +mod arccos; +mod arccosh; +mod arcsin; +mod arcsinh; +mod arctan; +mod arctanh; + +pub use cos::MathCos; +pub use cosh::MathCosH; +pub use sin::MathSin; +pub use sinh::MathSinH; +pub use tan::MathTan; +pub use tanh::MathTanH; + +pub use exp::MathExp; +pub use ln::MathLn; + +pub use arccos::MathArcCos; +pub use arccosh::MathArcCosH; +pub use arcsin::MathArcSin; +pub use arcsinh::MathArcSinH; +pub use arctan::MathArcTan; +pub use arctanh::MathArcTanH; diff --git a/nushell/crates/nu-cmd-extra/src/extra/math/sin.rs b/nushell/crates/nu-cmd-extra/src/extra/math/sin.rs new file mode 100644 index 0000000..e22dea8 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/math/sin.rs @@ -0,0 +1,113 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct MathSin; + +impl Command for MathSin { + fn name(&self) -> &str { + "math sin" + } + + fn signature(&self) -> Signature { + Signature::build("math sin") + .switch("degrees", "Use degrees instead of radians", Some('d')) + .input_output_types(vec![ + (Type::Number, Type::Float), + ( + Type::List(Box::new(Type::Number)), + Type::List(Box::new(Type::Float)), + ), + ]) + .category(Category::Math) + } + + fn description(&self) -> &str { + "Returns the sine of the number." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["trigonometry"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + let use_degrees = call.has_flag(engine_state, stack, "degrees")?; + // This doesn't match explicit nulls + if matches!(input, PipelineData::Empty) { + return Err(ShellError::PipelineEmpty { dst_span: head }); + } + input.map( + move |value| operate(value, head, use_degrees), + engine_state.signals(), + ) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Apply the sine to π/2", + example: "3.141592 / 2 | math sin | math round --precision 4", + result: Some(Value::test_float(1f64)), + }, + Example { + description: "Apply the sine to a list of angles in degrees", + example: "[0 90 180 270 360] | math sin -d | math round --precision 4", + result: Some(Value::list( + vec![ + Value::test_float(0f64), + Value::test_float(1f64), + Value::test_float(0f64), + Value::test_float(-1f64), + Value::test_float(0f64), + ], + Span::test_data(), + )), + }, + ] + } +} + +fn operate(value: Value, head: Span, use_degrees: bool) -> Value { + match value { + numeric @ (Value::Int { .. } | Value::Float { .. }) => { + let span = numeric.span(); + let (val, span) = match numeric { + Value::Int { val, .. } => (val as f64, span), + Value::Float { val, .. } => (val, span), + _ => unreachable!(), + }; + + let val = if use_degrees { val.to_radians() } else { val }; + + Value::float(val.sin(), span) + } + Value::Error { .. } => value, + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "numeric".into(), + wrong_type: other.get_type().to_string(), + dst_span: head, + src_span: other.span(), + }, + head, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(MathSin {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/math/sinh.rs b/nushell/crates/nu-cmd-extra/src/extra/math/sinh.rs new file mode 100644 index 0000000..3ac7d8f --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/math/sinh.rs @@ -0,0 +1,92 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct MathSinH; + +impl Command for MathSinH { + fn name(&self) -> &str { + "math sinh" + } + + fn signature(&self) -> Signature { + Signature::build("math sinh") + .input_output_types(vec![ + (Type::Number, Type::Float), + ( + Type::List(Box::new(Type::Number)), + Type::List(Box::new(Type::Float)), + ), + ]) + .allow_variants_without_examples(true) + .category(Category::Math) + } + + fn description(&self) -> &str { + "Returns the hyperbolic sine of the number." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["trigonometry", "hyperbolic"] + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + // This doesn't match explicit nulls + if matches!(input, PipelineData::Empty) { + return Err(ShellError::PipelineEmpty { dst_span: head }); + } + input.map(move |value| operate(value, head), engine_state.signals()) + } + + fn examples(&self) -> Vec { + let e = std::f64::consts::E; + vec![Example { + description: "Apply the hyperbolic sine to 1", + example: "1 | math sinh", + result: Some(Value::test_float((e * e - 1.0) / (2.0 * e))), + }] + } +} + +fn operate(value: Value, head: Span) -> Value { + match value { + numeric @ (Value::Int { .. } | Value::Float { .. }) => { + let span = numeric.span(); + let (val, span) = match numeric { + Value::Int { val, .. } => (val as f64, span), + Value::Float { val, .. } => (val, span), + _ => unreachable!(), + }; + + Value::float(val.sinh(), span) + } + Value::Error { .. } => value, + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "numeric".into(), + wrong_type: other.get_type().to_string(), + dst_span: head, + src_span: other.span(), + }, + head, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(MathSinH {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/math/tan.rs b/nushell/crates/nu-cmd-extra/src/extra/math/tan.rs new file mode 100644 index 0000000..81a81aa --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/math/tan.rs @@ -0,0 +1,111 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct MathTan; + +impl Command for MathTan { + fn name(&self) -> &str { + "math tan" + } + + fn signature(&self) -> Signature { + Signature::build("math tan") + .switch("degrees", "Use degrees instead of radians", Some('d')) + .input_output_types(vec![ + (Type::Number, Type::Float), + ( + Type::List(Box::new(Type::Number)), + Type::List(Box::new(Type::Float)), + ), + ]) + .category(Category::Math) + } + + fn description(&self) -> &str { + "Returns the tangent of the number." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["trigonometry"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + let use_degrees = call.has_flag(engine_state, stack, "degrees")?; + // This doesn't match explicit nulls + if matches!(input, PipelineData::Empty) { + return Err(ShellError::PipelineEmpty { dst_span: head }); + } + input.map( + move |value| operate(value, head, use_degrees), + engine_state.signals(), + ) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Apply the tangent to π/4", + example: "3.141592 / 4 | math tan | math round --precision 4", + result: Some(Value::test_float(1f64)), + }, + Example { + description: "Apply the tangent to a list of angles in degrees", + example: "[-45 0 45] | math tan --degrees", + result: Some(Value::list( + vec![ + Value::test_float(-1f64), + Value::test_float(0f64), + Value::test_float(1f64), + ], + Span::test_data(), + )), + }, + ] + } +} + +fn operate(value: Value, head: Span, use_degrees: bool) -> Value { + match value { + numeric @ (Value::Int { .. } | Value::Float { .. }) => { + let span = numeric.span(); + let (val, span) = match numeric { + Value::Int { val, .. } => (val as f64, span), + Value::Float { val, .. } => (val, span), + _ => unreachable!(), + }; + + let val = if use_degrees { val.to_radians() } else { val }; + + Value::float(val.tan(), span) + } + Value::Error { .. } => value, + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "numeric".into(), + wrong_type: other.get_type().to_string(), + dst_span: head, + src_span: other.span(), + }, + head, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(MathTan {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/math/tanh.rs b/nushell/crates/nu-cmd-extra/src/extra/math/tanh.rs new file mode 100644 index 0000000..1a09737 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/math/tanh.rs @@ -0,0 +1,91 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct MathTanH; + +impl Command for MathTanH { + fn name(&self) -> &str { + "math tanh" + } + + fn signature(&self) -> Signature { + Signature::build("math tanh") + .input_output_types(vec![ + (Type::Number, Type::Float), + ( + Type::List(Box::new(Type::Number)), + Type::List(Box::new(Type::Float)), + ), + ]) + .allow_variants_without_examples(true) + .category(Category::Math) + } + + fn description(&self) -> &str { + "Returns the hyperbolic tangent of the number." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["trigonometry", "hyperbolic"] + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + // This doesn't match explicit nulls + if matches!(input, PipelineData::Empty) { + return Err(ShellError::PipelineEmpty { dst_span: head }); + } + input.map(move |value| operate(value, head), engine_state.signals()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Apply the hyperbolic tangent to 10*π", + example: "3.141592 * 10 | math tanh | math round --precision 4", + result: Some(Value::test_float(1f64)), + }] + } +} + +fn operate(value: Value, head: Span) -> Value { + match value { + numeric @ (Value::Int { .. } | Value::Float { .. }) => { + let span = numeric.span(); + let (val, span) = match numeric { + Value::Int { val, .. } => (val as f64, span), + Value::Float { val, .. } => (val, span), + _ => unreachable!(), + }; + + Value::float(val.tanh(), span) + } + Value::Error { .. } => value, + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "numeric".into(), + wrong_type: other.get_type().to_string(), + dst_span: head, + src_span: other.span(), + }, + head, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(MathTanH {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/mod.rs b/nushell/crates/nu-cmd-extra/src/extra/mod.rs new file mode 100644 index 0000000..4dfcbdc --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/mod.rs @@ -0,0 +1,96 @@ +mod bits; +mod filters; +mod formats; +mod math; +mod platform; +mod strings; + +pub use bits::{Bits, BitsAnd, BitsNot, BitsOr, BitsRol, BitsRor, BitsShl, BitsShr, BitsXor}; +pub use formats::ToHtml; +pub use math::{MathArcCos, MathArcCosH, MathArcSin, MathArcSinH, MathArcTan, MathArcTanH}; +pub use math::{MathCos, MathCosH, MathSin, MathSinH, MathTan, MathTanH}; +pub use math::{MathExp, MathLn}; + +use nu_protocol::engine::{EngineState, StateWorkingSet}; + +pub fn add_extra_command_context(mut engine_state: EngineState) -> EngineState { + let delta = { + let mut working_set = StateWorkingSet::new(&engine_state); + + macro_rules! bind_command { + ( $command:expr ) => { + working_set.add_decl(Box::new($command)); + }; + ( $( $command:expr ),* ) => { + $( working_set.add_decl(Box::new($command)); )* + }; + } + + bind_command!( + filters::UpdateCells, + filters::EachWhile, + filters::Roll, + filters::RollDown, + filters::RollUp, + filters::RollLeft, + filters::RollRight, + filters::Rotate + ); + + bind_command!(platform::ansi::Gradient); + + bind_command!( + strings::format::FormatPattern, + strings::format::FormatBits, + strings::format::FormatNumber, + strings::str_::case::Str, + strings::str_::case::StrCamelCase, + strings::str_::case::StrKebabCase, + strings::str_::case::StrPascalCase, + strings::str_::case::StrScreamingSnakeCase, + strings::str_::case::StrSnakeCase, + strings::str_::case::StrTitleCase + ); + + bind_command!(ToHtml, formats::FromUrl); + + // Bits + bind_command! { + Bits, + BitsAnd, + BitsNot, + BitsOr, + BitsRol, + BitsRor, + BitsShl, + BitsShr, + BitsXor + } + + // Math + bind_command! { + MathArcSin, + MathArcCos, + MathArcTan, + MathArcSinH, + MathArcCosH, + MathArcTanH, + MathSin, + MathCos, + MathTan, + MathSinH, + MathCosH, + MathTanH, + MathExp, + MathLn + }; + + working_set.render() + }; + + if let Err(err) = engine_state.merge_delta(delta) { + eprintln!("Error creating extra command context: {err:?}"); + } + + engine_state +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/platform/ansi/gradient.rs b/nushell/crates/nu-cmd-extra/src/extra/platform/ansi/gradient.rs new file mode 100644 index 0000000..2db772a --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/platform/ansi/gradient.rs @@ -0,0 +1,328 @@ +use nu_ansi_term::{Gradient, Rgb, build_all_gradient_text, gradient::TargetGround}; +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "ansi gradient" + } + + fn signature(&self) -> Signature { + Signature::build("ansi gradient") + .named( + "fgstart", + SyntaxShape::String, + "foreground gradient start color in hex (0x123456)", + Some('a'), + ) + .named( + "fgend", + SyntaxShape::String, + "foreground gradient end color in hex", + Some('b'), + ) + .named( + "bgstart", + SyntaxShape::String, + "background gradient start color in hex", + Some('c'), + ) + .named( + "bgend", + SyntaxShape::String, + "background gradient end color in hex", + Some('d'), + ) + .rest( + "cell path", + SyntaxShape::CellPath, + "For a data structure input, add a gradient to strings at the given cell paths.", + ) + .input_output_types(vec![ + (Type::String, Type::String), + ( + Type::List(Box::new(Type::String)), + Type::List(Box::new(Type::String)), + ), + (Type::table(), Type::table()), + (Type::record(), Type::record()), + ]) + .allow_variants_without_examples(true) + .category(Category::Platform) + } + + fn description(&self) -> &str { + "Add a color gradient (using ANSI color codes) to the given string." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + operate(engine_state, stack, call, input) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "draw text in a gradient with foreground start and end colors", + example: "'Hello, Nushell! This is a gradient.' | ansi gradient --fgstart '0x40c9ff' --fgend '0xe81cff'", + result: None, + }, + Example { + description: "draw text in a gradient with foreground start and end colors and background start and end colors", + example: "'Hello, Nushell! This is a gradient.' | ansi gradient --fgstart '0x40c9ff' --fgend '0xe81cff' --bgstart '0xe81cff' --bgend '0x40c9ff'", + result: None, + }, + Example { + description: "draw text in a gradient by specifying foreground start color - end color is assumed to be black", + example: "'Hello, Nushell! This is a gradient.' | ansi gradient --fgstart '0x40c9ff'", + result: None, + }, + Example { + description: "draw text in a gradient by specifying foreground end color - start color is assumed to be black", + example: "'Hello, Nushell! This is a gradient.' | ansi gradient --fgend '0xe81cff'", + result: None, + }, + ] + } +} + +fn value_to_color(v: Option) -> Result, ShellError> { + let s = match v { + None => return Ok(None), + Some(x) => x.coerce_into_string()?, + }; + Ok(Some(Rgb::from_hex_string(s))) +} + +fn operate( + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, +) -> Result { + let fgstart: Option = call.get_flag(engine_state, stack, "fgstart")?; + let fgend: Option = call.get_flag(engine_state, stack, "fgend")?; + let bgstart: Option = call.get_flag(engine_state, stack, "bgstart")?; + let bgend: Option = call.get_flag(engine_state, stack, "bgend")?; + let column_paths: Vec = call.rest(engine_state, stack, 0)?; + + let fgs_hex = value_to_color(fgstart)?; + let fge_hex = value_to_color(fgend)?; + let bgs_hex = value_to_color(bgstart)?; + let bge_hex = value_to_color(bgend)?; + let head = call.head; + input.map( + move |v| { + if column_paths.is_empty() { + action(&v, fgs_hex, fge_hex, bgs_hex, bge_hex, head) + } else { + let mut ret = v; + for path in &column_paths { + let r = ret.update_cell_path( + &path.members, + Box::new(move |old| action(old, fgs_hex, fge_hex, bgs_hex, bge_hex, head)), + ); + if let Err(error) = r { + return Value::error(error, head); + } + } + ret + } + }, + engine_state.signals(), + ) +} + +fn action( + input: &Value, + fg_start: Option, + fg_end: Option, + bg_start: Option, + bg_end: Option, + command_span: Span, +) -> Value { + let span = input.span(); + match input { + Value::String { val, .. } => { + match (fg_start, fg_end, bg_start, bg_end) { + (None, None, None, None) => { + // Error - no colors + Value::error( + ShellError::MissingParameter { + param_name: + "please supply foreground and/or background color parameters".into(), + span: command_span, + }, + span, + ) + } + (None, None, None, Some(bg_end)) => { + // Error - missing bg_start, so assume black + let bg_start = Rgb::new(0, 0, 0); + let gradient = Gradient::new(bg_start, bg_end); + let gradient_string = gradient.build(val, TargetGround::Background); + Value::string(gradient_string, span) + } + (None, None, Some(bg_start), None) => { + // Error - missing bg_end, so assume black + let bg_end = Rgb::new(0, 0, 0); + let gradient = Gradient::new(bg_start, bg_end); + let gradient_string = gradient.build(val, TargetGround::Background); + Value::string(gradient_string, span) + } + (None, None, Some(bg_start), Some(bg_end)) => { + // Background Only + let gradient = Gradient::new(bg_start, bg_end); + let gradient_string = gradient.build(val, TargetGround::Background); + Value::string(gradient_string, span) + } + (None, Some(fg_end), None, None) => { + // Error - missing fg_start, so assume black + let fg_start = Rgb::new(0, 0, 0); + let gradient = Gradient::new(fg_start, fg_end); + let gradient_string = gradient.build(val, TargetGround::Foreground); + Value::string(gradient_string, span) + } + (None, Some(fg_end), None, Some(bg_end)) => { + // missing fg_start and bg_start, so assume black + let fg_start = Rgb::new(0, 0, 0); + let bg_start = Rgb::new(0, 0, 0); + let fg_gradient = Gradient::new(fg_start, fg_end); + let bg_gradient = Gradient::new(bg_start, bg_end); + let gradient_string = build_all_gradient_text(val, fg_gradient, bg_gradient); + Value::string(gradient_string, span) + } + (None, Some(fg_end), Some(bg_start), None) => { + // Error - missing fg_start and bg_end + let fg_start = Rgb::new(0, 0, 0); + let bg_end = Rgb::new(0, 0, 0); + let fg_gradient = Gradient::new(fg_start, fg_end); + let bg_gradient = Gradient::new(bg_start, bg_end); + let gradient_string = build_all_gradient_text(val, fg_gradient, bg_gradient); + Value::string(gradient_string, span) + } + (None, Some(fg_end), Some(bg_start), Some(bg_end)) => { + // Error - missing fg_start, so assume black + let fg_start = Rgb::new(0, 0, 0); + let fg_gradient = Gradient::new(fg_start, fg_end); + let bg_gradient = Gradient::new(bg_start, bg_end); + let gradient_string = build_all_gradient_text(val, fg_gradient, bg_gradient); + Value::string(gradient_string, span) + } + (Some(fg_start), None, None, None) => { + // Error - missing fg_end, so assume black + let fg_end = Rgb::new(0, 0, 0); + let gradient = Gradient::new(fg_start, fg_end); + let gradient_string = gradient.build(val, TargetGround::Foreground); + Value::string(gradient_string, span) + } + (Some(fg_start), None, None, Some(bg_end)) => { + // Error - missing fg_end, bg_start, so assume black + let fg_end = Rgb::new(0, 0, 0); + let bg_start = Rgb::new(0, 0, 0); + let fg_gradient = Gradient::new(fg_start, fg_end); + let bg_gradient = Gradient::new(bg_start, bg_end); + let gradient_string = build_all_gradient_text(val, fg_gradient, bg_gradient); + Value::string(gradient_string, span) + } + (Some(fg_start), None, Some(bg_start), None) => { + // Error - missing fg_end, bg_end, so assume black + let fg_end = Rgb::new(0, 0, 0); + let bg_end = Rgb::new(0, 0, 0); + let fg_gradient = Gradient::new(fg_start, fg_end); + let bg_gradient = Gradient::new(bg_start, bg_end); + let gradient_string = build_all_gradient_text(val, fg_gradient, bg_gradient); + Value::string(gradient_string, span) + } + (Some(fg_start), None, Some(bg_start), Some(bg_end)) => { + // Error - missing fg_end, so assume black + let fg_end = Rgb::new(0, 0, 0); + let fg_gradient = Gradient::new(fg_start, fg_end); + let bg_gradient = Gradient::new(bg_start, bg_end); + let gradient_string = build_all_gradient_text(val, fg_gradient, bg_gradient); + Value::string(gradient_string, span) + } + (Some(fg_start), Some(fg_end), None, None) => { + // Foreground Only + let gradient = Gradient::new(fg_start, fg_end); + let gradient_string = gradient.build(val, TargetGround::Foreground); + Value::string(gradient_string, span) + } + (Some(fg_start), Some(fg_end), None, Some(bg_end)) => { + // Error - missing bg_start, so assume black + let bg_start = Rgb::new(0, 0, 0); + let fg_gradient = Gradient::new(fg_start, fg_end); + let bg_gradient = Gradient::new(bg_start, bg_end); + let gradient_string = build_all_gradient_text(val, fg_gradient, bg_gradient); + Value::string(gradient_string, span) + } + (Some(fg_start), Some(fg_end), Some(bg_start), None) => { + // Error - missing bg_end, so assume black + let bg_end = Rgb::new(0, 0, 0); + let fg_gradient = Gradient::new(fg_start, fg_end); + let bg_gradient = Gradient::new(bg_start, bg_end); + let gradient_string = build_all_gradient_text(val, fg_gradient, bg_gradient); + Value::string(gradient_string, span) + } + (Some(fg_start), Some(fg_end), Some(bg_start), Some(bg_end)) => { + // Foreground and Background Gradient + let fg_gradient = Gradient::new(fg_start, fg_end); + let bg_gradient = Gradient::new(bg_start, bg_end); + let gradient_string = build_all_gradient_text(val, fg_gradient, bg_gradient); + Value::string(gradient_string, span) + } + } + } + other => { + let got = format!("value is {}, not string", other.get_type()); + + Value::error( + ShellError::TypeMismatch { + err_message: got, + span: other.span(), + }, + other.span(), + ) + } + } +} + +#[cfg(test)] +mod tests { + use super::{SubCommand, action}; + use nu_ansi_term::Rgb; + use nu_protocol::{Span, Value}; + + #[test] + fn examples_work_as_expected() { + use crate::test_examples; + + test_examples(SubCommand {}) + } + + #[test] + fn test_fg_gradient() { + let input_string = Value::test_string("Hello, World!"); + let expected = Value::test_string( + "\u{1b}[38;2;64;201;255mH\u{1b}[38;2;76;187;254me\u{1b}[38;2;89;174;254ml\u{1b}[38;2;102;160;254ml\u{1b}[38;2;115;147;254mo\u{1b}[38;2;128;133;254m,\u{1b}[38;2;141;120;254m \u{1b}[38;2;153;107;254mW\u{1b}[38;2;166;94;254mo\u{1b}[38;2;179;80;254mr\u{1b}[38;2;192;67;254ml\u{1b}[38;2;205;53;254md\u{1b}[38;2;218;40;254m!\u{1b}[0m", + ); + let fg_start = Rgb::from_hex_string("0x40c9ff".to_string()); + let fg_end = Rgb::from_hex_string("0xe81cff".to_string()); + let actual = action( + &input_string, + Some(fg_start), + Some(fg_end), + None, + None, + Span::test_data(), + ); + assert_eq!(actual, expected); + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/platform/ansi/mod.rs b/nushell/crates/nu-cmd-extra/src/extra/platform/ansi/mod.rs new file mode 100644 index 0000000..036fa1e --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/platform/ansi/mod.rs @@ -0,0 +1,3 @@ +mod gradient; + +pub(crate) use gradient::SubCommand as Gradient; diff --git a/nushell/crates/nu-cmd-extra/src/extra/platform/mod.rs b/nushell/crates/nu-cmd-extra/src/extra/platform/mod.rs new file mode 100644 index 0000000..123734c --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/platform/mod.rs @@ -0,0 +1 @@ +pub(crate) mod ansi; diff --git a/nushell/crates/nu-cmd-extra/src/extra/strings/encode_decode/decode_hex.rs b/nushell/crates/nu-cmd-extra/src/extra/strings/encode_decode/decode_hex.rs new file mode 100644 index 0000000..f846afe --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/strings/encode_decode/decode_hex.rs @@ -0,0 +1,76 @@ +use super::hex::{operate, ActionType}; +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct DecodeHex; + +impl Command for DecodeHex { + fn name(&self) -> &str { + "decode hex" + } + + fn signature(&self) -> Signature { + Signature::build("decode hex") + .input_output_types(vec![ + (Type::String, Type::Binary), + ( + Type::List(Box::new(Type::String)), + Type::List(Box::new(Type::Binary)), + ), + (Type::table(), Type::table()), + (Type::record(), Type::record()), + ]) + .allow_variants_without_examples(true) + .rest( + "rest", + SyntaxShape::CellPath, + "For a data structure input, decode data at the given cell paths", + ) + .category(Category::Formats) + } + + fn description(&self) -> &str { + "Hex decode a value." + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Hex decode a value and output as binary", + example: "'0102030A0a0B' | decode hex", + result: Some(Value::binary( + [0x01, 0x02, 0x03, 0x0A, 0x0A, 0x0B], + Span::test_data(), + )), + }, + Example { + description: "Whitespaces are allowed to be between hex digits", + example: "'01 02 03 0A 0a 0B' | decode hex", + result: Some(Value::binary( + [0x01, 0x02, 0x03, 0x0A, 0x0A, 0x0B], + Span::test_data(), + )), + }, + ] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + operate(ActionType::Decode, engine_state, stack, call, input) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_examples() { + crate::test_examples(DecodeHex) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/strings/encode_decode/encode_hex.rs b/nushell/crates/nu-cmd-extra/src/extra/strings/encode_decode/encode_hex.rs new file mode 100644 index 0000000..c3a5467 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/strings/encode_decode/encode_hex.rs @@ -0,0 +1,63 @@ +use super::hex::{operate, ActionType}; +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct EncodeHex; + +impl Command for EncodeHex { + fn name(&self) -> &str { + "encode hex" + } + + fn signature(&self) -> Signature { + Signature::build("encode hex") + .input_output_types(vec![ + (Type::Binary, Type::String), + ( + Type::List(Box::new(Type::Binary)), + Type::List(Box::new(Type::String)), + ), + (Type::table(), Type::table()), + (Type::record(), Type::record()), + ]) + .allow_variants_without_examples(true) + .rest( + "rest", + SyntaxShape::CellPath, + "For a data structure input, encode data at the given cell paths", + ) + .category(Category::Formats) + } + + fn description(&self) -> &str { + "Encode a binary value using hex." + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Encode binary data", + example: "0x[09 F9 11 02 9D 74 E3 5B D8 41 56 C5 63 56 88 C0] | encode hex", + result: Some(Value::test_string("09F911029D74E35BD84156C5635688C0")), + }] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + operate(ActionType::Encode, engine_state, stack, call, input) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_examples() { + crate::test_examples(EncodeHex) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/strings/format/bits.rs b/nushell/crates/nu-cmd-extra/src/extra/strings/format/bits.rs new file mode 100644 index 0000000..f8d9309 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/strings/format/bits.rs @@ -0,0 +1,239 @@ +use std::io::{self, Read, Write}; + +use nu_cmd_base::input_handler::{CmdArgument, operate}; +use nu_engine::command_prelude::*; + +use nu_protocol::{Signals, shell_error::io::IoError}; +use num_traits::ToPrimitive; + +struct Arguments { + cell_paths: Option>, +} + +impl CmdArgument for Arguments { + fn take_cell_paths(&mut self) -> Option> { + self.cell_paths.take() + } +} + +#[derive(Clone)] +pub struct FormatBits; + +impl Command for FormatBits { + fn name(&self) -> &str { + "format bits" + } + + fn signature(&self) -> Signature { + Signature::build("format bits") + .input_output_types(vec![ + (Type::Binary, Type::String), + (Type::Int, Type::String), + (Type::Filesize, Type::String), + (Type::Duration, Type::String), + (Type::String, Type::String), + (Type::Bool, Type::String), + (Type::table(), Type::table()), + (Type::record(), Type::record()), + ]) + .allow_variants_without_examples(true) // TODO: supply exhaustive examples + .rest( + "rest", + SyntaxShape::CellPath, + "For a data structure input, convert data at the given cell paths.", + ) + .category(Category::Conversions) + } + + fn description(&self) -> &str { + "Convert value to a string of binary data represented by 0 and 1." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["convert", "cast", "binary"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + format_bits(engine_state, stack, call, input) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "convert a binary value into a string, padded to 8 places with 0s", + example: "0x[1] | format bits", + result: Some(Value::string("00000001", Span::test_data())), + }, + Example { + description: "convert an int into a string, padded to 8 places with 0s", + example: "1 | format bits", + result: Some(Value::string("00000001", Span::test_data())), + }, + Example { + description: "convert a filesize value into a string, padded to 8 places with 0s", + example: "1b | format bits", + result: Some(Value::string("00000001", Span::test_data())), + }, + Example { + description: "convert a duration value into a string, padded to 8 places with 0s", + example: "1ns | format bits", + result: Some(Value::string("00000001", Span::test_data())), + }, + Example { + description: "convert a boolean value into a string, padded to 8 places with 0s", + example: "true | format bits", + result: Some(Value::string("00000001", Span::test_data())), + }, + Example { + description: "convert a string into a raw binary string, padded with 0s to 8 places", + example: "'nushell.sh' | format bits", + result: Some(Value::string( + "01101110 01110101 01110011 01101000 01100101 01101100 01101100 00101110 01110011 01101000", + Span::test_data(), + )), + }, + ] + } +} + +fn format_bits( + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, +) -> Result { + let head = call.head; + let cell_paths = call.rest(engine_state, stack, 0)?; + let cell_paths = (!cell_paths.is_empty()).then_some(cell_paths); + + if let PipelineData::ByteStream(stream, metadata) = input { + Ok(PipelineData::ByteStream( + byte_stream_to_bits(stream, head), + metadata, + )) + } else { + let args = Arguments { cell_paths }; + operate(action, args, input, call.head, engine_state.signals()) + } +} + +fn byte_stream_to_bits(stream: ByteStream, head: Span) -> ByteStream { + if let Some(mut reader) = stream.reader() { + let mut is_first = true; + ByteStream::from_fn( + head, + Signals::empty(), + ByteStreamType::String, + move |buffer| { + let mut byte = [0]; + if reader + .read(&mut byte[..]) + .map_err(|err| IoError::new(err, head, None))? + > 0 + { + // Format the byte as bits + if is_first { + is_first = false; + } else { + buffer.push(b' '); + } + write!(buffer, "{:08b}", byte[0]).expect("format failed"); + Ok(true) + } else { + // EOF + Ok(false) + } + }, + ) + } else { + ByteStream::read(io::empty(), head, Signals::empty(), ByteStreamType::String) + } +} + +fn convert_to_smallest_number_type(num: i64, span: Span) -> Value { + if let Some(v) = num.to_i8() { + let bytes = v.to_ne_bytes(); + let mut raw_string = "".to_string(); + for ch in bytes { + raw_string.push_str(&format!("{:08b} ", ch)); + } + Value::string(raw_string.trim(), span) + } else if let Some(v) = num.to_i16() { + let bytes = v.to_ne_bytes(); + let mut raw_string = "".to_string(); + for ch in bytes { + raw_string.push_str(&format!("{:08b} ", ch)); + } + Value::string(raw_string.trim(), span) + } else if let Some(v) = num.to_i32() { + let bytes = v.to_ne_bytes(); + let mut raw_string = "".to_string(); + for ch in bytes { + raw_string.push_str(&format!("{:08b} ", ch)); + } + Value::string(raw_string.trim(), span) + } else { + let bytes = num.to_ne_bytes(); + let mut raw_string = "".to_string(); + for ch in bytes { + raw_string.push_str(&format!("{:08b} ", ch)); + } + Value::string(raw_string.trim(), span) + } +} + +fn action(input: &Value, _args: &Arguments, span: Span) -> Value { + match input { + Value::Binary { val, .. } => { + let mut raw_string = "".to_string(); + for ch in val { + raw_string.push_str(&format!("{:08b} ", ch)); + } + Value::string(raw_string.trim(), span) + } + Value::Int { val, .. } => convert_to_smallest_number_type(*val, span), + Value::Filesize { val, .. } => convert_to_smallest_number_type(val.get(), span), + Value::Duration { val, .. } => convert_to_smallest_number_type(*val, span), + Value::String { val, .. } => { + let raw_bytes = val.as_bytes(); + let mut raw_string = "".to_string(); + for ch in raw_bytes { + raw_string.push_str(&format!("{:08b} ", ch)); + } + Value::string(raw_string.trim(), span) + } + Value::Bool { val, .. } => { + let v = >::from(*val); + convert_to_smallest_number_type(v, span) + } + // Propagate errors by explicitly matching them before the final case. + Value::Error { .. } => input.clone(), + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "int, filesize, string, duration, binary, or bool".into(), + wrong_type: other.get_type().to_string(), + dst_span: span, + src_span: other.span(), + }, + span, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(FormatBits {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/strings/format/command.rs b/nushell/crates/nu-cmd-extra/src/extra/strings/format/command.rs new file mode 100644 index 0000000..9e3adaf --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/strings/format/command.rs @@ -0,0 +1,276 @@ +use nu_engine::command_prelude::*; +use nu_protocol::{Config, ListStream, ast::PathMember, casing::Casing, engine::StateWorkingSet}; + +#[derive(Clone)] +pub struct FormatPattern; + +impl Command for FormatPattern { + fn name(&self) -> &str { + "format pattern" + } + + fn signature(&self) -> Signature { + Signature::build("format pattern") + .input_output_types(vec![ + (Type::table(), Type::List(Box::new(Type::String))), + (Type::record(), Type::Any), + ]) + .required( + "pattern", + SyntaxShape::String, + "The pattern to output. e.g.) \"{foo}: {bar}\".", + ) + .allow_variants_without_examples(true) + .category(Category::Strings) + } + + fn description(&self) -> &str { + "Format columns into a string using a simple pattern." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let mut working_set = StateWorkingSet::new(engine_state); + + let specified_pattern: Result = call.req(engine_state, stack, 0); + let input_val = input.into_value(call.head)?; + // add '$it' variable to support format like this: $it.column1.column2. + let it_id = working_set.add_variable(b"$it".to_vec(), call.head, Type::Any, false); + stack.add_var(it_id, input_val.clone()); + + let config = stack.get_config(engine_state); + + match specified_pattern { + Err(e) => Err(e), + Ok(pattern) => { + let string_span = pattern.span(); + let string_pattern = pattern.coerce_into_string()?; + // the string span is start as `"`, we don't need the character + // to generate proper span for sub expression. + let ops = extract_formatting_operations( + string_pattern, + call.head, + string_span.start + 1, + )?; + + format(input_val, &ops, engine_state, &config, call.head) + } + } + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Print filenames with their sizes", + example: "ls | format pattern '{name}: {size}'", + result: None, + }, + Example { + description: "Print elements from some columns of a table", + example: "[[col1, col2]; [v1, v2] [v3, v4]] | format pattern '{col2}'", + result: Some(Value::list( + vec![Value::test_string("v2"), Value::test_string("v4")], + Span::test_data(), + )), + }, + ] + } +} + +// NOTE: The reason to split {column1.column2} and {$it.column1.column2}: +// for {column1.column2}, we just need to follow given record or list. +// for {$it.column1.column2} or {$variable}, we need to manually evaluate the expression. +// +// Have thought about converting from {column1.column2} to {$it.column1.column2}, but that +// will extend input relative span, finally make `nu` panic out with message: span missing in file +// contents cache. +#[derive(Debug)] +enum FormatOperation { + FixedText(String), + // raw input is something like {column1.column2} + ValueFromColumn(String, Span), +} + +/// Given a pattern that is fed into the Format command, we can process it and subdivide it +/// in two kind of operations. +/// FormatOperation::FixedText contains a portion of the pattern that has to be placed +/// there without any further processing. +/// FormatOperation::ValueFromColumn contains the name of a column whose values will be +/// formatted according to the input pattern. +/// "$it.column1.column2" or "$variable" +fn extract_formatting_operations( + input: String, + error_span: Span, + span_start: usize, +) -> Result, ShellError> { + let mut output = vec![]; + + let mut characters = input.char_indices(); + + let mut column_span_start = 0; + let mut column_span_end = 0; + loop { + let mut before_bracket = String::new(); + + for (index, ch) in &mut characters { + if ch == '{' { + column_span_start = index + 1; // not include '{' character. + break; + } + before_bracket.push(ch); + } + + if !before_bracket.is_empty() { + output.push(FormatOperation::FixedText(before_bracket.to_string())); + } + + let mut column_name = String::new(); + let mut column_need_eval = false; + for (index, ch) in &mut characters { + if ch == '$' { + column_need_eval = true; + } + + if ch == '}' { + column_span_end = index; // not include '}' character. + break; + } + column_name.push(ch); + } + + if column_span_end < column_span_start { + return Err(ShellError::DelimiterError { + msg: "there are unmatched curly braces".to_string(), + span: error_span, + }); + } + + if !column_name.is_empty() { + if column_need_eval { + return Err(ShellError::GenericError { + error: "Removed functionality".into(), + msg: "The ability to use variables ($it) in `format pattern` has been removed." + .into(), + span: Some(error_span), + help: Some( + "You can use other formatting options, such as string interpolation." + .into(), + ), + inner: vec![], + }); + } else { + output.push(FormatOperation::ValueFromColumn( + column_name.clone(), + Span::new(span_start + column_span_start, span_start + column_span_end), + )); + } + } + + if before_bracket.is_empty() && column_name.is_empty() { + break; + } + } + Ok(output) +} + +/// Format the incoming PipelineData according to the pattern +fn format( + input_data: Value, + format_operations: &[FormatOperation], + engine_state: &EngineState, + config: &Config, + head_span: Span, +) -> Result { + let data_as_value = input_data; + + // We can only handle a Record or a List of Records + match data_as_value { + Value::Record { .. } => match format_record(format_operations, &data_as_value, config) { + Ok(value) => Ok(PipelineData::Value(Value::string(value, head_span), None)), + Err(value) => Err(value), + }, + + Value::List { vals, .. } => { + let mut list = vec![]; + for val in vals.iter() { + match val { + Value::Record { .. } => match format_record(format_operations, val, config) { + Ok(value) => { + list.push(Value::string(value, head_span)); + } + Err(value) => { + return Err(value); + } + }, + Value::Error { error, .. } => return Err(*error.clone()), + _ => { + return Err(ShellError::OnlySupportsThisInputType { + exp_input_type: "record".to_string(), + wrong_type: val.get_type().to_string(), + dst_span: head_span, + src_span: val.span(), + }); + } + } + } + + Ok(ListStream::new(list.into_iter(), head_span, engine_state.signals().clone()).into()) + } + // Unwrapping this ShellError is a bit unfortunate. + // Ideally, its Span would be preserved. + Value::Error { error, .. } => Err(*error), + _ => Err(ShellError::OnlySupportsThisInputType { + exp_input_type: "record".to_string(), + wrong_type: data_as_value.get_type().to_string(), + dst_span: head_span, + src_span: data_as_value.span(), + }), + } +} + +fn format_record( + format_operations: &[FormatOperation], + data_as_value: &Value, + config: &Config, +) -> Result { + let mut output = String::new(); + + for op in format_operations { + match op { + FormatOperation::FixedText(s) => output.push_str(s.as_str()), + FormatOperation::ValueFromColumn(col_name, span) => { + // path member should split by '.' to handle for nested structure. + let path_members: Vec = col_name + .split('.') + .map(|path| PathMember::String { + val: path.to_string(), + span: *span, + optional: false, + casing: Casing::Sensitive, + }) + .collect(); + + let expanded_string = data_as_value + .follow_cell_path(&path_members)? + .to_expanded_string(", ", config); + output.push_str(expanded_string.as_str()) + } + } + } + Ok(output) +} + +#[cfg(test)] +mod test { + #[test] + fn test_examples() { + use super::FormatPattern; + use crate::test_examples; + test_examples(FormatPattern {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/strings/format/mod.rs b/nushell/crates/nu-cmd-extra/src/extra/strings/format/mod.rs new file mode 100644 index 0000000..f032474 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/strings/format/mod.rs @@ -0,0 +1,7 @@ +mod bits; +mod command; +mod number; + +pub(crate) use bits::FormatBits; +pub(crate) use command::FormatPattern; +pub(crate) use number::FormatNumber; diff --git a/nushell/crates/nu-cmd-extra/src/extra/strings/format/number.rs b/nushell/crates/nu-cmd-extra/src/extra/strings/format/number.rs new file mode 100644 index 0000000..7af6a6e --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/strings/format/number.rs @@ -0,0 +1,204 @@ +use nu_cmd_base::input_handler::{CellPathOnlyArgs, operate}; +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct FormatNumber; + +impl Command for FormatNumber { + fn name(&self) -> &str { + "format number" + } + + fn description(&self) -> &str { + "Format a number." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("format number") + .input_output_types(vec![(Type::Number, Type::record())]) + .switch( + "no-prefix", + "don't include the binary, hex or octal prefixes", + Some('n'), + ) + .category(Category::Conversions) + } + + fn search_terms(&self) -> Vec<&str> { + vec!["display", "render", "fmt"] + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Get a record containing multiple formats for the number 42", + example: "42 | format number", + result: Some(Value::test_record(record! { + "debug" => Value::test_string("42"), + "display" => Value::test_string("42"), + "binary" => Value::test_string("0b101010"), + "lowerexp" => Value::test_string("4.2e1"), + "upperexp" => Value::test_string("4.2E1"), + "lowerhex" => Value::test_string("0x2a"), + "upperhex" => Value::test_string("0x2A"), + "octal" => Value::test_string("0o52"), + })), + }, + Example { + description: "Format float without prefixes", + example: "3.14 | format number --no-prefix", + result: Some(Value::test_record(record! { + "debug" => Value::test_string("3.14"), + "display" => Value::test_string("3.14"), + "binary" => Value::test_string("100000000001001000111101011100001010001111010111000010100011111"), + "lowerexp" => Value::test_string("3.14e0"), + "upperexp" => Value::test_string("3.14E0"), + "lowerhex" => Value::test_string("40091eb851eb851f"), + "upperhex" => Value::test_string("40091EB851EB851F"), + "octal" => Value::test_string("400110753412172702437"), + })), + }, + ] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + format_number(engine_state, stack, call, input) + } +} + +pub(crate) fn format_number( + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, +) -> Result { + let cell_paths: Vec = call.rest(engine_state, stack, 0)?; + let args = CellPathOnlyArgs::from(cell_paths); + if call.has_flag(engine_state, stack, "no-prefix")? { + operate( + action_no_prefix, + args, + input, + call.head, + engine_state.signals(), + ) + } else { + operate(action, args, input, call.head, engine_state.signals()) + } +} + +fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value { + match input { + Value::Float { val, .. } => format_f64(*val, false, span), + Value::Int { val, .. } => format_i64(*val, false, span), + Value::Filesize { val, .. } => format_i64(val.get(), false, span), + // Propagate errors by explicitly matching them before the final case. + Value::Error { .. } => input.clone(), + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "float, int, or filesize".into(), + wrong_type: other.get_type().to_string(), + dst_span: span, + src_span: other.span(), + }, + span, + ), + } +} + +fn action_no_prefix(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value { + match input { + Value::Float { val, .. } => format_f64(*val, true, span), + Value::Int { val, .. } => format_i64(*val, true, span), + Value::Filesize { val, .. } => format_i64(val.get(), true, span), + // Propagate errors by explicitly matching them before the final case. + Value::Error { .. } => input.clone(), + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "float, int, or filesize".into(), + wrong_type: other.get_type().to_string(), + dst_span: span, + src_span: other.span(), + }, + span, + ), + } +} + +fn format_i64(num: i64, no_prefix: bool, span: Span) -> Value { + Value::record( + record! { + "debug" => Value::string(format!("{num:#?}"), span), + "display" => Value::string(format!("{num}"), span), + "binary" => Value::string( + if no_prefix { format!("{num:b}") } else { format!("{num:#b}") }, + span, + ), + "lowerexp" => Value::string(format!("{num:#e}"), span), + "upperexp" => Value::string(format!("{num:#E}"), span), + "lowerhex" => Value::string( + if no_prefix { format!("{num:x}") } else { format!("{num:#x}") }, + span, + ), + "upperhex" => Value::string( + if no_prefix { format!("{num:X}") } else { format!("{num:#X}") }, + span, + ), + "octal" => Value::string( + if no_prefix { format!("{num:o}") } else { format!("{num:#o}") }, + span, + ) + }, + span, + ) +} + +fn format_f64(num: f64, no_prefix: bool, span: Span) -> Value { + Value::record( + record! { + "debug" => Value::string(format!("{num:#?}"), span), + "display" => Value::string(format!("{num}"), span), + "binary" => Value::string( + if no_prefix { + format!("{:b}", num.to_bits()) + } else { + format!("{:#b}", num.to_bits()) + }, + span, + ), + "lowerexp" => Value::string(format!("{num:#e}"), span), + "upperexp" => Value::string(format!("{num:#E}"), span), + "lowerhex" => Value::string( + if no_prefix { format!("{:x}", num.to_bits()) } else { format!("{:#x}", num.to_bits()) }, + span, + ), + "upperhex" => Value::string( + if no_prefix { format!("{:X}", num.to_bits()) } else { format!("{:#X}", num.to_bits()) }, + span, + ), + "octal" => Value::string( + if no_prefix { format!("{:o}", num.to_bits()) } else { format!("{:#o}", num.to_bits()) }, + span, + ) + }, + span, + ) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(FormatNumber {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/strings/mod.rs b/nushell/crates/nu-cmd-extra/src/extra/strings/mod.rs new file mode 100644 index 0000000..8d43cd8 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/strings/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod format; +pub(crate) mod str_; diff --git a/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/camel_case.rs b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/camel_case.rs new file mode 100644 index 0000000..a2809bd --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/camel_case.rs @@ -0,0 +1,96 @@ +use super::operate; +use heck::ToLowerCamelCase; +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct StrCamelCase; + +impl Command for StrCamelCase { + fn name(&self) -> &str { + "str camel-case" + } + + fn signature(&self) -> Signature { + Signature::build("str camel-case") + .input_output_types(vec![ + (Type::String, Type::String), + ( + Type::List(Box::new(Type::String)), + Type::List(Box::new(Type::String)), + ), + (Type::table(), Type::table()), + (Type::record(), Type::record()), + ]) + .allow_variants_without_examples(true) + .rest( + "rest", + SyntaxShape::CellPath, + "For a data structure input, convert strings at the given cell paths.", + ) + .category(Category::Strings) + } + + fn description(&self) -> &str { + "Convert a string to camelCase." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["convert", "style", "caps", "convention"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + operate( + engine_state, + stack, + call, + input, + &ToLowerCamelCase::to_lower_camel_case, + ) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "convert a string to camelCase", + example: " 'NuShell' | str camel-case", + result: Some(Value::test_string("nuShell")), + }, + Example { + description: "convert a string to camelCase", + example: "'this-is-the-first-case' | str camel-case", + result: Some(Value::test_string("thisIsTheFirstCase")), + }, + Example { + description: "convert a string to camelCase", + example: " 'this_is_the_second_case' | str camel-case", + result: Some(Value::test_string("thisIsTheSecondCase")), + }, + Example { + description: "convert a column from a table to camelCase", + example: r#"[[lang, gems]; [nu_test, 100]] | str camel-case lang"#, + result: Some(Value::test_list(vec![Value::test_record(record! { + "lang" => Value::test_string("nuTest"), + "gems" => Value::test_int(100), + })])), + }, + ] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(StrCamelCase {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/kebab_case.rs b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/kebab_case.rs new file mode 100644 index 0000000..61ba7d8 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/kebab_case.rs @@ -0,0 +1,95 @@ +use super::operate; +use heck::ToKebabCase; +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct StrKebabCase; + +impl Command for StrKebabCase { + fn name(&self) -> &str { + "str kebab-case" + } + + fn signature(&self) -> Signature { + Signature::build("str kebab-case") + .input_output_types(vec![ + (Type::String, Type::String), + (Type::table(), Type::table()), + (Type::record(), Type::record()), + ( + Type::List(Box::new(Type::String)), + Type::List(Box::new(Type::String)), + ), + ]) + .allow_variants_without_examples(true) + .rest( + "rest", + SyntaxShape::CellPath, + "For a data structure input, convert strings at the given cell paths.", + ) + .category(Category::Strings) + } + + fn description(&self) -> &str { + "Convert a string to kebab-case." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["convert", "style", "hyphens", "convention"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + operate( + engine_state, + stack, + call, + input, + &ToKebabCase::to_kebab_case, + ) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "convert a string to kebab-case", + example: "'NuShell' | str kebab-case", + result: Some(Value::test_string("nu-shell")), + }, + Example { + description: "convert a string to kebab-case", + example: "'thisIsTheFirstCase' | str kebab-case", + result: Some(Value::test_string("this-is-the-first-case")), + }, + Example { + description: "convert a string to kebab-case", + example: "'THIS_IS_THE_SECOND_CASE' | str kebab-case", + result: Some(Value::test_string("this-is-the-second-case")), + }, + Example { + description: "convert a column from a table to kebab-case", + example: r#"[[lang, gems]; [nuTest, 100]] | str kebab-case lang"#, + result: Some(Value::test_list(vec![Value::test_record(record! { + "lang" => Value::test_string("nu-test"), + "gems" => Value::test_int(100), + })])), + }, + ] + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(StrKebabCase {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/mod.rs b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/mod.rs new file mode 100644 index 0000000..d782856 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/mod.rs @@ -0,0 +1,68 @@ +mod camel_case; +mod kebab_case; +mod pascal_case; +mod screaming_snake_case; +mod snake_case; +mod str_; +mod title_case; + +pub use camel_case::StrCamelCase; +pub use kebab_case::StrKebabCase; +pub use pascal_case::StrPascalCase; +pub use screaming_snake_case::StrScreamingSnakeCase; +pub use snake_case::StrSnakeCase; +pub use str_::Str; +pub use title_case::StrTitleCase; + +use nu_cmd_base::input_handler::{CmdArgument, operate as general_operate}; +use nu_engine::command_prelude::*; + +struct Arguments String + Send + Sync + 'static> { + case_operation: &'static F, + cell_paths: Option>, +} + +impl String + Send + Sync + 'static> CmdArgument for Arguments { + fn take_cell_paths(&mut self) -> Option> { + self.cell_paths.take() + } +} + +pub fn operate( + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + case_operation: &'static F, +) -> Result +where + F: Fn(&str) -> String + Send + Sync + 'static, +{ + let cell_paths: Vec = call.rest(engine_state, stack, 0)?; + let cell_paths = (!cell_paths.is_empty()).then_some(cell_paths); + let args = Arguments { + case_operation, + cell_paths, + }; + general_operate(action, args, input, call.head, engine_state.signals()) +} + +fn action(input: &Value, args: &Arguments, head: Span) -> Value +where + F: Fn(&str) -> String + Send + Sync + 'static, +{ + let case_operation = args.case_operation; + match input { + Value::String { val, .. } => Value::string(case_operation(val), head), + Value::Error { .. } => input.clone(), + _ => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "string".into(), + wrong_type: input.get_type().to_string(), + dst_span: head, + src_span: input.span(), + }, + head, + ), + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/pascal_case.rs b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/pascal_case.rs new file mode 100644 index 0000000..ff15cee --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/pascal_case.rs @@ -0,0 +1,96 @@ +use super::operate; +use heck::ToUpperCamelCase; +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct StrPascalCase; + +impl Command for StrPascalCase { + fn name(&self) -> &str { + "str pascal-case" + } + + fn signature(&self) -> Signature { + Signature::build("str pascal-case") + .input_output_types(vec![ + (Type::String, Type::String), + (Type::table(), Type::table()), + (Type::record(), Type::record()), + ( + Type::List(Box::new(Type::String)), + Type::List(Box::new(Type::String)), + ), + ]) + .allow_variants_without_examples(true) + .rest( + "rest", + SyntaxShape::CellPath, + "For a data structure input, convert strings at the given cell paths.", + ) + .category(Category::Strings) + } + + fn description(&self) -> &str { + "Convert a string to PascalCase." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["convert", "style", "caps", "upper", "convention"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + operate( + engine_state, + stack, + call, + input, + &ToUpperCamelCase::to_upper_camel_case, + ) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "convert a string to PascalCase", + example: "'nu-shell' | str pascal-case", + result: Some(Value::test_string("NuShell")), + }, + Example { + description: "convert a string to PascalCase", + example: "'this-is-the-first-case' | str pascal-case", + result: Some(Value::test_string("ThisIsTheFirstCase")), + }, + Example { + description: "convert a string to PascalCase", + example: "'this_is_the_second_case' | str pascal-case", + result: Some(Value::test_string("ThisIsTheSecondCase")), + }, + Example { + description: "convert a column from a table to PascalCase", + example: r#"[[lang, gems]; [nu_test, 100]] | str pascal-case lang"#, + result: Some(Value::test_list(vec![Value::test_record(record! { + "lang" => Value::test_string("NuTest"), + "gems" => Value::test_int(100), + })])), + }, + ] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(StrPascalCase {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/screaming_snake_case.rs b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/screaming_snake_case.rs new file mode 100644 index 0000000..ef55254 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/screaming_snake_case.rs @@ -0,0 +1,96 @@ +use super::operate; +use heck::ToShoutySnakeCase; +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct StrScreamingSnakeCase; + +impl Command for StrScreamingSnakeCase { + fn name(&self) -> &str { + "str screaming-snake-case" + } + + fn signature(&self) -> Signature { + Signature::build("str screaming-snake-case") + .input_output_types(vec![ + (Type::String, Type::String), + ( + Type::List(Box::new(Type::String)), + Type::List(Box::new(Type::String)), + ), + (Type::table(), Type::table()), + (Type::record(), Type::record()), + ]) + .allow_variants_without_examples(true) + .rest( + "rest", + SyntaxShape::CellPath, + "For a data structure input, convert strings at the given cell paths.", + ) + .category(Category::Strings) + } + + fn description(&self) -> &str { + "Convert a string to SCREAMING_SNAKE_CASE." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["convert", "style", "underscore", "convention"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + operate( + engine_state, + stack, + call, + input, + &ToShoutySnakeCase::to_shouty_snake_case, + ) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "convert a string to SCREAMING_SNAKE_CASE", + example: r#" "NuShell" | str screaming-snake-case"#, + result: Some(Value::test_string("NU_SHELL")), + }, + Example { + description: "convert a string to SCREAMING_SNAKE_CASE", + example: r#" "this_is_the_second_case" | str screaming-snake-case"#, + result: Some(Value::test_string("THIS_IS_THE_SECOND_CASE")), + }, + Example { + description: "convert a string to SCREAMING_SNAKE_CASE", + example: r#""this-is-the-first-case" | str screaming-snake-case"#, + result: Some(Value::test_string("THIS_IS_THE_FIRST_CASE")), + }, + Example { + description: "convert a column from a table to SCREAMING_SNAKE_CASE", + example: r#"[[lang, gems]; [nu_test, 100]] | str screaming-snake-case lang"#, + result: Some(Value::test_list(vec![Value::test_record(record! { + "lang" => Value::test_string("NU_TEST"), + "gems" => Value::test_int(100), + })])), + }, + ] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(StrScreamingSnakeCase {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/snake_case.rs b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/snake_case.rs new file mode 100644 index 0000000..a3913eb --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/snake_case.rs @@ -0,0 +1,96 @@ +use super::operate; +use heck::ToSnakeCase; +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct StrSnakeCase; + +impl Command for StrSnakeCase { + fn name(&self) -> &str { + "str snake-case" + } + + fn signature(&self) -> Signature { + Signature::build("str snake-case") + .input_output_types(vec![ + (Type::String, Type::String), + ( + Type::List(Box::new(Type::String)), + Type::List(Box::new(Type::String)), + ), + (Type::table(), Type::table()), + (Type::record(), Type::record()), + ]) + .allow_variants_without_examples(true) + .rest( + "rest", + SyntaxShape::CellPath, + "For a data structure input, convert strings at the given cell paths.", + ) + .category(Category::Strings) + } + + fn description(&self) -> &str { + "Convert a string to snake_case." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["convert", "style", "underscore", "lower", "convention"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + operate( + engine_state, + stack, + call, + input, + &ToSnakeCase::to_snake_case, + ) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "convert a string to snake_case", + example: r#" "NuShell" | str snake-case"#, + result: Some(Value::test_string("nu_shell")), + }, + Example { + description: "convert a string to snake_case", + example: r#" "this_is_the_second_case" | str snake-case"#, + result: Some(Value::test_string("this_is_the_second_case")), + }, + Example { + description: "convert a string to snake_case", + example: r#""this-is-the-first-case" | str snake-case"#, + result: Some(Value::test_string("this_is_the_first_case")), + }, + Example { + description: "convert a column from a table to snake_case", + example: r#"[[lang, gems]; [nuTest, 100]] | str snake-case lang"#, + result: Some(Value::test_list(vec![Value::test_record(record! { + "lang" => Value::test_string("nu_test"), + "gems" => Value::test_int(100), + })])), + }, + ] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(StrSnakeCase {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/str_.rs b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/str_.rs new file mode 100644 index 0000000..4ee04ec --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/str_.rs @@ -0,0 +1,34 @@ +use nu_engine::{command_prelude::*, get_full_help}; + +#[derive(Clone)] +pub struct Str; + +impl Command for Str { + fn name(&self) -> &str { + "str" + } + + fn signature(&self) -> Signature { + Signature::build("str") + .category(Category::Strings) + .input_output_types(vec![(Type::Nothing, Type::String)]) + } + + fn description(&self) -> &str { + "Various commands for working with string data." + } + + fn extra_description(&self) -> &str { + "You must use one of the following subcommands. Using this command as-is will only produce this help message." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + Ok(Value::string(get_full_help(self, engine_state, stack), call.head).into_pipeline_data()) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/title_case.rs b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/title_case.rs new file mode 100644 index 0000000..7f83059 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/case/title_case.rs @@ -0,0 +1,91 @@ +use super::operate; +use heck::ToTitleCase; +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct StrTitleCase; + +impl Command for StrTitleCase { + fn name(&self) -> &str { + "str title-case" + } + + fn signature(&self) -> Signature { + Signature::build("str title-case") + .input_output_types(vec![ + (Type::String, Type::String), + ( + Type::List(Box::new(Type::String)), + Type::List(Box::new(Type::String)), + ), + (Type::table(), Type::table()), + (Type::record(), Type::record()), + ]) + .allow_variants_without_examples(true) + .rest( + "rest", + SyntaxShape::CellPath, + "For a data structure input, convert strings at the given cell paths.", + ) + .category(Category::Strings) + } + + fn description(&self) -> &str { + "Convert a string to Title Case." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["convert", "style", "convention"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + operate( + engine_state, + stack, + call, + input, + &ToTitleCase::to_title_case, + ) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "convert a string to Title Case", + example: "'nu-shell' | str title-case", + result: Some(Value::test_string("Nu Shell")), + }, + Example { + description: "convert a string to Title Case", + example: "'this is a test case' | str title-case", + result: Some(Value::test_string("This Is A Test Case")), + }, + Example { + description: "convert a column from a table to Title Case", + example: r#"[[title, count]; ['nu test', 100]] | str title-case title"#, + result: Some(Value::test_list(vec![Value::test_record(record! { + "title" => Value::test_string("Nu Test"), + "count" => Value::test_int(100), + })])), + }, + ] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(StrTitleCase {}) + } +} diff --git a/nushell/crates/nu-cmd-extra/src/extra/strings/str_/mod.rs b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/mod.rs new file mode 100644 index 0000000..481b440 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/extra/strings/str_/mod.rs @@ -0,0 +1 @@ +pub(crate) mod case; diff --git a/nushell/crates/nu-cmd-extra/src/lib.rs b/nushell/crates/nu-cmd-extra/src/lib.rs new file mode 100644 index 0000000..f6f97c2 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/src/lib.rs @@ -0,0 +1,7 @@ +#![doc = include_str!("../README.md")] +mod example_test; +pub mod extra; +pub use extra::*; + +#[cfg(test)] +pub use example_test::test_examples; diff --git a/nushell/crates/nu-cmd-extra/tests/commands/bits/format.rs b/nushell/crates/nu-cmd-extra/tests/commands/bits/format.rs new file mode 100644 index 0000000..a06b6d8 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/tests/commands/bits/format.rs @@ -0,0 +1,13 @@ +use nu_test_support::nu; + +#[test] +fn byte_stream_into_bits() { + let result = nu!("[0x[01] 0x[02 03]] | bytes collect | format bits"); + assert_eq!("00000001 00000010 00000011", result.out); +} + +#[test] +fn byte_stream_into_bits_is_stream() { + let result = nu!("[0x[01] 0x[02 03]] | bytes collect | format bits | describe"); + assert_eq!("string (stream)", result.out); +} diff --git a/nushell/crates/nu-cmd-extra/tests/commands/bits/mod.rs b/nushell/crates/nu-cmd-extra/tests/commands/bits/mod.rs new file mode 100644 index 0000000..8631268 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/tests/commands/bits/mod.rs @@ -0,0 +1 @@ +mod format; diff --git a/nushell/crates/nu-cmd-extra/tests/commands/bytes/ends_with.rs b/nushell/crates/nu-cmd-extra/tests/commands/bytes/ends_with.rs new file mode 100644 index 0000000..b90f936 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/tests/commands/bytes/ends_with.rs @@ -0,0 +1,120 @@ +use nu_test_support::nu; + +#[test] +fn basic_binary_end_with() { + let actual = nu!(r#" + "hello world" | into binary | bytes ends-with 0x[77 6f 72 6c 64] + "#); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn basic_string_fails() { + let actual = nu!(r#" + "hello world" | bytes ends-with 0x[77 6f 72 6c 64] + "#); + + assert!(actual.err.contains("command doesn't support")); + assert_eq!(actual.out, ""); +} + +#[test] +fn short_stream_binary() { + let actual = nu!(r#" + nu --testbin repeater (0x[01]) 5 | bytes ends-with 0x[010101] + "#); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn short_stream_mismatch() { + let actual = nu!(r#" + nu --testbin repeater (0x[010203]) 5 | bytes ends-with 0x[010204] + "#); + + assert_eq!(actual.out, "false"); +} + +#[test] +fn short_stream_binary_overflow() { + let actual = nu!(r#" + nu --testbin repeater (0x[01]) 5 | bytes ends-with 0x[010101010101] + "#); + + assert_eq!(actual.out, "false"); +} + +#[test] +fn long_stream_binary() { + let actual = nu!(r#" + nu --testbin repeater (0x[01]) 32768 | bytes ends-with 0x[010101] + "#); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn long_stream_binary_overflow() { + // .. ranges are inclusive..inclusive, so we don't need to +1 to check for an overflow + let actual = nu!(r#" + nu --testbin repeater (0x[01]) 32768 | bytes ends-with (0..32768 | each {|| 0x[01] } | bytes collect) + "#); + + assert_eq!(actual.out, "false"); +} + +#[test] +fn long_stream_binary_exact() { + // ranges are inclusive..inclusive, so we don't need to +1 to check for an overflow + let actual = nu!(r#" + nu --testbin repeater (0x[01020304]) 8192 | bytes ends-with (0..<8192 | each {|| 0x[01020304] } | bytes collect) + "#); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn long_stream_string_exact() { + // ranges are inclusive..inclusive, so we don't need to +1 to check for an overflow + let actual = nu!(r#" + nu --testbin repeater hell 8192 | bytes ends-with (0..<8192 | each {|| "hell" | into binary } | bytes collect) + "#); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn long_stream_mixed_exact() { + // ranges are inclusive..inclusive, so we don't need to +1 to check for an overflow + let actual = nu!(r#" + let binseg = (0..<2048 | each {|| 0x[003d9fbf] } | bytes collect) + let strseg = (0..<2048 | each {|| "hell" | into binary } | bytes collect) + + nu --testbin repeat_bytes 003d9fbf 2048 68656c6c 2048 | bytes ends-with (bytes build $binseg $strseg) + "#); + + assert_eq!( + actual.err, "", + "invocation failed. command line limit likely reached" + ); + assert_eq!(actual.out, "true"); +} + +#[test] +fn long_stream_mixed_overflow() { + // ranges are inclusive..inclusive, so we don't need to +1 to check for an overflow + let actual = nu!(r#" + let binseg = (0..<2048 | each {|| 0x[003d9fbf] } | bytes collect) + let strseg = (0..<2048 | each {|| "hell" | into binary } | bytes collect) + + nu --testbin repeat_bytes 003d9fbf 2048 68656c6c 2048 | bytes ends-with (bytes build 0x[01] $binseg $strseg) + "#); + + assert_eq!( + actual.err, "", + "invocation failed. command line limit likely reached" + ); + assert_eq!(actual.out, "false"); +} diff --git a/nushell/crates/nu-cmd-extra/tests/commands/bytes/mod.rs b/nushell/crates/nu-cmd-extra/tests/commands/bytes/mod.rs new file mode 100644 index 0000000..a8a241e --- /dev/null +++ b/nushell/crates/nu-cmd-extra/tests/commands/bytes/mod.rs @@ -0,0 +1,2 @@ +mod ends_with; +mod starts_with; diff --git a/nushell/crates/nu-cmd-extra/tests/commands/bytes/starts_with.rs b/nushell/crates/nu-cmd-extra/tests/commands/bytes/starts_with.rs new file mode 100644 index 0000000..e7d5769 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/tests/commands/bytes/starts_with.rs @@ -0,0 +1,120 @@ +use nu_test_support::nu; + +#[test] +fn basic_binary_starts_with() { + let actual = nu!(r#" + "hello world" | into binary | bytes starts-with 0x[68 65 6c 6c 6f] + "#); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn basic_string_fails() { + let actual = nu!(r#" + "hello world" | bytes starts-with 0x[68 65 6c 6c 6f] + "#); + + assert!(actual.err.contains("command doesn't support")); + assert_eq!(actual.out, ""); +} + +#[test] +fn short_stream_binary() { + let actual = nu!(r#" + nu --testbin repeater (0x[01]) 5 | bytes starts-with 0x[010101] + "#); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn short_stream_mismatch() { + let actual = nu!(r#" + nu --testbin repeater (0x[010203]) 5 | bytes starts-with 0x[010204] + "#); + + assert_eq!(actual.out, "false"); +} + +#[test] +fn short_stream_binary_overflow() { + let actual = nu!(r#" + nu --testbin repeater (0x[01]) 5 | bytes starts-with 0x[010101010101] + "#); + + assert_eq!(actual.out, "false"); +} + +#[test] +fn long_stream_binary() { + let actual = nu!(r#" + nu --testbin repeater (0x[01]) 32768 | bytes starts-with 0x[010101] + "#); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn long_stream_binary_overflow() { + // .. ranges are inclusive..inclusive, so we don't need to +1 to check for an overflow + let actual = nu!(r#" + nu --testbin repeater (0x[01]) 32768 | bytes starts-with (0..32768 | each {|| 0x[01] } | bytes collect) + "#); + + assert_eq!(actual.out, "false"); +} + +#[test] +fn long_stream_binary_exact() { + // ranges are inclusive..inclusive, so we don't need to +1 to check for an overflow + let actual = nu!(r#" + nu --testbin repeater (0x[01020304]) 8192 | bytes starts-with (0..<8192 | each {|| 0x[01020304] } | bytes collect) + "#); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn long_stream_string_exact() { + // ranges are inclusive..inclusive, so we don't need to +1 to check for an overflow + let actual = nu!(r#" + nu --testbin repeater hell 8192 | bytes starts-with (0..<8192 | each {|| "hell" | into binary } | bytes collect) + "#); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn long_stream_mixed_exact() { + // ranges are inclusive..inclusive, so we don't need to +1 to check for an overflow + let actual = nu!(r#" + let binseg = (0..<2048 | each {|| 0x[003d9fbf] } | bytes collect) + let strseg = (0..<2048 | each {|| "hell" | into binary } | bytes collect) + + nu --testbin repeat_bytes 003d9fbf 2048 68656c6c 2048 | bytes starts-with (bytes build $binseg $strseg) + "#); + + assert_eq!( + actual.err, "", + "invocation failed. command line limit likely reached" + ); + assert_eq!(actual.out, "true"); +} + +#[test] +fn long_stream_mixed_overflow() { + // ranges are inclusive..inclusive, so we don't need to +1 to check for an overflow + let actual = nu!(r#" + let binseg = (0..<2048 | each {|| 0x[003d9fbf] } | bytes collect) + let strseg = (0..<2048 | each {|| "hell" | into binary } | bytes collect) + + nu --testbin repeat_bytes 003d9fbf 2048 68656c6c 2048 | bytes starts-with (bytes build $binseg $strseg 0x[01]) + "#); + + assert_eq!( + actual.err, "", + "invocation failed. command line limit likely reached" + ); + assert_eq!(actual.out, "false"); +} diff --git a/nushell/crates/nu-cmd-extra/tests/commands/mod.rs b/nushell/crates/nu-cmd-extra/tests/commands/mod.rs new file mode 100644 index 0000000..fd216ce --- /dev/null +++ b/nushell/crates/nu-cmd-extra/tests/commands/mod.rs @@ -0,0 +1,2 @@ +mod bits; +mod bytes; diff --git a/nushell/crates/nu-cmd-extra/tests/main.rs b/nushell/crates/nu-cmd-extra/tests/main.rs new file mode 100644 index 0000000..f3d4468 --- /dev/null +++ b/nushell/crates/nu-cmd-extra/tests/main.rs @@ -0,0 +1 @@ +mod commands; diff --git a/nushell/crates/nu-cmd-lang/Cargo.toml b/nushell/crates/nu-cmd-lang/Cargo.toml new file mode 100644 index 0000000..0f371cc --- /dev/null +++ b/nushell/crates/nu-cmd-lang/Cargo.toml @@ -0,0 +1,45 @@ +[package] +authors = ["The Nushell Project Developers"] +build = "build.rs" +description = "Nushell's core language commands" +repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-lang" +edition = "2024" +license = "MIT" +name = "nu-cmd-lang" +version = "0.105.2" + +[lib] +bench = false + +[lints] +workspace = true + +[dependencies] +nu-engine = { path = "../nu-engine", version = "0.105.2", default-features = false } +nu-parser = { path = "../nu-parser", version = "0.105.2" } +nu-protocol = { path = "../nu-protocol", version = "0.105.2", default-features = false } +nu-utils = { path = "../nu-utils", version = "0.105.2", default-features = false } +nu-cmd-base = { path = "../nu-cmd-base", version = "0.105.2" } + +itertools = { workspace = true } +shadow-rs = { version = "1.2", default-features = false } + +[build-dependencies] +shadow-rs = { version = "1.2", default-features = false, features = ["build"] } + +[dev-dependencies] +quickcheck = { workspace = true } +quickcheck_macros = { workspace = true } +miette = { workspace = true } + +[features] +default = ["os"] +os = [ + "nu-engine/os", + "nu-protocol/os", + "nu-utils/os", +] +plugin = [ + "nu-protocol/plugin", + "os", +] diff --git a/nushell/crates/nu-cmd-lang/LICENSE b/nushell/crates/nu-cmd-lang/LICENSE new file mode 100644 index 0000000..ae174e8 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 - 2023 The Nushell Project Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/nushell/crates/nu-cmd-lang/README.md b/nushell/crates/nu-cmd-lang/README.md new file mode 100644 index 0000000..3ebfd93 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/README.md @@ -0,0 +1,21 @@ +# nu-cmd-lang + +## the base language and command crate of nu + +The commands in this crate are the *core commands* of the nu language. +It is also the base crate upon which all other command crates sit on +top of including: + +* nu-command +* nu-cli +* nu-cmd-extra + +As time goes on and the nu language develops further in parallel with nushell we will be adding other command crates to the system. + +### What does it mean to be a base crate ? + +A base crate is one with minimal dependencies in our system so that other developers can come along and use this crate without having a lot of baggage in terms of other crates which will bloat their underlying application. + +### Background on nu-cmd-lang + +This crate was designed to be a small, concise set of tools or commands that serve as the *foundation layer* of both nu and nushell. These are the core commands needed to have a nice working version of the *nu language* without all of the support that the other commands provide inside nushell. Prior to the launch of this crate all of our commands were housed in the crate *nu-command*. Moving forward we would like to *slowly* break out the commands in nu-command into different crates; the naming and how this will work and where all the commands will be located is a "work in progress" especially now that the *standard library* is starting to become more popular as a location for commands. As time goes on some of our commands written in rust will be migrated to nu and when this happens they will be moved into the *standard library*. diff --git a/nushell/crates/nu-cmd-lang/build.rs b/nushell/crates/nu-cmd-lang/build.rs new file mode 100644 index 0000000..8f2339b --- /dev/null +++ b/nushell/crates/nu-cmd-lang/build.rs @@ -0,0 +1,21 @@ +use std::process::Command; + +fn main() { + // Look up the current Git commit ourselves instead of relying on shadow_rs, + // because shadow_rs does it in a really slow-to-compile way (it builds libgit2) + let hash = get_git_hash().unwrap_or_default(); + println!("cargo:rustc-env=NU_COMMIT_HASH={hash}"); + shadow_rs::ShadowBuilder::builder() + .build() + .expect("shadow builder build should success"); +} + +fn get_git_hash() -> Option { + Command::new("git") + .args(["rev-parse", "HEAD"]) + .output() + .ok() + .filter(|output| output.status.success()) + .and_then(|output| String::from_utf8(output.stdout).ok()) + .map(|hash| hash.trim().to_string()) +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/alias.rs b/nushell/crates/nu-cmd-lang/src/core_commands/alias.rs new file mode 100644 index 0000000..07f41bb --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/alias.rs @@ -0,0 +1,58 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct Alias; + +impl Command for Alias { + fn name(&self) -> &str { + "alias" + } + + fn description(&self) -> &str { + "Alias a command (with optional flags) to a new name." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("alias") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .required("name", SyntaxShape::String, "Name of the alias.") + .required( + "initial_value", + SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::Expression)), + "Equals sign followed by value.", + ) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn search_terms(&self) -> Vec<&str> { + vec!["abbr", "aka", "fn", "func", "function"] + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Alias ll to ls -l", + example: "alias ll = ls -l", + result: Some(Value::nothing(Span::test_data())), + }] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/attr/category.rs b/nushell/crates/nu-cmd-lang/src/core_commands/attr/category.rs new file mode 100644 index 0000000..1633f43 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/attr/category.rs @@ -0,0 +1,61 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct AttrCategory; + +impl Command for AttrCategory { + fn name(&self) -> &str { + "attr category" + } + + fn signature(&self) -> Signature { + Signature::build("attr category") + .input_output_type(Type::Nothing, Type::list(Type::String)) + .allow_variants_without_examples(true) + .required( + "category", + SyntaxShape::String, + "Category of the custom command.", + ) + .category(Category::Core) + } + + fn description(&self) -> &str { + "Attribute for adding a category to custom commands." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let arg: String = call.req(engine_state, stack, 0)?; + Ok(Value::string(arg, call.head).into_pipeline_data()) + } + + fn run_const( + &self, + working_set: &StateWorkingSet, + call: &Call, + _input: PipelineData, + ) -> Result { + let arg: String = call.req_const(working_set, 0)?; + Ok(Value::string(arg, call.head).into_pipeline_data()) + } + + fn is_const(&self) -> bool { + true + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Add a category to a custom command", + example: r###"# Double numbers + @category math + def double []: [number -> number] { $in * 2 }"###, + result: None, + }] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/attr/deprecated.rs b/nushell/crates/nu-cmd-lang/src/core_commands/attr/deprecated.rs new file mode 100644 index 0000000..67a1298 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/attr/deprecated.rs @@ -0,0 +1,148 @@ +use nu_cmd_base::WrapCall; +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct AttrDeprecated; + +impl Command for AttrDeprecated { + fn name(&self) -> &str { + "attr deprecated" + } + + fn signature(&self) -> Signature { + Signature::build("attr deprecated") + .input_output_types(vec![ + (Type::Nothing, Type::Nothing), + (Type::Nothing, Type::String), + ]) + .optional( + "message", + SyntaxShape::String, + "Help message to include with deprecation warning.", + ) + .named( + "flag", + SyntaxShape::String, + "Mark a flag as deprecated rather than the command", + None, + ) + .named( + "since", + SyntaxShape::String, + "Denote a version when this item was deprecated", + Some('s'), + ) + .named( + "remove", + SyntaxShape::String, + "Denote a version when this item will be removed", + Some('r'), + ) + .named( + "report", + SyntaxShape::String, + "How to warn about this item. One of: first (default), every", + None, + ) + .category(Category::Core) + } + + fn description(&self) -> &str { + "Attribute for marking a command or flag as deprecated." + } + + fn extra_description(&self) -> &str { + "Mark a command (default) or flag/switch (--flag) as deprecated. By default, only the first usage will trigger a deprecation warning. + +A help message can be included to provide more context for the deprecation, such as what to use as a replacement. + +Also consider setting the category to deprecated with @category deprecated" + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let call = WrapCall::Eval(engine_state, stack, call); + Ok(deprecated_record(call)?.into_pipeline_data()) + } + + fn run_const( + &self, + working_set: &StateWorkingSet, + call: &Call, + _input: PipelineData, + ) -> Result { + let call = WrapCall::ConstEval(working_set, call); + Ok(deprecated_record(call)?.into_pipeline_data()) + } + + fn is_const(&self) -> bool { + true + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Add a deprecation warning to a custom command", + example: r###"@deprecated + def outdated [] {}"###, + result: Some(Value::nothing(Span::test_data())), + }, + Example { + description: "Add a deprecation warning with a custom message", + example: r###"@deprecated "Use my-new-command instead." + @category deprecated + def my-old-command [] {}"###, + result: Some(Value::string( + "Use my-new-command instead.", + Span::test_data(), + )), + }, + ] + } +} + +fn deprecated_record(call: WrapCall) -> Result { + let (call, message): (_, Option>) = call.opt(0)?; + let (call, flag): (_, Option>) = call.get_flag("flag")?; + let (call, since): (_, Option>) = call.get_flag("since")?; + let (call, remove): (_, Option>) = call.get_flag("remove")?; + let (call, report): (_, Option>) = call.get_flag("report")?; + + let mut record = Record::new(); + if let Some(message) = message { + record.push("help", Value::string(message.item, message.span)) + } + if let Some(flag) = flag { + record.push("flag", Value::string(flag.item, flag.span)) + } + if let Some(since) = since { + record.push("since", Value::string(since.item, since.span)) + } + if let Some(remove) = remove { + record.push("expected_removal", Value::string(remove.item, remove.span)) + } + + let report = if let Some(Spanned { item, span }) = report { + match item.as_str() { + "every" => Value::string(item, span), + "first" => Value::string(item, span), + _ => { + return Err(ShellError::IncorrectValue { + msg: "The report mode must be one of: every, first".into(), + val_span: span, + call_span: call.head(), + }); + } + } + } else { + Value::string("first", call.head()) + }; + record.push("report", report); + + Ok(Value::record(record, call.head())) +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/attr/example.rs b/nushell/crates/nu-cmd-lang/src/core_commands/attr/example.rs new file mode 100644 index 0000000..a12f83d --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/attr/example.rs @@ -0,0 +1,159 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct AttrExample; + +impl Command for AttrExample { + fn name(&self) -> &str { + "attr example" + } + + // TODO: When const closure are available, switch to using them for the `example` argument + // rather than a block. That should remove the need for `requires_ast_for_arguments` to be true + fn signature(&self) -> Signature { + Signature::build("attr example") + .input_output_types(vec![( + Type::Nothing, + Type::Record( + [ + ("description".into(), Type::String), + ("example".into(), Type::String), + ] + .into(), + ), + )]) + .allow_variants_without_examples(true) + .required( + "description", + SyntaxShape::String, + "Description of the example.", + ) + .required( + "example", + SyntaxShape::OneOf(vec![SyntaxShape::Block, SyntaxShape::String]), + "Example code snippet.", + ) + .named( + "result", + SyntaxShape::Any, + "Expected output of example.", + None, + ) + .category(Category::Core) + } + + fn description(&self) -> &str { + "Attribute for adding examples to custom commands." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let description: Spanned = call.req(engine_state, stack, 0)?; + let result: Option = call.get_flag(engine_state, stack, "result")?; + + let example_string: Result = call.req(engine_state, stack, 1); + let example_expr = call + .positional_nth(stack, 1) + .ok_or(ShellError::MissingParameter { + param_name: "example".into(), + span: call.head, + })?; + + let working_set = StateWorkingSet::new(engine_state); + + attr_example_impl( + example_expr, + example_string, + &working_set, + call, + description, + result, + ) + } + + fn run_const( + &self, + working_set: &StateWorkingSet, + call: &Call, + _input: PipelineData, + ) -> Result { + let description: Spanned = call.req_const(working_set, 0)?; + let result: Option = call.get_flag_const(working_set, "result")?; + + let example_string: Result = call.req_const(working_set, 1); + let example_expr = + call.assert_ast_call()? + .positional_nth(1) + .ok_or(ShellError::MissingParameter { + param_name: "example".into(), + span: call.head, + })?; + + attr_example_impl( + example_expr, + example_string, + working_set, + call, + description, + result, + ) + } + + fn is_const(&self) -> bool { + true + } + + fn requires_ast_for_arguments(&self) -> bool { + true + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Add examples to custom command", + example: r###"# Double numbers + @example "double an int" { 2 | double } --result 4 + @example "double a float" { 0.25 | double } --result 0.5 + def double []: [number -> number] { $in * 2 }"###, + result: None, + }] + } +} + +fn attr_example_impl( + example_expr: &nu_protocol::ast::Expression, + example_string: Result, + working_set: &StateWorkingSet<'_>, + call: &Call<'_>, + description: Spanned, + result: Option, +) -> Result { + let example_content = match example_expr.as_block() { + Some(block_id) => { + let block = working_set.get_block(block_id); + let contents = + working_set.get_span_contents(block.span.expect("a block must have a span")); + let contents = contents + .strip_prefix(b"{") + .and_then(|x| x.strip_suffix(b"}")) + .unwrap_or(contents) + .trim_ascii(); + String::from_utf8_lossy(contents).into_owned() + } + None => example_string?, + }; + + let mut rec = record! { + "description" => Value::string(description.item, description.span), + "example" => Value::string(example_content, example_expr.span), + }; + if let Some(result) = result { + rec.push("result", result); + } + + Ok(Value::record(rec, call.head).into_pipeline_data()) +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/attr/mod.rs b/nushell/crates/nu-cmd-lang/src/core_commands/attr/mod.rs new file mode 100644 index 0000000..8791bb4 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/attr/mod.rs @@ -0,0 +1,9 @@ +mod category; +mod deprecated; +mod example; +mod search_terms; + +pub use category::AttrCategory; +pub use deprecated::AttrDeprecated; +pub use example::AttrExample; +pub use search_terms::AttrSearchTerms; diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/attr/search_terms.rs b/nushell/crates/nu-cmd-lang/src/core_commands/attr/search_terms.rs new file mode 100644 index 0000000..767bbea --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/attr/search_terms.rs @@ -0,0 +1,57 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct AttrSearchTerms; + +impl Command for AttrSearchTerms { + fn name(&self) -> &str { + "attr search-terms" + } + + fn signature(&self) -> Signature { + Signature::build("attr search-terms") + .input_output_type(Type::Nothing, Type::list(Type::String)) + .allow_variants_without_examples(true) + .rest("terms", SyntaxShape::String, "Search terms.") + .category(Category::Core) + } + + fn description(&self) -> &str { + "Attribute for adding search terms to custom commands." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let args = call.rest(engine_state, stack, 0)?; + Ok(Value::list(args, call.head).into_pipeline_data()) + } + + fn run_const( + &self, + working_set: &StateWorkingSet, + call: &Call, + _input: PipelineData, + ) -> Result { + let args = call.rest_const(working_set, 0)?; + Ok(Value::list(args, call.head).into_pipeline_data()) + } + + fn is_const(&self) -> bool { + true + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Add search terms to a custom command", + example: r###"# Double numbers + @search-terms multiply times + def double []: [number -> number] { $in * 2 }"###, + result: None, + }] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/break_.rs b/nushell/crates/nu-cmd-lang/src/core_commands/break_.rs new file mode 100644 index 0000000..7fdf5a7 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/break_.rs @@ -0,0 +1,55 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct Break; + +impl Command for Break { + fn name(&self) -> &str { + "break" + } + + fn description(&self) -> &str { + "Break a loop." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("break") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html + + break can only be used in while, loop, and for loops. It can not be used with each or other filter commands"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + // This is compiled specially by the IR compiler. The code here is never used when + // running in IR mode. + eprintln!( + "Tried to execute 'run' for the 'break' command: this code path should never be reached in IR mode" + ); + unreachable!() + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Break out of a loop", + example: r#"loop { break }"#, + result: None, + }] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/collect.rs b/nushell/crates/nu-cmd-lang/src/core_commands/collect.rs new file mode 100644 index 0000000..654f165 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/collect.rs @@ -0,0 +1,129 @@ +use nu_engine::{command_prelude::*, get_eval_block, redirect_env}; +use nu_protocol::{DataSource, PipelineMetadata, engine::Closure}; + +#[derive(Clone)] +pub struct Collect; + +impl Command for Collect { + fn name(&self) -> &str { + "collect" + } + + fn signature(&self) -> Signature { + Signature::build("collect") + .input_output_types(vec![(Type::Any, Type::Any)]) + .optional( + "closure", + SyntaxShape::Closure(Some(vec![SyntaxShape::Any])), + "The closure to run once the stream is collected.", + ) + .switch( + "keep-env", + "let the closure affect environment variables", + None, + ) + .category(Category::Filters) + } + + fn description(&self) -> &str { + "Collect a stream into a value." + } + + fn extra_description(&self) -> &str { + r#"If provided, run a closure with the collected value as input. + +The entire stream will be collected into one value in memory, so if the stream +is particularly large, this can cause high memory usage."# + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let closure: Option = call.opt(engine_state, stack, 0)?; + + let metadata = match input.metadata() { + // Remove the `FilePath` metadata, because after `collect` it's no longer necessary to + // check where some input came from. + Some(PipelineMetadata { + data_source: DataSource::FilePath(_), + content_type: None, + }) => None, + other => other, + }; + + let input = input.into_value(call.head)?; + let result; + + if let Some(closure) = closure { + let block = engine_state.get_block(closure.block_id); + let mut stack_captures = + stack.captures_to_stack_preserve_out_dest(closure.captures.clone()); + + let mut saved_positional = None; + if let Some(var) = block.signature.get_positional(0) { + if let Some(var_id) = &var.var_id { + stack_captures.add_var(*var_id, input.clone()); + saved_positional = Some(*var_id); + } + } + + let eval_block = get_eval_block(engine_state); + + result = eval_block( + engine_state, + &mut stack_captures, + block, + input.into_pipeline_data_with_metadata(metadata), + ); + + if call.has_flag(engine_state, stack, "keep-env")? { + redirect_env(engine_state, stack, &stack_captures); + // for when we support `data | let x = $in;` + // remove the variables added earlier + for (var_id, _) in closure.captures { + stack_captures.remove_var(var_id); + } + if let Some(u) = saved_positional { + stack_captures.remove_var(u); + } + // add any new variables to the stack + stack.vars.extend(stack_captures.vars); + } + } else { + result = Ok(input.into_pipeline_data_with_metadata(metadata)); + } + + result + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Use the second value in the stream", + example: "[1 2 3] | collect { |x| $x.1 }", + result: Some(Value::test_int(2)), + }, + Example { + description: "Read and write to the same file", + example: "open file.txt | collect | save -f file.txt", + result: None, + }, + ] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(Collect {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/const_.rs b/nushell/crates/nu-cmd-lang/src/core_commands/const_.rs new file mode 100644 index 0000000..cfb5b66 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/const_.rs @@ -0,0 +1,103 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct Const; + +impl Command for Const { + fn name(&self) -> &str { + "const" + } + + fn description(&self) -> &str { + "Create a parse-time constant." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("const") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .allow_variants_without_examples(true) + .required("const_name", SyntaxShape::VarWithOptType, "Constant name.") + .required( + "initial_value", + SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::MathExpression)), + "Equals sign followed by constant value.", + ) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn search_terms(&self) -> Vec<&str> { + vec!["set", "let"] + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + // This is compiled specially by the IR compiler. The code here is never used when + // running in IR mode. + eprintln!( + "Tried to execute 'run' for the 'const' command: this code path should never be reached in IR mode" + ); + unreachable!() + } + + fn run_const( + &self, + _working_set: &StateWorkingSet, + _call: &Call, + _input: PipelineData, + ) -> Result { + Ok(PipelineData::empty()) + } + + fn is_const(&self) -> bool { + true + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Create a new parse-time constant.", + example: "const x = 10", + result: None, + }, + Example { + description: "Create a composite constant value", + example: "const x = { a: 10, b: 20 }", + result: None, + }, + ] + } +} + +#[cfg(test)] +mod test { + use nu_protocol::engine::CommandType; + + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(Const {}) + } + + #[test] + fn test_command_type() { + assert!(matches!(Const.command_type(), CommandType::Keyword)); + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/continue_.rs b/nushell/crates/nu-cmd-lang/src/core_commands/continue_.rs new file mode 100644 index 0000000..bb9c3e4 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/continue_.rs @@ -0,0 +1,54 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct Continue; + +impl Command for Continue { + fn name(&self) -> &str { + "continue" + } + + fn description(&self) -> &str { + "Continue a loop from the next iteration." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("continue") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html + + continue can only be used in while, loop, and for loops. It can not be used with each or other filter commands"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + // This is compiled specially by the IR compiler. The code here is never used when + // running in IR mode. + eprintln!( + "Tried to execute 'run' for the 'continue' command: this code path should never be reached in IR mode" + ); + unreachable!() + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Continue a loop from the next iteration", + example: r#"for i in 1..10 { if $i == 5 { continue }; print $i }"#, + result: None, + }] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/def.rs b/nushell/crates/nu-cmd-lang/src/core_commands/def.rs new file mode 100644 index 0000000..efb5bdf --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/def.rs @@ -0,0 +1,80 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct Def; + +impl Command for Def { + fn name(&self) -> &str { + "def" + } + + fn description(&self) -> &str { + "Define a custom command." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("def") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .required("def_name", SyntaxShape::String, "Command name.") + .required("params", SyntaxShape::Signature, "Parameters.") + .required("block", SyntaxShape::Closure(None), "Body of the definition.") + .switch("env", "keep the environment defined inside the command", None) + .switch("wrapped", "treat unknown flags and arguments as strings (requires ...rest-like parameter in signature)", None) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Define a command and run it", + example: r#"def say-hi [] { echo 'hi' }; say-hi"#, + result: Some(Value::test_string("hi")), + }, + Example { + description: "Define a command and run it with parameter(s)", + example: r#"def say-sth [sth: string] { echo $sth }; say-sth hi"#, + result: Some(Value::test_string("hi")), + }, + Example { + description: "Set environment variable by call a custom command", + example: r#"def --env foo [] { $env.BAR = "BAZ" }; foo; $env.BAR"#, + result: Some(Value::test_string("BAZ")), + }, + Example { + description: "cd affects the environment, so '--env' is required to change directory from within a command", + example: r#"def --env gohome [] { cd ~ }; gohome; $env.PWD == ('~' | path expand)"#, + result: Some(Value::test_string("true")), + }, + Example { + description: "Define a custom wrapper for an external command", + example: r#"def --wrapped my-echo [...rest] { ^echo ...$rest }; my-echo -e 'spam\tspam'"#, + result: Some(Value::test_string("spam\tspam")), + }, + Example { + description: "Define a custom command with a type signature. Passing a non-int value will result in an error", + example: r#"def only_int []: int -> int { $in }; 42 | only_int"#, + result: Some(Value::test_int(42)), + }, + ] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/describe.rs b/nushell/crates/nu-cmd-lang/src/core_commands/describe.rs new file mode 100644 index 0000000..d473b2b --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/describe.rs @@ -0,0 +1,506 @@ +use nu_engine::command_prelude::*; +use nu_protocol::{ + BlockId, ByteStreamSource, Category, PipelineMetadata, Signature, + engine::{Closure, StateWorkingSet}, +}; +use std::any::type_name; +#[derive(Clone)] +pub struct Describe; + +impl Command for Describe { + fn name(&self) -> &str { + "describe" + } + + fn description(&self) -> &str { + "Describe the type and structure of the value(s) piped in." + } + + fn signature(&self) -> Signature { + Signature::build("describe") + .input_output_types(vec![(Type::Any, Type::Any)]) + .switch( + "no-collect", + "do not collect streams of structured data", + Some('n'), + ) + .switch( + "detailed", + "show detailed information about the value", + Some('d'), + ) + .category(Category::Core) + } + + fn is_const(&self) -> bool { + true + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let options = Options { + no_collect: call.has_flag(engine_state, stack, "no-collect")?, + detailed: call.has_flag(engine_state, stack, "detailed")?, + }; + run(Some(engine_state), call, input, options) + } + + fn run_const( + &self, + working_set: &StateWorkingSet, + call: &Call, + input: PipelineData, + ) -> Result { + let options = Options { + no_collect: call.has_flag_const(working_set, "no-collect")?, + detailed: call.has_flag_const(working_set, "detailed")?, + }; + run(None, call, input, options) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Describe the type of a string", + example: "'hello' | describe", + result: Some(Value::test_string("string")), + }, + Example { + description: "Describe the type of a record in a detailed way", + example: "{shell:'true', uwu:true, features: {bugs:false, multiplatform:true, speed: 10}, fib: [1 1 2 3 5 8], on_save: {|x| $'Saving ($x)'}, first_commit: 2019-05-10, my_duration: (4min + 20sec)} | describe -d", + result: Some(Value::test_record(record!( + "type" => Value::test_string("record"), + "detailed_type" => Value::test_string("record, fib: list, on_save: closure, first_commit: datetime, my_duration: duration>"), + "columns" => Value::test_record(record!( + "shell" => Value::test_record(record!( + "type" => Value::test_string("string"), + "detailed_type" => Value::test_string("string"), + "rust_type" => Value::test_string("&alloc::string::String"), + "value" => Value::test_string("true"), + )), + "uwu" => Value::test_record(record!( + "type" => Value::test_string("bool"), + "detailed_type" => Value::test_string("bool"), + "rust_type" => Value::test_string("bool"), + "value" => Value::test_bool(true), + )), + "features" => Value::test_record(record!( + "type" => Value::test_string("record"), + "detailed_type" => Value::test_string("record"), + "columns" => Value::test_record(record!( + "bugs" => Value::test_record(record!( + "type" => Value::test_string("bool"), + "detailed_type" => Value::test_string("bool"), + "rust_type" => Value::test_string("bool"), + "value" => Value::test_bool(false), + )), + "multiplatform" => Value::test_record(record!( + "type" => Value::test_string("bool"), + "detailed_type" => Value::test_string("bool"), + "rust_type" => Value::test_string("bool"), + "value" => Value::test_bool(true), + )), + "speed" => Value::test_record(record!( + "type" => Value::test_string("int"), + "detailed_type" => Value::test_string("int"), + "rust_type" => Value::test_string("i64"), + "value" => Value::test_int(10), + )), + )), + "rust_type" => Value::test_string("&nu_utils::shared_cow::SharedCow"), + )), + "fib" => Value::test_record(record!( + "type" => Value::test_string("list"), + "detailed_type" => Value::test_string("list"), + "length" => Value::test_int(6), + "rust_type" => Value::test_string("&mut alloc::vec::Vec"), + "value" => Value::test_list(vec![ + Value::test_record(record!( + "type" => Value::test_string("int"), + "detailed_type" => Value::test_string("int"), + "rust_type" => Value::test_string("i64"), + "value" => Value::test_int(1), + )), + Value::test_record(record!( + "type" => Value::test_string("int"), + "detailed_type" => Value::test_string("int"), + "rust_type" => Value::test_string("i64"), + "value" => Value::test_int(1), + )), + Value::test_record(record!( + "type" => Value::test_string("int"), + "detailed_type" => Value::test_string("int"), + "rust_type" => Value::test_string("i64"), + "value" => Value::test_int(2), + )), + Value::test_record(record!( + "type" => Value::test_string("int"), + "detailed_type" => Value::test_string("int"), + "rust_type" => Value::test_string("i64"), + "value" => Value::test_int(3), + )), + Value::test_record(record!( + "type" => Value::test_string("int"), + "detailed_type" => Value::test_string("int"), + "rust_type" => Value::test_string("i64"), + "value" => Value::test_int(5), + )), + Value::test_record(record!( + "type" => Value::test_string("int"), + "detailed_type" => Value::test_string("int"), + "rust_type" => Value::test_string("i64"), + "value" => Value::test_int(8), + ))] + ), + )), + "on_save" => Value::test_record(record!( + "type" => Value::test_string("closure"), + "detailed_type" => Value::test_string("closure"), + "rust_type" => Value::test_string("&alloc::boxed::Box"), + "value" => Value::test_closure(Closure { + block_id: BlockId::new(1), + captures: vec![], + }), + "signature" => Value::test_record(record!( + "name" => Value::test_string(""), + "category" => Value::test_string("default"), + )), + )), + "first_commit" => Value::test_record(record!( + "type" => Value::test_string("datetime"), + "detailed_type" => Value::test_string("datetime"), + "rust_type" => Value::test_string("chrono::datetime::DateTime"), + "value" => Value::test_date("2019-05-10 00:00:00Z".parse().unwrap_or_default()), + )), + "my_duration" => Value::test_record(record!( + "type" => Value::test_string("duration"), + "detailed_type" => Value::test_string("duration"), + "rust_type" => Value::test_string("i64"), + "value" => Value::test_duration(260_000_000_000), + )) + )), + "rust_type" => Value::test_string("&nu_utils::shared_cow::SharedCow"), + ))), + }, + Example { + description: "Describe the type of a stream with detailed information", + example: "[1 2 3] | each {|i| echo $i} | describe -d", + result: None, // Give "Running external commands not supported" error + // result: Some(Value::test_record(record!( + // "type" => Value::test_string("stream"), + // "origin" => Value::test_string("nushell"), + // "subtype" => Value::test_record(record!( + // "type" => Value::test_string("list"), + // "length" => Value::test_int(3), + // "values" => Value::test_list(vec![ + // Value::test_string("int"), + // Value::test_string("int"), + // Value::test_string("int"), + // ]) + // )) + // ))), + }, + Example { + description: "Describe a stream of data, collecting it first", + example: "[1 2 3] | each {|i| echo $i} | describe", + result: None, // Give "Running external commands not supported" error + // result: Some(Value::test_string("list (stream)")), + }, + Example { + description: "Describe the input but do not collect streams", + example: "[1 2 3] | each {|i| echo $i} | describe --no-collect", + result: None, // Give "Running external commands not supported" error + // result: Some(Value::test_string("stream")), + }, + ] + } + + fn search_terms(&self) -> Vec<&str> { + vec!["type", "typeof", "info", "structure"] + } +} + +#[derive(Clone, Copy)] +struct Options { + no_collect: bool, + detailed: bool, +} + +fn run( + engine_state: Option<&EngineState>, + call: &Call, + input: PipelineData, + options: Options, +) -> Result { + let head = call.head; + let metadata = input.metadata(); + + let description = match input { + PipelineData::ByteStream(stream, ..) => { + let type_ = stream.type_().describe(); + + let description = if options.detailed { + let origin = match stream.source() { + ByteStreamSource::Read(_) => "unknown", + ByteStreamSource::File(_) => "file", + #[cfg(feature = "os")] + ByteStreamSource::Child(_) => "external", + }; + + Value::record( + record! { + "type" => Value::string("bytestream", head), + "detailed_type" => Value::string(type_, head), + "rust_type" => Value::string(type_of(&stream), head), + "origin" => Value::string(origin, head), + "metadata" => metadata_to_value(metadata, head), + }, + head, + ) + } else { + Value::string(type_, head) + }; + + if !options.no_collect { + stream.drain()?; + } + + description + } + PipelineData::ListStream(stream, ..) => { + let type_ = type_of(&stream); + if options.detailed { + let subtype = if options.no_collect { + Value::string("any", head) + } else { + describe_value(stream.into_value(), head, engine_state) + }; + Value::record( + record! { + "type" => Value::string("stream", head), + "detailed_type" => Value::string("list stream", head), + "rust_type" => Value::string(type_, head), + "origin" => Value::string("nushell", head), + "subtype" => subtype, + "metadata" => metadata_to_value(metadata, head), + }, + head, + ) + } else if options.no_collect { + Value::string("stream", head) + } else { + let value = stream.into_value(); + let base_description = value.get_type().to_string(); + Value::string(format!("{} (stream)", base_description), head) + } + } + PipelineData::Value(value, ..) => { + if !options.detailed { + Value::string(value.get_type().to_string(), head) + } else { + describe_value(value, head, engine_state) + } + } + PipelineData::Empty => Value::string(Type::Nothing.to_string(), head), + }; + + Ok(description.into_pipeline_data()) +} + +enum Description { + Record(Record), +} + +impl Description { + fn into_value(self, span: Span) -> Value { + match self { + Description::Record(record) => Value::record(record, span), + } + } +} + +fn describe_value(value: Value, head: Span, engine_state: Option<&EngineState>) -> Value { + let Description::Record(record) = describe_value_inner(value, head, engine_state); + Value::record(record, head) +} + +fn type_of(_: &T) -> String { + type_name::().to_string() +} + +fn describe_value_inner( + mut value: Value, + head: Span, + engine_state: Option<&EngineState>, +) -> Description { + let value_type = value.get_type().to_string(); + match value { + Value::Bool { val, .. } => Description::Record(record! { + "type" => Value::string("bool", head), + "detailed_type" => Value::string(value_type, head), + "rust_type" => Value::string(type_of(&val), head), + "value" => value, + }), + Value::Int { val, .. } => Description::Record(record! { + "type" => Value::string("int", head), + "detailed_type" => Value::string(value_type, head), + "rust_type" => Value::string(type_of(&val), head), + "value" => value, + }), + Value::Float { val, .. } => Description::Record(record! { + "type" => Value::string("float", head), + "detailed_type" => Value::string(value_type, head), + "rust_type" => Value::string(type_of(&val), head), + "value" => value, + }), + Value::Filesize { val, .. } => Description::Record(record! { + "type" => Value::string("filesize", head), + "detailed_type" => Value::string(value_type, head), + "rust_type" => Value::string(type_of(&val), head), + "value" => value, + }), + Value::Duration { val, .. } => Description::Record(record! { + "type" => Value::string("duration", head), + "detailed_type" => Value::string(value_type, head), + "rust_type" => Value::string(type_of(&val), head), + "value" => value, + }), + Value::Date { val, .. } => Description::Record(record! { + "type" => Value::string("datetime", head), + "detailed_type" => Value::string(value_type, head), + "rust_type" => Value::string(type_of(&val), head), + "value" => value, + }), + Value::Range { ref val, .. } => Description::Record(record! { + "type" => Value::string("range", head), + "detailed_type" => Value::string(value_type, head), + "rust_type" => Value::string(type_of(&val), head), + "value" => value, + }), + Value::String { ref val, .. } => Description::Record(record! { + "type" => Value::string("string", head), + "detailed_type" => Value::string(value_type, head), + "rust_type" => Value::string(type_of(&val), head), + "value" => value, + }), + Value::Glob { ref val, .. } => Description::Record(record! { + "type" => Value::string("glob", head), + "detailed_type" => Value::string(value_type, head), + "rust_type" => Value::string(type_of(&val), head), + "value" => value, + }), + Value::Nothing { .. } => Description::Record(record! { + "type" => Value::string("nothing", head), + "detailed_type" => Value::string(value_type, head), + "rust_type" => Value::string("", head), + "value" => value, + }), + Value::Record { ref val, .. } => { + let mut columns = val.clone().into_owned(); + for (_, val) in &mut columns { + *val = + describe_value_inner(std::mem::take(val), head, engine_state).into_value(head); + } + + Description::Record(record! { + "type" => Value::string("record", head), + "detailed_type" => Value::string(value_type, head), + "columns" => Value::record(columns.clone(), head), + "rust_type" => Value::string(type_of(&val), head), + }) + } + Value::List { ref mut vals, .. } => { + for val in &mut *vals { + *val = + describe_value_inner(std::mem::take(val), head, engine_state).into_value(head); + } + + Description::Record(record! { + "type" => Value::string("list", head), + "detailed_type" => Value::string(value_type, head), + "length" => Value::int(vals.len() as i64, head), + "rust_type" => Value::string(type_of(&vals), head), + "value" => value, + }) + } + Value::Closure { ref val, .. } => { + let block = engine_state.map(|engine_state| engine_state.get_block(val.block_id)); + + let mut record = record! { + "type" => Value::string("closure", head), + "detailed_type" => Value::string(value_type, head), + "rust_type" => Value::string(type_of(&val), head), + "value" => value, + }; + if let Some(block) = block { + record.push( + "signature", + Value::record( + record! { + "name" => Value::string(block.signature.name.clone(), head), + "category" => Value::string(block.signature.category.to_string(), head), + }, + head, + ), + ); + } + Description::Record(record) + } + Value::Error { ref error, .. } => Description::Record(record! { + "type" => Value::string("error", head), + "detailed_type" => Value::string(value_type, head), + "subtype" => Value::string(error.to_string(), head), + "rust_type" => Value::string(type_of(&error), head), + "value" => value, + }), + Value::Binary { ref val, .. } => Description::Record(record! { + "type" => Value::string("binary", head), + "detailed_type" => Value::string(value_type, head), + "length" => Value::int(val.len() as i64, head), + "rust_type" => Value::string(type_of(&val), head), + "value" => value, + }), + Value::CellPath { ref val, .. } => Description::Record(record! { + "type" => Value::string("cell-path", head), + "detailed_type" => Value::string(value_type, head), + "length" => Value::int(val.members.len() as i64, head), + "rust_type" => Value::string(type_of(&val), head), + "value" => value + }), + Value::Custom { ref val, .. } => Description::Record(record! { + "type" => Value::string("custom", head), + "detailed_type" => Value::string(value_type, head), + "subtype" => Value::string(val.type_name(), head), + "rust_type" => Value::string(type_of(&val), head), + "value" => + match val.to_base_value(head) { + Ok(base_value) => base_value, + Err(err) => Value::error(err, head), + } + }), + } +} + +fn metadata_to_value(metadata: Option, head: Span) -> Value { + if let Some(metadata) = metadata { + let data_source = Value::string(format!("{:?}", metadata.data_source), head); + Value::record(record! { "data_source" => data_source }, head) + } else { + Value::nothing(head) + } +} + +#[cfg(test)] +mod test { + #[test] + fn test_examples() { + use super::Describe; + use crate::test_examples; + test_examples(Describe {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/do_.rs b/nushell/crates/nu-cmd-lang/src/core_commands/do_.rs new file mode 100644 index 0000000..6c94f9e --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/do_.rs @@ -0,0 +1,318 @@ +use nu_engine::{command_prelude::*, get_eval_block_with_early_return, redirect_env}; +#[cfg(feature = "os")] +use nu_protocol::process::{ChildPipe, ChildProcess}; +use nu_protocol::{ + ByteStream, ByteStreamSource, OutDest, engine::Closure, shell_error::io::IoError, +}; + +use std::{ + io::{Cursor, Read}, + thread, +}; + +#[derive(Clone)] +pub struct Do; + +impl Command for Do { + fn name(&self) -> &str { + "do" + } + + fn description(&self) -> &str { + "Run a closure, providing it with the pipeline input." + } + + fn signature(&self) -> Signature { + Signature::build("do") + .required("closure", SyntaxShape::Closure(None), "The closure to run.") + .input_output_types(vec![(Type::Any, Type::Any)]) + .switch( + "ignore-errors", + "ignore errors as the closure runs", + Some('i'), + ) + .switch( + "capture-errors", + "catch errors as the closure runs, and return them", + Some('c'), + ) + .switch( + "env", + "keep the environment defined inside the command", + None, + ) + .rest( + "rest", + SyntaxShape::Any, + "The parameter(s) for the closure.", + ) + .category(Category::Core) + } + + fn run( + &self, + engine_state: &EngineState, + caller_stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + let block: Closure = call.req(engine_state, caller_stack, 0)?; + let rest: Vec = call.rest(engine_state, caller_stack, 1)?; + let ignore_all_errors = call.has_flag(engine_state, caller_stack, "ignore-errors")?; + + let capture_errors = call.has_flag(engine_state, caller_stack, "capture-errors")?; + let has_env = call.has_flag(engine_state, caller_stack, "env")?; + + let mut callee_stack = caller_stack.captures_to_stack_preserve_out_dest(block.captures); + let block = engine_state.get_block(block.block_id); + + bind_args_to(&mut callee_stack, &block.signature, rest, head)?; + let eval_block_with_early_return = get_eval_block_with_early_return(engine_state); + + let result = eval_block_with_early_return(engine_state, &mut callee_stack, block, input); + + if has_env { + // Merge the block's environment to the current stack + redirect_env(engine_state, caller_stack, &callee_stack); + } + + match result { + Ok(PipelineData::ByteStream(stream, metadata)) if capture_errors => { + let span = stream.span(); + #[cfg(not(feature = "os"))] + return Err(ShellError::DisabledOsSupport { + msg: "Cannot create a thread to receive stdout message.".to_string(), + span: Some(span), + }); + + #[cfg(feature = "os")] + match stream.into_child() { + Ok(mut child) => { + // Use a thread to receive stdout message. + // Or we may get a deadlock if child process sends out too much bytes to stderr. + // + // For example: in normal linux system, stderr pipe's limit is 65535 bytes. + // if child process sends out 65536 bytes, the process will be hanged because no consumer + // consumes the first 65535 bytes + // So we need a thread to receive stdout message, then the current thread can continue to consume + // stderr messages. + let stdout_handler = child + .stdout + .take() + .map(|mut stdout| { + thread::Builder::new() + .name("stdout consumer".to_string()) + .spawn(move || { + let mut buf = Vec::new(); + stdout.read_to_end(&mut buf).map_err(|err| { + IoError::new_internal( + err, + "Could not read stdout to end", + nu_protocol::location!(), + ) + })?; + Ok::<_, ShellError>(buf) + }) + .map_err(|err| IoError::new(err, head, None)) + }) + .transpose()?; + + // Intercept stderr so we can return it in the error if the exit code is non-zero. + // The threading issues mentioned above dictate why we also need to intercept stdout. + let stderr_msg = match child.stderr.take() { + None => String::new(), + Some(mut stderr) => { + let mut buf = String::new(); + stderr + .read_to_string(&mut buf) + .map_err(|err| IoError::new(err, span, None))?; + buf + } + }; + + let stdout = if let Some(handle) = stdout_handler { + match handle.join() { + Err(err) => { + return Err(ShellError::ExternalCommand { + label: "Fail to receive external commands stdout message" + .to_string(), + help: format!("{err:?}"), + span, + }); + } + Ok(res) => Some(res?), + } + } else { + None + }; + + child.ignore_error(false); + child.wait()?; + + let mut child = ChildProcess::from_raw(None, None, None, span); + if let Some(stdout) = stdout { + child.stdout = Some(ChildPipe::Tee(Box::new(Cursor::new(stdout)))); + } + if !stderr_msg.is_empty() { + child.stderr = Some(ChildPipe::Tee(Box::new(Cursor::new(stderr_msg)))); + } + Ok(PipelineData::ByteStream( + ByteStream::child(child, span), + metadata, + )) + } + Err(stream) => Ok(PipelineData::ByteStream(stream, metadata)), + } + } + Ok(PipelineData::ByteStream(mut stream, metadata)) + if ignore_all_errors + && !matches!( + caller_stack.stdout(), + OutDest::Pipe | OutDest::PipeSeparate | OutDest::Value + ) => + { + #[cfg(feature = "os")] + if let ByteStreamSource::Child(child) = stream.source_mut() { + child.ignore_error(true); + } + Ok(PipelineData::ByteStream(stream, metadata)) + } + Ok(PipelineData::Value(Value::Error { .. }, ..)) | Err(_) if ignore_all_errors => { + Ok(PipelineData::empty()) + } + Ok(PipelineData::ListStream(stream, metadata)) if ignore_all_errors => { + let stream = stream.map(move |value| { + if let Value::Error { .. } = value { + Value::nothing(head) + } else { + value + } + }); + Ok(PipelineData::ListStream(stream, metadata)) + } + r => r, + } + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Run the closure", + example: r#"do { echo hello }"#, + result: Some(Value::test_string("hello")), + }, + Example { + description: "Run a stored first-class closure", + example: r#"let text = "I am enclosed"; let hello = {|| echo $text}; do $hello"#, + result: Some(Value::test_string("I am enclosed")), + }, + Example { + description: "Run the closure and ignore both shell and external program errors", + example: r#"do --ignore-errors { thisisnotarealcommand }"#, + result: None, + }, + Example { + description: "Abort the pipeline if a program returns a non-zero exit code", + example: r#"do --capture-errors { nu --commands 'exit 1' } | myscarycommand"#, + result: None, + }, + Example { + description: "Run the closure with a positional, type-checked parameter", + example: r#"do {|x:int| 100 + $x } 77"#, + result: Some(Value::test_int(177)), + }, + Example { + description: "Run the closure with pipeline input", + example: r#"77 | do { 100 + $in }"#, + result: Some(Value::test_int(177)), + }, + Example { + description: "Run the closure with a default parameter value", + example: r#"77 | do {|x=100| $x + $in }"#, + result: Some(Value::test_int(177)), + }, + Example { + description: "Run the closure with two positional parameters", + example: r#"do {|x,y| $x + $y } 77 100"#, + result: Some(Value::test_int(177)), + }, + Example { + description: "Run the closure and keep changes to the environment", + example: r#"do --env { $env.foo = 'bar' }; $env.foo"#, + result: Some(Value::test_string("bar")), + }, + ] + } +} + +fn bind_args_to( + stack: &mut Stack, + signature: &Signature, + args: Vec, + head_span: Span, +) -> Result<(), ShellError> { + let mut val_iter = args.into_iter(); + for (param, required) in signature + .required_positional + .iter() + .map(|p| (p, true)) + .chain(signature.optional_positional.iter().map(|p| (p, false))) + { + let var_id = param + .var_id + .expect("internal error: all custom parameters must have var_ids"); + if let Some(result) = val_iter.next() { + let param_type = param.shape.to_type(); + if required && !result.is_subtype_of(¶m_type) { + return Err(ShellError::CantConvert { + to_type: param.shape.to_type().to_string(), + from_type: result.get_type().to_string(), + span: result.span(), + help: None, + }); + } + stack.add_var(var_id, result); + } else if let Some(value) = ¶m.default_value { + stack.add_var(var_id, value.to_owned()) + } else if !required { + stack.add_var(var_id, Value::nothing(head_span)) + } else { + return Err(ShellError::MissingParameter { + param_name: param.name.to_string(), + span: head_span, + }); + } + } + + if let Some(rest_positional) = &signature.rest_positional { + let mut rest_items = vec![]; + + for result in val_iter { + rest_items.push(result); + } + + let span = if let Some(rest_item) = rest_items.first() { + rest_item.span() + } else { + head_span + }; + + stack.add_var( + rest_positional + .var_id + .expect("Internal error: rest positional parameter lacks var_id"), + Value::list(rest_items, span), + ) + } + Ok(()) +} + +mod test { + #[test] + fn test_examples() { + use super::Do; + use crate::test_examples; + test_examples(Do {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/echo.rs b/nushell/crates/nu-cmd-lang/src/core_commands/echo.rs new file mode 100644 index 0000000..e260c64 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/echo.rs @@ -0,0 +1,91 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct Echo; + +impl Command for Echo { + fn name(&self) -> &str { + "echo" + } + + fn description(&self) -> &str { + "Returns its arguments, ignoring the piped-in value." + } + + fn signature(&self) -> Signature { + Signature::build("echo") + .input_output_types(vec![(Type::Nothing, Type::Any)]) + .rest("rest", SyntaxShape::Any, "The values to echo.") + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"Unlike `print`, which prints unstructured text to stdout, `echo` is like an +identity function and simply returns its arguments. When given no arguments, +it returns an empty string. When given one argument, it returns it as a +nushell value. Otherwise, it returns a list of the arguments. There is usually +little reason to use this over just writing the values as-is."# + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let args = call.rest(engine_state, stack, 0)?; + echo_impl(args, call.head) + } + + fn run_const( + &self, + working_set: &StateWorkingSet, + call: &Call, + _input: PipelineData, + ) -> Result { + let args = call.rest_const(working_set, 0)?; + echo_impl(args, call.head) + } + + fn is_const(&self) -> bool { + true + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Put a list of numbers in the pipeline. This is the same as [1 2 3].", + example: "echo 1 2 3", + result: Some(Value::list( + vec![Value::test_int(1), Value::test_int(2), Value::test_int(3)], + Span::test_data(), + )), + }, + Example { + description: "Returns the piped-in value, by using the special $in variable to obtain it.", + example: "echo $in", + result: None, + }, + ] + } +} + +fn echo_impl(mut args: Vec, head: Span) -> Result { + let value = match args.len() { + 0 => Value::string("", head), + 1 => args.pop().expect("one element"), + _ => Value::list(args, head), + }; + Ok(value.into_pipeline_data()) +} + +#[cfg(test)] +mod test { + #[test] + fn test_examples() { + use super::Echo; + use crate::test_examples; + test_examples(Echo {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/error_make.rs b/nushell/crates/nu-cmd-lang/src/core_commands/error_make.rs new file mode 100644 index 0000000..a43d36f --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/error_make.rs @@ -0,0 +1,262 @@ +use nu_engine::command_prelude::*; +use nu_protocol::LabeledError; + +#[derive(Clone)] +pub struct ErrorMake; + +impl Command for ErrorMake { + fn name(&self) -> &str { + "error make" + } + + fn signature(&self) -> Signature { + Signature::build("error make") + .input_output_types(vec![(Type::Nothing, Type::Error)]) + .required( + "error_struct", + SyntaxShape::Record(vec![]), + "The error to create.", + ) + .switch( + "unspanned", + "remove the origin label from the error", + Some('u'), + ) + .category(Category::Core) + } + + fn description(&self) -> &str { + "Create an error." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["panic", "crash", "throw"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let arg: Value = call.req(engine_state, stack, 0)?; + + let throw_span = if call.has_flag(engine_state, stack, "unspanned")? { + None + } else { + Some(call.head) + }; + + Err(make_other_error(&arg, throw_span)) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Create a simple custom error", + example: r#"error make {msg: "my custom error message"}"#, + result: None, + }, + Example { + description: "Create a more complex custom error", + example: r#"error make { + msg: "my custom error message" + label: { + text: "my custom label text" # not mandatory unless $.label exists + # optional + span: { + # if $.label.span exists, both start and end must be present + start: 123 + end: 456 + } + } + help: "A help string, suggesting a fix to the user" # optional + }"#, + result: None, + }, + Example { + description: "Create a custom error for a custom command that shows the span of the argument", + example: r#"def foo [x] { + error make { + msg: "this is fishy" + label: { + text: "fish right here" + span: (metadata $x).span + } + } + }"#, + result: None, + }, + ] + } +} + +const UNABLE_TO_PARSE: &str = "Unable to parse error format."; + +fn make_other_error(value: &Value, throw_span: Option) -> ShellError { + let span = value.span(); + let value = match value { + Value::Record { val, .. } => val, + _ => { + return ShellError::GenericError { + error: "Creating error value not supported.".into(), + msg: "unsupported error format, must be a record".into(), + span: throw_span, + help: None, + inner: vec![], + }; + } + }; + + let msg = match value.get("msg") { + Some(Value::String { val, .. }) => val.clone(), + Some(_) => { + return ShellError::GenericError { + error: UNABLE_TO_PARSE.into(), + msg: "`$.msg` has wrong type, must be string".into(), + span: Some(span), + help: None, + inner: vec![], + }; + } + None => { + return ShellError::GenericError { + error: UNABLE_TO_PARSE.into(), + msg: "missing required member `$.msg`".into(), + span: Some(span), + help: None, + inner: vec![], + }; + } + }; + + let help = match value.get("help") { + Some(Value::String { val, .. }) => Some(val.clone()), + _ => None, + }; + + let (label, label_span) = match value.get("label") { + Some(value @ Value::Record { val, .. }) => (val, value.span()), + Some(_) => { + return ShellError::GenericError { + error: UNABLE_TO_PARSE.into(), + msg: "`$.label` has wrong type, must be a record".into(), + span: Some(span), + help: None, + inner: vec![], + }; + } + // correct return: no label + None => { + return ShellError::GenericError { + error: msg, + msg: "originates from here".into(), + span: throw_span, + help, + inner: vec![], + }; + } + }; + + // remove after a few versions + if label.get("start").is_some() || label.get("end").is_some() { + return ShellError::GenericError { + error: UNABLE_TO_PARSE.into(), + msg: "`start` and `end` are deprecated".into(), + span: Some(span), + help: Some("Use `$.label.span` instead".into()), + inner: vec![], + }; + } + + let text = match label.get("text") { + Some(Value::String { val, .. }) => val.clone(), + Some(_) => { + return ShellError::GenericError { + error: UNABLE_TO_PARSE.into(), + msg: "`$.label.text` has wrong type, must be string".into(), + span: Some(label_span), + help: None, + inner: vec![], + }; + } + None => { + return ShellError::GenericError { + error: UNABLE_TO_PARSE.into(), + msg: "missing required member `$.label.text`".into(), + span: Some(label_span), + help: None, + inner: vec![], + }; + } + }; + + let (span, span_span) = match label.get("span") { + Some(value @ Value::Record { val, .. }) => (val, value.span()), + Some(value) => { + return ShellError::GenericError { + error: UNABLE_TO_PARSE.into(), + msg: "`$.label.span` has wrong type, must be record".into(), + span: Some(value.span()), + help: None, + inner: vec![], + }; + } + // correct return: label, no span + None => { + return ShellError::GenericError { + error: msg, + msg: text, + span: throw_span, + help, + inner: vec![], + }; + } + }; + + let span_start = match get_span_sides(span, span_span, "start") { + Ok(val) => val, + Err(err) => return err, + }; + let span_end = match get_span_sides(span, span_span, "end") { + Ok(val) => val, + Err(err) => return err, + }; + + if span_start > span_end { + return ShellError::GenericError { + error: "invalid error format.".into(), + msg: "`$.label.start` should be smaller than `$.label.end`".into(), + span: Some(label_span), + help: Some(format!("{} > {}", span_start, span_end)), + inner: vec![], + }; + } + + // correct return: everything present + let mut error = + LabeledError::new(msg).with_label(text, Span::new(span_start as usize, span_end as usize)); + error.help = help; + error.into() +} + +fn get_span_sides(span: &Record, span_span: Span, side: &str) -> Result { + match span.get(side) { + Some(Value::Int { val, .. }) => Ok(*val), + Some(_) => Err(ShellError::GenericError { + error: UNABLE_TO_PARSE.into(), + msg: format!("`$.span.{side}` must be int"), + span: Some(span_span), + help: None, + inner: vec![], + }), + None => Err(ShellError::GenericError { + error: UNABLE_TO_PARSE.into(), + msg: format!("`$.span.{side}` must be present, if span is specified."), + span: Some(span_span), + help: None, + inner: vec![], + }), + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/export.rs b/nushell/crates/nu-cmd-lang/src/core_commands/export.rs new file mode 100644 index 0000000..d7e923d --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/export.rs @@ -0,0 +1,52 @@ +use nu_engine::{command_prelude::*, get_full_help}; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct ExportCommand; + +impl Command for ExportCommand { + fn name(&self) -> &str { + "export" + } + + fn signature(&self) -> Signature { + Signature::build("export") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .category(Category::Core) + } + + fn description(&self) -> &str { + "Export definitions or environment variables from a module." + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + Ok(Value::string(get_full_help(self, engine_state, stack), call.head).into_pipeline_data()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Export a definition from a module", + example: r#"module utils { export def my-command [] { "hello" } }; use utils my-command; my-command"#, + result: Some(Value::test_string("hello")), + }] + } + + fn search_terms(&self) -> Vec<&str> { + vec!["module"] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/export_alias.rs b/nushell/crates/nu-cmd-lang/src/core_commands/export_alias.rs new file mode 100644 index 0000000..a3001cd --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/export_alias.rs @@ -0,0 +1,58 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct ExportAlias; + +impl Command for ExportAlias { + fn name(&self) -> &str { + "export alias" + } + + fn description(&self) -> &str { + "Alias a command (with optional flags) to a new name and export it from a module." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("export alias") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .required("name", SyntaxShape::String, "Name of the alias.") + .required( + "initial_value", + SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::Expression)), + "Equals sign followed by value.", + ) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn search_terms(&self) -> Vec<&str> { + vec!["abbr", "aka", "fn", "func", "function"] + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Alias ll to ls -l and export it from a module", + example: "module spam { export alias ll = ls -l }", + result: Some(Value::nothing(Span::test_data())), + }] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/export_const.rs b/nushell/crates/nu-cmd-lang/src/core_commands/export_const.rs new file mode 100644 index 0000000..59e9385 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/export_const.rs @@ -0,0 +1,63 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct ExportConst; + +impl Command for ExportConst { + fn name(&self) -> &str { + "export const" + } + + fn description(&self) -> &str { + "Use parse-time constant from a module and export them from this module." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("export const") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .allow_variants_without_examples(true) + .required("const_name", SyntaxShape::VarWithOptType, "Constant name.") + .required( + "initial_value", + SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::MathExpression)), + "Equals sign followed by constant value.", + ) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Re-export a command from another module", + example: r#"module spam { export const foo = 3; } + module eggs { export use spam foo } + use eggs foo + foo + "#, + result: Some(Value::test_int(3)), + }] + } + + fn search_terms(&self) -> Vec<&str> { + vec!["reexport", "import", "module"] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/export_def.rs b/nushell/crates/nu-cmd-lang/src/core_commands/export_def.rs new file mode 100644 index 0000000..51c4c87 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/export_def.rs @@ -0,0 +1,57 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct ExportDef; + +impl Command for ExportDef { + fn name(&self) -> &str { + "export def" + } + + fn description(&self) -> &str { + "Define a custom command and export it from a module." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("export def") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .required("def_name", SyntaxShape::String, "Command name.") + .required("params", SyntaxShape::Signature, "Parameters.") + .required("block", SyntaxShape::Block, "Body of the definition.") + .switch("env", "keep the environment defined inside the command", None) + .switch("wrapped", "treat unknown flags and arguments as strings (requires ...rest-like parameter in signature)", None) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Define a custom command in a module and call it", + example: r#"module spam { export def foo [] { "foo" } }; use spam foo; foo"#, + result: Some(Value::test_string("foo")), + }] + } + + fn search_terms(&self) -> Vec<&str> { + vec!["module"] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/export_extern.rs b/nushell/crates/nu-cmd-lang/src/core_commands/export_extern.rs new file mode 100644 index 0000000..580e503 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/export_extern.rs @@ -0,0 +1,54 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct ExportExtern; + +impl Command for ExportExtern { + fn name(&self) -> &str { + "export extern" + } + + fn description(&self) -> &str { + "Define an extern and export it from a module." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("export extern") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .required("def_name", SyntaxShape::String, "Definition name.") + .required("params", SyntaxShape::Signature, "Parameters.") + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Export the signature for an external command", + example: r#"export extern echo [text: string]"#, + result: None, + }] + } + + fn search_terms(&self) -> Vec<&str> { + vec!["signature", "module", "declare"] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/export_module.rs b/nushell/crates/nu-cmd-lang/src/core_commands/export_module.rs new file mode 100644 index 0000000..c749c1a --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/export_module.rs @@ -0,0 +1,72 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct ExportModule; + +impl Command for ExportModule { + fn name(&self) -> &str { + "export module" + } + + fn description(&self) -> &str { + "Export a custom module from a module." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("export module") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .allow_variants_without_examples(true) + .required("module", SyntaxShape::String, "Module name or module path.") + .optional( + "block", + SyntaxShape::Block, + "Body of the module if 'module' parameter is not a path.", + ) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Define a custom command in a submodule of a module and call it", + example: r#"module spam { + export module eggs { + export def foo [] { "foo" } + } + } + use spam eggs + eggs foo"#, + result: Some(Value::test_string("foo")), + }] + } +} + +#[cfg(test)] +mod test { + use super::*; + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(ExportModule {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/export_use.rs b/nushell/crates/nu-cmd-lang/src/core_commands/export_use.rs new file mode 100644 index 0000000..4d2c3bf --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/export_use.rs @@ -0,0 +1,62 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct ExportUse; + +impl Command for ExportUse { + fn name(&self) -> &str { + "export use" + } + + fn description(&self) -> &str { + "Use definitions from a module and export them from this module." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("export use") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .required("module", SyntaxShape::String, "Module or module file.") + .rest( + "members", + SyntaxShape::Any, + "Which members of the module to import.", + ) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Re-export a command from another module", + example: r#"module spam { export def foo [] { "foo" } } + module eggs { export use spam foo } + use eggs foo + foo + "#, + result: Some(Value::test_string("foo")), + }] + } + + fn search_terms(&self) -> Vec<&str> { + vec!["reexport", "import", "module"] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/extern_.rs b/nushell/crates/nu-cmd-lang/src/core_commands/extern_.rs new file mode 100644 index 0000000..c0afcdf --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/extern_.rs @@ -0,0 +1,50 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct Extern; + +impl Command for Extern { + fn name(&self) -> &str { + "extern" + } + + fn description(&self) -> &str { + "Define a signature for an external command." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("extern") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .required("def_name", SyntaxShape::String, "Definition name.") + .required("params", SyntaxShape::Signature, "Parameters.") + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Write a signature for an external command", + example: r#"extern echo [text: string]"#, + result: None, + }] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/for_.rs b/nushell/crates/nu-cmd-lang/src/core_commands/for_.rs new file mode 100644 index 0000000..1798650 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/for_.rs @@ -0,0 +1,90 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct For; + +impl Command for For { + fn name(&self) -> &str { + "for" + } + + fn description(&self) -> &str { + "Loop over a range." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("for") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .allow_variants_without_examples(true) + .required( + "var_name", + SyntaxShape::VarWithOptType, + "Name of the looping variable.", + ) + .required( + "range", + SyntaxShape::Keyword(b"in".to_vec(), Box::new(SyntaxShape::Any)), + "Range of the loop.", + ) + .required("block", SyntaxShape::Block, "The block to run.") + .creates_scope() + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + // This is compiled specially by the IR compiler. The code here is never used when + // running in IR mode. + eprintln!( + "Tried to execute 'run' for the 'for' command: this code path should never be reached in IR mode" + ); + unreachable!() + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Print the square of each integer", + example: "for x in [1 2 3] { print ($x * $x) }", + result: None, + }, + Example { + description: "Work with elements of a range", + example: "for $x in 1..3 { print $x }", + result: None, + }, + Example { + description: "Number each item and print a message", + example: r#"for $it in (['bob' 'fred'] | enumerate) { print $"($it.index) is ($it.item)" }"#, + result: None, + }, + ] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(For {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/hide.rs b/nushell/crates/nu-cmd-lang/src/core_commands/hide.rs new file mode 100644 index 0000000..8524f26 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/hide.rs @@ -0,0 +1,67 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct Hide; + +impl Command for Hide { + fn name(&self) -> &str { + "hide" + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("hide") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .required("module", SyntaxShape::String, "Module or module file.") + .optional( + "members", + SyntaxShape::Any, + "Which members of the module to import.", + ) + .category(Category::Core) + } + + fn description(&self) -> &str { + "Hide definitions in the current scope." + } + + fn extra_description(&self) -> &str { + r#"Definitions are hidden by priority: First aliases, then custom commands. + +This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn search_terms(&self) -> Vec<&str> { + vec!["unset"] + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Hide the alias just defined", + example: r#"alias lll = ls -l; hide lll"#, + result: None, + }, + Example { + description: "Hide a custom command", + example: r#"def say-hi [] { echo 'Hi!' }; hide say-hi"#, + result: None, + }, + ] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/hide_env.rs b/nushell/crates/nu-cmd-lang/src/core_commands/hide_env.rs new file mode 100644 index 0000000..857343e --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/hide_env.rs @@ -0,0 +1,74 @@ +use nu_engine::command_prelude::*; +use nu_protocol::did_you_mean; + +#[derive(Clone)] +pub struct HideEnv; + +impl Command for HideEnv { + fn name(&self) -> &str { + "hide-env" + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("hide-env") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .rest( + "name", + SyntaxShape::String, + "Environment variable names to hide.", + ) + .switch( + "ignore-errors", + "do not throw an error if an environment variable was not found", + Some('i'), + ) + .category(Category::Core) + } + + fn description(&self) -> &str { + "Hide environment variables in the current scope." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["unset", "drop"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let env_var_names: Vec> = call.rest(engine_state, stack, 0)?; + let ignore_errors = call.has_flag(engine_state, stack, "ignore-errors")?; + + for name in env_var_names { + if !stack.remove_env_var(engine_state, &name.item) && !ignore_errors { + let all_names = stack.get_env_var_names(engine_state); + if let Some(closest_match) = did_you_mean(&all_names, &name.item) { + return Err(ShellError::DidYouMeanCustom { + msg: format!("Environment variable '{}' not found", name.item), + suggestion: closest_match, + span: name.span, + }); + } else { + return Err(ShellError::EnvVarNotFoundAtRuntime { + envvar_name: name.item, + span: name.span, + }); + } + } + } + + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Hide an environment variable", + example: r#"$env.HZ_ENV_ABC = 1; hide-env HZ_ENV_ABC; 'HZ_ENV_ABC' in $env"#, + result: Some(Value::test_bool(false)), + }] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/if_.rs b/nushell/crates/nu-cmd-lang/src/core_commands/if_.rs new file mode 100644 index 0000000..7c54ca4 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/if_.rs @@ -0,0 +1,144 @@ +use nu_engine::command_prelude::*; +use nu_protocol::{ + engine::{CommandType, StateWorkingSet}, + eval_const::{eval_const_subexpression, eval_constant, eval_constant_with_input}, +}; + +#[derive(Clone)] +pub struct If; + +impl Command for If { + fn name(&self) -> &str { + "if" + } + + fn description(&self) -> &str { + "Conditionally run a block." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("if") + .input_output_types(vec![(Type::Any, Type::Any)]) + .required("cond", SyntaxShape::MathExpression, "Condition to check.") + .required( + "then_block", + SyntaxShape::Block, + "Block to run if check succeeds.", + ) + .optional( + "else_expression", + SyntaxShape::Keyword( + b"else".to_vec(), + Box::new(SyntaxShape::OneOf(vec![ + SyntaxShape::Block, + SyntaxShape::Expression, + ])), + ), + "Expression or block to run when the condition is false.", + ) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn is_const(&self) -> bool { + true + } + + fn run_const( + &self, + working_set: &StateWorkingSet, + call: &Call, + input: PipelineData, + ) -> Result { + let call = call.assert_ast_call()?; + let cond = call.positional_nth(0).expect("checked through parser"); + let then_block = call + .positional_nth(1) + .expect("checked through parser") + .as_block() + .expect("internal error: missing block"); + let else_case = call.positional_nth(2); + + if eval_constant(working_set, cond)?.as_bool()? { + let block = working_set.get_block(then_block); + eval_const_subexpression(working_set, block, input, block.span.unwrap_or(call.head)) + } else if let Some(else_case) = else_case { + if let Some(else_expr) = else_case.as_keyword() { + if let Some(block_id) = else_expr.as_block() { + let block = working_set.get_block(block_id); + eval_const_subexpression( + working_set, + block, + input, + block.span.unwrap_or(call.head), + ) + } else { + eval_constant_with_input(working_set, else_expr, input) + } + } else { + eval_constant_with_input(working_set, else_case, input) + } + } else { + Ok(PipelineData::empty()) + } + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + // This is compiled specially by the IR compiler. The code here is never used when + // running in IR mode. + eprintln!( + "Tried to execute 'run' for the 'if' command: this code path should never be reached in IR mode" + ); + unreachable!() + } + + fn search_terms(&self) -> Vec<&str> { + vec!["else", "conditional"] + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Output a value if a condition matches, otherwise return nothing", + example: "if 2 < 3 { 'yes!' }", + result: Some(Value::test_string("yes!")), + }, + Example { + description: "Output a value if a condition matches, else return another value", + example: "if 5 < 3 { 'yes!' } else { 'no!' }", + result: Some(Value::test_string("no!")), + }, + Example { + description: "Chain multiple if's together", + example: "if 5 < 3 { 'yes!' } else if 4 < 5 { 'no!' } else { 'okay!' }", + result: Some(Value::test_string("no!")), + }, + ] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(If {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/ignore.rs b/nushell/crates/nu-cmd-lang/src/core_commands/ignore.rs new file mode 100644 index 0000000..e4810e0 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/ignore.rs @@ -0,0 +1,78 @@ +use nu_engine::command_prelude::*; +use nu_protocol::{ByteStreamSource, OutDest, engine::StateWorkingSet}; + +#[derive(Clone)] +pub struct Ignore; + +impl Command for Ignore { + fn name(&self) -> &str { + "ignore" + } + + fn description(&self) -> &str { + "Ignore the output of the previous command in the pipeline." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("ignore") + .input_output_types(vec![(Type::Any, Type::Nothing)]) + .category(Category::Core) + } + + fn search_terms(&self) -> Vec<&str> { + vec!["silent", "quiet", "out-null"] + } + + fn is_const(&self) -> bool { + true + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + mut input: PipelineData, + ) -> Result { + if let PipelineData::ByteStream(stream, _) = &mut input { + #[cfg(feature = "os")] + if let ByteStreamSource::Child(child) = stream.source_mut() { + child.ignore_error(true); + } + } + input.drain()?; + Ok(PipelineData::empty()) + } + + fn run_const( + &self, + _working_set: &StateWorkingSet, + _call: &Call, + input: PipelineData, + ) -> Result { + input.drain()?; + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Ignore the output of an echo command", + example: "echo done | ignore", + result: Some(Value::nothing(Span::test_data())), + }] + } + + fn pipe_redirection(&self) -> (Option, Option) { + (Some(OutDest::Null), None) + } +} + +#[cfg(test)] +mod test { + #[test] + fn test_examples() { + use super::Ignore; + use crate::test_examples; + test_examples(Ignore {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/let_.rs b/nushell/crates/nu-cmd-lang/src/core_commands/let_.rs new file mode 100644 index 0000000..d34badf --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/let_.rs @@ -0,0 +1,95 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct Let; + +impl Command for Let { + fn name(&self) -> &str { + "let" + } + + fn description(&self) -> &str { + "Create a variable and give it a value." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("let") + .input_output_types(vec![(Type::Any, Type::Nothing)]) + .allow_variants_without_examples(true) + .required("var_name", SyntaxShape::VarWithOptType, "Variable name.") + .required( + "initial_value", + SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::MathExpression)), + "Equals sign followed by value.", + ) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn search_terms(&self) -> Vec<&str> { + vec!["set", "const"] + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + // This is compiled specially by the IR compiler. The code here is never used when + // running in IR mode. + eprintln!( + "Tried to execute 'run' for the 'let' command: this code path should never be reached in IR mode" + ); + unreachable!() + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Set a variable to a value", + example: "let x = 10", + result: None, + }, + Example { + description: "Set a variable to the result of an expression", + example: "let x = 10 + 100", + result: None, + }, + Example { + description: "Set a variable based on the condition", + example: "let x = if false { -1 } else { 1 }", + result: None, + }, + ] + } +} + +#[cfg(test)] +mod test { + use nu_protocol::engine::CommandType; + + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(Let {}) + } + + #[test] + fn test_command_type() { + assert!(matches!(Let.command_type(), CommandType::Keyword)); + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/loop_.rs b/nushell/crates/nu-cmd-lang/src/core_commands/loop_.rs new file mode 100644 index 0000000..502fbdb --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/loop_.rs @@ -0,0 +1,67 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct Loop; + +impl Command for Loop { + fn name(&self) -> &str { + "loop" + } + + fn description(&self) -> &str { + "Run a block in a loop." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("loop") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .allow_variants_without_examples(true) + .required("block", SyntaxShape::Block, "Block to loop.") + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + // This is compiled specially by the IR compiler. The code here is never used when + // running in IR mode. + eprintln!( + "Tried to execute 'run' for the 'loop' command: this code path should never be reached in IR mode" + ); + unreachable!() + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Loop while a condition is true", + example: "mut x = 0; loop { if $x > 10 { break }; $x = $x + 1 }; $x", + result: Some(Value::test_int(11)), + }] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(Loop {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/match_.rs b/nushell/crates/nu-cmd-lang/src/core_commands/match_.rs new file mode 100644 index 0000000..677dcb0 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/match_.rs @@ -0,0 +1,112 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct Match; + +impl Command for Match { + fn name(&self) -> &str { + "match" + } + + fn description(&self) -> &str { + "Conditionally run a block on a matched value." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("match") + .input_output_types(vec![(Type::Any, Type::Any)]) + .required("value", SyntaxShape::Any, "Value to check.") + .required( + "match_block", + SyntaxShape::MatchBlock, + "Block to run if check succeeds.", + ) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + // This is compiled specially by the IR compiler. The code here is never used when + // running in IR mode. + eprintln!( + "Tried to execute 'run' for the 'match' command: this code path should never be reached in IR mode" + ); + unreachable!() + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Match on a value", + example: "match 3 { 1 => 'one', 2 => 'two', 3 => 'three' }", + result: Some(Value::test_string("three")), + }, + Example { + description: "Match against alternative values", + example: "match 'three' { 1 | 'one' => '-', 2 | 'two' => '--', 3 | 'three' => '---' }", + result: Some(Value::test_string("---")), + }, + Example { + description: "Match on a value in range", + example: "match 3 { 1..10 => 'yes!' }", + result: Some(Value::test_string("yes!")), + }, + Example { + description: "Match on a field in a record", + example: "match {a: 100} { {a: $my_value} => { $my_value } }", + result: Some(Value::test_int(100)), + }, + Example { + description: "Match with a catch-all", + example: "match 3 { 1 => { 'yes!' }, _ => { 'no!' } }", + result: Some(Value::test_string("no!")), + }, + Example { + description: "Match against a list", + example: "match [1, 2, 3] { [$a, $b, $c] => { $a + $b + $c }, _ => 0 }", + result: Some(Value::test_int(6)), + }, + Example { + description: "Match against pipeline input", + example: "{a: {b: 3}} | match $in {{a: { $b }} => ($b + 10) }", + result: Some(Value::test_int(13)), + }, + Example { + description: "Match with a guard", + example: "match [1 2 3] { + [$x, ..$y] if $x == 1 => { 'good list' }, + _ => { 'not a very good list' } + } + ", + result: Some(Value::test_string("good list")), + }, + ] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(Match {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/mod.rs b/nushell/crates/nu-cmd-lang/src/core_commands/mod.rs new file mode 100644 index 0000000..dd54fff --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/mod.rs @@ -0,0 +1,73 @@ +mod alias; +mod attr; +mod break_; +mod collect; +mod const_; +mod continue_; +mod def; +mod describe; +mod do_; +mod echo; +mod error_make; +mod export; +mod export_alias; +mod export_const; +mod export_def; +mod export_extern; +mod export_module; +mod export_use; +mod extern_; +mod for_; +mod hide; +mod hide_env; +mod if_; +mod ignore; +mod let_; +mod loop_; +mod match_; +mod module; +mod mut_; +pub(crate) mod overlay; +mod return_; +mod scope; +mod try_; +mod use_; +mod version; +mod while_; + +pub use alias::Alias; +pub use attr::*; +pub use break_::Break; +pub use collect::Collect; +pub use const_::Const; +pub use continue_::Continue; +pub use def::Def; +pub use describe::Describe; +pub use do_::Do; +pub use echo::Echo; +pub use error_make::ErrorMake; +pub use export::ExportCommand; +pub use export_alias::ExportAlias; +pub use export_const::ExportConst; +pub use export_def::ExportDef; +pub use export_extern::ExportExtern; +pub use export_module::ExportModule; +pub use export_use::ExportUse; +pub use extern_::Extern; +pub use for_::For; +pub use hide::Hide; +pub use hide_env::HideEnv; +pub use if_::If; +pub use ignore::Ignore; +pub use let_::Let; +pub use loop_::Loop; +pub use match_::Match; +pub use module::Module; +pub use mut_::Mut; +pub use overlay::*; +pub use return_::Return; +pub use scope::*; +pub use try_::Try; +pub use use_::Use; +pub use version::{VERSION_NU_FEATURES, Version}; +pub use while_::While; diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/module.rs b/nushell/crates/nu-cmd-lang/src/core_commands/module.rs new file mode 100644 index 0000000..4ed2d5c --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/module.rs @@ -0,0 +1,67 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct Module; + +impl Command for Module { + fn name(&self) -> &str { + "module" + } + + fn description(&self) -> &str { + "Define a custom module." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("module") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .allow_variants_without_examples(true) + .required("module", SyntaxShape::String, "Module name or module path.") + .optional( + "block", + SyntaxShape::Block, + "Body of the module if 'module' parameter is not a module path.", + ) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Define a custom command in a module and call it", + example: r#"module spam { export def foo [] { "foo" } }; use spam foo; foo"#, + result: Some(Value::test_string("foo")), + }, + Example { + description: "Define an environment variable in a module", + example: r#"module foo { export-env { $env.FOO = "BAZ" } }; use foo; $env.FOO"#, + result: Some(Value::test_string("BAZ")), + }, + Example { + description: "Define a custom command that participates in the environment in a module and call it", + example: r#"module foo { export def --env bar [] { $env.FOO_BAR = "BAZ" } }; use foo bar; bar; $env.FOO_BAR"#, + result: Some(Value::test_string("BAZ")), + }, + ] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/mut_.rs b/nushell/crates/nu-cmd-lang/src/core_commands/mut_.rs new file mode 100644 index 0000000..85cff33 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/mut_.rs @@ -0,0 +1,100 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct Mut; + +impl Command for Mut { + fn name(&self) -> &str { + "mut" + } + + fn description(&self) -> &str { + "Create a mutable variable and give it a value." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("mut") + .input_output_types(vec![(Type::Any, Type::Nothing)]) + .allow_variants_without_examples(true) + .required("var_name", SyntaxShape::VarWithOptType, "Variable name.") + .required( + "initial_value", + SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::MathExpression)), + "Equals sign followed by value.", + ) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn search_terms(&self) -> Vec<&str> { + vec!["set", "mutable"] + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + // This is compiled specially by the IR compiler. The code here is never used when + // running in IR mode. + eprintln!( + "Tried to execute 'run' for the 'mut' command: this code path should never be reached in IR mode" + ); + unreachable!() + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Set a mutable variable to a value, then update it", + example: "mut x = 10; $x = 12", + result: None, + }, + Example { + description: "Upsert a value inside a mutable data structure", + example: "mut a = {b:{c:1}}; $a.b.c = 2", + result: None, + }, + Example { + description: "Set a mutable variable to the result of an expression", + example: "mut x = 10 + 100", + result: None, + }, + Example { + description: "Set a mutable variable based on the condition", + example: "mut x = if false { -1 } else { 1 }", + result: None, + }, + ] + } +} + +#[cfg(test)] +mod test { + use nu_protocol::engine::CommandType; + + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(Mut {}) + } + + #[test] + fn test_command_type() { + assert!(matches!(Mut.command_type(), CommandType::Keyword)); + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/overlay/command.rs b/nushell/crates/nu-cmd-lang/src/core_commands/overlay/command.rs new file mode 100644 index 0000000..c39df28 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/overlay/command.rs @@ -0,0 +1,42 @@ +use nu_engine::{command_prelude::*, get_full_help}; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct Overlay; + +impl Command for Overlay { + fn name(&self) -> &str { + "overlay" + } + + fn signature(&self) -> Signature { + Signature::build("overlay") + .category(Category::Core) + .input_output_types(vec![(Type::Nothing, Type::String)]) + } + + fn description(&self) -> &str { + "Commands for manipulating overlays." + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html + + You must use one of the following subcommands. Using this command as-is will only produce this help message."# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + Ok(Value::string(get_full_help(self, engine_state, stack), call.head).into_pipeline_data()) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/overlay/hide.rs b/nushell/crates/nu-cmd-lang/src/core_commands/overlay/hide.rs new file mode 100644 index 0000000..666fede --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/overlay/hide.rs @@ -0,0 +1,137 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct OverlayHide; + +impl Command for OverlayHide { + fn name(&self) -> &str { + "overlay hide" + } + + fn description(&self) -> &str { + "Hide an active overlay." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("overlay hide") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .optional("name", SyntaxShape::String, "Overlay to hide.") + .switch( + "keep-custom", + "Keep all newly added commands and aliases in the next activated overlay.", + Some('k'), + ) + .named( + "keep-env", + SyntaxShape::List(Box::new(SyntaxShape::String)), + "List of environment variables to keep in the next activated overlay", + Some('e'), + ) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let overlay_name: Spanned = if let Some(name) = call.opt(engine_state, stack, 0)? { + name + } else { + Spanned { + item: stack.last_overlay_name()?, + span: call.head, + } + }; + + if !stack.is_overlay_active(&overlay_name.item) { + return Err(ShellError::OverlayNotFoundAtRuntime { + overlay_name: overlay_name.item, + span: overlay_name.span, + }); + } + + let keep_env: Option>> = + call.get_flag(engine_state, stack, "keep-env")?; + + let env_vars_to_keep = if let Some(env_var_names_to_keep) = keep_env { + let mut env_vars_to_keep = vec![]; + + for name in env_var_names_to_keep.into_iter() { + match stack.get_env_var(engine_state, &name.item) { + Some(val) => env_vars_to_keep.push((name.item, val.clone())), + None => { + return Err(ShellError::EnvVarNotFoundAtRuntime { + envvar_name: name.item, + span: name.span, + }); + } + } + } + + env_vars_to_keep + } else { + vec![] + }; + + // also restore env vars which has been hidden + let env_vars_to_restore = stack.get_hidden_env_vars(&overlay_name.item, engine_state); + stack.remove_overlay(&overlay_name.item); + for (name, val) in env_vars_to_restore { + stack.add_env_var(name, val); + } + + for (name, val) in env_vars_to_keep { + stack.add_env_var(name, val); + } + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Keep a custom command after hiding the overlay", + example: r#"module spam { export def foo [] { "foo" } } + overlay use spam + def bar [] { "bar" } + overlay hide spam --keep-custom + bar + "#, + result: None, + }, + Example { + description: "Hide an overlay created from a file", + example: r#"'export alias f = "foo"' | save spam.nu + overlay use spam.nu + overlay hide spam"#, + result: None, + }, + Example { + description: "Hide the last activated overlay", + example: r#"module spam { export-env { $env.FOO = "foo" } } + overlay use spam + overlay hide"#, + result: None, + }, + Example { + description: "Keep the current working directory when removing an overlay", + example: r#"overlay new spam + cd some-dir + overlay hide --keep-env [ PWD ] spam"#, + result: None, + }, + ] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/overlay/list.rs b/nushell/crates/nu-cmd-lang/src/core_commands/overlay/list.rs new file mode 100644 index 0000000..d646d63 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/overlay/list.rs @@ -0,0 +1,50 @@ +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct OverlayList; + +impl Command for OverlayList { + fn name(&self) -> &str { + "overlay list" + } + + fn description(&self) -> &str { + "List all active overlays." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("overlay list") + .category(Category::Core) + .input_output_types(vec![(Type::Nothing, Type::List(Box::new(Type::String)))]) + } + + fn extra_description(&self) -> &str { + "The overlays are listed in the order they were activated." + } + + fn run( + &self, + _engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let active_overlays_engine: Vec = stack + .active_overlays + .iter() + .map(|s| Value::string(s, call.head)) + .collect(); + + Ok(Value::list(active_overlays_engine, call.head).into_pipeline_data()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Get the last activated overlay", + example: r#"module spam { export def foo [] { "foo" } } + overlay use spam + overlay list | last"#, + result: Some(Value::test_string("spam")), + }] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/overlay/mod.rs b/nushell/crates/nu-cmd-lang/src/core_commands/overlay/mod.rs new file mode 100644 index 0000000..23ca1f9 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/overlay/mod.rs @@ -0,0 +1,11 @@ +mod command; +mod hide; +mod list; +mod new; +mod use_; + +pub use command::Overlay; +pub use hide::OverlayHide; +pub use list::OverlayList; +pub use new::OverlayNew; +pub use use_::OverlayUse; diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/overlay/new.rs b/nushell/crates/nu-cmd-lang/src/core_commands/overlay/new.rs new file mode 100644 index 0000000..fa1acbc --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/overlay/new.rs @@ -0,0 +1,86 @@ +use nu_engine::{command_prelude::*, redirect_env}; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct OverlayNew; + +impl Command for OverlayNew { + fn name(&self) -> &str { + "overlay new" + } + + fn description(&self) -> &str { + "Create an empty overlay." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("overlay new") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .allow_variants_without_examples(true) + .required("name", SyntaxShape::String, "Name of the overlay.") + .switch( + "reload", + "If the overlay already exists, reload its environment.", + Some('r'), + ) + // TODO: + // .switch( + // "prefix", + // "Prepend module name to the imported symbols", + // Some('p'), + // ) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"The command will first create an empty module, then add it as an overlay. + +This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + engine_state: &EngineState, + caller_stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let name_arg: Spanned = call.req(engine_state, caller_stack, 0)?; + let reload = call.has_flag(engine_state, caller_stack, "reload")?; + + if reload { + let callee_stack = caller_stack.clone(); + caller_stack.add_overlay(name_arg.item); + redirect_env(engine_state, caller_stack, &callee_stack); + } else { + caller_stack.add_overlay(name_arg.item); + } + + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Create an empty overlay", + example: r#"overlay new spam"#, + result: None, + }] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(OverlayNew {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/overlay/use_.rs b/nushell/crates/nu-cmd-lang/src/core_commands/overlay/use_.rs new file mode 100644 index 0000000..bf29087 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/overlay/use_.rs @@ -0,0 +1,230 @@ +use nu_engine::{ + command_prelude::*, find_in_dirs_env, get_dirs_var_from_call, get_eval_block, redirect_env, +}; +use nu_parser::trim_quotes_str; +use nu_protocol::{ModuleId, ast::Expr, engine::CommandType}; + +use std::path::Path; + +#[derive(Clone)] +pub struct OverlayUse; + +impl Command for OverlayUse { + fn name(&self) -> &str { + "overlay use" + } + + fn description(&self) -> &str { + "Use definitions from a module as an overlay." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("overlay use") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .allow_variants_without_examples(true) + .required( + "name", + SyntaxShape::OneOf(vec![SyntaxShape::String, SyntaxShape::Nothing]), + "Module name to use overlay for (`null` for no-op).", + ) + .optional( + "as", + SyntaxShape::Keyword(b"as".to_vec(), Box::new(SyntaxShape::String)), + "`as` keyword followed by a new name.", + ) + .switch( + "prefix", + "Prepend module name to the imported commands and aliases", + Some('p'), + ) + .switch( + "reload", + "If the overlay already exists, reload its definitions and environment.", + Some('r'), + ) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + engine_state: &EngineState, + caller_stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let noop = call.get_parser_info(caller_stack, "noop"); + if noop.is_some() { + return Ok(PipelineData::empty()); + } + + let mut name_arg: Spanned = call.req(engine_state, caller_stack, 0)?; + name_arg.item = trim_quotes_str(&name_arg.item).to_string(); + + let maybe_origin_module_id: Option = + if let Some(overlay_expr) = call.get_parser_info(caller_stack, "overlay_expr") { + if let Expr::Overlay(module_id) = &overlay_expr.expr { + *module_id + } else { + return Err(ShellError::NushellFailedSpanned { + msg: "Not an overlay".to_string(), + label: "requires an overlay (path or a string)".to_string(), + span: overlay_expr.span, + }); + } + } else { + return Err(ShellError::NushellFailedSpanned { + msg: "Missing positional".to_string(), + label: "missing required overlay".to_string(), + span: call.head, + }); + }; + + let overlay_name = if let Some(name) = call.opt(engine_state, caller_stack, 1)? { + name + } else if engine_state + .find_overlay(name_arg.item.as_bytes()) + .is_some() + { + name_arg.item.clone() + } else if let Some(os_str) = Path::new(&name_arg.item).file_stem() { + if let Some(name) = os_str.to_str() { + name.to_string() + } else { + return Err(ShellError::NonUtf8 { + span: name_arg.span, + }); + } + } else { + return Err(ShellError::OverlayNotFoundAtRuntime { + overlay_name: name_arg.item, + span: name_arg.span, + }); + }; + + if let Some(module_id) = maybe_origin_module_id { + // Add environment variables only if (determined by parser): + // a) adding a new overlay + // b) refreshing an active overlay (the origin module changed) + + let module = engine_state.get_module(module_id); + // in such case, should also make sure that PWD is not restored in old overlays. + let cwd = caller_stack.get_env_var(engine_state, "PWD").cloned(); + + // Evaluate the export-env block (if any) and keep its environment + if let Some(block_id) = module.env_block { + let maybe_file_path_or_dir = find_in_dirs_env( + &name_arg.item, + engine_state, + caller_stack, + get_dirs_var_from_call(caller_stack, call), + )?; + let block = engine_state.get_block(block_id); + let mut callee_stack = caller_stack + .gather_captures(engine_state, &block.captures) + .reset_pipes(); + + if let Some(path) = &maybe_file_path_or_dir { + // Set the currently evaluated directory, if the argument is a valid path + let parent = if path.is_dir() { + path.clone() + } else { + let mut parent = path.clone(); + parent.pop(); + parent + }; + let file_pwd = Value::string(parent.to_string_lossy(), call.head); + + callee_stack.add_env_var("FILE_PWD".to_string(), file_pwd); + } + + if let Some(path) = &maybe_file_path_or_dir { + let module_file_path = if path.is_dir() { + // the existence of `mod.nu` is verified in parsing time + // so it's safe to use it here. + Value::string(path.join("mod.nu").to_string_lossy(), call.head) + } else { + Value::string(path.to_string_lossy(), call.head) + }; + callee_stack.add_env_var("CURRENT_FILE".to_string(), module_file_path); + } + + let eval_block = get_eval_block(engine_state); + let _ = eval_block(engine_state, &mut callee_stack, block, input); + + // The export-env block should see the env vars *before* activating this overlay + caller_stack.add_overlay(overlay_name); + // make sure that PWD is not restored in old overlays. + if let Some(cwd) = cwd { + caller_stack.add_env_var("PWD".to_string(), cwd); + } + + // Merge the block's environment to the current stack + redirect_env(engine_state, caller_stack, &callee_stack); + } else { + caller_stack.add_overlay(overlay_name); + // make sure that PWD is not restored in old overlays. + if let Some(cwd) = cwd { + caller_stack.add_env_var("PWD".to_string(), cwd); + } + } + } else { + caller_stack.add_overlay(overlay_name); + } + + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Create an overlay from a module", + example: r#"module spam { export def foo [] { "foo" } } + overlay use spam + foo"#, + result: None, + }, + Example { + description: "Create an overlay from a module and rename it", + example: r#"module spam { export def foo [] { "foo" } } + overlay use spam as spam_new + foo"#, + result: None, + }, + Example { + description: "Create an overlay with a prefix", + example: r#"'export def foo { "foo" }' + overlay use --prefix spam + spam foo"#, + result: None, + }, + Example { + description: "Create an overlay from a file", + example: r#"'export-env { $env.FOO = "foo" }' | save spam.nu + overlay use spam.nu + $env.FOO"#, + result: None, + }, + ] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(OverlayUse {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/return_.rs b/nushell/crates/nu-cmd-lang/src/core_commands/return_.rs new file mode 100644 index 0000000..72a46d1 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/return_.rs @@ -0,0 +1,58 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct Return; + +impl Command for Return { + fn name(&self) -> &str { + "return" + } + + fn description(&self) -> &str { + "Return early from a custom command." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("return") + .input_output_types(vec![(Type::Nothing, Type::Any)]) + .optional( + "return_value", + SyntaxShape::Any, + "Optional value to return.", + ) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + // This is compiled specially by the IR compiler. The code here is never used when + // running in IR mode. + eprintln!( + "Tried to execute 'run' for the 'return' command: this code path should never be reached in IR mode" + ); + unreachable!() + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Return early", + example: r#"def foo [] { return }"#, + result: None, + }] + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/scope/aliases.rs b/nushell/crates/nu-cmd-lang/src/core_commands/scope/aliases.rs new file mode 100644 index 0000000..6e5290a --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/scope/aliases.rs @@ -0,0 +1,54 @@ +use nu_engine::{command_prelude::*, scope::ScopeData}; + +#[derive(Clone)] +pub struct ScopeAliases; + +impl Command for ScopeAliases { + fn name(&self) -> &str { + "scope aliases" + } + + fn signature(&self) -> Signature { + Signature::build("scope aliases") + .input_output_types(vec![(Type::Nothing, Type::Any)]) + .allow_variants_without_examples(true) + .category(Category::Core) + } + + fn description(&self) -> &str { + "Output info on the aliases in the current scope." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let head = call.head; + let mut scope_data = ScopeData::new(engine_state, stack); + scope_data.populate_decls(); + Ok(Value::list(scope_data.collect_aliases(head), head).into_pipeline_data()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Show the aliases in the current scope", + example: "scope aliases", + result: None, + }] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(ScopeAliases {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/scope/command.rs b/nushell/crates/nu-cmd-lang/src/core_commands/scope/command.rs new file mode 100644 index 0000000..5e252c0 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/scope/command.rs @@ -0,0 +1,31 @@ +use nu_engine::{command_prelude::*, get_full_help}; + +#[derive(Clone)] +pub struct Scope; + +impl Command for Scope { + fn name(&self) -> &str { + "scope" + } + + fn signature(&self) -> Signature { + Signature::build("scope") + .category(Category::Core) + .input_output_types(vec![(Type::Nothing, Type::String)]) + .allow_variants_without_examples(true) + } + + fn description(&self) -> &str { + "Commands for getting info about what is in scope." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + Ok(Value::string(get_full_help(self, engine_state, stack), call.head).into_pipeline_data()) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/scope/commands.rs b/nushell/crates/nu-cmd-lang/src/core_commands/scope/commands.rs new file mode 100644 index 0000000..a1fcd7b --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/scope/commands.rs @@ -0,0 +1,54 @@ +use nu_engine::{command_prelude::*, scope::ScopeData}; + +#[derive(Clone)] +pub struct ScopeCommands; + +impl Command for ScopeCommands { + fn name(&self) -> &str { + "scope commands" + } + + fn signature(&self) -> Signature { + Signature::build("scope commands") + .input_output_types(vec![(Type::Nothing, Type::List(Box::new(Type::Any)))]) + .allow_variants_without_examples(true) + .category(Category::Core) + } + + fn description(&self) -> &str { + "Output info on the commands in the current scope." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let head = call.head; + let mut scope_data = ScopeData::new(engine_state, stack); + scope_data.populate_decls(); + Ok(Value::list(scope_data.collect_commands(head), head).into_pipeline_data()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Show the commands in the current scope", + example: "scope commands", + result: None, + }] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(ScopeCommands {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/scope/engine_stats.rs b/nushell/crates/nu-cmd-lang/src/core_commands/scope/engine_stats.rs new file mode 100644 index 0000000..3109ef2 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/scope/engine_stats.rs @@ -0,0 +1,55 @@ +use nu_engine::{command_prelude::*, scope::ScopeData}; + +#[derive(Clone)] +pub struct ScopeEngineStats; + +impl Command for ScopeEngineStats { + fn name(&self) -> &str { + "scope engine-stats" + } + + fn signature(&self) -> Signature { + Signature::build("scope engine-stats") + .input_output_types(vec![(Type::Nothing, Type::Any)]) + .allow_variants_without_examples(true) + .category(Category::Core) + } + + fn description(&self) -> &str { + "Output stats on the engine in the current state." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let span = call.head; + + let scope_data = ScopeData::new(engine_state, stack); + + Ok(scope_data.collect_engine_state(span).into_pipeline_data()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Show the stats on the current engine state", + example: "scope engine-stats", + result: None, + }] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(ScopeEngineStats {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/scope/externs.rs b/nushell/crates/nu-cmd-lang/src/core_commands/scope/externs.rs new file mode 100644 index 0000000..fc7980c --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/scope/externs.rs @@ -0,0 +1,54 @@ +use nu_engine::{command_prelude::*, scope::ScopeData}; + +#[derive(Clone)] +pub struct ScopeExterns; + +impl Command for ScopeExterns { + fn name(&self) -> &str { + "scope externs" + } + + fn signature(&self) -> Signature { + Signature::build("scope externs") + .input_output_types(vec![(Type::Nothing, Type::Any)]) + .allow_variants_without_examples(true) + .category(Category::Core) + } + + fn description(&self) -> &str { + "Output info on the known externals in the current scope." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let head = call.head; + let mut scope_data = ScopeData::new(engine_state, stack); + scope_data.populate_decls(); + Ok(Value::list(scope_data.collect_externs(head), head).into_pipeline_data()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Show the known externals in the current scope", + example: "scope externs", + result: None, + }] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(ScopeExterns {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/scope/mod.rs b/nushell/crates/nu-cmd-lang/src/core_commands/scope/mod.rs new file mode 100644 index 0000000..1a65812 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/scope/mod.rs @@ -0,0 +1,15 @@ +mod aliases; +mod command; +mod commands; +mod engine_stats; +mod externs; +mod modules; +mod variables; + +pub use aliases::*; +pub use command::*; +pub use commands::*; +pub use engine_stats::*; +pub use externs::*; +pub use modules::*; +pub use variables::*; diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/scope/modules.rs b/nushell/crates/nu-cmd-lang/src/core_commands/scope/modules.rs new file mode 100644 index 0000000..1f5ca9e --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/scope/modules.rs @@ -0,0 +1,54 @@ +use nu_engine::{command_prelude::*, scope::ScopeData}; + +#[derive(Clone)] +pub struct ScopeModules; + +impl Command for ScopeModules { + fn name(&self) -> &str { + "scope modules" + } + + fn signature(&self) -> Signature { + Signature::build("scope modules") + .input_output_types(vec![(Type::Nothing, Type::Any)]) + .allow_variants_without_examples(true) + .category(Category::Core) + } + + fn description(&self) -> &str { + "Output info on the modules in the current scope." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let head = call.head; + let mut scope_data = ScopeData::new(engine_state, stack); + scope_data.populate_modules(); + Ok(Value::list(scope_data.collect_modules(head), head).into_pipeline_data()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Show the modules in the current scope", + example: "scope modules", + result: None, + }] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(ScopeModules {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/scope/variables.rs b/nushell/crates/nu-cmd-lang/src/core_commands/scope/variables.rs new file mode 100644 index 0000000..c07eb76 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/scope/variables.rs @@ -0,0 +1,54 @@ +use nu_engine::{command_prelude::*, scope::ScopeData}; + +#[derive(Clone)] +pub struct ScopeVariables; + +impl Command for ScopeVariables { + fn name(&self) -> &str { + "scope variables" + } + + fn signature(&self) -> Signature { + Signature::build("scope variables") + .input_output_types(vec![(Type::Nothing, Type::Any)]) + .allow_variants_without_examples(true) + .category(Category::Core) + } + + fn description(&self) -> &str { + "Output info on the variables in the current scope." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let head = call.head; + let mut scope_data = ScopeData::new(engine_state, stack); + scope_data.populate_vars(); + Ok(Value::list(scope_data.collect_vars(head), head).into_pipeline_data()) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Show the variables in the current scope", + example: "scope variables", + result: None, + }] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(ScopeVariables {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/try_.rs b/nushell/crates/nu-cmd-lang/src/core_commands/try_.rs new file mode 100644 index 0000000..e0570cb --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/try_.rs @@ -0,0 +1,89 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct Try; + +impl Command for Try { + fn name(&self) -> &str { + "try" + } + + fn description(&self) -> &str { + "Try to run a block, if it fails optionally run a catch closure." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("try") + .input_output_types(vec![(Type::Any, Type::Any)]) + .required("try_block", SyntaxShape::Block, "Block to run.") + .optional( + "catch_closure", + SyntaxShape::Keyword( + b"catch".to_vec(), + Box::new(SyntaxShape::OneOf(vec![ + SyntaxShape::Closure(None), + SyntaxShape::Closure(Some(vec![SyntaxShape::Any])), + ])), + ), + "Closure to run if try block fails.", + ) + .category(Category::Core) + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + // This is compiled specially by the IR compiler. The code here is never used when + // running in IR mode. + eprintln!( + "Tried to execute 'run' for the 'try' command: this code path should never be reached in IR mode" + ); + unreachable!(); + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Try to run a division by zero", + example: "try { 1 / 0 }", + result: None, + }, + Example { + description: "Try to run a division by zero and return a string instead", + example: "try { 1 / 0 } catch { 'divided by zero' }", + result: Some(Value::test_string("divided by zero")), + }, + Example { + description: "Try to run a division by zero and report the message", + example: "try { 1 / 0 } catch { |err| $err.msg }", + result: None, + }, + ] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(Try {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/use_.rs b/nushell/crates/nu-cmd-lang/src/core_commands/use_.rs new file mode 100644 index 0000000..3968e28 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/use_.rs @@ -0,0 +1,213 @@ +use nu_engine::{ + command_prelude::*, find_in_dirs_env, get_dirs_var_from_call, get_eval_block, redirect_env, +}; +use nu_protocol::{ + ast::{Expr, Expression}, + engine::CommandType, +}; + +#[derive(Clone)] +pub struct Use; + +impl Command for Use { + fn name(&self) -> &str { + "use" + } + + fn description(&self) -> &str { + "Use definitions from a module, making them available in your shell." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("use") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .allow_variants_without_examples(true) + .required( + "module", + SyntaxShape::OneOf(vec![SyntaxShape::String, SyntaxShape::Nothing]), + "Module or module file (`null` for no-op).", + ) + .rest( + "members", + SyntaxShape::Any, + "Which members of the module to import.", + ) + .category(Category::Core) + } + + fn search_terms(&self) -> Vec<&str> { + vec!["module", "import", "include", "scope"] + } + + fn extra_description(&self) -> &str { + r#"See `help std` for the standard library module. +See `help modules` to list all available modules. + +This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + engine_state: &EngineState, + caller_stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + if call.get_parser_info(caller_stack, "noop").is_some() { + return Ok(PipelineData::empty()); + } + let Some(Expression { + expr: Expr::ImportPattern(import_pattern), + .. + }) = call.get_parser_info(caller_stack, "import_pattern") + else { + return Err(ShellError::GenericError { + error: "Unexpected import".into(), + msg: "import pattern not supported".into(), + span: Some(call.head), + help: None, + inner: vec![], + }); + }; + + // Necessary so that we can modify the stack. + let import_pattern = import_pattern.clone(); + + if let Some(module_id) = import_pattern.head.id { + // Add constants + for var_id in &import_pattern.constants { + let var = engine_state.get_var(*var_id); + + if let Some(constval) = &var.const_val { + caller_stack.add_var(*var_id, constval.clone()); + } else { + return Err(ShellError::NushellFailedSpanned { + msg: "Missing Constant".to_string(), + label: "constant not added by the parser".to_string(), + span: var.declaration_span, + }); + } + } + + // Evaluate the export-env block if there is one + let module = engine_state.get_module(module_id); + + if let Some(block_id) = module.env_block { + let block = engine_state.get_block(block_id); + + // See if the module is a file + let module_arg_str = String::from_utf8_lossy( + engine_state.get_span_contents(import_pattern.head.span), + ); + + let maybe_file_path_or_dir = find_in_dirs_env( + &module_arg_str, + engine_state, + caller_stack, + get_dirs_var_from_call(caller_stack, call), + )?; + // module_arg_str maybe a directory, in this case + // find_in_dirs_env returns a directory. + let maybe_parent = maybe_file_path_or_dir.as_ref().and_then(|path| { + if path.is_dir() { + Some(path.to_path_buf()) + } else { + path.parent().map(|p| p.to_path_buf()) + } + }); + + let mut callee_stack = caller_stack + .gather_captures(engine_state, &block.captures) + .reset_pipes(); + + // If so, set the currently evaluated directory (file-relative PWD) + if let Some(parent) = maybe_parent { + let file_pwd = Value::string(parent.to_string_lossy(), call.head); + callee_stack.add_env_var("FILE_PWD".to_string(), file_pwd); + } + + if let Some(path) = maybe_file_path_or_dir { + let module_file_path = if path.is_dir() { + // the existence of `mod.nu` is verified in parsing time + // so it's safe to use it here. + Value::string(path.join("mod.nu").to_string_lossy(), call.head) + } else { + Value::string(path.to_string_lossy(), call.head) + }; + callee_stack.add_env_var("CURRENT_FILE".to_string(), module_file_path); + } + + let eval_block = get_eval_block(engine_state); + + // Run the block (discard the result) + let _ = eval_block(engine_state, &mut callee_stack, block, input)?; + + // Merge the block's environment to the current stack + redirect_env(engine_state, caller_stack, &callee_stack); + } + } else { + return Err(ShellError::GenericError { + error: format!( + "Could not import from '{}'", + String::from_utf8_lossy(&import_pattern.head.name) + ), + msg: "module does not exist".to_string(), + span: Some(import_pattern.head.span), + help: None, + inner: vec![], + }); + } + + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Define a custom command in a module and call it", + example: r#"module spam { export def foo [] { "foo" } }; use spam foo; foo"#, + result: Some(Value::test_string("foo")), + }, + Example { + description: "Define a custom command that participates in the environment in a module and call it", + example: r#"module foo { export def --env bar [] { $env.FOO_BAR = "BAZ" } }; use foo bar; bar; $env.FOO_BAR"#, + result: Some(Value::test_string("BAZ")), + }, + Example { + description: "Use a plain module name to import its definitions qualified by the module name", + example: r#"module spam { export def foo [] { "foo" }; export def bar [] { "bar" } }; use spam; (spam foo) + (spam bar)"#, + result: Some(Value::test_string("foobar")), + }, + Example { + description: "Specify * to use all definitions in a module", + example: r#"module spam { export def foo [] { "foo" }; export def bar [] { "bar" } }; use spam *; (foo) + (bar)"#, + result: Some(Value::test_string("foobar")), + }, + Example { + description: "To use commands with spaces, like subcommands, surround them with quotes", + example: r#"module spam { export def 'foo bar' [] { "baz" } }; use spam 'foo bar'; foo bar"#, + result: Some(Value::test_string("baz")), + }, + Example { + description: "To use multiple definitions from a module, wrap them in a list", + example: r#"module spam { export def foo [] { "foo" }; export def 'foo bar' [] { "baz" } }; use spam ['foo', 'foo bar']; (foo) + (foo bar)"#, + result: Some(Value::test_string("foobaz")), + }, + ] + } +} + +#[cfg(test)] +mod test { + #[test] + fn test_examples() { + use super::Use; + use crate::test_examples; + test_examples(Use {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/version.rs b/nushell/crates/nu-cmd-lang/src/core_commands/version.rs new file mode 100644 index 0000000..eee2d34 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/version.rs @@ -0,0 +1,222 @@ +use std::{borrow::Cow, sync::OnceLock}; + +use itertools::Itertools; +use nu_engine::command_prelude::*; +use nu_protocol::engine::StateWorkingSet; +use shadow_rs::shadow; + +shadow!(build); + +/// Static container for the cargo features used by the `version` command. +/// +/// This `OnceLock` holds the features from `nu`. +/// When you build `nu_cmd_lang`, Cargo doesn't pass along the same features that `nu` itself uses. +/// By setting this static before calling `version`, you make it show `nu`'s features instead +/// of `nu_cmd_lang`'s. +/// +/// Embedders can set this to any feature list they need, but in most cases you'll probably want to +/// pass the cargo features of your host binary. +/// +/// # How to get cargo features in your build script +/// +/// In your binary's build script: +/// ```rust,ignore +/// // Re-export CARGO_CFG_FEATURE to the main binary. +/// // It holds all the features that cargo sets for your binary as a comma-separated list. +/// println!( +/// "cargo:rustc-env=NU_FEATURES={}", +/// std::env::var("CARGO_CFG_FEATURE").expect("set by cargo") +/// ); +/// ``` +/// +/// Then, before you call `version`: +/// ```rust,ignore +/// // This uses static strings, but since we're using `Cow`, you can also pass owned strings. +/// let features = env!("NU_FEATURES") +/// .split(',') +/// .map(Cow::Borrowed) +/// .collect(); +/// +/// nu_cmd_lang::VERSION_NU_FEATURES +/// .set(features) +/// .expect("couldn't set VERSION_NU_FEATURES"); +/// ``` +pub static VERSION_NU_FEATURES: OnceLock>> = OnceLock::new(); + +#[derive(Clone)] +pub struct Version; + +impl Command for Version { + fn name(&self) -> &str { + "version" + } + + fn signature(&self) -> Signature { + Signature::build("version") + .input_output_types(vec![(Type::Nothing, Type::record())]) + .allow_variants_without_examples(true) + .category(Category::Core) + } + + fn description(&self) -> &str { + "Display Nu version, and its build configuration." + } + + fn is_const(&self) -> bool { + true + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + version(engine_state, call.head) + } + + fn run_const( + &self, + working_set: &StateWorkingSet, + call: &Call, + _input: PipelineData, + ) -> Result { + version(working_set.permanent(), call.head) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Display Nu version", + example: "version", + result: None, + }] + } +} + +fn push_non_empty(record: &mut Record, name: &str, value: &str, span: Span) { + if !value.is_empty() { + record.push(name, Value::string(value, span)) + } +} + +pub fn version(engine_state: &EngineState, span: Span) -> Result { + // Pre-allocate the arrays in the worst case (17 items): + // - version + // - major + // - minor + // - patch + // - pre + // - branch + // - commit_hash + // - build_os + // - build_target + // - rust_version + // - rust_channel + // - cargo_version + // - build_time + // - build_rust_channel + // - allocator + // - features + // - installed_plugins + let mut record = Record::with_capacity(17); + + record.push("version", Value::string(env!("CARGO_PKG_VERSION"), span)); + + push_version_numbers(&mut record, span); + + push_non_empty(&mut record, "pre", build::PKG_VERSION_PRE, span); + + record.push("branch", Value::string(build::BRANCH, span)); + + if let Some(commit_hash) = option_env!("NU_COMMIT_HASH") { + record.push("commit_hash", Value::string(commit_hash, span)); + } + + push_non_empty(&mut record, "build_os", build::BUILD_OS, span); + push_non_empty(&mut record, "build_target", build::BUILD_TARGET, span); + push_non_empty(&mut record, "rust_version", build::RUST_VERSION, span); + push_non_empty(&mut record, "rust_channel", build::RUST_CHANNEL, span); + push_non_empty(&mut record, "cargo_version", build::CARGO_VERSION, span); + push_non_empty(&mut record, "build_time", build::BUILD_TIME, span); + push_non_empty( + &mut record, + "build_rust_channel", + build::BUILD_RUST_CHANNEL, + span, + ); + + record.push("allocator", Value::string(global_allocator(), span)); + + record.push( + "features", + Value::string( + VERSION_NU_FEATURES + .get() + .as_ref() + .map(|v| v.as_slice()) + .unwrap_or_default() + .iter() + .filter(|f| !f.starts_with("dep:")) + .join(", "), + span, + ), + ); + + #[cfg(not(feature = "plugin"))] + let _ = engine_state; + + #[cfg(feature = "plugin")] + { + // Get a list of plugin names and versions if present + let installed_plugins = engine_state + .plugins() + .iter() + .map(|x| { + let name = x.identity().name(); + if let Some(version) = x.metadata().and_then(|m| m.version) { + format!("{name} {version}") + } else { + name.into() + } + }) + .collect::>(); + + record.push( + "installed_plugins", + Value::string(installed_plugins.join(", "), span), + ); + } + + Ok(Value::record(record, span).into_pipeline_data()) +} + +/// Add version numbers as integers to the given record +fn push_version_numbers(record: &mut Record, head: Span) { + static VERSION_NUMBERS: OnceLock<(u8, u8, u8)> = OnceLock::new(); + + let &(major, minor, patch) = VERSION_NUMBERS.get_or_init(|| { + ( + build::PKG_VERSION_MAJOR.parse().expect("Always set"), + build::PKG_VERSION_MINOR.parse().expect("Always set"), + build::PKG_VERSION_PATCH.parse().expect("Always set"), + ) + }); + record.push("major", Value::int(major.into(), head)); + record.push("minor", Value::int(minor.into(), head)); + record.push("patch", Value::int(patch.into(), head)); +} + +fn global_allocator() -> &'static str { + "standard" +} + +#[cfg(test)] +mod test { + #[test] + fn test_examples() { + use super::Version; + use crate::test_examples; + test_examples(Version) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/core_commands/while_.rs b/nushell/crates/nu-cmd-lang/src/core_commands/while_.rs new file mode 100644 index 0000000..b64a0ec --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/core_commands/while_.rs @@ -0,0 +1,76 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct While; + +impl Command for While { + fn name(&self) -> &str { + "while" + } + + fn description(&self) -> &str { + "Conditionally run a block in a loop." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("while") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .allow_variants_without_examples(true) + .required("cond", SyntaxShape::MathExpression, "Condition to check.") + .required( + "block", + SyntaxShape::Block, + "Block to loop if check succeeds.", + ) + .category(Category::Core) + } + + fn search_terms(&self) -> Vec<&str> { + vec!["loop"] + } + + fn extra_description(&self) -> &str { + r#"This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html"# + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + // This is compiled specially by the IR compiler. The code here is never used when + // running in IR mode. + eprintln!( + "Tried to execute 'run' for the 'while' command: this code path should never be reached in IR mode" + ); + unreachable!() + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Loop while a condition is true", + example: "mut x = 0; while $x < 10 { $x = $x + 1 }", + result: None, + }] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(While {}) + } +} diff --git a/nushell/crates/nu-cmd-lang/src/default_context.rs b/nushell/crates/nu-cmd-lang/src/default_context.rs new file mode 100644 index 0000000..e3b0d2d --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/default_context.rs @@ -0,0 +1,77 @@ +use crate::*; +use nu_protocol::engine::{EngineState, StateWorkingSet}; + +pub fn create_default_context() -> EngineState { + let mut engine_state = EngineState::new(); + + let delta = { + let mut working_set = StateWorkingSet::new(&engine_state); + + macro_rules! bind_command { + ( $( $command:expr ),* $(,)? ) => { + $( working_set.add_decl(Box::new($command)); )* + }; + } + + // Core + bind_command! { + Alias, + AttrCategory, + AttrDeprecated, + AttrExample, + AttrSearchTerms, + Break, + Collect, + Const, + Continue, + Def, + Describe, + Do, + Echo, + ErrorMake, + ExportAlias, + ExportCommand, + ExportConst, + ExportDef, + ExportExtern, + ExportUse, + ExportModule, + Extern, + For, + Hide, + HideEnv, + If, + Ignore, + Overlay, + OverlayUse, + OverlayList, + OverlayNew, + OverlayHide, + Let, + Loop, + Match, + Module, + Mut, + Return, + Scope, + ScopeAliases, + ScopeCommands, + ScopeEngineStats, + ScopeExterns, + ScopeModules, + ScopeVariables, + Try, + Use, + Version, + While, + }; + + working_set.render() + }; + + if let Err(err) = engine_state.merge_delta(delta) { + eprintln!("Error creating default context: {err:?}"); + } + + engine_state +} diff --git a/nushell/crates/nu-cmd-lang/src/example_support.rs b/nushell/crates/nu-cmd-lang/src/example_support.rs new file mode 100644 index 0000000..d78e606 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/example_support.rs @@ -0,0 +1,327 @@ +use itertools::Itertools; +use nu_engine::{command_prelude::*, compile}; +use nu_protocol::{ + Range, ast::Block, debugger::WithoutDebug, engine::StateWorkingSet, report_shell_error, +}; +use std::{ + sync::Arc, + {collections::HashSet, ops::Bound}, +}; + +pub fn check_example_input_and_output_types_match_command_signature( + example: &Example, + cwd: &std::path::Path, + engine_state: &mut Box, + signature_input_output_types: &[(Type, Type)], + signature_operates_on_cell_paths: bool, +) -> HashSet<(Type, Type)> { + let mut witnessed_type_transformations = HashSet::<(Type, Type)>::new(); + + // Skip tests that don't have results to compare to + if let Some(example_output) = example.result.as_ref() { + if let Some(example_input) = + eval_pipeline_without_terminal_expression(example.example, cwd, engine_state) + { + let example_matches_signature = + signature_input_output_types + .iter() + .any(|(sig_in_type, sig_out_type)| { + example_input.is_subtype_of(sig_in_type) + && example_output.is_subtype_of(sig_out_type) + && { + witnessed_type_transformations + .insert((sig_in_type.clone(), sig_out_type.clone())); + true + } + }); + + let example_input_type = example_input.get_type(); + let example_output_type = example_output.get_type(); + + // The example type checks as a cell path operation if both: + // 1. The command is declared to operate on cell paths. + // 2. The example_input_type is list or record or table, and the example + // output shape is the same as the input shape. + let example_matches_signature_via_cell_path_operation = signature_operates_on_cell_paths + && example_input_type.accepts_cell_paths() + // TODO: This is too permissive; it should make use of the signature.input_output_types at least. + && example_output_type.to_shape() == example_input_type.to_shape(); + + if !(example_matches_signature || example_matches_signature_via_cell_path_operation) { + panic!( + "The example `{}` demonstrates a transformation of type {:?} -> {:?}. \ + However, this does not match the declared signature: {:?}.{} \ + For this command `operates_on_cell_paths()` is {}.", + example.example, + example_input_type, + example_output_type, + signature_input_output_types, + if signature_input_output_types.is_empty() { + " (Did you forget to declare the input and output types for the command?)" + } else { + "" + }, + signature_operates_on_cell_paths + ); + }; + }; + } + witnessed_type_transformations +} + +pub fn eval_pipeline_without_terminal_expression( + src: &str, + cwd: &std::path::Path, + engine_state: &mut Box, +) -> Option { + let (mut block, mut working_set) = parse(src, engine_state); + if block.pipelines.len() == 1 { + let n_expressions = block.pipelines[0].elements.len(); + // Modify the block to remove the last element and recompile it + { + let mut_block = Arc::make_mut(&mut block); + mut_block.pipelines[0].elements.truncate(n_expressions - 1); + mut_block.ir_block = Some(compile(&working_set, mut_block).expect( + "failed to compile block modified by eval_pipeline_without_terminal_expression", + )); + } + working_set.add_block(block.clone()); + engine_state + .merge_delta(working_set.render()) + .expect("failed to merge delta"); + + if !block.pipelines[0].elements.is_empty() { + let empty_input = PipelineData::empty(); + Some(eval_block(block, empty_input, cwd, engine_state)) + } else { + Some(Value::nothing(Span::test_data())) + } + } else { + // E.g. multiple semicolon-separated statements + None + } +} + +pub fn parse<'engine>( + contents: &str, + engine_state: &'engine EngineState, +) -> (Arc, StateWorkingSet<'engine>) { + let mut working_set = StateWorkingSet::new(engine_state); + let output = nu_parser::parse(&mut working_set, None, contents.as_bytes(), false); + + if let Some(err) = working_set.parse_errors.first() { + panic!("test parse error in `{contents}`: {err:?}"); + } + + if let Some(err) = working_set.compile_errors.first() { + panic!("test compile error in `{contents}`: {err:?}"); + } + + (output, working_set) +} + +pub fn eval_block( + block: Arc, + input: PipelineData, + cwd: &std::path::Path, + engine_state: &EngineState, +) -> Value { + let mut stack = Stack::new().collect_value(); + + stack.add_env_var("PWD".to_string(), Value::test_string(cwd.to_string_lossy())); + + nu_engine::eval_block::(engine_state, &mut stack, &block, input) + .and_then(|data| data.into_value(Span::test_data())) + .unwrap_or_else(|err| { + report_shell_error(engine_state, &err); + panic!("test eval error in `{}`: {:?}", "TODO", err) + }) +} + +pub fn check_example_evaluates_to_expected_output( + cmd_name: &str, + example: &Example, + cwd: &std::path::Path, + engine_state: &mut Box, +) { + let mut stack = Stack::new().collect_value(); + + // Set up PWD + stack.add_env_var("PWD".to_string(), Value::test_string(cwd.to_string_lossy())); + + engine_state + .merge_env(&mut stack) + .expect("Error merging environment"); + + let empty_input = PipelineData::empty(); + let result = eval(example.example, empty_input, cwd, engine_state); + + // Note. Value implements PartialEq for Bool, Int, Float, String and Block + // If the command you are testing requires to compare another case, then + // you need to define its equality in the Value struct + if let Some(expected) = example.result.as_ref() { + let expected = DebuggableValue(expected); + let result = DebuggableValue(&result); + assert_eq!( + result, expected, + "Error: The result of example '{}' for the command '{}' differs from the expected value.\n\nExpected: {:?}\nActual: {:?}\n", + example.description, cmd_name, expected, result, + ); + } +} + +pub fn check_all_signature_input_output_types_entries_have_examples( + signature: Signature, + witnessed_type_transformations: HashSet<(Type, Type)>, +) { + let declared_type_transformations = HashSet::from_iter(signature.input_output_types); + assert!( + witnessed_type_transformations.is_subset(&declared_type_transformations), + "This should not be possible (bug in test): the type transformations \ + collected in the course of matching examples to the signature type map \ + contain type transformations not present in the signature type map." + ); + + if !signature.allow_variants_without_examples { + assert_eq!( + witnessed_type_transformations, + declared_type_transformations, + "There are entries in the signature type map which do not correspond to any example: \ + {:?}", + declared_type_transformations + .difference(&witnessed_type_transformations) + .map(|(s1, s2)| format!("{s1} -> {s2}")) + .join(", ") + ); + } +} + +fn eval( + contents: &str, + input: PipelineData, + cwd: &std::path::Path, + engine_state: &mut Box, +) -> Value { + let (block, working_set) = parse(contents, engine_state); + engine_state + .merge_delta(working_set.render()) + .expect("failed to merge delta"); + eval_block(block, input, cwd, engine_state) +} + +pub struct DebuggableValue<'a>(pub &'a Value); + +impl PartialEq for DebuggableValue<'_> { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl std::fmt::Debug for DebuggableValue<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self.0 { + Value::Bool { val, .. } => { + write!(f, "{:?}", val) + } + Value::Int { val, .. } => { + write!(f, "{:?}", val) + } + Value::Float { val, .. } => { + write!(f, "{:?}f", val) + } + Value::Filesize { val, .. } => { + write!(f, "Filesize({:?})", val) + } + Value::Duration { val, .. } => { + let duration = std::time::Duration::from_nanos(*val as u64); + write!(f, "Duration({:?})", duration) + } + Value::Date { val, .. } => { + write!(f, "Date({:?})", val) + } + Value::Range { val, .. } => match **val { + Range::IntRange(range) => match range.end() { + Bound::Included(end) => write!( + f, + "Range({:?}..{:?}, step: {:?})", + range.start(), + end, + range.step(), + ), + Bound::Excluded(end) => write!( + f, + "Range({:?}..<{:?}, step: {:?})", + range.start(), + end, + range.step(), + ), + Bound::Unbounded => { + write!(f, "Range({:?}.., step: {:?})", range.start(), range.step()) + } + }, + Range::FloatRange(range) => match range.end() { + Bound::Included(end) => write!( + f, + "Range({:?}..{:?}, step: {:?})", + range.start(), + end, + range.step(), + ), + Bound::Excluded(end) => write!( + f, + "Range({:?}..<{:?}, step: {:?})", + range.start(), + end, + range.step(), + ), + Bound::Unbounded => { + write!(f, "Range({:?}.., step: {:?})", range.start(), range.step()) + } + }, + }, + Value::String { val, .. } | Value::Glob { val, .. } => { + write!(f, "{:?}", val) + } + Value::Record { val, .. } => { + write!(f, "{{")?; + let mut first = true; + for (col, value) in (&**val).into_iter() { + if !first { + write!(f, ", ")?; + } + first = false; + write!(f, "{:?}: {:?}", col, DebuggableValue(value))?; + } + write!(f, "}}") + } + Value::List { vals, .. } => { + write!(f, "[")?; + for (i, value) in vals.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + write!(f, "{:?}", DebuggableValue(value))?; + } + write!(f, "]") + } + Value::Closure { val, .. } => { + write!(f, "Closure({:?})", val) + } + Value::Nothing { .. } => { + write!(f, "Nothing") + } + Value::Error { error, .. } => { + write!(f, "Error({:?})", error) + } + Value::Binary { val, .. } => { + write!(f, "Binary({:?})", val) + } + Value::CellPath { val, .. } => { + write!(f, "CellPath({:?})", val.to_string()) + } + Value::Custom { val, .. } => { + write!(f, "CustomValue({:?})", val) + } + } + } +} diff --git a/nushell/crates/nu-cmd-lang/src/example_test.rs b/nushell/crates/nu-cmd-lang/src/example_test.rs new file mode 100644 index 0000000..d334d63 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/example_test.rs @@ -0,0 +1,99 @@ +#[cfg(test)] +use nu_protocol::engine::Command; + +#[cfg(test)] +pub fn test_examples(cmd: impl Command + 'static) { + test_examples::test_examples(cmd); +} + +#[cfg(test)] +mod test_examples { + use crate::example_support::{ + check_all_signature_input_output_types_entries_have_examples, + check_example_evaluates_to_expected_output, + check_example_input_and_output_types_match_command_signature, + }; + use crate::{ + Break, Collect, Def, Describe, Echo, ExportCommand, ExportDef, If, Let, Module, Mut, Use, + }; + use nu_protocol::{ + Type, Value, + engine::{Command, EngineState, StateWorkingSet}, + }; + use std::collections::HashSet; + + pub fn test_examples(cmd: impl Command + 'static) { + let examples = cmd.examples(); + let signature = cmd.signature(); + let mut engine_state = make_engine_state(cmd.clone_box()); + + let cwd = std::env::current_dir().expect("Could not get current working directory."); + + let mut witnessed_type_transformations = HashSet::<(Type, Type)>::new(); + + for example in examples { + if example.result.is_none() { + continue; + } + witnessed_type_transformations.extend( + check_example_input_and_output_types_match_command_signature( + &example, + &cwd, + &mut make_engine_state(cmd.clone_box()), + &signature.input_output_types, + signature.operates_on_cell_paths(), + ), + ); + check_example_evaluates_to_expected_output( + cmd.name(), + &example, + cwd.as_path(), + &mut engine_state, + ); + } + + check_all_signature_input_output_types_entries_have_examples( + signature, + witnessed_type_transformations, + ); + } + + fn make_engine_state(cmd: Box) -> Box { + let mut engine_state = Box::new(EngineState::new()); + let cwd = std::env::current_dir() + .expect("Could not get current working directory.") + .to_string_lossy() + .to_string(); + engine_state.add_env_var("PWD".to_string(), Value::test_string(cwd)); + + let delta = { + // Base functions that are needed for testing + // Try to keep this working set small to keep tests running as fast as possible + let mut working_set = StateWorkingSet::new(&engine_state); + working_set.add_decl(Box::new(Break)); + working_set.add_decl(Box::new(Collect)); + working_set.add_decl(Box::new(Def)); + working_set.add_decl(Box::new(Describe)); + working_set.add_decl(Box::new(Echo)); + working_set.add_decl(Box::new(ExportCommand)); + working_set.add_decl(Box::new(ExportDef)); + working_set.add_decl(Box::new(If)); + working_set.add_decl(Box::new(Let)); + working_set.add_decl(Box::new(Module)); + working_set.add_decl(Box::new(Mut)); + working_set.add_decl(Box::new(Use)); + + // Adding the command that is being tested to the working set + working_set.add_decl(cmd); + + working_set.render() + }; + + engine_state.add_env_var("PWD".to_string(), Value::test_string(".")); + + engine_state + .merge_delta(delta) + .expect("Error merging delta"); + engine_state + } +} diff --git a/nushell/crates/nu-cmd-lang/src/lib.rs b/nushell/crates/nu-cmd-lang/src/lib.rs new file mode 100644 index 0000000..3d6f506 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/lib.rs @@ -0,0 +1,14 @@ +#![cfg_attr(not(feature = "os"), allow(unused))] +#![doc = include_str!("../README.md")] +mod core_commands; +mod default_context; +pub mod example_support; +mod example_test; +#[cfg(test)] +mod parse_const_test; + +pub use core_commands::*; +pub use default_context::*; +pub use example_support::*; +#[cfg(test)] +pub use example_test::test_examples; diff --git a/nushell/crates/nu-cmd-lang/src/parse_const_test.rs b/nushell/crates/nu-cmd-lang/src/parse_const_test.rs new file mode 100644 index 0000000..e0b90a9 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/src/parse_const_test.rs @@ -0,0 +1,19 @@ +use nu_protocol::{Span, engine::StateWorkingSet}; +use quickcheck_macros::quickcheck; + +#[quickcheck] +fn quickcheck_parse(data: String) -> bool { + let (tokens, err) = nu_parser::lex(data.as_bytes(), 0, b"", b"", true); + + if err.is_none() { + let context = crate::create_default_context(); + { + let mut working_set = StateWorkingSet::new(&context); + let _ = working_set.add_file("quickcheck".into(), data.as_bytes()); + + let _ = + nu_parser::parse_block(&mut working_set, &tokens, Span::new(0, 0), false, false); + } + } + true +} diff --git a/nushell/crates/nu-cmd-lang/tests/commands/attr/deprecated.rs b/nushell/crates/nu-cmd-lang/tests/commands/attr/deprecated.rs new file mode 100644 index 0000000..7ddda3a --- /dev/null +++ b/nushell/crates/nu-cmd-lang/tests/commands/attr/deprecated.rs @@ -0,0 +1,114 @@ +use miette::{Diagnostic, LabeledSpan}; +use nu_cmd_lang::{Alias, Def}; +use nu_parser::parse; +use nu_protocol::engine::{EngineState, StateWorkingSet}; + +use nu_cmd_lang::AttrDeprecated; + +#[test] +pub fn test_deprecated_attribute() { + let engine_state = EngineState::new(); + let mut working_set = StateWorkingSet::new(&engine_state); + + working_set.add_decl(Box::new(Def)); + working_set.add_decl(Box::new(Alias)); + working_set.add_decl(Box::new(AttrDeprecated)); + + // test deprecation with no message + let source = br#" + @deprecated + def foo [] {} + "#; + let _ = parse(&mut working_set, None, source, false); + + // there should be no warning until the command is called + assert!(working_set.parse_errors.is_empty()); + assert!(working_set.parse_warnings.is_empty()); + + let source = b"foo"; + let _ = parse(&mut working_set, None, source, false); + + // command called, there should be a deprecation warning + assert!(working_set.parse_errors.is_empty()); + assert!(!working_set.parse_warnings.is_empty()); + let labels: Vec = working_set.parse_warnings[0].labels().unwrap().collect(); + let label = labels.first().unwrap().label().unwrap(); + assert!(label.contains("foo is deprecated")); + working_set.parse_warnings.clear(); + + // test deprecation with message + let source = br#" + @deprecated "Use new-command instead" + def old-command [] {} + + old-command + "#; + let _ = parse(&mut working_set, None, source, false); + + assert!(working_set.parse_errors.is_empty()); + assert!(!working_set.parse_warnings.is_empty()); + + let help = &working_set.parse_warnings[0].help().unwrap().to_string(); + assert!(help.contains("Use new-command instead")); +} + +#[test] +pub fn test_deprecated_attribute_flag() { + let engine_state = EngineState::new(); + let mut working_set = StateWorkingSet::new(&engine_state); + + working_set.add_decl(Box::new(Def)); + working_set.add_decl(Box::new(Alias)); + working_set.add_decl(Box::new(AttrDeprecated)); + + let source = br#" + @deprecated "Use foo instead of bar" --flag bar + @deprecated "Use foo instead of baz" --flag baz + def old-command [--foo, --bar, --baz] {} + old-command --foo + old-command --bar + old-command --baz + old-command --foo --bar --baz + "#; + let _ = parse(&mut working_set, None, source, false); + + assert!(working_set.parse_errors.is_empty()); + assert!(!working_set.parse_warnings.is_empty()); + + let help = &working_set.parse_warnings[0].help().unwrap().to_string(); + assert!(help.contains("Use foo instead of bar")); + + let help = &working_set.parse_warnings[1].help().unwrap().to_string(); + assert!(help.contains("Use foo instead of baz")); + + let help = &working_set.parse_warnings[2].help().unwrap().to_string(); + assert!(help.contains("Use foo instead of bar")); + + let help = &working_set.parse_warnings[3].help().unwrap().to_string(); + assert!(help.contains("Use foo instead of baz")); +} + +#[test] +pub fn test_deprecated_attribute_since_remove() { + let engine_state = EngineState::new(); + let mut working_set = StateWorkingSet::new(&engine_state); + + working_set.add_decl(Box::new(Def)); + working_set.add_decl(Box::new(Alias)); + working_set.add_decl(Box::new(AttrDeprecated)); + + let source = br#" + @deprecated --since 0.10000.0 --remove 1.0 + def old-command [] {} + old-command + "#; + let _ = parse(&mut working_set, None, source, false); + + assert!(working_set.parse_errors.is_empty()); + assert!(!working_set.parse_warnings.is_empty()); + + let labels: Vec = working_set.parse_warnings[0].labels().unwrap().collect(); + let label = labels.first().unwrap().label().unwrap(); + assert!(label.contains("0.10000.0")); + assert!(label.contains("1.0")); +} diff --git a/nushell/crates/nu-cmd-lang/tests/commands/attr/mod.rs b/nushell/crates/nu-cmd-lang/tests/commands/attr/mod.rs new file mode 100644 index 0000000..312dcd9 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/tests/commands/attr/mod.rs @@ -0,0 +1 @@ +mod deprecated; diff --git a/nushell/crates/nu-cmd-lang/tests/commands/mod.rs b/nushell/crates/nu-cmd-lang/tests/commands/mod.rs new file mode 100644 index 0000000..ddd623b --- /dev/null +++ b/nushell/crates/nu-cmd-lang/tests/commands/mod.rs @@ -0,0 +1 @@ +mod attr; diff --git a/nushell/crates/nu-cmd-lang/tests/main.rs b/nushell/crates/nu-cmd-lang/tests/main.rs new file mode 100644 index 0000000..f3d4468 --- /dev/null +++ b/nushell/crates/nu-cmd-lang/tests/main.rs @@ -0,0 +1 @@ +mod commands; diff --git a/nushell/crates/nu-cmd-plugin/Cargo.toml b/nushell/crates/nu-cmd-plugin/Cargo.toml new file mode 100644 index 0000000..54ef9f1 --- /dev/null +++ b/nushell/crates/nu-cmd-plugin/Cargo.toml @@ -0,0 +1,23 @@ +[package] +authors = ["The Nushell Project Developers"] +description = "Commands for managing Nushell plugins." +edition = "2024" +license = "MIT" +name = "nu-cmd-plugin" +repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-plugin" +version = "0.105.2" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lints] +workspace = true + +[dependencies] +nu-engine = { path = "../nu-engine", version = "0.105.2" } +nu-path = { path = "../nu-path", version = "0.105.2" } +nu-protocol = { path = "../nu-protocol", version = "0.105.2", features = ["plugin"] } +nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.105.2" } + +itertools = { workspace = true } + +[dev-dependencies] diff --git a/nushell/crates/nu-cmd-plugin/LICENSE b/nushell/crates/nu-cmd-plugin/LICENSE new file mode 100644 index 0000000..ae174e8 --- /dev/null +++ b/nushell/crates/nu-cmd-plugin/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 - 2023 The Nushell Project Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/nushell/crates/nu-cmd-plugin/README.md b/nushell/crates/nu-cmd-plugin/README.md new file mode 100644 index 0000000..0c62ad1 --- /dev/null +++ b/nushell/crates/nu-cmd-plugin/README.md @@ -0,0 +1,3 @@ +# nu-cmd-plugin + +This crate implements Nushell commands related to plugin management. diff --git a/nushell/crates/nu-cmd-plugin/src/commands/mod.rs b/nushell/crates/nu-cmd-plugin/src/commands/mod.rs new file mode 100644 index 0000000..17ff32f --- /dev/null +++ b/nushell/crates/nu-cmd-plugin/src/commands/mod.rs @@ -0,0 +1,3 @@ +mod plugin; + +pub use plugin::*; diff --git a/nushell/crates/nu-cmd-plugin/src/commands/plugin/add.rs b/nushell/crates/nu-cmd-plugin/src/commands/plugin/add.rs new file mode 100644 index 0000000..1e9b441 --- /dev/null +++ b/nushell/crates/nu-cmd-plugin/src/commands/plugin/add.rs @@ -0,0 +1,142 @@ +use crate::util::{get_plugin_dirs, modify_plugin_file}; +use nu_engine::command_prelude::*; +use nu_plugin_engine::{GetPlugin, PersistentPlugin}; +use nu_protocol::{ + PluginGcConfig, PluginIdentity, PluginRegistryItem, RegisteredPlugin, shell_error::io::IoError, +}; +use std::{path::PathBuf, sync::Arc}; + +#[derive(Clone)] +pub struct PluginAdd; + +impl Command for PluginAdd { + fn name(&self) -> &str { + "plugin add" + } + + fn signature(&self) -> Signature { + Signature::build(self.name()) + .input_output_type(Type::Nothing, Type::Nothing) + // This matches the option to `nu` + .named( + "plugin-config", + SyntaxShape::Filepath, + "Use a plugin registry file other than the one set in `$nu.plugin-path`", + None, + ) + .named( + "shell", + SyntaxShape::Filepath, + "Use an additional shell program (cmd, sh, python, etc.) to run the plugin", + Some('s'), + ) + .required( + "filename", + SyntaxShape::String, + "Path to the executable for the plugin.", + ) + .category(Category::Plugin) + } + + fn description(&self) -> &str { + "Add a plugin to the plugin registry file." + } + + fn extra_description(&self) -> &str { + r#" +This does not load the plugin commands into the scope - see `plugin use` for +that. + +Instead, it runs the plugin to get its command signatures, and then edits the +plugin registry file (by default, `$nu.plugin-path`). The changes will be +apparent the next time `nu` is next launched with that plugin registry file. +"# + .trim() + } + + fn search_terms(&self) -> Vec<&str> { + vec!["load", "register", "signature"] + } + + fn examples(&self) -> Vec { + vec![ + Example { + example: "plugin add nu_plugin_inc", + description: "Run the `nu_plugin_inc` plugin from the current directory or $env.NU_PLUGIN_DIRS and install its signatures.", + result: None, + }, + Example { + example: "plugin add --plugin-config polars.msgpackz nu_plugin_polars", + description: "Run the `nu_plugin_polars` plugin from the current directory or $env.NU_PLUGIN_DIRS, and install its signatures to the \"polars.msgpackz\" plugin registry file.", + result: None, + }, + ] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let filename: Spanned = call.req(engine_state, stack, 0)?; + let shell: Option> = call.get_flag(engine_state, stack, "shell")?; + let cwd = engine_state.cwd(Some(stack))?; + + // Check the current directory, or fall back to NU_PLUGIN_DIRS + let filename_expanded = nu_path::locate_in_dirs(&filename.item, &cwd, || { + get_plugin_dirs(engine_state, stack) + }) + .map_err(|err| { + IoError::new( + err.not_found_as(NotFound::File), + filename.span, + PathBuf::from(filename.item), + ) + })?; + + let shell_expanded = shell + .as_ref() + .map(|s| { + nu_path::canonicalize_with(&s.item, &cwd) + .map_err(|err| IoError::new(err, s.span, None)) + }) + .transpose()?; + + // Parse the plugin filename so it can be used to spawn the plugin + let identity = PluginIdentity::new(filename_expanded, shell_expanded).map_err(|_| { + ShellError::GenericError { + error: "Plugin filename is invalid".into(), + msg: "plugin executable files must start with `nu_plugin_`".into(), + span: Some(filename.span), + help: None, + inner: vec![], + } + })?; + + let custom_path = call.get_flag(engine_state, stack, "plugin-config")?; + + // Start the plugin manually, to get the freshest signatures and to not affect engine + // state. Provide a GC config that will stop it ASAP + let plugin = Arc::new(PersistentPlugin::new( + identity, + PluginGcConfig { + enabled: true, + stop_after: 0, + }, + )); + let interface = plugin.clone().get_plugin(Some((engine_state, stack)))?; + let metadata = interface.get_metadata()?; + let commands = interface.get_signature()?; + + modify_plugin_file(engine_state, stack, call.head, &custom_path, |contents| { + // Update the file with the received metadata and signatures + let item = PluginRegistryItem::new(plugin.identity(), metadata, commands); + contents.upsert_plugin(item); + Ok(()) + })?; + + Ok(Value::nothing(call.head).into_pipeline_data()) + } +} diff --git a/nushell/crates/nu-cmd-plugin/src/commands/plugin/list.rs b/nushell/crates/nu-cmd-plugin/src/commands/plugin/list.rs new file mode 100644 index 0000000..367a532 --- /dev/null +++ b/nushell/crates/nu-cmd-plugin/src/commands/plugin/list.rs @@ -0,0 +1,301 @@ +use itertools::{EitherOrBoth, Itertools}; +use nu_engine::command_prelude::*; +use nu_protocol::{IntoValue, PluginRegistryItemData}; + +use crate::util::read_plugin_file; + +#[derive(Clone)] +pub struct PluginList; + +impl Command for PluginList { + fn name(&self) -> &str { + "plugin list" + } + + fn signature(&self) -> Signature { + Signature::build("plugin list") + .input_output_type( + Type::Nothing, + Type::Table( + [ + ("name".into(), Type::String), + ("version".into(), Type::String), + ("status".into(), Type::String), + ("pid".into(), Type::Int), + ("filename".into(), Type::String), + ("shell".into(), Type::String), + ("commands".into(), Type::List(Type::String.into())), + ] + .into(), + ), + ) + .named( + "plugin-config", + SyntaxShape::Filepath, + "Use a plugin registry file other than the one set in `$nu.plugin-path`", + None, + ) + .switch( + "engine", + "Show info for plugins that are loaded into the engine only.", + Some('e'), + ) + .switch( + "registry", + "Show info for plugins from the registry file only.", + Some('r'), + ) + .category(Category::Plugin) + } + + fn description(&self) -> &str { + "List loaded and installed plugins." + } + + fn extra_description(&self) -> &str { + r#" +The `status` column will contain one of the following values: + +- `added`: The plugin is present in the plugin registry file, but not in + the engine. +- `loaded`: The plugin is present both in the plugin registry file and in + the engine, but is not running. +- `running`: The plugin is currently running, and the `pid` column should + contain its process ID. +- `modified`: The plugin state present in the plugin registry file is different + from the state in the engine. +- `removed`: The plugin is still loaded in the engine, but is not present in + the plugin registry file. +- `invalid`: The data in the plugin registry file couldn't be deserialized, + and the plugin most likely needs to be added again. + +`running` takes priority over any other status. Unless `--registry` is used +or the plugin has not been loaded yet, the values of `version`, `filename`, +`shell`, and `commands` reflect the values in the engine and not the ones in +the plugin registry file. + +See also: `plugin use` +"# + .trim() + } + + fn search_terms(&self) -> Vec<&str> { + vec!["scope"] + } + + fn examples(&self) -> Vec { + vec![ + Example { + example: "plugin list", + description: "List installed plugins.", + result: Some(Value::test_list(vec![Value::test_record(record! { + "name" => Value::test_string("inc"), + "version" => Value::test_string(env!("CARGO_PKG_VERSION")), + "status" => Value::test_string("running"), + "pid" => Value::test_int(106480), + "filename" => if cfg!(windows) { + Value::test_string(r"C:\nu\plugins\nu_plugin_inc.exe") + } else { + Value::test_string("/opt/nu/plugins/nu_plugin_inc") + }, + "shell" => Value::test_nothing(), + "commands" => Value::test_list(vec![Value::test_string("inc")]), + })])), + }, + Example { + example: "ps | where pid in (plugin list).pid", + description: "Get process information for running plugins.", + result: None, + }, + ] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let custom_path = call.get_flag(engine_state, stack, "plugin-config")?; + let engine_mode = call.has_flag(engine_state, stack, "engine")?; + let registry_mode = call.has_flag(engine_state, stack, "registry")?; + + let plugins_info = match (engine_mode, registry_mode) { + // --engine and --registry together is equivalent to the default. + (false, false) | (true, true) => { + if engine_state.plugin_path.is_some() || custom_path.is_some() { + let plugins_in_engine = get_plugins_in_engine(engine_state); + let plugins_in_registry = + get_plugins_in_registry(engine_state, stack, call.head, &custom_path)?; + merge_plugin_info(plugins_in_engine, plugins_in_registry) + } else { + // Don't produce error when running nu --no-config-file + get_plugins_in_engine(engine_state) + } + } + (true, false) => get_plugins_in_engine(engine_state), + (false, true) => get_plugins_in_registry(engine_state, stack, call.head, &custom_path)?, + }; + + Ok(plugins_info.into_value(call.head).into_pipeline_data()) + } +} + +#[derive(Debug, Clone, IntoValue, PartialOrd, Ord, PartialEq, Eq)] +struct PluginInfo { + name: String, + version: Option, + status: PluginStatus, + pid: Option, + filename: String, + shell: Option, + commands: Vec, +} + +#[derive(Debug, Clone, Copy, IntoValue, PartialOrd, Ord, PartialEq, Eq)] +#[nu_value(rename_all = "snake_case")] +enum PluginStatus { + Added, + Loaded, + Running, + Modified, + Removed, + Invalid, +} + +fn get_plugins_in_engine(engine_state: &EngineState) -> Vec { + // Group plugin decls by plugin identity + let decls = engine_state.plugin_decls().into_group_map_by(|decl| { + decl.plugin_identity() + .expect("plugin decl should have identity") + }); + + // Build plugins list + engine_state + .plugins() + .iter() + .map(|plugin| { + // Find commands that belong to the plugin + let commands = decls + .get(plugin.identity()) + .into_iter() + .flat_map(|decls| decls.iter().map(|decl| decl.name().to_owned())) + .sorted() + .collect(); + + PluginInfo { + name: plugin.identity().name().into(), + version: plugin.metadata().and_then(|m| m.version), + status: if plugin.pid().is_some() { + PluginStatus::Running + } else { + PluginStatus::Loaded + }, + pid: plugin.pid(), + filename: plugin.identity().filename().to_string_lossy().into_owned(), + shell: plugin + .identity() + .shell() + .map(|path| path.to_string_lossy().into_owned()), + commands, + } + }) + .sorted() + .collect() +} + +fn get_plugins_in_registry( + engine_state: &EngineState, + stack: &mut Stack, + span: Span, + custom_path: &Option>, +) -> Result, ShellError> { + let plugin_file_contents = read_plugin_file(engine_state, stack, span, custom_path)?; + + let plugins_info = plugin_file_contents + .plugins + .into_iter() + .map(|plugin| { + let mut info = PluginInfo { + name: plugin.name, + version: None, + status: PluginStatus::Added, + pid: None, + filename: plugin.filename.to_string_lossy().into_owned(), + shell: plugin.shell.map(|path| path.to_string_lossy().into_owned()), + commands: vec![], + }; + + if let PluginRegistryItemData::Valid { metadata, commands } = plugin.data { + info.version = metadata.version; + info.commands = commands + .into_iter() + .map(|command| command.sig.name) + .sorted() + .collect(); + } else { + info.status = PluginStatus::Invalid; + } + info + }) + .sorted() + .collect(); + + Ok(plugins_info) +} + +/// If no options are provided, the command loads from both the plugin list in the engine and what's +/// in the registry file. We need to reconcile the two to set the proper states and make sure that +/// new plugins that were added to the plugin registry file show up. +fn merge_plugin_info( + from_engine: Vec, + from_registry: Vec, +) -> Vec { + from_engine + .into_iter() + .merge_join_by(from_registry, |info_a, info_b| { + info_a.name.cmp(&info_b.name) + }) + .map(|either_or_both| match either_or_both { + // Exists in the engine, but not in the registry file + EitherOrBoth::Left(info) => PluginInfo { + status: match info.status { + PluginStatus::Running => info.status, + // The plugin is not in the registry file, so it should be marked as `removed` + _ => PluginStatus::Removed, + }, + ..info + }, + // Exists in the registry file, but not in the engine + EitherOrBoth::Right(info) => info, + // Exists in both + EitherOrBoth::Both(info_engine, info_registry) => PluginInfo { + status: match (info_engine.status, info_registry.status) { + // Above all, `running` should be displayed if the plugin is running + (PluginStatus::Running, _) => PluginStatus::Running, + // `invalid` takes precedence over other states because the user probably wants + // to fix it + (_, PluginStatus::Invalid) => PluginStatus::Invalid, + // Display `modified` if the state in the registry is different somehow + _ if info_engine.is_modified(&info_registry) => PluginStatus::Modified, + // Otherwise, `loaded` (it's not running) + _ => PluginStatus::Loaded, + }, + ..info_engine + }, + }) + .sorted() + .collect() +} + +impl PluginInfo { + /// True if the plugin info shows some kind of change (other than status/pid) relative to the + /// other + fn is_modified(&self, other: &PluginInfo) -> bool { + self.name != other.name + || self.filename != other.filename + || self.shell != other.shell + || self.commands != other.commands + } +} diff --git a/nushell/crates/nu-cmd-plugin/src/commands/plugin/mod.rs b/nushell/crates/nu-cmd-plugin/src/commands/plugin/mod.rs new file mode 100644 index 0000000..ae4e5a7 --- /dev/null +++ b/nushell/crates/nu-cmd-plugin/src/commands/plugin/mod.rs @@ -0,0 +1,77 @@ +use nu_engine::{command_prelude::*, get_full_help}; + +mod add; +mod list; +mod rm; +mod stop; +mod use_; + +pub use add::PluginAdd; +pub use list::PluginList; +pub use rm::PluginRm; +pub use stop::PluginStop; +pub use use_::PluginUse; + +#[derive(Clone)] +pub struct PluginCommand; + +impl Command for PluginCommand { + fn name(&self) -> &str { + "plugin" + } + + fn signature(&self) -> Signature { + Signature::build("plugin") + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .category(Category::Plugin) + } + + fn description(&self) -> &str { + "Commands for managing plugins." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + Ok(Value::string(get_full_help(self, engine_state, stack), call.head).into_pipeline_data()) + } + + fn examples(&self) -> Vec { + vec![ + Example { + example: "plugin add nu_plugin_inc", + description: "Run the `nu_plugin_inc` plugin from the current directory and install its signatures.", + result: None, + }, + Example { + example: "plugin use inc", + description: " +Load (or reload) the `inc` plugin from the plugin registry file and put its +commands in scope. The plugin must already be in the registry file at parse +time. +" + .trim(), + result: None, + }, + Example { + example: "plugin list", + description: "List installed plugins", + result: None, + }, + Example { + example: "plugin stop inc", + description: "Stop the plugin named `inc`.", + result: None, + }, + Example { + example: "plugin rm inc", + description: "Remove the installed signatures for the `inc` plugin.", + result: None, + }, + ] + } +} diff --git a/nushell/crates/nu-cmd-plugin/src/commands/plugin/rm.rs b/nushell/crates/nu-cmd-plugin/src/commands/plugin/rm.rs new file mode 100644 index 0000000..82b909a --- /dev/null +++ b/nushell/crates/nu-cmd-plugin/src/commands/plugin/rm.rs @@ -0,0 +1,113 @@ +use nu_engine::command_prelude::*; + +use crate::util::{canonicalize_possible_filename_arg, modify_plugin_file}; + +#[derive(Clone)] +pub struct PluginRm; + +impl Command for PluginRm { + fn name(&self) -> &str { + "plugin rm" + } + + fn signature(&self) -> Signature { + Signature::build(self.name()) + .input_output_type(Type::Nothing, Type::Nothing) + // This matches the option to `nu` + .named( + "plugin-config", + SyntaxShape::Filepath, + "Use a plugin registry file other than the one set in `$nu.plugin-path`", + None, + ) + .switch( + "force", + "Don't cause an error if the plugin name wasn't found in the file", + Some('f'), + ) + .required( + "name", + SyntaxShape::String, + "The name, or filename, of the plugin to remove.", + ) + .category(Category::Plugin) + } + + fn description(&self) -> &str { + "Remove a plugin from the plugin registry file." + } + + fn extra_description(&self) -> &str { + r#" +This does not remove the plugin commands from the current scope or from `plugin +list` in the current shell. It instead removes the plugin from the plugin +registry file (by default, `$nu.plugin-path`). The changes will be apparent the +next time `nu` is launched with that plugin registry file. + +This can be useful for removing an invalid plugin signature, if it can't be +fixed with `plugin add`. +"# + .trim() + } + + fn search_terms(&self) -> Vec<&str> { + vec!["remove", "delete", "signature"] + } + + fn examples(&self) -> Vec { + vec![ + Example { + example: "plugin rm inc", + description: "Remove the installed signatures for the `inc` plugin.", + result: None, + }, + Example { + example: "plugin rm ~/.cargo/bin/nu_plugin_inc", + description: "Remove the installed signatures for the plugin with the filename `~/.cargo/bin/nu_plugin_inc`.", + result: None, + }, + Example { + example: "plugin rm --plugin-config polars.msgpackz polars", + description: "Remove the installed signatures for the `polars` plugin from the \"polars.msgpackz\" plugin registry file.", + result: None, + }, + ] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let name: Spanned = call.req(engine_state, stack, 0)?; + let custom_path = call.get_flag(engine_state, stack, "plugin-config")?; + let force = call.has_flag(engine_state, stack, "force")?; + + let filename = canonicalize_possible_filename_arg(engine_state, stack, &name.item); + + modify_plugin_file(engine_state, stack, call.head, &custom_path, |contents| { + if let Some(index) = contents + .plugins + .iter() + .position(|p| p.name == name.item || p.filename == filename) + { + contents.plugins.remove(index); + Ok(()) + } else if force { + Ok(()) + } else { + Err(ShellError::GenericError { + error: format!("Failed to remove the `{}` plugin", name.item), + msg: "couldn't find a plugin with this name in the registry file".into(), + span: Some(name.span), + help: None, + inner: vec![], + }) + } + })?; + + Ok(Value::nothing(call.head).into_pipeline_data()) + } +} diff --git a/nushell/crates/nu-cmd-plugin/src/commands/plugin/stop.rs b/nushell/crates/nu-cmd-plugin/src/commands/plugin/stop.rs new file mode 100644 index 0000000..3437294 --- /dev/null +++ b/nushell/crates/nu-cmd-plugin/src/commands/plugin/stop.rs @@ -0,0 +1,80 @@ +use nu_engine::command_prelude::*; + +use crate::util::canonicalize_possible_filename_arg; + +#[derive(Clone)] +pub struct PluginStop; + +impl Command for PluginStop { + fn name(&self) -> &str { + "plugin stop" + } + + fn signature(&self) -> Signature { + Signature::build("plugin stop") + .input_output_type(Type::Nothing, Type::Nothing) + .required( + "name", + SyntaxShape::String, + "The name, or filename, of the plugin to stop.", + ) + .category(Category::Plugin) + } + + fn description(&self) -> &str { + "Stop an installed plugin if it was running." + } + + fn examples(&self) -> Vec { + vec![ + Example { + example: "plugin stop inc", + description: "Stop the plugin named `inc`.", + result: None, + }, + Example { + example: "plugin stop ~/.cargo/bin/nu_plugin_inc", + description: "Stop the plugin with the filename `~/.cargo/bin/nu_plugin_inc`.", + result: None, + }, + Example { + example: "plugin list | each { |p| plugin stop $p.name }", + description: "Stop all plugins.", + result: None, + }, + ] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let name: Spanned = call.req(engine_state, stack, 0)?; + + let filename = canonicalize_possible_filename_arg(engine_state, stack, &name.item); + + let mut found = false; + for plugin in engine_state.plugins() { + let id = &plugin.identity(); + if id.name() == name.item || id.filename() == filename { + plugin.stop()?; + found = true; + } + } + + if found { + Ok(PipelineData::Empty) + } else { + Err(ShellError::GenericError { + error: format!("Failed to stop the `{}` plugin", name.item), + msg: "couldn't find a plugin with this name".into(), + span: Some(name.span), + help: Some("you may need to `plugin add` the plugin first".into()), + inner: vec![], + }) + } + } +} diff --git a/nushell/crates/nu-cmd-plugin/src/commands/plugin/use_.rs b/nushell/crates/nu-cmd-plugin/src/commands/plugin/use_.rs new file mode 100644 index 0000000..64fec14 --- /dev/null +++ b/nushell/crates/nu-cmd-plugin/src/commands/plugin/use_.rs @@ -0,0 +1,89 @@ +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; + +#[derive(Clone)] +pub struct PluginUse; + +impl Command for PluginUse { + fn name(&self) -> &str { + "plugin use" + } + + fn description(&self) -> &str { + "Load a plugin from the plugin registry file into scope." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build(self.name()) + .input_output_types(vec![(Type::Nothing, Type::Nothing)]) + .named( + "plugin-config", + SyntaxShape::Filepath, + "Use a plugin registry file other than the one set in `$nu.plugin-path`", + None, + ) + .required( + "name", + SyntaxShape::String, + "The name, or filename, of the plugin to load.", + ) + .category(Category::Plugin) + } + + fn extra_description(&self) -> &str { + r#" +This command is a parser keyword. For details, check: + https://www.nushell.sh/book/thinking_in_nu.html + +The plugin definition must be available in the plugin registry file at parse +time. Run `plugin add` first in the REPL to do this, or from a script consider +preparing a plugin registry file and passing `--plugin-config`, or using the +`--plugin` option to `nu` instead. + +If the plugin was already loaded, this will reload the latest definition from +the registry file into scope. + +Note that even if the plugin filename is specified, it will only be loaded if +it was already previously registered with `plugin add`. +"# + .trim() + } + + fn search_terms(&self) -> Vec<&str> { + vec!["add", "register", "scope"] + } + + fn command_type(&self) -> CommandType { + CommandType::Keyword + } + + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, + ) -> Result { + Ok(PipelineData::empty()) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Load the commands for the `query` plugin from $nu.plugin-path", + example: r#"plugin use query"#, + result: None, + }, + Example { + description: "Load the commands for the plugin with the filename `~/.cargo/bin/nu_plugin_query` from $nu.plugin-path", + example: r#"plugin use ~/.cargo/bin/nu_plugin_query"#, + result: None, + }, + Example { + description: "Load the commands for the `query` plugin from a custom plugin registry file", + example: r#"plugin use --plugin-config local-plugins.msgpackz query"#, + result: None, + }, + ] + } +} diff --git a/nushell/crates/nu-cmd-plugin/src/default_context.rs b/nushell/crates/nu-cmd-plugin/src/default_context.rs new file mode 100644 index 0000000..1ef6a90 --- /dev/null +++ b/nushell/crates/nu-cmd-plugin/src/default_context.rs @@ -0,0 +1,31 @@ +use crate::*; +use nu_protocol::engine::{EngineState, StateWorkingSet}; + +pub fn add_plugin_command_context(mut engine_state: EngineState) -> EngineState { + let delta = { + let mut working_set = StateWorkingSet::new(&engine_state); + + macro_rules! bind_command { + ( $( $command:expr ),* $(,)? ) => { + $( working_set.add_decl(Box::new($command)); )* + }; + } + + bind_command!( + PluginAdd, + PluginCommand, + PluginList, + PluginRm, + PluginStop, + PluginUse, + ); + + working_set.render() + }; + + if let Err(err) = engine_state.merge_delta(delta) { + eprintln!("Error creating default context: {err:?}"); + } + + engine_state +} diff --git a/nushell/crates/nu-cmd-plugin/src/lib.rs b/nushell/crates/nu-cmd-plugin/src/lib.rs new file mode 100644 index 0000000..d6fb5bb --- /dev/null +++ b/nushell/crates/nu-cmd-plugin/src/lib.rs @@ -0,0 +1,8 @@ +//! Nushell commands for managing plugins. + +mod commands; +mod default_context; +mod util; + +pub use commands::*; +pub use default_context::*; diff --git a/nushell/crates/nu-cmd-plugin/src/util.rs b/nushell/crates/nu-cmd-plugin/src/util.rs new file mode 100644 index 0000000..223e93b --- /dev/null +++ b/nushell/crates/nu-cmd-plugin/src/util.rs @@ -0,0 +1,145 @@ +#[allow(deprecated)] +use nu_engine::{command_prelude::*, current_dir}; +use nu_protocol::{ + PluginRegistryFile, + engine::StateWorkingSet, + shell_error::{self, io::IoError}, +}; +use std::{ + fs::{self, File}, + path::PathBuf, +}; + +fn get_plugin_registry_file_path( + engine_state: &EngineState, + stack: &mut Stack, + span: Span, + custom_path: &Option>, +) -> Result { + #[allow(deprecated)] + let cwd = current_dir(engine_state, stack)?; + + if let Some(custom_path) = custom_path { + Ok(nu_path::expand_path_with(&custom_path.item, cwd, true)) + } else { + engine_state + .plugin_path + .clone() + .ok_or_else(|| ShellError::GenericError { + error: "Plugin registry file not set".into(), + msg: "pass --plugin-config explicitly here".into(), + span: Some(span), + help: Some("you may be running `nu` with --no-config-file".into()), + inner: vec![], + }) + } +} + +pub(crate) fn read_plugin_file( + engine_state: &EngineState, + stack: &mut Stack, + span: Span, + custom_path: &Option>, +) -> Result { + let plugin_registry_file_path = + get_plugin_registry_file_path(engine_state, stack, span, custom_path)?; + + let file_span = custom_path.as_ref().map(|p| p.span).unwrap_or(span); + + // Try to read the plugin file if it exists + if fs::metadata(&plugin_registry_file_path).is_ok_and(|m| m.len() > 0) { + PluginRegistryFile::read_from( + File::open(&plugin_registry_file_path) + .map_err(|err| IoError::new(err, file_span, plugin_registry_file_path))?, + Some(file_span), + ) + } else if let Some(path) = custom_path { + Err(ShellError::Io(IoError::new( + shell_error::io::ErrorKind::FileNotFound, + path.span, + PathBuf::from(&path.item), + ))) + } else { + Ok(PluginRegistryFile::default()) + } +} + +pub(crate) fn modify_plugin_file( + engine_state: &EngineState, + stack: &mut Stack, + span: Span, + custom_path: &Option>, + operate: impl FnOnce(&mut PluginRegistryFile) -> Result<(), ShellError>, +) -> Result<(), ShellError> { + let plugin_registry_file_path = + get_plugin_registry_file_path(engine_state, stack, span, custom_path)?; + + let file_span = custom_path.as_ref().map(|p| p.span).unwrap_or(span); + + // Try to read the plugin file if it exists + let mut contents = if fs::metadata(&plugin_registry_file_path).is_ok_and(|m| m.len() > 0) { + PluginRegistryFile::read_from( + File::open(&plugin_registry_file_path) + .map_err(|err| IoError::new(err, file_span, plugin_registry_file_path.clone()))?, + Some(file_span), + )? + } else { + PluginRegistryFile::default() + }; + + // Do the operation + operate(&mut contents)?; + + // Save the modified file on success + contents.write_to( + File::create(&plugin_registry_file_path) + .map_err(|err| IoError::new(err, file_span, plugin_registry_file_path))?, + Some(span), + )?; + + Ok(()) +} + +pub(crate) fn canonicalize_possible_filename_arg( + engine_state: &EngineState, + stack: &Stack, + arg: &str, +) -> PathBuf { + // This results in the best possible chance of a match with the plugin item + #[allow(deprecated)] + if let Ok(cwd) = nu_engine::current_dir(engine_state, stack) { + let path = nu_path::expand_path_with(arg, &cwd, true); + // Try to canonicalize + nu_path::locate_in_dirs(&path, &cwd, || get_plugin_dirs(engine_state, stack)) + // If we couldn't locate it, return the expanded path alone + .unwrap_or(path) + } else { + arg.into() + } +} + +pub(crate) fn get_plugin_dirs( + engine_state: &EngineState, + stack: &Stack, +) -> impl Iterator { + // Get the NU_PLUGIN_DIRS from the constant and/or env var + let working_set = StateWorkingSet::new(engine_state); + let dirs_from_const = working_set + .find_variable(b"$NU_PLUGIN_DIRS") + .and_then(|var_id| working_set.get_constant(var_id).ok()) + .cloned() // TODO: avoid this clone + .into_iter() + .flat_map(|value| value.into_list().ok()) + .flatten() + .flat_map(|list_item| list_item.coerce_into_string().ok()); + + let dirs_from_env = stack + .get_env_var(engine_state, "NU_PLUGIN_DIRS") + .cloned() // TODO: avoid this clone + .into_iter() + .flat_map(|value| value.into_list().ok()) + .flatten() + .flat_map(|list_item| list_item.coerce_into_string().ok()); + + dirs_from_const.chain(dirs_from_env) +} diff --git a/nushell/crates/nu-color-config/Cargo.toml b/nushell/crates/nu-color-config/Cargo.toml new file mode 100644 index 0000000..6b3aa21 --- /dev/null +++ b/nushell/crates/nu-color-config/Cargo.toml @@ -0,0 +1,25 @@ +[package] +authors = ["The Nushell Project Developers"] +description = "Color configuration code used by Nushell" +repository = "https://github.com/nushell/nushell/tree/main/crates/nu-color-config" +edition = "2024" +license = "MIT" +name = "nu-color-config" +version = "0.105.2" + +[lib] +bench = false + +[lints] +workspace = true + +[dependencies] +nu-protocol = { path = "../nu-protocol", version = "0.105.2", default-features = false } +nu-engine = { path = "../nu-engine", version = "0.105.2", default-features = false } +nu-json = { path = "../nu-json", version = "0.105.2" } +nu-ansi-term = { workspace = true } + +serde = { workspace = true, features = ["derive"] } + +[dev-dependencies] +nu-test-support = { path = "../nu-test-support", version = "0.105.2" } diff --git a/nushell/crates/nu-color-config/LICENSE b/nushell/crates/nu-color-config/LICENSE new file mode 100644 index 0000000..ae174e8 --- /dev/null +++ b/nushell/crates/nu-color-config/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 - 2023 The Nushell Project Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/nushell/crates/nu-color-config/README.md b/nushell/crates/nu-color-config/README.md new file mode 100644 index 0000000..f037536 --- /dev/null +++ b/nushell/crates/nu-color-config/README.md @@ -0,0 +1,5 @@ +Logic to resolve colors for syntax highlighting and output formatting + +## Internal Nushell crate + +This crate implements components of Nushell and is not designed to support plugin authors or other users directly. diff --git a/nushell/crates/nu-color-config/src/color_config.rs b/nushell/crates/nu-color-config/src/color_config.rs new file mode 100644 index 0000000..11db4c8 --- /dev/null +++ b/nushell/crates/nu-color-config/src/color_config.rs @@ -0,0 +1,159 @@ +use crate::{ + NuStyle, + nu_style::{color_from_hex, lookup_style}, + parse_nustyle, +}; +use nu_ansi_term::Style; +use nu_protocol::{Record, Value}; +use std::collections::HashMap; + +pub fn lookup_ansi_color_style(s: &str) -> Style { + if s.starts_with('#') { + color_from_hex(s) + .ok() + .and_then(|c| c.map(|c| c.normal())) + .unwrap_or_default() + } else if s.starts_with('{') { + color_string_to_nustyle(s) + } else { + lookup_style(s) + } +} + +pub fn get_color_map(colors: &HashMap) -> HashMap { + let mut hm: HashMap = HashMap::new(); + + for (key, value) in colors { + parse_map_entry(&mut hm, key, value); + } + + hm +} + +fn parse_map_entry(hm: &mut HashMap, key: &str, value: &Value) { + let value = match value { + Value::String { val, .. } => Some(lookup_ansi_color_style(val)), + Value::Record { val, .. } => get_style_from_value(val).map(parse_nustyle), + _ => None, + }; + if let Some(value) = value { + hm.entry(key.to_owned()).or_insert(value); + } +} + +fn get_style_from_value(record: &Record) -> Option { + let mut was_set = false; + let mut style = NuStyle::from(Style::default()); + for (col, val) in record { + match col.as_str() { + "bg" => { + if let Value::String { val, .. } = val { + style.bg = Some(val.clone()); + was_set = true; + } + } + "fg" => { + if let Value::String { val, .. } = val { + style.fg = Some(val.clone()); + was_set = true; + } + } + "attr" => { + if let Value::String { val, .. } = val { + style.attr = Some(val.clone()); + was_set = true; + } + } + _ => (), + } + } + + if was_set { Some(style) } else { None } +} + +fn color_string_to_nustyle(color_string: &str) -> Style { + // eprintln!("color_string: {}", &color_string); + if color_string.is_empty() { + return Style::default(); + } + + let nu_style = match nu_json::from_str::(color_string) { + Ok(s) => s, + Err(_) => return Style::default(), + }; + + parse_nustyle(nu_style) +} + +#[cfg(test)] +mod tests { + use super::*; + use nu_ansi_term::{Color, Style}; + use nu_protocol::{Span, Value, record}; + + #[test] + fn test_color_string_to_nustyle_empty_string() { + let color_string = String::new(); + let style = color_string_to_nustyle(&color_string); + assert_eq!(style, Style::default()); + } + + #[test] + fn test_color_string_to_nustyle_valid_string() { + let color_string = r#"{"fg": "black", "bg": "white", "attr": "b"}"#; + let style = color_string_to_nustyle(color_string); + assert_eq!(style.foreground, Some(Color::Black)); + assert_eq!(style.background, Some(Color::White)); + assert!(style.is_bold); + } + + #[test] + fn test_color_string_to_nustyle_invalid_string() { + let color_string = "invalid string"; + let style = color_string_to_nustyle(color_string); + assert_eq!(style, Style::default()); + } + + #[test] + fn test_get_style_from_value() { + // Test case 1: all values are valid + let record = record! { + "bg" => Value::test_string("red"), + "fg" => Value::test_string("blue"), + "attr" => Value::test_string("bold"), + }; + let expected_style = NuStyle { + bg: Some("red".to_string()), + fg: Some("blue".to_string()), + attr: Some("bold".to_string()), + }; + assert_eq!(get_style_from_value(&record), Some(expected_style)); + + // Test case 2: no values are valid + let record = record! { + "invalid" => Value::nothing(Span::test_data()), + }; + assert_eq!(get_style_from_value(&record), None); + + // Test case 3: some values are valid + let record = record! { + "bg" => Value::test_string("green"), + "invalid" => Value::nothing(Span::unknown()), + }; + let expected_style = NuStyle { + bg: Some("green".to_string()), + fg: None, + attr: None, + }; + assert_eq!(get_style_from_value(&record), Some(expected_style)); + } + + #[test] + fn test_parse_map_entry() { + let mut hm = HashMap::new(); + let key = "test_key".to_owned(); + let value = Value::string("red", Span::unknown()); + parse_map_entry(&mut hm, &key, &value); + assert_eq!(hm.get(&key), Some(&lookup_ansi_color_style("red"))); + } +} diff --git a/nushell/crates/nu-color-config/src/lib.rs b/nushell/crates/nu-color-config/src/lib.rs new file mode 100644 index 0000000..77ec9d0 --- /dev/null +++ b/nushell/crates/nu-color-config/src/lib.rs @@ -0,0 +1,14 @@ +#![doc = include_str!("../README.md")] +mod color_config; +mod matching_brackets_style; +mod nu_style; +mod shape_color; +mod style_computer; +mod text_style; + +pub use color_config::*; +pub use matching_brackets_style::*; +pub use nu_style::*; +pub use shape_color::*; +pub use style_computer::*; +pub use text_style::*; diff --git a/nushell/crates/nu-color-config/src/matching_brackets_style.rs b/nushell/crates/nu-color-config/src/matching_brackets_style.rs new file mode 100644 index 0000000..85ac23a --- /dev/null +++ b/nushell/crates/nu-color-config/src/matching_brackets_style.rs @@ -0,0 +1,31 @@ +use crate::color_config::lookup_ansi_color_style; +use nu_ansi_term::Style; +use nu_protocol::Config; + +pub fn get_matching_brackets_style(default_style: Style, conf: &Config) -> Style { + const MATCHING_BRACKETS_CONFIG_KEY: &str = "shape_matching_brackets"; + + match conf.color_config.get(MATCHING_BRACKETS_CONFIG_KEY) { + Some(int_color) => match int_color.coerce_str() { + Ok(int_color) => merge_styles(default_style, lookup_ansi_color_style(&int_color)), + Err(_) => default_style, + }, + None => default_style, + } +} + +fn merge_styles(base: Style, extra: Style) -> Style { + Style { + foreground: extra.foreground.or(base.foreground), + background: extra.background.or(base.background), + is_bold: extra.is_bold || base.is_bold, + is_dimmed: extra.is_dimmed || base.is_dimmed, + is_italic: extra.is_italic || base.is_italic, + is_underline: extra.is_underline || base.is_underline, + is_blink: extra.is_blink || base.is_blink, + is_reverse: extra.is_reverse || base.is_reverse, + is_hidden: extra.is_hidden || base.is_hidden, + is_strikethrough: extra.is_strikethrough || base.is_strikethrough, + prefix_with_reset: false, + } +} diff --git a/nushell/crates/nu-color-config/src/nu_style.rs b/nushell/crates/nu-color-config/src/nu_style.rs new file mode 100644 index 0000000..578534a --- /dev/null +++ b/nushell/crates/nu-color-config/src/nu_style.rs @@ -0,0 +1,599 @@ +use nu_ansi_term::{Color, Style}; +use nu_protocol::Value; +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize, PartialEq, Eq, Debug)] +pub struct NuStyle { + pub fg: Option, + pub bg: Option, + pub attr: Option, +} + +impl From3" + ); +} + +#[test] +fn out_html_metadata() { + let actual = nu!(r#" + echo 3 | to html | metadata | get content_type + "#); + + assert_eq!(actual.out, r#"text/html; charset=utf-8"#); +} + +#[test] +fn out_html_partial() { + let actual = nu!(r#" + echo 3 | to html -p + "#); + + assert_eq!( + actual.out, + "
3
" + ); +} + +#[test] +fn out_html_table() { + let actual = nu!(r#" + echo '{"name": "darren"}' | from json | to html + "#); + + assert_eq!( + actual.out, + r"
name
darren
" + ); +} + +#[test] +#[ignore] +fn test_cd_html_color_flag_dark_false() { + let actual = nu!(r#" + cd --help | to html --html-color + "#); + assert_eq!( + actual.out, + r"Change directory.

Usage:
> cd (path)

Flags:
-h, --help - Display the help message for this command

Signatures:
<nothing> | cd <string?> -> <nothing>
<string> | cd <string?> -> <nothing>

Parameters:
(optional)
path <directory>: the path to change to

Examples:
Change to your home directory
>
cd
~

Change to a directory via abbreviations
>
cd
d/s/9

Change to the previous working directory ($OLDPWD)
>
cd
-

" + ); +} + +#[test] +#[ignore] +fn test_no_color_flag() { + // TODO replace with something potentially more stable, otherwise this test needs to be + // manuallly updated when ever the help output changes + let actual = nu!(r#" + cd --help | to html --no-color + "#); + assert_eq!( + actual.out, + r"Change directory.

Usage:
> cd (path)

Flags:
-h, --help - Display the help message for this command

Parameters:
path <directory>: The path to change to. (optional)

Input/output types:
╭─#─┬──input──┬─output──╮
│ 0 │ nothing │ nothing │
│ 1 │ string │ nothing │
╰───┴─────────┴─────────╯

Examples:
Change to your home directory
> cd ~

Change to the previous working directory ($OLDPWD)
> cd -

" + ) +} + +#[test] +fn test_list() { + let actual = nu!(r#"to html --list | where name == C64 | get 0 | to nuon"#); + assert_eq!( + actual.out, + r##"{name: "C64", black: "#090300", red: "#883932", green: "#55a049", yellow: "#bfce72", blue: "#40318d", purple: "#8b3f96", cyan: "#67b6bd", white: "#ffffff", brightBlack: "#000000", brightRed: "#883932", brightGreen: "#55a049", brightYellow: "#bfce72", brightBlue: "#40318d", brightPurple: "#8b3f96", brightCyan: "#67b6bd", brightWhite: "#f7f7f7", background: "#40318d", foreground: "#7869c4"}"## + ); +} diff --git a/nushell/crates/nu-command/tests/format_conversions/json.rs b/nushell/crates/nu-command/tests/format_conversions/json.rs new file mode 100644 index 0000000..9b6c045 --- /dev/null +++ b/nushell/crates/nu-command/tests/format_conversions/json.rs @@ -0,0 +1,299 @@ +use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; +use nu_test_support::playground::Playground; +use nu_test_support::{nu, pipeline}; + +#[test] +fn table_to_json_text_and_from_json_text_back_into_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sgml_description.json + | to json + | from json + | get glossary.GlossDiv.GlossList.GlossEntry.GlossSee + "# + )); + + assert_eq!(actual.out, "markup"); +} + +#[test] +fn from_json_text_to_table() { + Playground::setup("filter_from_json_test_1", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "katz.txt", + r#" + { + "katz": [ + {"name": "Yehuda", "rusty_luck": 1}, + {"name": "JT", "rusty_luck": 1}, + {"name": "Andres", "rusty_luck": 1}, + {"name":"GorbyPuff", "rusty_luck": 1} + ] + } + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), + "open katz.txt | from json | get katz | get rusty_luck | length " + ); + + assert_eq!(actual.out, "4"); + }) +} + +#[test] +fn from_json_text_to_table_strict() { + Playground::setup("filter_from_json_test_1_strict", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "katz.txt", + r#" + { + "katz": [ + {"name": "Yehuda", "rusty_luck": 1}, + {"name": "JT", "rusty_luck": 1}, + {"name": "Andres", "rusty_luck": 1}, + {"name":"GorbyPuff", "rusty_luck": 1} + ] + } + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), + "open katz.txt | from json -s | get katz | get rusty_luck | length " + ); + + assert_eq!(actual.out, "4"); + }) +} + +#[test] +fn from_json_text_recognizing_objects_independently_to_table() { + Playground::setup("filter_from_json_test_2", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "katz.txt", + r#" + {"name": "Yehuda", "rusty_luck": 1} + {"name": "JT", "rusty_luck": 1} + {"name": "Andres", "rusty_luck": 1} + {"name":"GorbyPuff", "rusty_luck": 3} + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open katz.txt + | from json -o + | where name == "GorbyPuff" + | get rusty_luck.0 + "# + )); + + assert_eq!(actual.out, "3"); + }) +} + +#[test] +fn from_json_text_objects_is_stream() { + Playground::setup("filter_from_json_test_2_is_stream", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "katz.txt", + r#" + {"name": "Yehuda", "rusty_luck": 1} + {"name": "JT", "rusty_luck": 1} + {"name": "Andres", "rusty_luck": 1} + {"name":"GorbyPuff", "rusty_luck": 3} + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open katz.txt + | from json -o + | describe -n + "# + )); + + assert_eq!(actual.out, "stream"); + }) +} + +#[test] +fn from_json_text_recognizing_objects_independently_to_table_strict() { + Playground::setup("filter_from_json_test_2_strict", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "katz.txt", + r#" + {"name": "Yehuda", "rusty_luck": 1} + {"name": "JT", "rusty_luck": 1} + {"name": "Andres", "rusty_luck": 1} + {"name":"GorbyPuff", "rusty_luck": 3} + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open katz.txt + | from json -o -s + | where name == "GorbyPuff" + | get rusty_luck.0 + "# + )); + + assert_eq!(actual.out, "3"); + }) +} + +#[test] +fn table_to_json_text() { + Playground::setup("filter_to_json_test", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "sample.txt", + r#" + JonAndrehudaTZ,3 + GorbyPuff,100 + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open sample.txt + | lines + | split column "," name luck + | select name + | to json + | from json + | get 0 + | get name + "# + )); + + assert_eq!(actual.out, "JonAndrehudaTZ"); + }) +} + +#[test] +fn table_to_json_text_strict() { + Playground::setup("filter_to_json_test_strict", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "sample.txt", + r#" + JonAndrehudaTZ,3 + GorbyPuff,100 + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open sample.txt + | lines + | split column "," name luck + | select name + | to json + | from json -s + | get 0 + | get name + "# + )); + + assert_eq!(actual.out, "JonAndrehudaTZ"); + }) +} + +#[test] +fn top_level_values_from_json() { + for (value, type_name) in [("null", "nothing"), ("true", "bool"), ("false", "bool")] { + let actual = nu!(r#""{}" | from json | to json"#, value); + assert_eq!(actual.out, value); + let actual = nu!(r#""{}" | from json | describe"#, value); + assert_eq!(actual.out, type_name); + } +} + +#[test] +fn top_level_values_from_json_strict() { + for (value, type_name) in [("null", "nothing"), ("true", "bool"), ("false", "bool")] { + let actual = nu!(r#""{}" | from json -s | to json"#, value); + assert_eq!(actual.out, value); + let actual = nu!(r#""{}" | from json -s | describe"#, value); + assert_eq!(actual.out, type_name); + } +} + +#[test] +fn strict_parsing_fails_on_comment() { + let actual = nu!(r#"'{ "a": 1, /* comment */ "b": 2 }' | from json -s"#); + assert!(actual.err.contains("error parsing JSON text")); +} + +#[test] +fn strict_parsing_fails_on_trailing_comma() { + let actual = nu!(r#"'{ "a": 1, "b": 2, }' | from json -s"#); + assert!(actual.err.contains("error parsing JSON text")); +} + +#[test] +fn ranges_to_json_as_array() { + let value = r#"[ 1, 2, 3]"#; + let actual = nu!(r#"1..3 | to json"#); + assert_eq!(actual.out, value); +} + +#[test] +fn unbounded_from_in_range_fails() { + let actual = nu!(r#"1.. | to json"#); + assert!(actual.err.contains("Cannot create range")); +} + +#[test] +fn inf_in_range_fails() { + let actual = nu!(r#"inf..5 | to json"#); + assert!(actual.err.contains("can't convert to countable values")); + let actual = nu!(r#"5..inf | to json"#); + assert!( + actual + .err + .contains("Unbounded ranges are not allowed when converting to this format") + ); + let actual = nu!(r#"-inf..inf | to json"#); + assert!(actual.err.contains("can't convert to countable values")); +} + +#[test] +fn test_indent_flag() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + echo '{ "a": 1, "b": 2, "c": 3 }' + | from json + | to json --indent 3 + "# + )); + + let expected_output = "{ \"a\": 1, \"b\": 2, \"c\": 3}"; + + assert_eq!(actual.out, expected_output); +} + +#[test] +fn test_tabs_indent_flag() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + echo '{ "a": 1, "b": 2, "c": 3 }' + | from json + | to json --tabs 2 + "# + )); + + let expected_output = "{\t\t\"a\": 1,\t\t\"b\": 2,\t\t\"c\": 3}"; + + assert_eq!(actual.out, expected_output); +} diff --git a/nushell/crates/nu-command/tests/format_conversions/markdown.rs b/nushell/crates/nu-command/tests/format_conversions/markdown.rs new file mode 100644 index 0000000..9fefaf5 --- /dev/null +++ b/nushell/crates/nu-command/tests/format_conversions/markdown.rs @@ -0,0 +1,79 @@ +use nu_test_support::{nu, pipeline}; + +#[test] +fn md_empty() { + let actual = nu!(r#" + echo [[]; []] | from json | to md + "#); + + assert_eq!(actual.out, ""); +} + +#[test] +fn md_empty_pretty() { + let actual = nu!(r#" + echo "{}" | from json | to md -p + "#); + + assert_eq!(actual.out, ""); +} + +#[test] +fn md_simple() { + let actual = nu!(r#" + echo 3 | to md + "#); + + assert_eq!(actual.out, "3"); +} + +#[test] +fn md_simple_pretty() { + let actual = nu!(r#" + echo 3 | to md -p + "#); + + assert_eq!(actual.out, "3"); +} + +#[test] +fn md_table() { + let actual = nu!(r#" + echo [[name]; [jason]] | to md + "#); + + assert_eq!(actual.out, "|name||-||jason|"); +} + +#[test] +fn md_table_pretty() { + let actual = nu!(r#" + echo [[name]; [joseph]] | to md -p + "#); + + assert_eq!(actual.out, "| name || ------ || joseph |"); +} + +#[test] +fn md_combined() { + let actual = nu!(pipeline( + r#" + def title [] { + echo [[H1]; ["Nu top meals"]] + }; + + def meals [] { + echo [[dish]; [Arepa] [Taco] [Pizza]] + }; + + title + | append (meals) + | to md --per-element --pretty + "# + )); + + assert_eq!( + actual.out, + "# Nu top meals| dish || ----- || Arepa || Taco || Pizza |" + ); +} diff --git a/nushell/crates/nu-command/tests/format_conversions/mod.rs b/nushell/crates/nu-command/tests/format_conversions/mod.rs new file mode 100644 index 0000000..939a55d --- /dev/null +++ b/nushell/crates/nu-command/tests/format_conversions/mod.rs @@ -0,0 +1,15 @@ +mod csv; +mod html; +mod json; +mod markdown; +mod msgpack; +mod msgpackz; +mod nuon; +mod ods; +mod ssv; +mod toml; +mod tsv; +mod url; +mod xlsx; +mod xml; +mod yaml; diff --git a/nushell/crates/nu-command/tests/format_conversions/msgpack.rs b/nushell/crates/nu-command/tests/format_conversions/msgpack.rs new file mode 100644 index 0000000..578e96e --- /dev/null +++ b/nushell/crates/nu-command/tests/format_conversions/msgpack.rs @@ -0,0 +1,161 @@ +use nu_test_support::{nu, playground::Playground}; +use pretty_assertions::assert_eq; + +fn msgpack_test(fixture_name: &str, commands: Option<&str>) -> nu_test_support::Outcome { + let path_to_generate_nu = nu_test_support::fs::fixtures() + .join("formats") + .join("msgpack") + .join("generate.nu"); + + let mut outcome = None; + Playground::setup(&format!("msgpack test {}", fixture_name), |dirs, _| { + assert!( + nu!( + cwd: dirs.test(), + format!( + "nu -n '{}' '{}'", + path_to_generate_nu.display(), + fixture_name + ), + ) + .status + .success() + ); + + outcome = Some(nu!( + cwd: dirs.test(), + collapse_output: false, + commands.map(|c| c.to_owned()).unwrap_or_else(|| format!("open {fixture_name}.msgpack")) + )); + }); + outcome.expect("failed to get outcome") +} + +fn msgpack_nuon_test(fixture_name: &str, opts: &str) { + let path_to_nuon = nu_test_support::fs::fixtures() + .join("formats") + .join("msgpack") + .join(format!("{fixture_name}.nuon")); + + let sample_nuon = std::fs::read_to_string(path_to_nuon).expect("failed to open nuon file"); + + let outcome = msgpack_test( + fixture_name, + Some(&format!( + "open --raw {fixture_name}.msgpack | from msgpack {opts} | to nuon --indent 4" + )), + ); + + assert!(outcome.status.success()); + assert!(outcome.err.is_empty()); + assert_eq!( + sample_nuon.replace("\r\n", "\n"), + outcome.out.replace("\r\n", "\n") + ); +} + +#[test] +fn sample() { + msgpack_nuon_test("sample", ""); +} + +#[test] +fn sample_roundtrip() { + let path_to_sample_nuon = nu_test_support::fs::fixtures() + .join("formats") + .join("msgpack") + .join("sample.nuon"); + + let sample_nuon = + std::fs::read_to_string(&path_to_sample_nuon).expect("failed to open sample.nuon"); + + let outcome = nu!( + collapse_output: false, + format!( + "open '{}' | to msgpack | from msgpack | to nuon --indent 4", + path_to_sample_nuon.display() + ) + ); + + assert!(outcome.status.success()); + assert!(outcome.err.is_empty()); + assert_eq!( + sample_nuon.replace("\r\n", "\n"), + outcome.out.replace("\r\n", "\n") + ); +} + +#[test] +fn objects() { + msgpack_nuon_test("objects", "--objects"); +} + +#[test] +fn max_depth() { + let outcome = msgpack_test("max-depth", None); + assert!(!outcome.status.success()); + assert!(outcome.err.contains("exceeded depth limit")); +} + +#[test] +fn non_utf8() { + let outcome = msgpack_test("non-utf8", None); + assert!(!outcome.status.success()); + assert!(outcome.err.contains("utf-8")); +} + +#[test] +fn empty() { + let outcome = msgpack_test("empty", None); + assert!(!outcome.status.success()); + assert!(outcome.err.contains("fill whole buffer")); +} + +#[test] +fn eof() { + let outcome = msgpack_test("eof", None); + assert!(!outcome.status.success()); + assert!(outcome.err.contains("fill whole buffer")); +} + +#[test] +fn after_eof() { + let outcome = msgpack_test("after-eof", None); + assert!(!outcome.status.success()); + assert!(outcome.err.contains("after end of")); +} + +#[test] +fn reserved() { + let outcome = msgpack_test("reserved", None); + assert!(!outcome.status.success()); + assert!(outcome.err.contains("Reserved")); +} + +#[test] +fn u64_too_large() { + let outcome = msgpack_test("u64-too-large", None); + assert!(!outcome.status.success()); + assert!(outcome.err.contains("integer too big")); +} + +#[test] +fn non_string_map_key() { + let outcome = msgpack_test("non-string-map-key", None); + assert!(!outcome.status.success()); + assert!(outcome.err.contains("string key")); +} + +#[test] +fn timestamp_wrong_length() { + let outcome = msgpack_test("timestamp-wrong-length", None); + assert!(!outcome.status.success()); + assert!(outcome.err.contains("Unknown MessagePack extension")); +} + +#[test] +fn other_extension_type() { + let outcome = msgpack_test("other-extension-type", None); + assert!(!outcome.status.success()); + assert!(outcome.err.contains("Unknown MessagePack extension")); +} diff --git a/nushell/crates/nu-command/tests/format_conversions/msgpackz.rs b/nushell/crates/nu-command/tests/format_conversions/msgpackz.rs new file mode 100644 index 0000000..c2a7ade --- /dev/null +++ b/nushell/crates/nu-command/tests/format_conversions/msgpackz.rs @@ -0,0 +1,28 @@ +use nu_test_support::nu; +use pretty_assertions::assert_eq; + +#[test] +fn sample_roundtrip() { + let path_to_sample_nuon = nu_test_support::fs::fixtures() + .join("formats") + .join("msgpack") + .join("sample.nuon"); + + let sample_nuon = + std::fs::read_to_string(&path_to_sample_nuon).expect("failed to open sample.nuon"); + + let outcome = nu!( + collapse_output: false, + format!( + "open '{}' | to msgpackz | from msgpackz | to nuon --indent 4", + path_to_sample_nuon.display() + ) + ); + + assert!(outcome.status.success()); + assert!(outcome.err.is_empty()); + assert_eq!( + sample_nuon.replace("\r\n", "\n"), + outcome.out.replace("\r\n", "\n") + ); +} diff --git a/nushell/crates/nu-command/tests/format_conversions/nuon.rs b/nushell/crates/nu-command/tests/format_conversions/nuon.rs new file mode 100644 index 0000000..cdac532 --- /dev/null +++ b/nushell/crates/nu-command/tests/format_conversions/nuon.rs @@ -0,0 +1,524 @@ +use nu_test_support::{nu, pipeline}; + +#[test] +fn to_nuon_correct_compaction() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open appveyor.yml + | to nuon + | str length + | $in > 500 + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn to_nuon_list_of_numbers() { + let actual = nu!(pipeline( + r#" + [1, 2, 3, 4] + | to nuon + | from nuon + | $in == [1, 2, 3, 4] + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn to_nuon_list_of_strings() { + let actual = nu!(pipeline( + r#" + [abc, xyz, def] + | to nuon + | from nuon + | $in == [abc, xyz, def] + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn to_nuon_table() { + let actual = nu!(pipeline( + r#" + [[my, columns]; [abc, xyz], [def, ijk]] + | to nuon + | from nuon + | $in == [[my, columns]; [abc, xyz], [def, ijk]] + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn from_nuon_illegal_table() { + let actual = nu!(pipeline( + r#" + "[[repeated repeated]; [abc, xyz], [def, ijk]]" + | from nuon + "# + )); + + assert!(actual.err.contains("column_defined_twice")); +} + +#[test] +fn to_nuon_bool() { + let actual = nu!(pipeline( + r#" + false + | to nuon + | from nuon + "# + )); + + assert_eq!(actual.out, "false"); +} + +#[test] +fn to_nuon_escaping() { + let actual = nu!(pipeline( + r#" + "hello\"world" + | to nuon + | from nuon + "# + )); + + assert_eq!(actual.out, "hello\"world"); +} + +#[test] +fn to_nuon_escaping2() { + let actual = nu!(pipeline( + r#" + "hello\\world" + | to nuon + | from nuon + "# + )); + + assert_eq!(actual.out, "hello\\world"); +} + +#[test] +fn to_nuon_escaping3() { + let actual = nu!(pipeline( + r#" + ["hello\\world"] + | to nuon + | from nuon + | $in == [hello\world] + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn to_nuon_escaping4() { + let actual = nu!(pipeline( + r#" + ["hello\"world"] + | to nuon + | from nuon + | $in == ["hello\"world"] + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn to_nuon_escaping5() { + let actual = nu!(pipeline( + r#" + {s: "hello\"world"} + | to nuon + | from nuon + | $in == {s: "hello\"world"} + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn to_nuon_negative_int() { + let actual = nu!(pipeline( + r#" + -1 + | to nuon + | from nuon + "# + )); + + assert_eq!(actual.out, "-1"); +} + +#[test] +fn to_nuon_records() { + let actual = nu!(pipeline( + r#" + {name: "foo bar", age: 100, height: 10} + | to nuon + | from nuon + | $in == {name: "foo bar", age: 100, height: 10} + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn to_nuon_range() { + let actual = nu!(r#"1..42 | to nuon"#); + assert_eq!(actual.out, "1..42"); + + let actual = nu!(r#"1..<42 | to nuon"#); + assert_eq!(actual.out, "1..<42"); + + let actual = nu!(r#"1..4..42 | to nuon"#); + assert_eq!(actual.out, "1..4..42"); + + let actual = nu!(r#"1..4..<42 | to nuon"#); + assert_eq!(actual.out, "1..4..<42"); + + let actual = nu!(r#"1.0..42.0 | to nuon"#); + assert_eq!(actual.out, "1.0..42.0"); + + let actual = nu!(r#"1.0..<42.0 | to nuon"#); + assert_eq!(actual.out, "1.0..<42.0"); + + let actual = nu!(r#"1.0..4.0..42.0 | to nuon"#); + assert_eq!(actual.out, "1.0..4.0..42.0"); + + let actual = nu!(r#"1.0..4.0..<42.0 | to nuon"#); + assert_eq!(actual.out, "1.0..4.0..<42.0"); +} + +#[test] +fn from_nuon_range() { + let actual = nu!(r#"'1..42' | from nuon | to nuon"#); + assert_eq!(actual.out, "1..42"); + + let actual = nu!(r#"'1..<42' | from nuon | to nuon"#); + assert_eq!(actual.out, "1..<42"); + + let actual = nu!(r#"'1..4..42' | from nuon | to nuon"#); + assert_eq!(actual.out, "1..4..42"); + + let actual = nu!(r#"'1..4..<42' | from nuon | to nuon"#); + assert_eq!(actual.out, "1..4..<42"); + + let actual = nu!(r#"'1.0..42.0' | from nuon | to nuon"#); + assert_eq!(actual.out, "1.0..42.0"); + + let actual = nu!(r#"'1.0..<42.0' | from nuon | to nuon"#); + assert_eq!(actual.out, "1.0..<42.0"); + + let actual = nu!(r#"'1.0..4.0..42.0' | from nuon | to nuon"#); + assert_eq!(actual.out, "1.0..4.0..42.0"); + + let actual = nu!(r#"'1.0..4.0..<42.0' | from nuon | to nuon"#); + assert_eq!(actual.out, "1.0..4.0..<42.0"); +} + +#[test] +fn to_nuon_filesize() { + let actual = nu!(pipeline( + r#" + 1kib + | to nuon + "# + )); + + assert_eq!(actual.out, "1024b"); +} + +#[test] +fn from_nuon_filesize() { + let actual = nu!(pipeline( + r#" + "1024b" + | from nuon + | describe + "# + )); + + assert_eq!(actual.out, "filesize"); +} + +#[test] +fn to_nuon_duration() { + let actual = nu!(pipeline( + r#" + 1min + | to nuon + "# + )); + + assert_eq!(actual.out, "60000000000ns"); +} + +#[test] +fn from_nuon_duration() { + let actual = nu!(pipeline( + r#" + "60000000000ns" + | from nuon + | describe + "# + )); + + assert_eq!(actual.out, "duration"); +} + +#[test] +fn to_nuon_datetime() { + let actual = nu!(pipeline( + r#" + 2019-05-10 + | to nuon + "# + )); + + assert_eq!(actual.out, "2019-05-10T00:00:00+00:00"); +} + +#[test] +fn from_nuon_datetime() { + let actual = nu!(pipeline( + r#" + "2019-05-10T00:00:00+00:00" + | from nuon + | describe + "# + )); + + assert_eq!(actual.out, "datetime"); +} + +#[test] +fn to_nuon_errs_on_closure() { + let actual = nu!(pipeline( + r#" + {|| to nuon} + | to nuon + "# + )); + + assert!(actual.err.contains("not deserializable")); +} + +#[test] +fn to_nuon_closure_coerced_to_quoted_string() { + let actual = nu!(pipeline( + r#" + {|| to nuon} + | to nuon --serialize + "# + )); + + assert_eq!(actual.out, "\"{|| to nuon}\""); +} + +#[test] +fn binary_to() { + let actual = nu!(pipeline( + r#" + 0x[ab cd ef] | to nuon + "# + )); + + assert_eq!(actual.out, "0x[ABCDEF]"); +} + +#[test] +fn binary_roundtrip() { + let actual = nu!(pipeline( + r#" + "0x[1f ff]" | from nuon | to nuon + "# + )); + + assert_eq!(actual.out, "0x[1FFF]"); +} + +#[test] +fn read_binary_data() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample.nuon | get 5.3 + "# + )); + + assert_eq!(actual.out, "31") +} + +#[test] +fn read_record() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample.nuon | get 4.name + "# + )); + + assert_eq!(actual.out, "Bobby") +} + +#[test] +fn read_bool() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample.nuon | get 3 | $in == true + "# + )); + + assert_eq!(actual.out, "true") +} + +#[test] +fn float_doesnt_become_int() { + let actual = nu!(pipeline( + r#" + 1.0 | to nuon + "# + )); + + assert_eq!(actual.out, "1.0") +} + +#[test] +fn float_inf_parsed_properly() { + let actual = nu!(pipeline( + r#" + inf | to nuon + "# + )); + + assert_eq!(actual.out, "inf") +} + +#[test] +fn float_neg_inf_parsed_properly() { + let actual = nu!(pipeline( + r#" + -inf | to nuon + "# + )); + + assert_eq!(actual.out, "-inf") +} + +#[test] +fn float_nan_parsed_properly() { + let actual = nu!(pipeline( + r#" + NaN | to nuon + "# + )); + + assert_eq!(actual.out, "NaN") +} + +#[test] +fn to_nuon_converts_columns_with_spaces() { + let actual = nu!(pipeline( + r#" + let test = [[a, b, "c d"]; [1 2 3] [4 5 6]]; $test | to nuon | from nuon + "# + )); + assert!(actual.err.is_empty()); +} + +#[test] +fn to_nuon_quotes_empty_string() { + let actual = nu!(pipeline( + r#" + let test = ""; $test | to nuon + "# + )); + assert!(actual.err.is_empty()); + assert_eq!(actual.out, r#""""#) +} + +#[test] +fn to_nuon_quotes_empty_string_in_list() { + let actual = nu!(pipeline( + r#" + let test = [""]; $test | to nuon | from nuon | $in == [""] + "# + )); + assert!(actual.err.is_empty()); + assert_eq!(actual.out, "true") +} + +#[test] +fn to_nuon_quotes_empty_string_in_table() { + let actual = nu!(pipeline( + r#" + let test = [[a, b]; ['', la] [le lu]]; $test | to nuon | from nuon + "# + )); + assert!(actual.err.is_empty()); +} + +#[test] +fn does_not_quote_strings_unnecessarily() { + let actual = nu!(pipeline( + r#" + let test = [["a", "b", "c d"]; [1 2 3] [4 5 6]]; $test | to nuon + "# + )); + assert_eq!(actual.out, "[[a, b, \"c d\"]; [1, 2, 3], [4, 5, 6]]"); + let actual = nu!(pipeline( + r#" + let a = {"ro name": "sam" rank: 10}; $a | to nuon + "# + )); + assert_eq!(actual.out, "{\"ro name\": sam, rank: 10}"); +} + +#[test] +fn quotes_some_strings_necessarily() { + let actual = nu!(pipeline( + r#" + ['true','false','null', + 'NaN','NAN','nan','+nan','-nan', + 'inf','+inf','-inf','INF', + 'Infinity','+Infinity','-Infinity','INFINITY', + '+19.99','-19.99', '19.99b', + '19.99kb','19.99mb','19.99gb','19.99tb','19.99pb','19.99eb','19.99zb', + '19.99kib','19.99mib','19.99gib','19.99tib','19.99pib','19.99eib','19.99zib', + '19ns', '19us', '19ms', '19sec', '19min', '19hr', '19day', '19wk', + '-11.0..-15.0', '11.0..-15.0', '-11.0..15.0', + '-11.0..<-15.0', '11.0..<-15.0', '-11.0..<15.0', + '-11.0..', '11.0..', '..15.0', '..-15.0', '..<15.0', '..<-15.0', + '2000-01-01', '2022-02-02T14:30:00', '2022-02-02T14:30:00+05:00', + ',','' + '&&' + ] | to nuon | from nuon | describe + "# + )); + + assert_eq!(actual.out, "list"); +} + +#[test] +fn read_code_should_fail_rather_than_panic() { + let actual = nu!(cwd: "tests/fixtures/formats", pipeline( + r#"open code.nu | from nuon"# + )); + assert!(actual.err.contains("Error when loading")) +} diff --git a/nushell/crates/nu-command/tests/format_conversions/ods.rs b/nushell/crates/nu-command/tests/format_conversions/ods.rs new file mode 100644 index 0000000..8a69493 --- /dev/null +++ b/nushell/crates/nu-command/tests/format_conversions/ods.rs @@ -0,0 +1,48 @@ +use nu_test_support::{nu, pipeline}; + +#[test] +fn from_ods_file_to_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample_data.ods + | get SalesOrders + | get 4 + | get column2 + "# + )); + + assert_eq!(actual.out, "Gill"); +} + +#[test] +fn from_ods_file_to_table_select_sheet() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample_data.ods --raw + | from ods --sheets ["SalesOrders"] + | columns + | get 0 + "# + )); + + assert_eq!(actual.out, "SalesOrders"); +} + +#[test] +fn from_ods_file_to_table_select_sheet_with_annotations() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample_data_with_annotation.ods --raw + | from ods --sheets ["SalesOrders"] + | get SalesOrders + | get column4 + | get 0 + "# + )); + + // The Units column in the sheet SalesOrders has an annotation and should be ignored. + assert_eq!(actual.out, "Units"); +} diff --git a/nushell/crates/nu-command/tests/format_conversions/ssv.rs b/nushell/crates/nu-command/tests/format_conversions/ssv.rs new file mode 100644 index 0000000..5a62f79 --- /dev/null +++ b/nushell/crates/nu-command/tests/format_conversions/ssv.rs @@ -0,0 +1,95 @@ +use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; +use nu_test_support::playground::Playground; +use nu_test_support::{nu, pipeline}; + +#[test] +fn from_ssv_text_to_table() { + Playground::setup("filter_from_ssv_test_1", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "oc_get_svc.txt", + r#" + NAME LABELS SELECTOR IP PORT(S) + docker-registry docker-registry=default docker-registry=default 172.30.78.158 5000/TCP + kubernetes component=apiserver,provider=kubernetes 172.30.0.2 443/TCP + kubernetes-ro component=apiserver,provider=kubernetes 172.30.0.1 80/TCP + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open oc_get_svc.txt + | from ssv + | get 0 + | get IP + "# + )); + + assert_eq!(actual.out, "172.30.78.158"); + }) +} + +#[test] +fn from_ssv_text_to_table_with_separator_specified() { + Playground::setup("filter_from_ssv_test_1", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "oc_get_svc.txt", + r#" + NAME LABELS SELECTOR IP PORT(S) + docker-registry docker-registry=default docker-registry=default 172.30.78.158 5000/TCP + kubernetes component=apiserver,provider=kubernetes 172.30.0.2 443/TCP + kubernetes-ro component=apiserver,provider=kubernetes 172.30.0.1 80/TCP + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open oc_get_svc.txt + | from ssv --minimum-spaces 3 + | get 0 + | get IP + "# + )); + + assert_eq!(actual.out, "172.30.78.158"); + }) +} + +#[test] +fn from_ssv_text_treating_first_line_as_data_with_flag() { + Playground::setup("filter_from_ssv_test_2", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "oc_get_svc.txt", + r#" + docker-registry docker-registry=default docker-registry=default 172.30.78.158 5000/TCP + kubernetes component=apiserver,provider=kubernetes 172.30.0.2 443/TCP + kubernetes-ro component=apiserver,provider=kubernetes 172.30.0.1 80/TCP + "#, + )]); + + let aligned_columns = nu!( + cwd: dirs.test(), pipeline( + r#" + open oc_get_svc.txt + | from ssv --noheaders -a + | first + | get column0 + "# + )); + + let separator_based = nu!( + cwd: dirs.test(), pipeline( + r#" + open oc_get_svc.txt + | from ssv --noheaders + | first + | get column0 + + "# + )); + + assert_eq!(aligned_columns.out, separator_based.out); + assert_eq!(separator_based.out, "docker-registry"); + }) +} diff --git a/nushell/crates/nu-command/tests/format_conversions/toml.rs b/nushell/crates/nu-command/tests/format_conversions/toml.rs new file mode 100644 index 0000000..1b6e139 --- /dev/null +++ b/nushell/crates/nu-command/tests/format_conversions/toml.rs @@ -0,0 +1,96 @@ +use nu_test_support::{nu, pipeline}; + +#[test] +fn record_map_to_toml() { + let actual = nu!(pipeline( + r#" + {a: 1 b: 2 c: 'qwe'} + | to toml + | from toml + | $in == {a: 1 b: 2 c: 'qwe'} + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn nested_records_to_toml() { + let actual = nu!(pipeline( + r#" + {a: {a: a b: b} c: 1} + | to toml + | from toml + | $in == {a: {a: a b: b} c: 1} + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn records_with_tables_to_toml() { + let actual = nu!(pipeline( + r#" + {a: [[a b]; [1 2] [3 4]] b: [[c d e]; [1 2 3]]} + | to toml + | from toml + | $in == {a: [[a b]; [1 2] [3 4]] b: [[c d e]; [1 2 3]]} + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn nested_tables_to_toml() { + let actual = nu!(pipeline( + r#" + {c: [[f g]; [[[h k]; [1 2] [3 4]] 1]]} + | to toml + | from toml + | $in == {c: [[f g]; [[[h k]; [1 2] [3 4]] 1]]} + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn table_to_toml_fails() { + // Tables can't be represented in toml + let actual = nu!(pipeline( + r#" + try { [[a b]; [1 2] [5 6]] | to toml | false } catch { true } + "# + )); + + assert!(actual.err.contains("command doesn't support")); +} + +#[test] +fn string_to_toml_fails() { + // Strings are not a top-level toml structure + let actual = nu!(pipeline( + r#" + try { 'not a valid toml' | to toml | false } catch { true } + "# + )); + + assert!(actual.err.contains("command doesn't support")); +} + +#[test] +fn big_record_to_toml_text_and_from_toml_text_back_into_record() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open cargo_sample.toml + | to toml + | from toml + | get package.name + "# + )); + + assert_eq!(actual.out, "nu"); +} diff --git a/nushell/crates/nu-command/tests/format_conversions/tsv.rs b/nushell/crates/nu-command/tests/format_conversions/tsv.rs new file mode 100644 index 0000000..31740ef --- /dev/null +++ b/nushell/crates/nu-command/tests/format_conversions/tsv.rs @@ -0,0 +1,295 @@ +use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; +use nu_test_support::playground::Playground; +use nu_test_support::{nu, pipeline}; + +#[test] +fn table_to_tsv_text_and_from_tsv_text_back_into_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", + "open caco3_plastics.tsv | to tsv | from tsv | first | get origin" + ); + + assert_eq!(actual.out, "SPAIN"); +} + +#[test] +fn table_to_tsv_text_and_from_tsv_text_back_into_table_using_csv_separator() { + let actual = nu!( + cwd: "tests/fixtures/formats", + r#"open caco3_plastics.tsv | to tsv | from csv --separator "\t" | first | get origin"# + ); + + assert_eq!(actual.out, "SPAIN"); +} + +#[test] +fn table_to_tsv_text() { + Playground::setup("filter_to_tsv_test_1", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "tsv_text_sample.txt", + r#" + importer shipper tariff_item name origin + Plasticos Rival Reverte 2509000000 Calcium carbonate Spain + Tigre Ecuador OMYA Andina 3824909999 Calcium carbonate Colombia + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open tsv_text_sample.txt + | lines + | split column "\t" a b c d origin + | last 1 + | to tsv + | lines + | select 1 + "# + )); + + assert!(actual.out.contains("Colombia")); + }) +} + +#[test] +fn table_to_tsv_text_skipping_headers_after_conversion() { + Playground::setup("filter_to_tsv_test_2", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "tsv_text_sample.txt", + r#" + importer shipper tariff_item name origin + Plasticos Rival Reverte 2509000000 Calcium carbonate Spain + Tigre Ecuador OMYA Andina 3824909999 Calcium carbonate Colombia + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open tsv_text_sample.txt + | lines + | split column "\t" a b c d origin + | last 1 + | to tsv --noheaders + "# + )); + + assert!(actual.out.contains("Colombia")); + }) +} + +#[test] +fn from_tsv_text_to_table() { + Playground::setup("filter_from_tsv_test_1", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "los_tres_amigos.txt", + r#" + first Name Last Name rusty_luck + Andrés Robalino 1 + JT Turner 1 + Yehuda Katz 1 + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_amigos.txt + | from tsv + | get rusty_luck + | length + "# + )); + + assert_eq!(actual.out, "3"); + }) +} + +#[test] +#[ignore = "csv crate has a bug when the last line is a comment: https://github.com/BurntSushi/rust-csv/issues/363"] +fn from_tsv_text_with_comments_to_table() { + Playground::setup("filter_from_tsv_test_2", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "los_tres_caballeros.txt", + r#" + # This is a comment + first_name last_name rusty_luck + # This one too + Andrés Robalino 1 + Jonathan Turner 1 + Yehuda Katz 1 + # This one also + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r##" + open los_tres_caballeros.txt + | from tsv --comment "#" + | get rusty_luck + | length + "## + )); + + assert_eq!(actual.out, "3"); + }) +} + +#[test] +fn from_tsv_text_with_custom_quotes_to_table() { + Playground::setup("filter_from_tsv_test_3", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "los_tres_caballeros.txt", + r#" + first_name last_name rusty_luck + 'And''rés' Robalino 1 + Jonathan Turner 1 + Yehuda Katz 1 + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_caballeros.txt + | from tsv --quote "'" + | first + | get first_name + "# + )); + + assert_eq!(actual.out, "And'rés"); + }) +} + +#[test] +fn from_tsv_text_with_custom_escapes_to_table() { + Playground::setup("filter_from_tsv_test_4", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "los_tres_caballeros.txt", + r#" + first_name last_name rusty_luck + "And\"rés" Robalino 1 + Jonathan Turner 1 + Yehuda Katz 1 + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r" + open los_tres_caballeros.txt + | from tsv --escape '\' + | first + | get first_name + " + )); + + assert_eq!(actual.out, "And\"rés"); + }) +} + +#[test] +fn from_tsv_text_skipping_headers_to_table() { + Playground::setup("filter_from_tsv_test_5", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "los_tres_amigos.txt", + r#" + Andrés Robalino 1 + JT Turner 1 + Yehuda Katz 1 + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_amigos.txt + | from tsv --noheaders + | get column2 + | length + "# + )); + + assert_eq!(actual.out, "3"); + }) +} + +#[test] +fn from_tsv_text_with_missing_columns_to_table() { + Playground::setup("filter_from_tsv_test_6", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "los_tres_caballeros.txt", + r#" + first_name last_name rusty_luck + Andrés Robalino + Jonathan Turner 1 + Yehuda Katz 1 + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_caballeros.txt + | from tsv --flexible + | get -i rusty_luck + | compact + | length + "# + )); + + assert_eq!(actual.out, "2"); + }) +} + +#[test] +fn from_tsv_text_with_multiple_char_comment() { + Playground::setup("filter_from_tsv_test_7", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "los_tres_caballeros.txt", + r#" + first_name last_name rusty_luck + Andrés Robalino 1 + Jonathan Turner 1 + Yehuda Katz 1 + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_caballeros.txt + | from csv --comment "li" + "# + )); + + assert!(actual.err.contains("single character separator")); + }) +} + +#[test] +fn from_tsv_text_with_wrong_type_comment() { + Playground::setup("filter_from_csv_test_8", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "los_tres_caballeros.txt", + r#" + first_name last_name rusty_luck + Andrés Robalino 1 + Jonathan Turner 1 + Yehuda Katz 1 + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_caballeros.txt + | from csv --comment ('123' | into int) + "# + )); + + assert!(actual.err.contains("can't convert int to char")); + }) +} diff --git a/nushell/crates/nu-command/tests/format_conversions/url.rs b/nushell/crates/nu-command/tests/format_conversions/url.rs new file mode 100644 index 0000000..3660653 --- /dev/null +++ b/nushell/crates/nu-command/tests/format_conversions/url.rs @@ -0,0 +1,16 @@ +use nu_test_support::{nu, pipeline}; + +#[test] +fn can_encode_and_decode_urlencoding() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample.url + | url build-query + | from url + | get cheese + "# + )); + + assert_eq!(actual.out, "comté"); +} diff --git a/nushell/crates/nu-command/tests/format_conversions/xlsx.rs b/nushell/crates/nu-command/tests/format_conversions/xlsx.rs new file mode 100644 index 0000000..06c07e7 --- /dev/null +++ b/nushell/crates/nu-command/tests/format_conversions/xlsx.rs @@ -0,0 +1,45 @@ +use nu_test_support::{nu, pipeline}; + +#[test] +fn from_excel_file_to_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample_data.xlsx + | get SalesOrders + | get 4 + | get column2 + "# + )); + + assert_eq!(actual.out, "Gill"); +} + +#[test] +fn from_excel_file_to_table_select_sheet() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample_data.xlsx --raw + | from xlsx --sheets ["SalesOrders"] + | columns + | get 0 + "# + )); + + assert_eq!(actual.out, "SalesOrders"); +} + +#[test] +fn from_excel_file_to_date() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample_data.xlsx + | get SalesOrders.4.column0 + | format date "%Y-%m-%d" + "# + )); + + assert_eq!(actual.out, "2018-02-26"); +} diff --git a/nushell/crates/nu-command/tests/format_conversions/xml.rs b/nushell/crates/nu-command/tests/format_conversions/xml.rs new file mode 100644 index 0000000..cf84371 --- /dev/null +++ b/nushell/crates/nu-command/tests/format_conversions/xml.rs @@ -0,0 +1,112 @@ +use nu_test_support::{nu, pipeline}; + +#[test] +fn table_to_xml_text_and_from_xml_text_back_into_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open jt.xml + | to xml + | from xml + | get content + | where tag == channel + | get content + | flatten + | where tag == item + | get content + | flatten + | where tag == guid + | get 0.attributes.isPermaLink + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn to_xml_error_unknown_column() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + {tag: a bad_column: b} | to xml + "# + )); + + assert!(actual.err.contains("Invalid column \"bad_column\"")); +} + +#[test] +fn to_xml_error_no_tag() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + {attributes: {a: b c: d}} | to xml + "# + )); + + assert!(actual.err.contains("Tag missing")); +} + +#[test] +fn to_xml_error_tag_not_string() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + {tag: 1 attributes: {a: b c: d}} | to xml + "# + )); + + assert!(actual.err.contains("not a string")); +} + +#[test] +fn to_xml_partial_escape() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + { + tag: a + attributes: { a: "'a'\\" } + content: [ `'"qwe\` ] + } | to xml --partial-escape + "# + )); + assert_eq!(actual.out, r#"
'"qwe\"#); +} + +#[test] +fn to_xml_pi_comment_not_escaped() { + // PI and comment content should not be escaped + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + { + tag: a + content: [ + {tag: ?qwe content: `"'<>&`} + {tag: ! content: `"'<>&`} + ] + } | to xml + "# + )); + assert_eq!(actual.out, r#"&?>"#); +} + +#[test] +fn to_xml_self_closed() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + { + tag: root + content: [ + [tag attributes content]; + [a null null] + [b {e: r} null] + [c {t: y} []] + ] + } | to xml --self-closed + "# + )); + assert_eq!(actual.out, r#""#); +} diff --git a/nushell/crates/nu-command/tests/format_conversions/yaml.rs b/nushell/crates/nu-command/tests/format_conversions/yaml.rs new file mode 100644 index 0000000..9aa9e16 --- /dev/null +++ b/nushell/crates/nu-command/tests/format_conversions/yaml.rs @@ -0,0 +1,81 @@ +use nu_test_support::{nu, pipeline}; + +#[test] +fn table_to_yaml_text_and_from_yaml_text_back_into_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open appveyor.yml + | to yaml + | from yaml + | get environment.global.PROJECT_NAME + "# + )); + + assert_eq!(actual.out, "nushell"); +} + +#[test] +fn table_to_yml_text_and_from_yml_text_back_into_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open appveyor.yml + | to yml + | from yml + | get environment.global.PROJECT_NAME + "# + )); + + assert_eq!(actual.out, "nushell"); +} + +#[test] +fn convert_dict_to_yaml_with_boolean_key() { + let actual = nu!(pipeline( + r#" + "true: BooleanKey " | from yaml + "# + )); + assert!(actual.out.contains("BooleanKey")); + assert!(actual.err.is_empty()); +} + +#[test] +fn convert_dict_to_yaml_with_integer_key() { + let actual = nu!(pipeline( + r#" + "200: [] " | from yaml + "# + )); + + assert!(actual.out.contains("200")); + assert!(actual.err.is_empty()); +} + +#[test] +fn convert_dict_to_yaml_with_integer_floats_key() { + let actual = nu!(pipeline( + r#" + "2.11: "1" " | from yaml + "# + )); + assert!(actual.out.contains("2.11")); + assert!(actual.err.is_empty()); +} + +#[test] +#[ignore] +fn convert_bool_to_yaml_in_yaml_spec_1_2() { + let actual = nu!(pipeline( + r#" + [y n no On OFF True true false] | to yaml + "# + )); + + assert_eq!( + actual.out, + "- 'y'- 'n'- 'no'- 'On'- 'OFF'- 'True'- true- false" + ); + assert!(actual.err.is_empty()); +} diff --git a/nushell/crates/nu-command/tests/main.rs b/nushell/crates/nu-command/tests/main.rs new file mode 100644 index 0000000..f6f2ad6 --- /dev/null +++ b/nushell/crates/nu-command/tests/main.rs @@ -0,0 +1,4 @@ +mod commands; +mod format_conversions; +mod sort_utils; +mod string; diff --git a/nushell/crates/nu-command/tests/sort_utils.rs b/nushell/crates/nu-command/tests/sort_utils.rs new file mode 100644 index 0000000..c7043a2 --- /dev/null +++ b/nushell/crates/nu-command/tests/sort_utils.rs @@ -0,0 +1,559 @@ +use nu_command::{Comparator, sort, sort_by, sort_record}; +use nu_protocol::{ + Record, Span, Value, + ast::{CellPath, PathMember}, + casing::Casing, + record, +}; + +#[test] +fn test_sort_basic() { + let mut list = vec![ + Value::test_string("foo"), + Value::test_int(2), + Value::test_int(3), + Value::test_string("bar"), + Value::test_int(1), + Value::test_string("baz"), + ]; + + assert!(sort(&mut list, false, false).is_ok()); + assert_eq!( + list, + vec![ + Value::test_int(1), + Value::test_int(2), + Value::test_int(3), + Value::test_string("bar"), + Value::test_string("baz"), + Value::test_string("foo") + ] + ); +} + +#[test] +fn test_sort_nothing() { + // Nothing values should always be sorted to the end of any list + let mut list = vec![ + Value::test_int(1), + Value::test_nothing(), + Value::test_int(2), + Value::test_string("foo"), + Value::test_nothing(), + Value::test_string("bar"), + ]; + + assert!(sort(&mut list, false, false).is_ok()); + assert_eq!( + list, + vec![ + Value::test_int(1), + Value::test_int(2), + Value::test_string("bar"), + Value::test_string("foo"), + Value::test_nothing(), + Value::test_nothing() + ] + ); + + // Ensure that nothing values are sorted after *all* types, + // even types which may follow `Nothing` in the PartialOrd order + + // unstable_name_collision + // can be switched to std intersperse when stabilized + let mut values: Vec = + itertools::intersperse(Value::test_values(), Value::test_nothing()).collect(); + + let nulls = values + .iter() + .filter(|item| item == &&Value::test_nothing()) + .count(); + + assert!(sort(&mut values, false, false).is_ok()); + + // check if the last `nulls` values of the sorted list are indeed null + assert_eq!(&values[(nulls - 1)..], vec![Value::test_nothing(); nulls]) +} + +#[test] +fn test_sort_natural_basic() { + let mut list = vec![ + Value::test_string("foo99"), + Value::test_string("foo9"), + Value::test_string("foo1"), + Value::test_string("foo100"), + Value::test_string("foo10"), + Value::test_string("1"), + Value::test_string("10"), + Value::test_string("100"), + Value::test_string("9"), + Value::test_string("99"), + ]; + + assert!(sort(&mut list, false, false).is_ok()); + assert_eq!( + list, + vec![ + Value::test_string("1"), + Value::test_string("10"), + Value::test_string("100"), + Value::test_string("9"), + Value::test_string("99"), + Value::test_string("foo1"), + Value::test_string("foo10"), + Value::test_string("foo100"), + Value::test_string("foo9"), + Value::test_string("foo99"), + ] + ); + + assert!(sort(&mut list, false, true).is_ok()); + assert_eq!( + list, + vec![ + Value::test_string("1"), + Value::test_string("9"), + Value::test_string("10"), + Value::test_string("99"), + Value::test_string("100"), + Value::test_string("foo1"), + Value::test_string("foo9"), + Value::test_string("foo10"), + Value::test_string("foo99"), + Value::test_string("foo100"), + ] + ); +} + +#[test] +fn test_sort_natural_mixed_types() { + let mut list = vec![ + Value::test_string("1"), + Value::test_int(99), + Value::test_int(1), + Value::test_float(1000.0), + Value::test_int(9), + Value::test_string("9"), + Value::test_int(100), + Value::test_string("99"), + Value::test_float(2.0), + Value::test_string("100"), + Value::test_int(10), + Value::test_string("10"), + ]; + + assert!(sort(&mut list, false, false).is_ok()); + assert_eq!( + list, + vec![ + Value::test_int(1), + Value::test_float(2.0), + Value::test_int(9), + Value::test_int(10), + Value::test_int(99), + Value::test_int(100), + Value::test_float(1000.0), + Value::test_string("1"), + Value::test_string("10"), + Value::test_string("100"), + Value::test_string("9"), + Value::test_string("99") + ] + ); + + assert!(sort(&mut list, false, true).is_ok()); + assert_eq!( + list, + vec![ + Value::test_int(1), + Value::test_string("1"), + Value::test_float(2.0), + Value::test_int(9), + Value::test_string("9"), + Value::test_int(10), + Value::test_string("10"), + Value::test_int(99), + Value::test_string("99"), + Value::test_int(100), + Value::test_string("100"), + Value::test_float(1000.0), + ] + ); +} + +#[test] +fn test_sort_natural_no_numeric_values() { + // If list contains no numeric strings, it should be sorted the + // same with or without natural sorting + let mut normal = vec![ + Value::test_string("golf"), + Value::test_bool(false), + Value::test_string("alfa"), + Value::test_string("echo"), + Value::test_int(7), + Value::test_int(10), + Value::test_bool(true), + Value::test_string("uniform"), + Value::test_int(3), + Value::test_string("tango"), + ]; + let mut natural = normal.clone(); + + assert!(sort(&mut normal, false, false).is_ok()); + assert!(sort(&mut natural, false, true).is_ok()); + assert_eq!(normal, natural); +} + +#[test] +fn test_sort_natural_type_order() { + // This test is to prevent regression to a previous natural sort behavior + // where values of different types would be intermixed. + // Only numeric values (ints, floats, and numeric strings) should be intermixed + // + // This list would previously be incorrectly sorted like this: + // ╭────┬─────────╮ + // │ 0 │ 1 │ + // │ 1 │ golf │ + // │ 2 │ false │ + // │ 3 │ 7 │ + // │ 4 │ 10 │ + // │ 5 │ alfa │ + // │ 6 │ true │ + // │ 7 │ uniform │ + // │ 8 │ true │ + // │ 9 │ 3 │ + // │ 10 │ false │ + // │ 11 │ tango │ + // ╰────┴─────────╯ + + let mut list = vec![ + Value::test_string("golf"), + Value::test_int(1), + Value::test_bool(false), + Value::test_string("alfa"), + Value::test_int(7), + Value::test_int(10), + Value::test_bool(true), + Value::test_string("uniform"), + Value::test_bool(true), + Value::test_int(3), + Value::test_bool(false), + Value::test_string("tango"), + ]; + + assert!(sort(&mut list, false, true).is_ok()); + assert_eq!( + list, + vec![ + Value::test_bool(false), + Value::test_bool(false), + Value::test_bool(true), + Value::test_bool(true), + Value::test_int(1), + Value::test_int(3), + Value::test_int(7), + Value::test_int(10), + Value::test_string("alfa"), + Value::test_string("golf"), + Value::test_string("tango"), + Value::test_string("uniform") + ] + ); + + // Only ints, floats, and numeric strings should be intermixed + // While binary primitives and datetimes can be coerced into strings, it doesn't make sense to sort them with numbers + // Binary primitives can hold multiple values, not just one, so shouldn't be compared to single values + // Datetimes don't have a single obvious numeric representation, and if we chose one it would be ambiguous to the user + + let year_three = chrono::NaiveDate::from_ymd_opt(3, 1, 1) + .unwrap() + .and_hms_opt(0, 0, 0) + .unwrap() + .and_utc(); + + let mut list = vec![ + Value::test_int(10), + Value::test_float(6.0), + Value::test_int(1), + Value::test_binary([3]), + Value::test_string("2"), + Value::test_date(year_three.into()), + Value::test_int(4), + Value::test_binary([52]), + Value::test_float(9.0), + Value::test_string("5"), + Value::test_date(chrono::DateTime::UNIX_EPOCH.into()), + Value::test_int(7), + Value::test_string("8"), + Value::test_float(3.0), + Value::test_string("foobar"), + ]; + assert!(sort(&mut list, false, true).is_ok()); + assert_eq!( + list, + vec![ + Value::test_int(1), + Value::test_string("2"), + Value::test_float(3.0), + Value::test_int(4), + Value::test_string("5"), + Value::test_float(6.0), + Value::test_int(7), + Value::test_string("8"), + Value::test_float(9.0), + Value::test_int(10), + Value::test_string("foobar"), + // the ordering of date and binary here may change if the PartialOrd order is changed, + // but they should not be intermixed with the above + Value::test_date(year_three.into()), + Value::test_date(chrono::DateTime::UNIX_EPOCH.into()), + Value::test_binary([3]), + Value::test_binary([52]), + ] + ); +} + +#[test] +fn test_sort_insensitive() { + // Test permutations between insensitive and natural + // Ensure that strings with equal insensitive orderings + // are sorted stably. (FOO then foo, bar then BAR) + let source = vec![ + Value::test_string("FOO"), + Value::test_string("foo"), + Value::test_int(100), + Value::test_string("9"), + Value::test_string("bar"), + Value::test_int(10), + Value::test_string("baz"), + Value::test_string("BAR"), + ]; + let mut list; + + // sensitive + non-natural + list = source.clone(); + assert!(sort(&mut list, false, false).is_ok()); + assert_eq!( + list, + vec![ + Value::test_int(10), + Value::test_int(100), + Value::test_string("9"), + Value::test_string("BAR"), + Value::test_string("FOO"), + Value::test_string("bar"), + Value::test_string("baz"), + Value::test_string("foo"), + ] + ); + + // sensitive + natural + list = source.clone(); + assert!(sort(&mut list, false, true).is_ok()); + assert_eq!( + list, + vec![ + Value::test_string("9"), + Value::test_int(10), + Value::test_int(100), + Value::test_string("BAR"), + Value::test_string("FOO"), + Value::test_string("bar"), + Value::test_string("baz"), + Value::test_string("foo"), + ] + ); + + // insensitive + non-natural + list = source.clone(); + assert!(sort(&mut list, true, false).is_ok()); + assert_eq!( + list, + vec![ + Value::test_int(10), + Value::test_int(100), + Value::test_string("9"), + Value::test_string("bar"), + Value::test_string("BAR"), + Value::test_string("baz"), + Value::test_string("FOO"), + Value::test_string("foo"), + ] + ); + + // insensitive + natural + list = source.clone(); + assert!(sort(&mut list, true, true).is_ok()); + assert_eq!( + list, + vec![ + Value::test_string("9"), + Value::test_int(10), + Value::test_int(100), + Value::test_string("bar"), + Value::test_string("BAR"), + Value::test_string("baz"), + Value::test_string("FOO"), + Value::test_string("foo"), + ] + ); +} + +// Helper function to assert that two records are equal +// with their key-value pairs in the same order +fn assert_record_eq(a: Record, b: Record) { + assert_eq!( + a.into_iter().collect::>(), + b.into_iter().collect::>(), + ) +} + +#[test] +fn test_sort_record_keys() { + // Basic record sort test + let record = record! { + "golf" => Value::test_string("bar"), + "alfa" => Value::test_string("foo"), + "echo" => Value::test_int(123), + }; + + let sorted = sort_record(record, false, false, false, false).unwrap(); + assert_record_eq( + sorted, + record! { + "alfa" => Value::test_string("foo"), + "echo" => Value::test_int(123), + "golf" => Value::test_string("bar"), + }, + ); +} + +#[test] +fn test_sort_record_values() { + // This test is to prevent a regression where integers and strings would be + // intermixed non-naturally when sorting a record by value without the natural flag: + // + // This record would previously be incorrectly sorted like this: + // ╭─────────┬─────╮ + // │ alfa │ 1 │ + // │ charlie │ 1 │ + // │ india │ 10 │ + // │ juliett │ 10 │ + // │ foxtrot │ 100 │ + // │ hotel │ 100 │ + // │ delta │ 9 │ + // │ echo │ 9 │ + // │ bravo │ 99 │ + // │ golf │ 99 │ + // ╰─────────┴─────╯ + + let record = record! { + "alfa" => Value::test_string("1"), + "bravo" => Value::test_int(99), + "charlie" => Value::test_int(1), + "delta" => Value::test_int(9), + "echo" => Value::test_string("9"), + "foxtrot" => Value::test_int(100), + "golf" => Value::test_string("99"), + "hotel" => Value::test_string("100"), + "india" => Value::test_int(10), + "juliett" => Value::test_string("10"), + }; + + // non-natural sort + let sorted = sort_record(record.clone(), true, false, false, false).unwrap(); + assert_record_eq( + sorted, + record! { + "charlie" => Value::test_int(1), + "delta" => Value::test_int(9), + "india" => Value::test_int(10), + "bravo" => Value::test_int(99), + "foxtrot" => Value::test_int(100), + "alfa" => Value::test_string("1"), + "juliett" => Value::test_string("10"), + "hotel" => Value::test_string("100"), + "echo" => Value::test_string("9"), + "golf" => Value::test_string("99"), + }, + ); + + // natural sort + let sorted = sort_record(record.clone(), true, false, false, true).unwrap(); + assert_record_eq( + sorted, + record! { + "alfa" => Value::test_string("1"), + "charlie" => Value::test_int(1), + "delta" => Value::test_int(9), + "echo" => Value::test_string("9"), + "india" => Value::test_int(10), + "juliett" => Value::test_string("10"), + "bravo" => Value::test_int(99), + "golf" => Value::test_string("99"), + "foxtrot" => Value::test_int(100), + "hotel" => Value::test_string("100"), + }, + ); +} + +#[test] +fn test_sort_equivalent() { + // Ensure that sort, sort_by, and record sort have equivalent sorting logic + let phonetic = vec![ + "alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india", + "juliett", "kilo", "lima", "mike", "november", "oscar", "papa", "quebec", "romeo", + "sierra", "tango", "uniform", "victor", "whiskey", "xray", "yankee", "zulu", + ]; + + // filter out errors, since we can't sort_by on those + let mut values: Vec = Value::test_values() + .into_iter() + .filter(|val| !matches!(val, Value::Error { .. })) + .collect(); + + // reverse sort test values + values.sort_by(|a, b| b.partial_cmp(a).unwrap()); + + let mut list = values.clone(); + let mut table: Vec = values + .clone() + .into_iter() + .map(|val| Value::test_record(record! { "value" => val })) + .collect(); + let record = Record::from_iter(phonetic.into_iter().map(str::to_string).zip(values)); + + let comparator = Comparator::CellPath(CellPath { + members: vec![PathMember::String { + val: "value".to_string(), + span: Span::test_data(), + optional: false, + casing: Casing::Sensitive, + }], + }); + + assert!(sort(&mut list, false, false).is_ok()); + assert!( + sort_by( + &mut table, + vec![comparator], + Span::test_data(), + false, + false + ) + .is_ok() + ); + + let record_sorted = sort_record(record.clone(), true, false, false, false).unwrap(); + let record_vals: Vec = record_sorted.into_iter().map(|pair| pair.1).collect(); + + let table_vals: Vec = table + .clone() + .into_iter() + .map(|record| record.into_record().unwrap().remove("value").unwrap()) + .collect(); + + assert_eq!(list, record_vals); + assert_eq!(record_vals, table_vals); + // list == table_vals by transitive property +} diff --git a/nushell/crates/nu-command/tests/string/format/duration.rs b/nushell/crates/nu-command/tests/string/format/duration.rs new file mode 100644 index 0000000..d5fb702 --- /dev/null +++ b/nushell/crates/nu-command/tests/string/format/duration.rs @@ -0,0 +1,15 @@ +use nu_test_support::nu; + +#[test] +fn format_duration() { + let actual = nu!(r#"1hr | format duration sec"#); + + assert_eq!("3600 sec", actual.out); +} + +#[test] +fn format_duration_with_invalid_unit() { + let actual = nu!(r#"1hr | format duration MB"#); + + assert!(actual.err.contains("invalid_unit")); +} diff --git a/nushell/crates/nu-command/tests/string/format/filesize.rs b/nushell/crates/nu-command/tests/string/format/filesize.rs new file mode 100644 index 0000000..426c6bd --- /dev/null +++ b/nushell/crates/nu-command/tests/string/format/filesize.rs @@ -0,0 +1,15 @@ +use nu_test_support::nu; + +#[test] +fn format_duration() { + let actual = nu!(r#"1MB | format filesize kB"#); + + assert_eq!("1000 kB", actual.out); +} + +#[test] +fn format_duration_with_invalid_unit() { + let actual = nu!(r#"1MB | format filesize sec"#); + + assert!(actual.err.contains("invalid_unit")); +} diff --git a/nushell/crates/nu-command/tests/string/format/mod.rs b/nushell/crates/nu-command/tests/string/format/mod.rs new file mode 100644 index 0000000..d1a100f --- /dev/null +++ b/nushell/crates/nu-command/tests/string/format/mod.rs @@ -0,0 +1,2 @@ +mod duration; +mod filesize; diff --git a/nushell/crates/nu-command/tests/string/mod.rs b/nushell/crates/nu-command/tests/string/mod.rs new file mode 100644 index 0000000..8631268 --- /dev/null +++ b/nushell/crates/nu-command/tests/string/mod.rs @@ -0,0 +1 @@ +mod format; diff --git a/nushell/crates/nu-derive-value/Cargo.toml b/nushell/crates/nu-derive-value/Cargo.toml new file mode 100644 index 0000000..66724aa --- /dev/null +++ b/nushell/crates/nu-derive-value/Cargo.toml @@ -0,0 +1,24 @@ +[package] +authors = ["The Nushell Project Developers"] +description = "Macros implementation of #[derive(FromValue, IntoValue)]" +edition = "2024" +license = "MIT" +name = "nu-derive-value" +repository = "https://github.com/nushell/nushell/tree/main/crates/nu-derive-value" +version = "0.105.2" + +[lib] +proc-macro = true +# we can only use exposed macros in doctests really, +# so we cannot test anything useful in a doctest +doctest = false + +[lints] +workspace = true + +[dependencies] +proc-macro2 = { workspace = true } +syn = { workspace = true } +quote = { workspace = true } +proc-macro-error2 = { workspace = true } +heck = { workspace = true } diff --git a/nushell/crates/nu-derive-value/LICENSE b/nushell/crates/nu-derive-value/LICENSE new file mode 100644 index 0000000..ae174e8 --- /dev/null +++ b/nushell/crates/nu-derive-value/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 - 2023 The Nushell Project Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/nushell/crates/nu-derive-value/src/attributes.rs b/nushell/crates/nu-derive-value/src/attributes.rs new file mode 100644 index 0000000..6718b01 --- /dev/null +++ b/nushell/crates/nu-derive-value/src/attributes.rs @@ -0,0 +1,133 @@ +use syn::{Attribute, Fields, LitStr, meta::ParseNestedMeta, spanned::Spanned}; + +use crate::{HELPER_ATTRIBUTE, case::Case, error::DeriveError}; + +pub trait ParseAttrs: Default { + fn parse_attrs<'a, M>( + iter: impl IntoIterator, + ) -> Result> { + let mut attrs = Self::default(); + for attr in filter(iter.into_iter()) { + // This is a container to allow returning derive errors inside the parse_nested_meta fn. + let mut err = Ok(()); + let _ = attr.parse_nested_meta(|meta| { + attrs.parse_attr(meta).or_else(|e| { + err = Err(e); + Ok(()) // parse_nested_meta requires another error type, so we escape it here + }) + }); + err?; // Shortcircuit here if `err` is holding some error. + } + + Ok(attrs) + } + + fn parse_attr(&mut self, attr_meta: ParseNestedMeta<'_>) -> Result<(), DeriveError>; +} + +#[derive(Debug, Default)] +pub struct ContainerAttributes { + pub rename_all: Option, + pub type_name: Option, +} + +impl ParseAttrs for ContainerAttributes { + fn parse_attr(&mut self, attr_meta: ParseNestedMeta<'_>) -> Result<(), DeriveError> { + let ident = attr_meta.path.require_ident()?; + match ident.to_string().as_str() { + "rename_all" => { + let case: LitStr = attr_meta.value()?.parse()?; + let value_span = case.span(); + let case = case.value(); + match Case::from_str(&case) { + Some(case) => self.rename_all = Some(case), + None => { + return Err(DeriveError::InvalidAttributeValue { + value_span, + value: Box::new(case), + }); + } + } + } + "type_name" => { + let type_name: LitStr = attr_meta.value()?.parse()?; + let type_name = type_name.value(); + self.type_name = Some(type_name); + } + ident => { + return Err(DeriveError::UnexpectedAttribute { + meta_span: ident.span(), + }); + } + } + + Ok(()) + } +} + +#[derive(Debug, Default)] +pub struct MemberAttributes { + pub rename: Option, + pub default: bool, +} + +impl ParseAttrs for MemberAttributes { + fn parse_attr(&mut self, attr_meta: ParseNestedMeta<'_>) -> Result<(), DeriveError> { + let ident = attr_meta.path.require_ident()?; + match ident.to_string().as_str() { + "rename" => { + let rename: LitStr = attr_meta.value()?.parse()?; + let rename = rename.value(); + self.rename = Some(rename); + } + "default" => { + self.default = true; + } + ident => { + return Err(DeriveError::UnexpectedAttribute { + meta_span: ident.span(), + }); + } + } + + Ok(()) + } +} + +pub fn filter<'a>( + iter: impl Iterator, +) -> impl Iterator { + iter.filter(|attr| attr.path().is_ident(HELPER_ATTRIBUTE)) +} + +// The deny functions are built to easily deny the use of the helper attribute if used incorrectly. +// As the usage of it gets more complex, these functions might be discarded or replaced. + +/// Deny any attribute that uses the helper attribute. +pub fn deny(attrs: &[Attribute]) -> Result<(), DeriveError> { + match filter(attrs.iter()).next() { + Some(attr) => Err(DeriveError::InvalidAttributePosition { + attribute_span: attr.span(), + }), + None => Ok(()), + } +} + +/// Deny any attributes that uses the helper attribute on any field. +pub fn deny_fields(fields: &Fields) -> Result<(), DeriveError> { + match fields { + Fields::Named(fields) => { + for field in fields.named.iter() { + deny(&field.attrs)?; + } + } + Fields::Unnamed(fields) => { + for field in fields.unnamed.iter() { + deny(&field.attrs)?; + } + } + Fields::Unit => (), + } + + Ok(()) +} diff --git a/nushell/crates/nu-derive-value/src/case.rs b/nushell/crates/nu-derive-value/src/case.rs new file mode 100644 index 0000000..5962a29 --- /dev/null +++ b/nushell/crates/nu-derive-value/src/case.rs @@ -0,0 +1,76 @@ +use heck::*; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum Case { + // directly supported by heck + Pascal, + Camel, + Snake, + Kebab, + ScreamingSnake, + Title, + Cobol, + Train, + + // custom variants + Upper, + Lower, + Flat, + ScreamingFlat, +} + +impl Case { + pub fn from_str(s: impl AsRef) -> Option { + match s.as_ref() { + // The matched case are all useful variants from `convert_case` with aliases + // that `serde` uses. + "PascalCase" | "UpperCamelCase" => Case::Pascal, + "camelCase" | "lowerCamelCase" => Case::Camel, + "snake_case" => Case::Snake, + "kebab-case" => Case::Kebab, + "SCREAMING_SNAKE_CASE" | "UPPER_SNAKE_CASE" | "SHOUTY_SNAKE_CASE" => { + Case::ScreamingSnake + } + "Title Case" => Case::Title, + "COBOL-CASE" | "SCREAMING-KEBAB-CASE" | "UPPER-KEBAB-CASE" => Case::Cobol, + "Train-Case" => Case::Train, + + "UPPER CASE" | "UPPER WITH SPACES CASE" => Case::Upper, + "lower case" | "lower with spaces case" => Case::Lower, + "flatcase" | "lowercase" => Case::Flat, + "SCREAMINGFLATCASE" | "UPPERFLATCASE" | "UPPERCASE" => Case::ScreamingFlat, + + _ => return None, + } + .into() + } +} + +pub trait Casing { + fn to_case(&self, case: impl Into>) -> String; +} + +impl Casing for T { + fn to_case(&self, case: impl Into>) -> String { + let s = self.to_string(); + let Some(case) = case.into() else { + return s.to_string(); + }; + + match case { + Case::Pascal => s.to_upper_camel_case(), + Case::Camel => s.to_lower_camel_case(), + Case::Snake => s.to_snake_case(), + Case::Kebab => s.to_kebab_case(), + Case::ScreamingSnake => s.to_shouty_snake_case(), + Case::Title => s.to_title_case(), + Case::Cobol => s.to_shouty_kebab_case(), + Case::Train => s.to_train_case(), + + Case::Upper => s.to_shouty_snake_case().replace('_', " "), + Case::Lower => s.to_snake_case().replace('_', " "), + Case::Flat => s.to_snake_case().replace('_', ""), + Case::ScreamingFlat => s.to_shouty_snake_case().replace('_', ""), + } + } +} diff --git a/nushell/crates/nu-derive-value/src/error.rs b/nushell/crates/nu-derive-value/src/error.rs new file mode 100644 index 0000000..eb9bd28 --- /dev/null +++ b/nushell/crates/nu-derive-value/src/error.rs @@ -0,0 +1,104 @@ +use std::{any, fmt::Debug, marker::PhantomData}; + +use proc_macro_error2::{Diagnostic, Level}; +use proc_macro2::Span; + +#[derive(Debug)] +pub enum DeriveError { + /// Marker variant, makes the `M` generic parameter valid. + _Marker(PhantomData), + + /// Parsing errors thrown by `syn`. + Syn(syn::parse::Error), + + /// `syn::DeriveInput` was a union, currently not supported + UnsupportedUnions, + + /// Only plain enums are supported right now. + UnsupportedEnums { fields_span: Span }, + + /// Found a `#[nu_value(x)]` attribute where `x` is unexpected. + UnexpectedAttribute { meta_span: Span }, + + /// Found a `#[nu_value(x)]` attribute at a invalid position. + InvalidAttributePosition { attribute_span: Span }, + + /// Found a valid `#[nu_value(x)]` attribute but the passed values is invalid. + InvalidAttributeValue { + value_span: Span, + value: Box, + }, + + /// Two keys or variants are called the same name breaking bidirectionality. + NonUniqueName { + name: String, + first: Span, + second: Span, + }, +} + +impl From for DeriveError { + fn from(value: syn::parse::Error) -> Self { + Self::Syn(value) + } +} + +impl From> for Diagnostic { + fn from(value: DeriveError) -> Self { + let derive_name = any::type_name::().split("::").last().expect("not empty"); + match value { + DeriveError::_Marker(_) => panic!("used marker variant"), + + DeriveError::Syn(e) => Diagnostic::spanned(e.span(), Level::Error, e.to_string()), + + DeriveError::UnsupportedUnions => Diagnostic::new( + Level::Error, + format!("`{derive_name}` cannot be derived from unions"), + ) + .help("consider refactoring to a struct".to_string()) + .note("if you really need a union, consider opening an issue on Github".to_string()), + + DeriveError::UnsupportedEnums { fields_span } => Diagnostic::spanned( + fields_span, + Level::Error, + format!("`{derive_name}` can only be derived from plain enums"), + ) + .help( + "consider refactoring your data type to a struct with a plain enum as a field" + .to_string(), + ) + .note("more complex enums could be implemented in the future".to_string()), + + DeriveError::InvalidAttributePosition { attribute_span } => Diagnostic::spanned( + attribute_span, + Level::Error, + "invalid attribute position".to_string(), + ) + .help(format!( + "check documentation for `{derive_name}` for valid placements" + )), + + DeriveError::UnexpectedAttribute { meta_span } => { + Diagnostic::spanned(meta_span, Level::Error, "unknown attribute".to_string()).help( + format!("check documentation for `{derive_name}` for valid attributes"), + ) + } + + DeriveError::InvalidAttributeValue { value_span, value } => { + Diagnostic::spanned(value_span, Level::Error, format!("invalid value {value:?}")) + .help(format!( + "check documentation for `{derive_name}` for valid attribute values" + )) + } + + DeriveError::NonUniqueName { + name, + first, + second, + } => Diagnostic::new(Level::Error, format!("non-unique name {name:?} found")) + .span_error(first, "first occurrence found here".to_string()) + .span_error(second, "second occurrence found here".to_string()) + .help("use `#[nu_value(rename = \"...\")]` to ensure unique names".to_string()), + } + } +} diff --git a/nushell/crates/nu-derive-value/src/from.rs b/nushell/crates/nu-derive-value/src/from.rs new file mode 100644 index 0000000..41ad461 --- /dev/null +++ b/nushell/crates/nu-derive-value/src/from.rs @@ -0,0 +1,664 @@ +use proc_macro2::TokenStream as TokenStream2; +use quote::{ToTokens, quote}; +use syn::{ + Attribute, Data, DataEnum, DataStruct, DeriveInput, Fields, Generics, Ident, Type, + spanned::Spanned, +}; + +use crate::{ + attributes::{self, ContainerAttributes, MemberAttributes, ParseAttrs}, + case::Case, + names::NameResolver, +}; + +#[derive(Debug)] +pub struct FromValue; +type DeriveError = super::error::DeriveError; +type Result = std::result::Result; + +/// Inner implementation of the `#[derive(FromValue)]` macro for structs and enums. +/// +/// Uses `proc_macro2::TokenStream` for better testing support, unlike `proc_macro::TokenStream`. +/// +/// This function directs the `FromValue` trait derivation to the correct implementation based on +/// the input type: +/// - For structs: [`derive_struct_from_value`] +/// - For enums: [`derive_enum_from_value`] +/// - Unions are not supported and will return an error. +pub fn derive_from_value(input: TokenStream2) -> Result { + let input: DeriveInput = syn::parse2(input).map_err(DeriveError::Syn)?; + match input.data { + Data::Struct(data_struct) => Ok(derive_struct_from_value( + input.ident, + data_struct, + input.generics, + input.attrs, + )?), + Data::Enum(data_enum) => Ok(derive_enum_from_value( + input.ident, + data_enum, + input.generics, + input.attrs, + )?), + Data::Union(_) => Err(DeriveError::UnsupportedUnions), + } +} + +/// Implements the `#[derive(FromValue)]` macro for structs. +/// +/// This function provides the impl signature for `FromValue`. +/// The implementation for `FromValue::from_value` is handled by [`struct_from_value`] and the +/// `FromValue::expected_type` is handled by [`struct_expected_type`]. +fn derive_struct_from_value( + ident: Ident, + data: DataStruct, + generics: Generics, + attrs: Vec, +) -> Result { + let container_attrs = ContainerAttributes::parse_attrs(attrs.iter())?; + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let from_value_impl = struct_from_value(&data, &container_attrs)?; + let expected_type_impl = struct_expected_type( + &data.fields, + container_attrs.type_name.as_deref(), + &container_attrs, + )?; + Ok(quote! { + #[automatically_derived] + impl #impl_generics nu_protocol::FromValue for #ident #ty_generics #where_clause { + #from_value_impl + #expected_type_impl + } + }) +} + +/// Implements `FromValue::from_value` for structs. +/// +/// This function constructs the `from_value` function for structs. +/// The implementation is straightforward as most of the heavy lifting is handled by +/// [`parse_value_via_fields`], and this function only needs to construct the signature around it. +/// +/// For structs with named fields, this constructs a large return type where each field +/// contains the implementation for that specific field. +/// In structs with unnamed fields, a [`VecDeque`](std::collections::VecDeque) is used to load each +/// field one after another, and the result is used to construct the tuple. +/// For unit structs, this only checks if the input value is `Value::Nothing`. +/// +/// # Examples +/// +/// These examples show what the macro would generate. +/// +/// Struct with named fields: +/// ```rust +/// #[derive(IntoValue)] +/// struct Pet { +/// name: String, +/// age: u8, +/// favorite_toy: Option, +/// } +/// +/// impl nu_protocol::FromValue for Pet { +/// fn from_value( +/// v: nu_protocol::Value +/// ) -> std::result::Result { +/// let span = v.span(); +/// let mut record = v.into_record()?; +/// std::result::Result::Ok(Pet { +/// name: ::from_value( +/// record +/// .remove("name") +/// .ok_or_else(|| nu_protocol::ShellError::CantFindColumn { +/// col_name: std::string::ToString::to_string("name"), +/// span: std::option::Option::None, +/// src_span: span +/// })?, +/// )?, +/// age: ::from_value( +/// record +/// .remove("age") +/// .ok_or_else(|| nu_protocol::ShellError::CantFindColumn { +/// col_name: std::string::ToString::to_string("age"), +/// span: std::option::Option::None, +/// src_span: span +/// })?, +/// )?, +/// favorite_toy: record +/// .remove("favorite_toy") +/// .map(|v| <#ty as nu_protocol::FromValue>::from_value(v)) +/// .transpose()? +/// .flatten(), +/// }) +/// } +/// } +/// ``` +/// +/// Struct with unnamed fields: +/// ```rust +/// #[derive(IntoValue)] +/// struct Color(u8, u8, u8); +/// +/// impl nu_protocol::FromValue for Color { +/// fn from_value( +/// v: nu_protocol::Value +/// ) -> std::result::Result { +/// let span = v.span(); +/// let list = v.into_list()?; +/// let mut deque: std::collections::VecDeque<_> = std::convert::From::from(list); +/// std::result::Result::Ok(Self( +/// { +/// ::from_value( +/// deque +/// .pop_front() +/// .ok_or_else(|| nu_protocol::ShellError::CantFindColumn { +/// col_name: std::string::ToString::to_string(&0), +/// span: std::option::Option::None, +/// src_span: span +/// })?, +/// )? +/// }, +/// { +/// ::from_value( +/// deque +/// .pop_front() +/// .ok_or_else(|| nu_protocol::ShellError::CantFindColumn { +/// col_name: std::string::ToString::to_string(&1), +/// span: std::option::Option::None, +/// src_span: span +/// })?, +/// )? +/// }, +/// { +/// ::from_value( +/// deque +/// .pop_front() +/// .ok_or_else(|| nu_protocol::ShellError::CantFindColumn { +/// col_name: std::string::ToString::to_string(&2), +/// span: std::option::Option::None, +/// src_span: span +/// })?, +/// )? +/// } +/// )) +/// } +/// } +/// ``` +/// +/// Unit struct: +/// ```rust +/// #[derive(IntoValue)] +/// struct Unicorn; +/// +/// impl nu_protocol::FromValue for Unicorn { +/// fn from_value( +/// v: nu_protocol::Value +/// ) -> std::result::Result { +/// match v { +/// nu_protocol::Value::Nothing {..} => Ok(Self), +/// v => std::result::Result::Err(nu_protocol::ShellError::CantConvert { +/// to_type: std::string::ToString::to_string(&::expected_type()), +/// from_type: std::string::ToString::to_string(&v.get_type()), +/// span: v.span(), +/// help: std::option::Option::None +/// }) +/// } +/// } +/// } +/// ``` +fn struct_from_value(data: &DataStruct, container_attrs: &ContainerAttributes) -> Result { + let body = parse_value_via_fields(&data.fields, quote!(Self), container_attrs)?; + Ok(quote! { + fn from_value( + v: nu_protocol::Value + ) -> std::result::Result { + #body + } + }) +} + +/// Implements `FromValue::expected_type` for structs. +/// +/// This function constructs the `expected_type` function for structs based on the provided fields. +/// The type depends on the `fields`: +/// - Named fields construct a record type where each key corresponds to a field name. +/// The specific keys are resolved by [`NameResolver::resolve_ident`]. +/// - Unnamed fields construct a custom type with the format `list[type0, type1, type2]`. +/// - Unit structs expect `Type::Nothing`. +/// +/// If the `#[nu_value(type_name = "...")]` attribute is used, the output type will be +/// `Type::Custom` with the provided name. +/// +/// # Examples +/// +/// These examples show what the macro would generate. +/// +/// Struct with named fields: +/// ```rust +/// #[derive(FromValue)] +/// struct Pet { +/// name: String, +/// age: u8, +/// #[nu_value(rename = "toy")] +/// favorite_toy: Option, +/// } +/// +/// impl nu_protocol::FromValue for Pet { +/// fn expected_type() -> nu_protocol::Type { +/// nu_protocol::Type::Record( +/// std::vec![ +/// ( +/// std::string::ToString::to_string("name"), +/// ::expected_type(), +/// ), +/// ( +/// std::string::ToString::to_string("age"), +/// ::expected_type(), +/// ), +/// ( +/// std::string::ToString::to_string("toy"), +/// as nu_protocol::FromValue>::expected_type(), +/// ) +/// ].into_boxed_slice() +/// ) +/// } +/// } +/// ``` +/// +/// Struct with unnamed fields: +/// ```rust +/// #[derive(FromValue)] +/// struct Color(u8, u8, u8); +/// +/// impl nu_protocol::FromValue for Color { +/// fn expected_type() -> nu_protocol::Type { +/// nu_protocol::Type::Custom( +/// std::format!( +/// "[{}, {}, {}]", +/// ::expected_type(), +/// ::expected_type(), +/// ::expected_type() +/// ) +/// .into_boxed_str() +/// ) +/// } +/// } +/// ``` +/// +/// Unit struct: +/// ```rust +/// #[derive(FromValue)] +/// struct Unicorn; +/// +/// impl nu_protocol::FromValue for Color { +/// fn expected_type() -> nu_protocol::Type { +/// nu_protocol::Type::Nothing +/// } +/// } +/// ``` +/// +/// Struct with passed type name: +/// ```rust +/// #[derive(FromValue)] +/// #[nu_value(type_name = "bird")] +/// struct Parrot; +/// +/// impl nu_protocol::FromValue for Parrot { +/// fn expected_type() -> nu_protocol::Type { +/// nu_protocol::Type::Custom( +/// >::from("bird") +/// .into_boxed_str() +/// ) +/// } +/// } +/// ``` +fn struct_expected_type( + fields: &Fields, + attr_type_name: Option<&str>, + container_attrs: &ContainerAttributes, +) -> Result { + let ty = match (fields, attr_type_name) { + (_, Some(type_name)) => { + quote!(nu_protocol::Type::Custom( + >::from(#type_name).into_boxed_str() + )) + } + (Fields::Named(fields), _) => { + let mut name_resolver = NameResolver::new(); + let mut fields_ts = Vec::with_capacity(fields.named.len()); + for field in fields.named.iter() { + let member_attrs = MemberAttributes::parse_attrs(&field.attrs)?; + let ident = field.ident.as_ref().expect("named has idents"); + let ident_s = + name_resolver.resolve_ident(ident, container_attrs, &member_attrs, None)?; + let ty = &field.ty; + fields_ts.push(quote! {( + std::string::ToString::to_string(#ident_s), + <#ty as nu_protocol::FromValue>::expected_type(), + )}); + } + quote!(nu_protocol::Type::Record( + std::vec![#(#fields_ts),*].into_boxed_slice() + )) + } + (f @ Fields::Unnamed(fields), _) => { + attributes::deny_fields(f)?; + let mut iter = fields.unnamed.iter(); + let fields = fields.unnamed.iter().map(|field| { + let ty = &field.ty; + quote!(<#ty as nu_protocol::FromValue>::expected_type()) + }); + let mut template = String::new(); + template.push('['); + if iter.next().is_some() { + template.push_str("{}") + } + iter.for_each(|_| template.push_str(", {}")); + template.push(']'); + quote! { + nu_protocol::Type::Custom( + std::format!( + #template, + #(#fields),* + ) + .into_boxed_str() + ) + } + } + (Fields::Unit, _) => quote!(nu_protocol::Type::Nothing), + }; + + Ok(quote! { + fn expected_type() -> nu_protocol::Type { + #ty + } + }) +} + +/// Implements the `#[derive(FromValue)]` macro for enums. +/// +/// This function constructs the implementation of the `FromValue` trait for enums. +/// It is designed to be on the same level as [`derive_struct_from_value`], even though this +/// implementation is a lot simpler. +/// The main `FromValue::from_value` implementation is handled by [`enum_from_value`]. +/// The `FromValue::expected_type` implementation is usually kept empty to use the default +/// implementation, but if `#[nu_value(type_name = "...")]` if given, we use that. +fn derive_enum_from_value( + ident: Ident, + data: DataEnum, + generics: Generics, + attrs: Vec, +) -> Result { + let container_attrs = ContainerAttributes::parse_attrs(attrs.iter())?; + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let from_value_impl = enum_from_value(&data, &attrs)?; + let expected_type_impl = enum_expected_type(container_attrs.type_name.as_deref()); + Ok(quote! { + #[automatically_derived] + impl #impl_generics nu_protocol::FromValue for #ident #ty_generics #where_clause { + #from_value_impl + #expected_type_impl + } + }) +} + +/// Implements `FromValue::from_value` for enums. +/// +/// This function constructs the `from_value` implementation for enums. +/// It only accepts enums with unit variants, as it is currently unclear how other types of enums +/// should be represented via a `Value`. +/// This function checks that every field is a unit variant and constructs a match statement over +/// all possible variants. +/// The input value is expected to be a `Value::String` containing the name of the variant. +/// That string is defined by the [`NameResolver::resolve_ident`] method with the `default` value +/// being [`Case::Snake`]. +/// +/// If no matching variant is found, `ShellError::CantConvert` is returned. +/// +/// This is how such a derived implementation looks: +/// ```rust +/// #[derive(IntoValue)] +/// enum Weather { +/// Sunny, +/// Cloudy, +/// #[nu_value(rename = "rain")] +/// Raining +/// } +/// +/// impl nu_protocol::IntoValue for Weather { +/// fn into_value(self, span: nu_protocol::Span) -> nu_protocol::Value { +/// let span = v.span(); +/// let ty = v.get_type(); +/// +/// let s = v.into_string()?; +/// match s.as_str() { +/// "sunny" => std::result::Ok(Self::Sunny), +/// "cloudy" => std::result::Ok(Self::Cloudy), +/// "rain" => std::result::Ok(Self::Raining), +/// _ => std::result::Result::Err(nu_protocol::ShellError::CantConvert { +/// to_type: std::string::ToString::to_string( +/// &::expected_type() +/// ), +/// from_type: std::string::ToString::to_string(&ty), +/// span: span,help: std::option::Option::None, +/// }), +/// } +/// } +/// } +/// ``` +fn enum_from_value(data: &DataEnum, attrs: &[Attribute]) -> Result { + let container_attrs = ContainerAttributes::parse_attrs(attrs.iter())?; + let mut name_resolver = NameResolver::new(); + let arms: Vec = data + .variants + .iter() + .map(|variant| { + let member_attrs = MemberAttributes::parse_attrs(&variant.attrs)?; + let ident = &variant.ident; + let ident_s = + name_resolver.resolve_ident(ident, &container_attrs, &member_attrs, Case::Snake)?; + match &variant.fields { + Fields::Named(fields) => Err(DeriveError::UnsupportedEnums { + fields_span: fields.span(), + }), + Fields::Unnamed(fields) => Err(DeriveError::UnsupportedEnums { + fields_span: fields.span(), + }), + Fields::Unit => Ok(quote!(#ident_s => std::result::Result::Ok(Self::#ident))), + } + }) + .collect::>()?; + + Ok(quote! { + fn from_value( + v: nu_protocol::Value + ) -> std::result::Result { + let span = v.span(); + let ty = v.get_type(); + + let s = v.into_string()?; + match s.as_str() { + #(#arms,)* + _ => std::result::Result::Err(nu_protocol::ShellError::CantConvert { + to_type: std::string::ToString::to_string( + &::expected_type() + ), + from_type: std::string::ToString::to_string(&ty), + span: span, + help: std::option::Option::None, + }), + } + } + }) +} + +/// Implements `FromValue::expected_type` for enums. +/// +/// Since it's difficult to name the type of an enum in the current type system, we want to use the +/// default implementation if `#[nu_value(type_name = "...")]` was *not* given. +/// For that, a `None` value is returned, for a passed type name we return something like this: +/// ```rust +/// #[derive(IntoValue)] +/// #[nu_value(type_name = "sunny | cloudy | raining")] +/// enum Weather { +/// Sunny, +/// Cloudy, +/// Raining +/// } +/// +/// impl nu_protocol::FromValue for Weather { +/// fn expected_type() -> nu_protocol::Type { +/// nu_protocol::Type::Custom( +/// >::from("sunny | cloudy | raining") +/// .into_boxed_str() +/// ) +/// } +/// } +/// ``` +fn enum_expected_type(attr_type_name: Option<&str>) -> Option { + let type_name = attr_type_name?; + Some(quote! { + fn expected_type() -> nu_protocol::Type { + nu_protocol::Type::Custom( + >::from(#type_name) + .into_boxed_str() + ) + } + }) +} + +/// Parses a `Value` into self. +/// +/// This function handles parsing a `Value` into the corresponding struct or enum variant (`self`). +/// It takes three parameters: `fields`, `self_ident`, and `rename_all`. +/// +/// - The `fields` parameter specifies the expected structure of the `Value`: +/// - Named fields expect a `Value::Record`. +/// - Unnamed fields expect a `Value::List`. +/// - A unit struct expects `Value::Nothing`. +/// +/// For named fields, each field in the record is matched to a struct field. +/// The name matching uses the identifiers resolved by +/// [`NameResolver`](NameResolver::resolve_ident) with `default` being `None`. +/// +/// The `self_ident` parameter is used to specify the identifier for the returned value. +/// For most structs, `Self` is sufficient, but `Self::Variant` may be needed for enum variants. +/// +/// The `container_attrs` parameters, provided through `#[nu_value]` on the container, defines +/// global rules for the `FromValue` implementation. +/// This is used for the [`NameResolver`] to resolve the correct ident in the `Value`. +/// +/// This function is more complex than the equivalent for `IntoValue` due to additional error +/// handling: +/// - If a named field is missing in the `Value`, `ShellError::CantFindColumn` is returned. +/// - For unit structs, if the value is not `Value::Nothing`, `ShellError::CantConvert` is returned. +/// +/// The implementation avoids local variables for fields to prevent accidental shadowing, ensuring +/// that fields with similar names do not cause unexpected behavior. +/// This approach is not typically recommended in handwritten Rust, but it is acceptable for code +/// generation. +fn parse_value_via_fields( + fields: &Fields, + self_ident: impl ToTokens, + container_attrs: &ContainerAttributes, +) -> Result { + match fields { + Fields::Named(fields) => { + let mut name_resolver = NameResolver::new(); + let mut fields_ts: Vec = Vec::with_capacity(fields.named.len()); + for field in fields.named.iter() { + let member_attrs = MemberAttributes::parse_attrs(&field.attrs)?; + let ident = field.ident.as_ref().expect("named has idents"); + let ident_s = + name_resolver.resolve_ident(ident, container_attrs, &member_attrs, None)?; + let ty = &field.ty; + fields_ts.push(match (type_is_option(ty), member_attrs.default) { + (true, _) => quote! { + #ident: record + .remove(#ident_s) + .map(|v| <#ty as nu_protocol::FromValue>::from_value(v)) + .transpose()? + .flatten() + }, + (false, false) => quote! { + #ident: <#ty as nu_protocol::FromValue>::from_value( + record + .remove(#ident_s) + .ok_or_else(|| nu_protocol::ShellError::CantFindColumn { + col_name: std::string::ToString::to_string(#ident_s), + span: std::option::Option::None, + src_span: span + })?, + )? + }, + (false, true) => quote! { + #ident: record + .remove(#ident_s) + .map(|v| <#ty as nu_protocol::FromValue>::from_value(v)) + .transpose()? + .unwrap_or_default() + }, + }); + } + Ok(quote! { + let span = v.span(); + let mut record = v.into_record()?; + std::result::Result::Ok(#self_ident {#(#fields_ts),*}) + }) + } + f @ Fields::Unnamed(fields) => { + attributes::deny_fields(f)?; + let fields = fields.unnamed.iter().enumerate().map(|(i, field)| { + let ty = &field.ty; + quote! {{ + <#ty as nu_protocol::FromValue>::from_value( + deque + .pop_front() + .ok_or_else(|| nu_protocol::ShellError::CantFindColumn { + col_name: std::string::ToString::to_string(&#i), + span: std::option::Option::None, + src_span: span + })?, + )? + }} + }); + Ok(quote! { + let span = v.span(); + let list = v.into_list()?; + let mut deque: std::collections::VecDeque<_> = std::convert::From::from(list); + std::result::Result::Ok(#self_ident(#(#fields),*)) + }) + } + Fields::Unit => Ok(quote! { + match v { + nu_protocol::Value::Nothing {..} => Ok(#self_ident), + v => std::result::Result::Err(nu_protocol::ShellError::CantConvert { + to_type: std::string::ToString::to_string(&::expected_type()), + from_type: std::string::ToString::to_string(&v.get_type()), + span: v.span(), + help: std::option::Option::None + }) + } + }), + } +} + +const FULLY_QUALIFIED_OPTION: &str = "std::option::Option"; +const PARTIALLY_QUALIFIED_OPTION: &str = "option::Option"; +const PRELUDE_OPTION: &str = "Option"; + +/// Check if the field type is an `Option`. +/// +/// This function checks if a given type is an `Option`. +/// We assume that an `Option` is [`std::option::Option`] because we can't see the whole code and +/// can't ask the compiler itself. +/// If the `Option` type isn't `std::option::Option`, the user will get a compile error due to a +/// type mismatch. +/// It's very unusual for people to override `Option`, so this should rarely be an issue. +/// +/// When [rust#63084](https://github.com/rust-lang/rust/issues/63084) is resolved, we can use +/// [`std::any::type_name`] for a static assertion check to get a more direct error messages. +fn type_is_option(ty: &Type) -> bool { + let s = ty.to_token_stream().to_string(); + s.starts_with(PRELUDE_OPTION) + || s.starts_with(PARTIALLY_QUALIFIED_OPTION) + || s.starts_with(FULLY_QUALIFIED_OPTION) +} diff --git a/nushell/crates/nu-derive-value/src/into.rs b/nushell/crates/nu-derive-value/src/into.rs new file mode 100644 index 0000000..de34a89 --- /dev/null +++ b/nushell/crates/nu-derive-value/src/into.rs @@ -0,0 +1,291 @@ +use proc_macro2::TokenStream as TokenStream2; +use quote::{ToTokens, quote}; +use syn::{ + Attribute, Data, DataEnum, DataStruct, DeriveInput, Fields, Generics, Ident, Index, + spanned::Spanned, +}; + +use crate::{ + attributes::{self, ContainerAttributes, MemberAttributes, ParseAttrs}, + case::Case, + names::NameResolver, +}; + +#[derive(Debug)] +pub struct IntoValue; +type DeriveError = super::error::DeriveError; +type Result = std::result::Result; + +/// Inner implementation of the `#[derive(IntoValue)]` macro for structs and enums. +/// +/// Uses `proc_macro2::TokenStream` for better testing support, unlike `proc_macro::TokenStream`. +/// +/// This function directs the `IntoValue` trait derivation to the correct implementation based on +/// the input type: +/// - For structs: [`struct_into_value`] +/// - For enums: [`enum_into_value`] +/// - Unions are not supported and will return an error. +pub fn derive_into_value(input: TokenStream2) -> Result { + let input: DeriveInput = syn::parse2(input).map_err(DeriveError::Syn)?; + match input.data { + Data::Struct(data_struct) => Ok(struct_into_value( + input.ident, + data_struct, + input.generics, + input.attrs, + )?), + Data::Enum(data_enum) => Ok(enum_into_value( + input.ident, + data_enum, + input.generics, + input.attrs, + )?), + Data::Union(_) => Err(DeriveError::UnsupportedUnions), + } +} + +/// Implements the `#[derive(IntoValue)]` macro for structs. +/// +/// Automatically derives the `IntoValue` trait for any struct where each field implements +/// `IntoValue`. +/// For structs with named fields, the derived implementation creates a `Value::Record` using the +/// struct fields as keys. +/// The specific keys are resolved by [`NameResolver`](NameResolver::resolve_ident). +/// Each field value is converted using the `IntoValue::into_value` method. +/// For structs with unnamed fields, this generates a `Value::List` with each field in the list. +/// For unit structs, this generates `Value::Nothing`, because there is no data. +/// +/// This function provides the signature and prepares the call to the [`fields_return_value`] +/// function which does the heavy lifting of creating the `Value` calls. +/// +/// # Examples +/// +/// These examples show what the macro would generate. +/// +/// Struct with named fields: +/// ```rust +/// #[derive(IntoValue)] +/// struct Pet { +/// name: String, +/// age: u8, +/// favorite_toy: Option, +/// } +/// +/// impl nu_protocol::IntoValue for Pet { +/// fn into_value(self, span: nu_protocol::Span) -> nu_protocol::Value { +/// nu_protocol::Value::record(nu_protocol::record! { +/// "name" => nu_protocol::IntoValue::into_value(self.name, span), +/// "age" => nu_protocol::IntoValue::into_value(self.age, span), +/// "favorite_toy" => nu_protocol::IntoValue::into_value(self.favorite_toy, span), +/// }, span) +/// } +/// } +/// ``` +/// +/// Struct with unnamed fields: +/// ```rust +/// #[derive(IntoValue)] +/// struct Color(u8, u8, u8); +/// +/// impl nu_protocol::IntoValue for Color { +/// fn into_value(self, span: nu_protocol::Span) -> nu_protocol::Value { +/// nu_protocol::Value::list(vec![ +/// nu_protocol::IntoValue::into_value(self.0, span), +/// nu_protocol::IntoValue::into_value(self.1, span), +/// nu_protocol::IntoValue::into_value(self.2, span), +/// ], span) +/// } +/// } +/// ``` +/// +/// Unit struct: +/// ```rust +/// #[derive(IntoValue)] +/// struct Unicorn; +/// +/// impl nu_protocol::IntoValue for Unicorn { +/// fn into_value(self, span: nu_protocol::Span) -> nu_protocol::Value { +/// nu_protocol::Value::nothing(span) +/// } +/// } +/// ``` +fn struct_into_value( + ident: Ident, + data: DataStruct, + generics: Generics, + attrs: Vec, +) -> Result { + let container_attrs = ContainerAttributes::parse_attrs(attrs.iter())?; + let record = match &data.fields { + Fields::Named(fields) => { + let accessor = fields + .named + .iter() + .map(|field| field.ident.as_ref().expect("named has idents")) + .map(|ident| quote!(self.#ident)); + fields_return_value(&data.fields, accessor, &container_attrs)? + } + Fields::Unnamed(fields) => { + let accessor = fields + .unnamed + .iter() + .enumerate() + .map(|(n, _)| Index::from(n)) + .map(|index| quote!(self.#index)); + fields_return_value(&data.fields, accessor, &container_attrs)? + } + Fields::Unit => quote!(nu_protocol::Value::nothing(span)), + }; + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + Ok(quote! { + #[automatically_derived] + impl #impl_generics nu_protocol::IntoValue for #ident #ty_generics #where_clause { + fn into_value(self, span: nu_protocol::Span) -> nu_protocol::Value { + #record + } + } + }) +} + +/// Implements the `#[derive(IntoValue)]` macro for enums. +/// +/// This function implements the derive macro `IntoValue` for enums. +/// Currently, only unit enum variants are supported as it is not clear how other types of enums +/// should be represented in a `Value`. +/// For simple enums, we represent the enum as a `Value::String`. +/// For other types of variants, we return an error. +/// +/// The variant name used in the `Value::String` is resolved by the +/// [`NameResolver`](NameResolver::resolve_ident) with the `default` being [`Case::Snake`]. +/// The implementation matches over all variants, uses the appropriate variant name, and constructs +/// a `Value::String`. +/// +/// This is how such a derived implementation looks: +/// ```rust +/// #[derive(IntoValue)] +/// enum Weather { +/// Sunny, +/// Cloudy, +/// #[nu_value(rename = "rain")] +/// Raining +/// } +/// +/// impl nu_protocol::IntoValue for Weather { +/// fn into_value(self, span: nu_protocol::Span) -> nu_protocol::Value { +/// match self { +/// Self::Sunny => nu_protocol::Value::string("sunny", span), +/// Self::Cloudy => nu_protocol::Value::string("cloudy", span), +/// Self::Raining => nu_protocol::Value::string("rain", span), +/// } +/// } +/// } +/// ``` +fn enum_into_value( + ident: Ident, + data: DataEnum, + generics: Generics, + attrs: Vec, +) -> Result { + let container_attrs = ContainerAttributes::parse_attrs(attrs.iter())?; + let mut name_resolver = NameResolver::new(); + let arms: Vec = data + .variants + .into_iter() + .map(|variant| { + let member_attrs = MemberAttributes::parse_attrs(variant.attrs.iter())?; + let ident = variant.ident; + let ident_s = name_resolver.resolve_ident( + &ident, + &container_attrs, + &member_attrs, + Case::Snake, + )?; + match &variant.fields { + // In the future we can implement more complex enums here. + Fields::Named(fields) => Err(DeriveError::UnsupportedEnums { + fields_span: fields.span(), + }), + Fields::Unnamed(fields) => Err(DeriveError::UnsupportedEnums { + fields_span: fields.span(), + }), + Fields::Unit => { + Ok(quote!(Self::#ident => nu_protocol::Value::string(#ident_s, span))) + } + } + }) + .collect::>()?; + + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + Ok(quote! { + impl #impl_generics nu_protocol::IntoValue for #ident #ty_generics #where_clause { + fn into_value(self, span: nu_protocol::Span) -> nu_protocol::Value { + match self { + #(#arms,)* + } + } + } + }) +} + +/// Constructs the final `Value` that the macro generates. +/// +/// This function handles the construction of the final `Value` that the macro generates, primarily +/// for structs. +/// It takes three parameters: `fields`, which allows iterating over each field of a data type, +/// `accessor`, which generalizes data access, and `container_attrs`, which is used for the +/// [`NameResolver`]. +/// +/// - **Field Keys**: +/// The field key is field name of the input struct and resolved the +/// [`NameResolver`](NameResolver::resolve_ident). +/// +/// - **Fields Type**: +/// - Determines whether to generate a `Value::Record`, `Value::List`, or `Value::Nothing` based +/// on the nature of the fields. +/// - Named fields are directly used to generate the record key, as described above. +/// +/// - **Accessor**: +/// - Generalizes how data is accessed for different data types. +/// - For named fields in structs, this is typically `self.field_name`. +/// - For unnamed fields (e.g., tuple structs), it should be an iterator similar to named fields +/// but accessing fields like `self.0`. +/// - For unit structs, this parameter is ignored. +/// +/// This design allows the same function to potentially handle both structs and enums with data +/// variants in the future. +fn fields_return_value( + fields: &Fields, + accessor: impl Iterator, + container_attrs: &ContainerAttributes, +) -> Result { + match fields { + Fields::Named(fields) => { + let mut name_resolver = NameResolver::new(); + let mut items: Vec = Vec::with_capacity(fields.named.len()); + for (field, accessor) in fields.named.iter().zip(accessor) { + let member_attrs = MemberAttributes::parse_attrs(field.attrs.iter())?; + let ident = field.ident.as_ref().expect("named has idents"); + let field = + name_resolver.resolve_ident(ident, container_attrs, &member_attrs, None)?; + items.push(quote!(#field => nu_protocol::IntoValue::into_value(#accessor, span))); + } + Ok(quote! { + nu_protocol::Value::record(nu_protocol::record! { + #(#items),* + }, span) + }) + } + f @ Fields::Unnamed(fields) => { + attributes::deny_fields(f)?; + let items = + fields.unnamed.iter().zip(accessor).map( + |(_, accessor)| quote!(nu_protocol::IntoValue::into_value(#accessor, span)), + ); + Ok(quote!(nu_protocol::Value::list( + std::vec![#(#items),*], + span + ))) + } + Fields::Unit => Ok(quote!(nu_protocol::Value::nothing(span))), + } +} diff --git a/nushell/crates/nu-derive-value/src/lib.rs b/nushell/crates/nu-derive-value/src/lib.rs new file mode 100644 index 0000000..1324516 --- /dev/null +++ b/nushell/crates/nu-derive-value/src/lib.rs @@ -0,0 +1,71 @@ +//! Macro implementations of `#[derive(FromValue, IntoValue)]`. +//! +//! As this crate is a [`proc_macro`] crate, it is only allowed to export +//! [procedural macros](https://doc.rust-lang.org/reference/procedural-macros.html). +//! Therefore, it only exports [`IntoValue`] and [`FromValue`]. +//! +//! To get documentation for other functions and types used in this crate, run +//! `cargo doc -p nu-derive-value --document-private-items`. +//! +//! This crate uses a lot of +//! [`proc_macro2::TokenStream`](https://docs.rs/proc-macro2/1.0.24/proc_macro2/struct.TokenStream.html) +//! as `TokenStream2` to allow testing the behavior of the macros directly, including the output +//! token stream or if the macro errors as expected. +//! The tests for functionality can be found in `nu_protocol::value::test_derive`. +//! +//! This documentation is often less reference-heavy than typical Rust documentation. +//! This is because this crate is a dependency for `nu_protocol`, and linking to it would create a +//! cyclic dependency. +//! Also all examples in the documentation aren't tested as this crate cannot be compiled as a +//! normal library very easily. +//! This might change in the future if cargo allows building a proc-macro crate differently for +//! `cfg(doctest)` as they are already doing for `cfg(test)`. +//! +//! The generated code from the derive macros tries to be as +//! [hygienic](https://doc.rust-lang.org/reference/macros-by-example.html#hygiene) as possible. +//! This ensures that the macro can be called anywhere without requiring specific imports. +//! This results in obtuse code, which isn't recommended for manual, handwritten Rust +//! but ensures that no other code may influence this generated code or vice versa. + +use proc_macro::TokenStream; +use proc_macro_error2::{Diagnostic, proc_macro_error}; +use proc_macro2::TokenStream as TokenStream2; + +mod attributes; +mod case; +mod error; +mod from; +mod into; +mod names; +#[cfg(test)] +mod tests; + +const HELPER_ATTRIBUTE: &str = "nu_value"; + +/// Derive macro generating an impl of the trait `IntoValue`. +/// +/// For further information, see the docs on the trait itself. +#[proc_macro_derive(IntoValue, attributes(nu_value))] +#[proc_macro_error] +pub fn derive_into_value(input: TokenStream) -> TokenStream { + let input = TokenStream2::from(input); + let output = match into::derive_into_value(input) { + Ok(output) => output, + Err(e) => Diagnostic::from(e).abort(), + }; + TokenStream::from(output) +} + +/// Derive macro generating an impl of the trait `FromValue`. +/// +/// For further information, see the docs on the trait itself. +#[proc_macro_derive(FromValue, attributes(nu_value))] +#[proc_macro_error] +pub fn derive_from_value(input: TokenStream) -> TokenStream { + let input = TokenStream2::from(input); + let output = match from::derive_from_value(input) { + Ok(output) => output, + Err(e) => Diagnostic::from(e).abort(), + }; + TokenStream::from(output) +} diff --git a/nushell/crates/nu-derive-value/src/names.rs b/nushell/crates/nu-derive-value/src/names.rs new file mode 100644 index 0000000..825f3e4 --- /dev/null +++ b/nushell/crates/nu-derive-value/src/names.rs @@ -0,0 +1,61 @@ +use proc_macro2::Span; +use std::collections::HashMap; +use syn::Ident; +use syn::ext::IdentExt; + +use crate::attributes::{ContainerAttributes, MemberAttributes}; +use crate::case::{Case, Casing}; +use crate::error::DeriveError; + +#[derive(Debug, Default)] +pub struct NameResolver { + seen_names: HashMap, +} + +impl NameResolver { + pub fn new() -> Self { + Self::default() + } + + /// Resolves an identifier using attributes and ensures its uniqueness. + /// + /// The identifier is transformed according to these rules: + /// - If [`MemberAttributes::rename`] is set, this explicitly renamed value is used. + /// The value is defined by the helper attribute `#[nu_value(rename = "...")]` on a member. + /// - If the above is not set but [`ContainerAttributes::rename_all`] is, the identifier + /// undergoes case conversion as specified by the helper attribute + /// `#[nu_value(rename_all = "...")]` on the container (struct or enum). + /// - If neither renaming attribute is set, the function applies the case conversion provided + /// by the `default` parameter. + /// If `default` is `None`, the identifier remains unchanged. + /// + /// This function checks the transformed identifier against previously seen identifiers to + /// ensure it is unique. + /// If a duplicate identifier is detected, it returns [`DeriveError::NonUniqueName`]. + pub fn resolve_ident( + &mut self, + ident: &Ident, + container_attrs: &ContainerAttributes, + member_attrs: &MemberAttributes, + default: impl Into>, + ) -> Result> { + let span = ident.span(); + let ident = if let Some(rename) = &member_attrs.rename { + rename.clone() + } else { + let case = container_attrs.rename_all.or(default.into()); + ident.unraw().to_case(case) + }; + + if let Some(seen) = self.seen_names.get(&ident) { + return Err(DeriveError::NonUniqueName { + name: ident.to_string(), + first: *seen, + second: span, + }); + } + + self.seen_names.insert(ident.clone(), span); + Ok(ident) + } +} diff --git a/nushell/crates/nu-derive-value/src/tests.rs b/nushell/crates/nu-derive-value/src/tests.rs new file mode 100644 index 0000000..87a4b7c --- /dev/null +++ b/nushell/crates/nu-derive-value/src/tests.rs @@ -0,0 +1,242 @@ +// These tests only check that the derive macros throw the relevant errors. +// Functionality of the derived types is tested in nu_protocol::value::test_derive. + +use crate::error::DeriveError; +use crate::from::derive_from_value; +use crate::into::derive_into_value; +use quote::quote; + +#[test] +fn unsupported_unions() { + let input = quote! { + #[nu_value] + union SomeUnion { + f1: u32, + f2: f32, + } + }; + + let from_res = derive_from_value(input.clone()); + assert!( + matches!(from_res, Err(DeriveError::UnsupportedUnions)), + "expected `DeriveError::UnsupportedUnions`, got {:?}", + from_res + ); + + let into_res = derive_into_value(input); + assert!( + matches!(into_res, Err(DeriveError::UnsupportedUnions)), + "expected `DeriveError::UnsupportedUnions`, got {:?}", + into_res + ); +} + +#[test] +fn unsupported_enums() { + let input = quote! { + #[nu_value(rename_all = "SCREAMING_SNAKE_CASE")] + enum ComplexEnum { + Unit, + Unnamed(u32, f32), + Named { + u: u32, + f: f32, + } + } + }; + + let from_res = derive_from_value(input.clone()); + assert!( + matches!(from_res, Err(DeriveError::UnsupportedEnums { .. })), + "expected `DeriveError::UnsupportedEnums`, got {:?}", + from_res + ); + + let into_res = derive_into_value(input); + assert!( + matches!(into_res, Err(DeriveError::UnsupportedEnums { .. })), + "expected `DeriveError::UnsupportedEnums`, got {:?}", + into_res + ); +} + +#[test] +fn unexpected_attribute() { + let input = quote! { + #[nu_value(what)] + enum SimpleEnum { + A, + B, + } + }; + + let from_res = derive_from_value(input.clone()); + assert!( + matches!(from_res, Err(DeriveError::UnexpectedAttribute { .. })), + "expected `DeriveError::UnexpectedAttribute`, got {:?}", + from_res + ); + + let into_res = derive_into_value(input); + assert!( + matches!(into_res, Err(DeriveError::UnexpectedAttribute { .. })), + "expected `DeriveError::UnexpectedAttribute`, got {:?}", + into_res + ); +} + +#[test] +fn unexpected_attribute_on_struct_field() { + let input = quote! { + struct SimpleStruct { + #[nu_value(what)] + field_a: i32, + field_b: String, + } + }; + + let from_res = derive_from_value(input.clone()); + assert!( + matches!(from_res, Err(DeriveError::UnexpectedAttribute { .. })), + "expected `DeriveError::UnexpectedAttribute`, got {:?}", + from_res + ); + + let into_res = derive_into_value(input); + assert!( + matches!(into_res, Err(DeriveError::UnexpectedAttribute { .. })), + "expected `DeriveError::UnexpectedAttribute`, got {:?}", + into_res + ); +} + +#[test] +fn unexpected_attribute_on_enum_variant() { + let input = quote! { + enum SimpleEnum { + #[nu_value(what)] + A, + B, + } + }; + + let from_res = derive_from_value(input.clone()); + assert!( + matches!(from_res, Err(DeriveError::UnexpectedAttribute { .. })), + "expected `DeriveError::UnexpectedAttribute`, got {:?}", + from_res + ); + + let into_res = derive_into_value(input); + assert!( + matches!(into_res, Err(DeriveError::UnexpectedAttribute { .. })), + "expected `DeriveError::UnexpectedAttribute`, got {:?}", + into_res + ); +} + +#[test] +fn invalid_attribute_position_in_tuple_struct() { + let input = quote! { + struct SimpleTupleStruct( + #[nu_value(what)] + i32, + String, + ); + }; + + let from_res = derive_from_value(input.clone()); + assert!( + matches!( + from_res, + Err(DeriveError::InvalidAttributePosition { attribute_span: _ }) + ), + "expected `DeriveError::InvalidAttributePosition`, got {:?}", + from_res + ); + + let into_res = derive_into_value(input); + assert!( + matches!( + into_res, + Err(DeriveError::InvalidAttributePosition { attribute_span: _ }) + ), + "expected `DeriveError::InvalidAttributePosition`, got {:?}", + into_res + ); +} + +#[test] +fn invalid_attribute_value() { + let input = quote! { + #[nu_value(rename_all = "CrazY-CasE")] + enum SimpleEnum { + A, + B + } + }; + + let from_res = derive_from_value(input.clone()); + assert!( + matches!(from_res, Err(DeriveError::InvalidAttributeValue { .. })), + "expected `DeriveError::InvalidAttributeValue`, got {:?}", + from_res + ); + + let into_res = derive_into_value(input); + assert!( + matches!(into_res, Err(DeriveError::InvalidAttributeValue { .. })), + "expected `DeriveError::InvalidAttributeValue`, got {:?}", + into_res + ); +} + +#[test] +fn non_unique_struct_keys() { + let input = quote! { + struct DuplicateStruct { + #[nu_value(rename = "field")] + some_field: (), + field: (), + } + }; + + let from_res = derive_from_value(input.clone()); + assert!( + matches!(from_res, Err(DeriveError::NonUniqueName { .. })), + "expected `DeriveError::NonUniqueName`, got {:?}", + from_res + ); + + let into_res = derive_into_value(input); + assert!( + matches!(into_res, Err(DeriveError::NonUniqueName { .. })), + "expected `DeriveError::NonUniqueName`, got {:?}", + into_res + ); +} + +#[test] +fn non_unique_enum_variants() { + let input = quote! { + enum DuplicateEnum { + #[nu_value(rename = "variant")] + SomeVariant, + Variant + } + }; + + let from_res = derive_from_value(input.clone()); + assert!( + matches!(from_res, Err(DeriveError::NonUniqueName { .. })), + "expected `DeriveError::NonUniqueName`, got {:?}", + from_res + ); + + let into_res = derive_into_value(input); + assert!( + matches!(into_res, Err(DeriveError::NonUniqueName { .. })), + "expected `DeriveError::NonUniqueName`, got {:?}", + into_res + ); +} diff --git a/nushell/crates/nu-engine/Cargo.toml b/nushell/crates/nu-engine/Cargo.toml new file mode 100644 index 0000000..8f6aba6 --- /dev/null +++ b/nushell/crates/nu-engine/Cargo.toml @@ -0,0 +1,32 @@ +[package] +authors = ["The Nushell Project Developers"] +description = "Nushell's evaluation engine" +repository = "https://github.com/nushell/nushell/tree/main/crates/nu-engine" +edition = "2024" +license = "MIT" +name = "nu-engine" +version = "0.105.2" + +[lib] +bench = false + +[lints] +workspace = true + +[dependencies] +nu-protocol = { path = "../nu-protocol", version = "0.105.2", default-features = false } +nu-path = { path = "../nu-path", version = "0.105.2" } +nu-glob = { path = "../nu-glob", version = "0.105.2" } +nu-utils = { path = "../nu-utils", version = "0.105.2", default-features = false } +log = { workspace = true } + +[features] +default = ["os"] +os = [ + "nu-protocol/os", + "nu-utils/os", +] +plugin = [ + "nu-protocol/plugin", + "os", +] diff --git a/nushell/crates/nu-engine/LICENSE b/nushell/crates/nu-engine/LICENSE new file mode 100644 index 0000000..ae174e8 --- /dev/null +++ b/nushell/crates/nu-engine/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 - 2023 The Nushell Project Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/nushell/crates/nu-engine/README.md b/nushell/crates/nu-engine/README.md new file mode 100644 index 0000000..d5198cf --- /dev/null +++ b/nushell/crates/nu-engine/README.md @@ -0,0 +1,9 @@ +This crate primarily drives the evaluation of expressions. + +(Some overlap with nu-protocol) + +- Provides `CallExt` + +## Internal Nushell crate + +This crate implements components of Nushell and is not designed to support plugin authors or other users directly. diff --git a/nushell/crates/nu-engine/src/call_ext.rs b/nushell/crates/nu-engine/src/call_ext.rs new file mode 100644 index 0000000..7698a50 --- /dev/null +++ b/nushell/crates/nu-engine/src/call_ext.rs @@ -0,0 +1,400 @@ +use crate::eval_expression; +use nu_protocol::{ + FromValue, ShellError, Span, Value, ast, + debugger::WithoutDebug, + engine::{self, EngineState, Stack, StateWorkingSet}, + eval_const::eval_constant, + ir, +}; + +pub trait CallExt { + /// Check if a boolean flag is set (i.e. `--bool` or `--bool=true`) + fn has_flag( + &self, + engine_state: &EngineState, + stack: &mut Stack, + flag_name: &str, + ) -> Result; + + fn get_flag( + &self, + engine_state: &EngineState, + stack: &mut Stack, + name: &str, + ) -> Result, ShellError>; + + /// Efficiently get the span of a flag argument + fn get_flag_span(&self, stack: &Stack, name: &str) -> Option; + + fn rest( + &self, + engine_state: &EngineState, + stack: &mut Stack, + starting_pos: usize, + ) -> Result, ShellError>; + + fn opt( + &self, + engine_state: &EngineState, + stack: &mut Stack, + pos: usize, + ) -> Result, ShellError>; + + fn opt_const( + &self, + working_set: &StateWorkingSet, + pos: usize, + ) -> Result, ShellError>; + + fn req( + &self, + engine_state: &EngineState, + stack: &mut Stack, + pos: usize, + ) -> Result; + + fn req_parser_info( + &self, + engine_state: &EngineState, + stack: &mut Stack, + name: &str, + ) -> Result; + + /// True if the command has any positional or rest arguments, excluding before the given index. + fn has_positional_args(&self, stack: &Stack, starting_pos: usize) -> bool; +} + +impl CallExt for ast::Call { + fn has_flag( + &self, + engine_state: &EngineState, + stack: &mut Stack, + flag_name: &str, + ) -> Result { + for name in self.named_iter() { + if flag_name == name.0.item { + return if let Some(expr) = &name.2 { + // Check --flag=false + let stack = &mut stack.use_call_arg_out_dest(); + let result = eval_expression::(engine_state, stack, expr)?; + match result { + Value::Bool { val, .. } => Ok(val), + _ => Err(ShellError::CantConvert { + to_type: "bool".into(), + from_type: result.get_type().to_string(), + span: result.span(), + help: Some("".into()), + }), + } + } else { + Ok(true) + }; + } + } + + Ok(false) + } + + fn get_flag( + &self, + engine_state: &EngineState, + stack: &mut Stack, + name: &str, + ) -> Result, ShellError> { + if let Some(expr) = self.get_flag_expr(name) { + let stack = &mut stack.use_call_arg_out_dest(); + let result = eval_expression::(engine_state, stack, expr)?; + FromValue::from_value(result).map(Some) + } else { + Ok(None) + } + } + + fn get_flag_span(&self, _stack: &Stack, name: &str) -> Option { + self.get_named_arg(name).map(|arg| arg.span) + } + + fn rest( + &self, + engine_state: &EngineState, + stack: &mut Stack, + starting_pos: usize, + ) -> Result, ShellError> { + let stack = &mut stack.use_call_arg_out_dest(); + self.rest_iter_flattened(starting_pos, |expr| { + eval_expression::(engine_state, stack, expr) + })? + .into_iter() + .map(FromValue::from_value) + .collect() + } + + fn opt( + &self, + engine_state: &EngineState, + stack: &mut Stack, + pos: usize, + ) -> Result, ShellError> { + if let Some(expr) = self.positional_nth(pos) { + let stack = &mut stack.use_call_arg_out_dest(); + let result = eval_expression::(engine_state, stack, expr)?; + FromValue::from_value(result).map(Some) + } else { + Ok(None) + } + } + + fn opt_const( + &self, + working_set: &StateWorkingSet, + pos: usize, + ) -> Result, ShellError> { + if let Some(expr) = self.positional_nth(pos) { + let result = eval_constant(working_set, expr)?; + FromValue::from_value(result).map(Some) + } else { + Ok(None) + } + } + + fn req( + &self, + engine_state: &EngineState, + stack: &mut Stack, + pos: usize, + ) -> Result { + if let Some(expr) = self.positional_nth(pos) { + let stack = &mut stack.use_call_arg_out_dest(); + let result = eval_expression::(engine_state, stack, expr)?; + FromValue::from_value(result) + } else if self.positional_len() == 0 { + Err(ShellError::AccessEmptyContent { span: self.head }) + } else { + Err(ShellError::AccessBeyondEnd { + max_idx: self.positional_len() - 1, + span: self.head, + }) + } + } + + fn req_parser_info( + &self, + engine_state: &EngineState, + stack: &mut Stack, + name: &str, + ) -> Result { + if let Some(expr) = self.get_parser_info(name) { + let stack = &mut stack.use_call_arg_out_dest(); + let result = eval_expression::(engine_state, stack, expr)?; + FromValue::from_value(result) + } else if self.parser_info.is_empty() { + Err(ShellError::AccessEmptyContent { span: self.head }) + } else { + Err(ShellError::AccessBeyondEnd { + max_idx: self.parser_info.len() - 1, + span: self.head, + }) + } + } + + fn has_positional_args(&self, _stack: &Stack, starting_pos: usize) -> bool { + self.rest_iter(starting_pos).next().is_some() + } +} + +impl CallExt for ir::Call { + fn has_flag( + &self, + _engine_state: &EngineState, + stack: &mut Stack, + flag_name: &str, + ) -> Result { + Ok(self + .named_iter(stack) + .find(|(name, _)| name.item == flag_name) + .is_some_and(|(_, value)| { + // Handle --flag=false + !matches!(value, Some(Value::Bool { val: false, .. })) + })) + } + + fn get_flag( + &self, + _engine_state: &EngineState, + stack: &mut Stack, + name: &str, + ) -> Result, ShellError> { + if let Some(val) = self.get_named_arg(stack, name) { + T::from_value(val.clone()).map(Some) + } else { + Ok(None) + } + } + + fn get_flag_span(&self, stack: &Stack, name: &str) -> Option { + self.named_iter(stack) + .find_map(|(i_name, _)| (i_name.item == name).then_some(i_name.span)) + } + + fn rest( + &self, + _engine_state: &EngineState, + stack: &mut Stack, + starting_pos: usize, + ) -> Result, ShellError> { + self.rest_iter_flattened(stack, starting_pos)? + .into_iter() + .map(T::from_value) + .collect() + } + + fn opt( + &self, + _engine_state: &EngineState, + stack: &mut Stack, + pos: usize, + ) -> Result, ShellError> { + self.positional_iter(stack) + .nth(pos) + .cloned() + .map(T::from_value) + .transpose() + } + + fn opt_const( + &self, + _working_set: &StateWorkingSet, + _pos: usize, + ) -> Result, ShellError> { + Err(ShellError::IrEvalError { + msg: "const evaluation is not yet implemented on ir::Call".into(), + span: Some(self.head), + }) + } + + fn req( + &self, + engine_state: &EngineState, + stack: &mut Stack, + pos: usize, + ) -> Result { + if let Some(val) = self.opt(engine_state, stack, pos)? { + Ok(val) + } else if self.positional_len(stack) == 0 { + Err(ShellError::AccessEmptyContent { span: self.head }) + } else { + Err(ShellError::AccessBeyondEnd { + max_idx: self.positional_len(stack) - 1, + span: self.head, + }) + } + } + + fn req_parser_info( + &self, + engine_state: &EngineState, + stack: &mut Stack, + name: &str, + ) -> Result { + // FIXME: this depends on the AST evaluator. We can fix this by making the parser info an + // enum rather than using expressions. It's not clear that evaluation of this is ever really + // needed. + if let Some(expr) = self.get_parser_info(stack, name) { + let expr = expr.clone(); + let stack = &mut stack.use_call_arg_out_dest(); + let result = eval_expression::(engine_state, stack, &expr)?; + FromValue::from_value(result) + } else { + Err(ShellError::CantFindColumn { + col_name: name.into(), + span: None, + src_span: self.head, + }) + } + } + + fn has_positional_args(&self, stack: &Stack, starting_pos: usize) -> bool { + self.rest_iter(stack, starting_pos).next().is_some() + } +} + +macro_rules! proxy { + ($self:ident . $method:ident ($($param:expr),*)) => (match &$self.inner { + engine::CallImpl::AstRef(call) => call.$method($($param),*), + engine::CallImpl::AstBox(call) => call.$method($($param),*), + engine::CallImpl::IrRef(call) => call.$method($($param),*), + engine::CallImpl::IrBox(call) => call.$method($($param),*), + }) +} + +impl CallExt for engine::Call<'_> { + fn has_flag( + &self, + engine_state: &EngineState, + stack: &mut Stack, + flag_name: &str, + ) -> Result { + proxy!(self.has_flag(engine_state, stack, flag_name)) + } + + fn get_flag( + &self, + engine_state: &EngineState, + stack: &mut Stack, + name: &str, + ) -> Result, ShellError> { + proxy!(self.get_flag(engine_state, stack, name)) + } + + fn get_flag_span(&self, stack: &Stack, name: &str) -> Option { + proxy!(self.get_flag_span(stack, name)) + } + + fn rest( + &self, + engine_state: &EngineState, + stack: &mut Stack, + starting_pos: usize, + ) -> Result, ShellError> { + proxy!(self.rest(engine_state, stack, starting_pos)) + } + + fn opt( + &self, + engine_state: &EngineState, + stack: &mut Stack, + pos: usize, + ) -> Result, ShellError> { + proxy!(self.opt(engine_state, stack, pos)) + } + + fn opt_const( + &self, + working_set: &StateWorkingSet, + pos: usize, + ) -> Result, ShellError> { + proxy!(self.opt_const(working_set, pos)) + } + + fn req( + &self, + engine_state: &EngineState, + stack: &mut Stack, + pos: usize, + ) -> Result { + proxy!(self.req(engine_state, stack, pos)) + } + + fn req_parser_info( + &self, + engine_state: &EngineState, + stack: &mut Stack, + name: &str, + ) -> Result { + proxy!(self.req_parser_info(engine_state, stack, name)) + } + + fn has_positional_args(&self, stack: &Stack, starting_pos: usize) -> bool { + proxy!(self.has_positional_args(stack, starting_pos)) + } +} diff --git a/nushell/crates/nu-engine/src/closure_eval.rs b/nushell/crates/nu-engine/src/closure_eval.rs new file mode 100644 index 0000000..6778c09 --- /dev/null +++ b/nushell/crates/nu-engine/src/closure_eval.rs @@ -0,0 +1,275 @@ +use crate::{ + EvalBlockWithEarlyReturnFn, eval_block_with_early_return, get_eval_block_with_early_return, +}; +use nu_protocol::{ + IntoPipelineData, PipelineData, ShellError, Value, + ast::Block, + debugger::{WithDebug, WithoutDebug}, + engine::{Closure, EngineState, EnvVars, Stack}, +}; +use std::{ + borrow::Cow, + collections::{HashMap, HashSet}, + sync::Arc, +}; + +fn eval_fn(debug: bool) -> EvalBlockWithEarlyReturnFn { + if debug { + eval_block_with_early_return:: + } else { + eval_block_with_early_return:: + } +} + +/// [`ClosureEval`] is used to repeatedly evaluate a closure with different values/inputs. +/// +/// [`ClosureEval`] has a builder API. +/// It is first created via [`ClosureEval::new`], +/// then has arguments added via [`ClosureEval::add_arg`], +/// and then can be run using [`ClosureEval::run_with_input`]. +/// +/// ```no_run +/// # use nu_protocol::{PipelineData, Value}; +/// # use nu_engine::ClosureEval; +/// # let engine_state = unimplemented!(); +/// # let stack = unimplemented!(); +/// # let closure = unimplemented!(); +/// let mut closure = ClosureEval::new(engine_state, stack, closure); +/// let iter = Vec::::new() +/// .into_iter() +/// .map(move |value| closure.add_arg(value).run_with_input(PipelineData::Empty)); +/// ``` +/// +/// Many closures follow a simple, common scheme where the pipeline input and the first argument are the same value. +/// In this case, use [`ClosureEval::run_with_value`]: +/// +/// ```no_run +/// # use nu_protocol::{PipelineData, Value}; +/// # use nu_engine::ClosureEval; +/// # let engine_state = unimplemented!(); +/// # let stack = unimplemented!(); +/// # let closure = unimplemented!(); +/// let mut closure = ClosureEval::new(engine_state, stack, closure); +/// let iter = Vec::::new() +/// .into_iter() +/// .map(move |value| closure.run_with_value(value)); +/// ``` +/// +/// Environment isolation and other cleanup is handled by [`ClosureEval`], +/// so nothing needs to be done following [`ClosureEval::run_with_input`] or [`ClosureEval::run_with_value`]. +pub struct ClosureEval { + engine_state: EngineState, + stack: Stack, + block: Arc, + arg_index: usize, + env_vars: Vec>, + env_hidden: Arc>>, + eval: EvalBlockWithEarlyReturnFn, +} + +impl ClosureEval { + /// Create a new [`ClosureEval`]. + pub fn new(engine_state: &EngineState, stack: &Stack, closure: Closure) -> Self { + let engine_state = engine_state.clone(); + let stack = stack.captures_to_stack(closure.captures); + let block = engine_state.get_block(closure.block_id).clone(); + let env_vars = stack.env_vars.clone(); + let env_hidden = stack.env_hidden.clone(); + let eval = get_eval_block_with_early_return(&engine_state); + + Self { + engine_state, + stack, + block, + arg_index: 0, + env_vars, + env_hidden, + eval, + } + } + + pub fn new_preserve_out_dest( + engine_state: &EngineState, + stack: &Stack, + closure: Closure, + ) -> Self { + let engine_state = engine_state.clone(); + let stack = stack.captures_to_stack_preserve_out_dest(closure.captures); + let block = engine_state.get_block(closure.block_id).clone(); + let env_vars = stack.env_vars.clone(); + let env_hidden = stack.env_hidden.clone(); + let eval = get_eval_block_with_early_return(&engine_state); + + Self { + engine_state, + stack, + block, + arg_index: 0, + env_vars, + env_hidden, + eval, + } + } + + /// Sets whether to enable debugging when evaluating the closure. + /// + /// By default, this is controlled by the [`EngineState`] used to create this [`ClosureEval`]. + pub fn debug(&mut self, debug: bool) -> &mut Self { + self.eval = eval_fn(debug); + self + } + + fn try_add_arg(&mut self, value: Cow) { + if let Some(var_id) = self + .block + .signature + .get_positional(self.arg_index) + .and_then(|var| var.var_id) + { + self.stack.add_var(var_id, value.into_owned()); + self.arg_index += 1; + } + } + + /// Add an argument [`Value`] to the closure. + /// + /// Multiple [`add_arg`](Self::add_arg) calls can be chained together, + /// but make sure that arguments are added based on their positional order. + pub fn add_arg(&mut self, value: Value) -> &mut Self { + self.try_add_arg(Cow::Owned(value)); + self + } + + /// Run the closure, passing the given [`PipelineData`] as input. + /// + /// Any arguments should be added beforehand via [`add_arg`](Self::add_arg). + pub fn run_with_input(&mut self, input: PipelineData) -> Result { + self.arg_index = 0; + self.stack.with_env(&self.env_vars, &self.env_hidden); + (self.eval)(&self.engine_state, &mut self.stack, &self.block, input) + } + + /// Run the closure using the given [`Value`] as both the pipeline input and the first argument. + /// + /// Using this function after or in combination with [`add_arg`](Self::add_arg) is most likely an error. + /// This function is equivalent to `self.add_arg(value)` followed by `self.run_with_input(value.into_pipeline_data())`. + pub fn run_with_value(&mut self, value: Value) -> Result { + self.try_add_arg(Cow::Borrowed(&value)); + self.run_with_input(value.into_pipeline_data()) + } +} + +/// [`ClosureEvalOnce`] is used to evaluate a closure a single time. +/// +/// [`ClosureEvalOnce`] has a builder API. +/// It is first created via [`ClosureEvalOnce::new`], +/// then has arguments added via [`ClosureEvalOnce::add_arg`], +/// and then can be run using [`ClosureEvalOnce::run_with_input`]. +/// +/// ```no_run +/// # use nu_protocol::{ListStream, PipelineData, PipelineIterator}; +/// # use nu_engine::ClosureEvalOnce; +/// # let engine_state = unimplemented!(); +/// # let stack = unimplemented!(); +/// # let closure = unimplemented!(); +/// # let value = unimplemented!(); +/// let result = ClosureEvalOnce::new(engine_state, stack, closure) +/// .add_arg(value) +/// .run_with_input(PipelineData::Empty); +/// ``` +/// +/// Many closures follow a simple, common scheme where the pipeline input and the first argument are the same value. +/// In this case, use [`ClosureEvalOnce::run_with_value`]: +/// +/// ```no_run +/// # use nu_protocol::{PipelineData, PipelineIterator}; +/// # use nu_engine::ClosureEvalOnce; +/// # let engine_state = unimplemented!(); +/// # let stack = unimplemented!(); +/// # let closure = unimplemented!(); +/// # let value = unimplemented!(); +/// let result = ClosureEvalOnce::new(engine_state, stack, closure).run_with_value(value); +/// ``` +pub struct ClosureEvalOnce<'a> { + engine_state: &'a EngineState, + stack: Stack, + block: &'a Block, + arg_index: usize, + eval: EvalBlockWithEarlyReturnFn, +} + +impl<'a> ClosureEvalOnce<'a> { + /// Create a new [`ClosureEvalOnce`]. + pub fn new(engine_state: &'a EngineState, stack: &Stack, closure: Closure) -> Self { + let block = engine_state.get_block(closure.block_id); + let eval = get_eval_block_with_early_return(engine_state); + Self { + engine_state, + stack: stack.captures_to_stack(closure.captures), + block, + arg_index: 0, + eval, + } + } + + pub fn new_preserve_out_dest( + engine_state: &'a EngineState, + stack: &Stack, + closure: Closure, + ) -> Self { + let block = engine_state.get_block(closure.block_id); + let eval = get_eval_block_with_early_return(engine_state); + Self { + engine_state, + stack: stack.captures_to_stack_preserve_out_dest(closure.captures), + block, + arg_index: 0, + eval, + } + } + + /// Sets whether to enable debugging when evaluating the closure. + /// + /// By default, this is controlled by the [`EngineState`] used to create this [`ClosureEvalOnce`]. + pub fn debug(mut self, debug: bool) -> Self { + self.eval = eval_fn(debug); + self + } + + fn try_add_arg(&mut self, value: Cow) { + if let Some(var_id) = self + .block + .signature + .get_positional(self.arg_index) + .and_then(|var| var.var_id) + { + self.stack.add_var(var_id, value.into_owned()); + self.arg_index += 1; + } + } + + /// Add an argument [`Value`] to the closure. + /// + /// Multiple [`add_arg`](Self::add_arg) calls can be chained together, + /// but make sure that arguments are added based on their positional order. + pub fn add_arg(mut self, value: Value) -> Self { + self.try_add_arg(Cow::Owned(value)); + self + } + + /// Run the closure, passing the given [`PipelineData`] as input. + /// + /// Any arguments should be added beforehand via [`add_arg`](Self::add_arg). + pub fn run_with_input(mut self, input: PipelineData) -> Result { + (self.eval)(self.engine_state, &mut self.stack, self.block, input) + } + + /// Run the closure using the given [`Value`] as both the pipeline input and the first argument. + /// + /// Using this function after or in combination with [`add_arg`](Self::add_arg) is most likely an error. + /// This function is equivalent to `self.add_arg(value)` followed by `self.run_with_input(value.into_pipeline_data())`. + pub fn run_with_value(mut self, value: Value) -> Result { + self.try_add_arg(Cow::Borrowed(&value)); + self.run_with_input(value.into_pipeline_data()) + } +} diff --git a/nushell/crates/nu-engine/src/column.rs b/nushell/crates/nu-engine/src/column.rs new file mode 100644 index 0000000..483ca79 --- /dev/null +++ b/nushell/crates/nu-engine/src/column.rs @@ -0,0 +1,36 @@ +use nu_protocol::Value; +use std::collections::HashSet; + +pub fn get_columns(input: &[Value]) -> Vec { + let mut column_set = HashSet::new(); + let mut columns = Vec::new(); + for item in input { + let Value::Record { val, .. } = item else { + return vec![]; + }; + + for col in val.columns() { + if column_set.insert(col) { + columns.push(col.to_string()); + } + } + } + + columns +} + +// If a column doesn't exist in the input, return it. +pub fn nonexistent_column<'a, I>(inputs: &[String], columns: I) -> Option +where + I: IntoIterator, +{ + let set: HashSet<&String> = HashSet::from_iter(columns); + + for input in inputs { + if set.contains(input) { + continue; + } + return Some(input.clone()); + } + None +} diff --git a/nushell/crates/nu-engine/src/command_prelude.rs b/nushell/crates/nu-engine/src/command_prelude.rs new file mode 100644 index 0000000..702a6a4 --- /dev/null +++ b/nushell/crates/nu-engine/src/command_prelude.rs @@ -0,0 +1,10 @@ +pub use crate::CallExt; +pub use nu_protocol::{ + ByteStream, ByteStreamType, Category, ErrSpan, Example, IntoInterruptiblePipelineData, + IntoPipelineData, IntoSpanned, IntoValue, PipelineData, Record, ShellError, Signature, Span, + Spanned, SyntaxShape, Type, Value, + ast::CellPath, + engine::{Call, Command, EngineState, Stack, StateWorkingSet}, + record, + shell_error::{io::*, job::*}, +}; diff --git a/nushell/crates/nu-engine/src/compile/builder.rs b/nushell/crates/nu-engine/src/compile/builder.rs new file mode 100644 index 0000000..4d9117f --- /dev/null +++ b/nushell/crates/nu-engine/src/compile/builder.rs @@ -0,0 +1,599 @@ +use nu_protocol::{ + CompileError, IntoSpanned, RegId, Span, Spanned, + ast::Pattern, + ir::{DataSlice, Instruction, IrAstRef, IrBlock, Literal}, +}; + +/// A label identifier. Only exists while building code. Replaced with the actual target. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) struct LabelId(pub usize); + +/// Builds [`IrBlock`]s progressively by consuming instructions and handles register allocation. +#[derive(Debug)] +pub(crate) struct BlockBuilder { + pub(crate) block_span: Option, + pub(crate) instructions: Vec, + pub(crate) spans: Vec, + /// The actual instruction index that a label refers to. While building IR, branch targets are + /// specified as indices into this array rather than the true instruction index. This makes it + /// easier to make modifications to code, as just this array needs to be changed, and it's also + /// less error prone as during `finish()` we check to make sure all of the used labels have had + /// an index actually set. + pub(crate) labels: Vec>, + pub(crate) data: Vec, + pub(crate) ast: Vec>, + pub(crate) comments: Vec, + pub(crate) register_allocation_state: Vec, + pub(crate) file_count: u32, + pub(crate) loop_stack: Vec, +} + +impl BlockBuilder { + /// Starts a new block, with the first register (`%0`) allocated as input. + pub(crate) fn new(block_span: Option) -> Self { + BlockBuilder { + block_span, + instructions: vec![], + spans: vec![], + labels: vec![], + data: vec![], + ast: vec![], + comments: vec![], + register_allocation_state: vec![true], + file_count: 0, + loop_stack: vec![], + } + } + + /// Get the next unused register for code generation. + pub(crate) fn next_register(&mut self) -> Result { + if let Some(index) = self + .register_allocation_state + .iter_mut() + .position(|is_allocated| { + if !*is_allocated { + *is_allocated = true; + true + } else { + false + } + }) + { + Ok(RegId::new(index as u32)) + } else if self.register_allocation_state.len() < (u32::MAX as usize - 2) { + let reg_id = RegId::new(self.register_allocation_state.len() as u32); + self.register_allocation_state.push(true); + Ok(reg_id) + } else { + Err(CompileError::RegisterOverflow { + block_span: self.block_span, + }) + } + } + + /// Check if a register is initialized with a value. + pub(crate) fn is_allocated(&self, reg_id: RegId) -> bool { + self.register_allocation_state + .get(reg_id.get() as usize) + .is_some_and(|state| *state) + } + + /// Mark a register as initialized. + pub(crate) fn mark_register(&mut self, reg_id: RegId) -> Result<(), CompileError> { + if let Some(is_allocated) = self + .register_allocation_state + .get_mut(reg_id.get() as usize) + { + *is_allocated = true; + Ok(()) + } else { + Err(CompileError::RegisterOverflow { + block_span: self.block_span, + }) + } + } + + /// Mark a register as empty, so that it can be used again by something else. + #[track_caller] + pub(crate) fn free_register(&mut self, reg_id: RegId) -> Result<(), CompileError> { + let index = reg_id.get() as usize; + + if self + .register_allocation_state + .get(index) + .is_some_and(|is_allocated| *is_allocated) + { + self.register_allocation_state[index] = false; + Ok(()) + } else { + log::warn!("register {reg_id} uninitialized, builder = {self:#?}"); + Err(CompileError::RegisterUninitialized { + reg_id, + caller: std::panic::Location::caller().to_string(), + }) + } + } + + /// Define a label, which can be used by branch instructions. The target can optionally be + /// specified now. + pub(crate) fn label(&mut self, target_index: Option) -> LabelId { + let label_id = self.labels.len(); + self.labels.push(target_index); + LabelId(label_id) + } + + /// Change the target of a label. + pub(crate) fn set_label( + &mut self, + label_id: LabelId, + target_index: usize, + ) -> Result<(), CompileError> { + *self + .labels + .get_mut(label_id.0) + .ok_or(CompileError::UndefinedLabel { + label_id: label_id.0, + span: None, + })? = Some(target_index); + Ok(()) + } + + /// Insert an instruction into the block, automatically marking any registers populated by + /// the instruction, and freeing any registers consumed by the instruction. + #[track_caller] + pub(crate) fn push(&mut self, instruction: Spanned) -> Result<(), CompileError> { + // Free read registers, and mark write registers. + // + // If a register is both read and written, it should be on both sides, so that we can verify + // that the register was in the right state beforehand. + let mut allocate = |read: &[RegId], write: &[RegId]| -> Result<(), CompileError> { + for reg in read { + self.free_register(*reg)?; + } + for reg in write { + self.mark_register(*reg)?; + } + Ok(()) + }; + + let allocate_result = match &instruction.item { + Instruction::Unreachable => Ok(()), + Instruction::LoadLiteral { dst, lit } => { + allocate(&[], &[*dst]).and( + // Free any registers on the literal + match lit { + Literal::Range { + start, + step, + end, + inclusion: _, + } => allocate(&[*start, *step, *end], &[]), + Literal::Bool(_) + | Literal::Int(_) + | Literal::Float(_) + | Literal::Filesize(_) + | Literal::Duration(_) + | Literal::Binary(_) + | Literal::Block(_) + | Literal::Closure(_) + | Literal::RowCondition(_) + | Literal::List { capacity: _ } + | Literal::Record { capacity: _ } + | Literal::Filepath { + val: _, + no_expand: _, + } + | Literal::Directory { + val: _, + no_expand: _, + } + | Literal::GlobPattern { + val: _, + no_expand: _, + } + | Literal::String(_) + | Literal::RawString(_) + | Literal::CellPath(_) + | Literal::Date(_) + | Literal::Nothing => Ok(()), + }, + ) + } + Instruction::LoadValue { dst, val: _ } => allocate(&[], &[*dst]), + Instruction::Move { dst, src } => allocate(&[*src], &[*dst]), + Instruction::Clone { dst, src } => allocate(&[*src], &[*dst, *src]), + Instruction::Collect { src_dst } => allocate(&[*src_dst], &[*src_dst]), + Instruction::Span { src_dst } => allocate(&[*src_dst], &[*src_dst]), + Instruction::Drop { src } => allocate(&[*src], &[]), + Instruction::Drain { src } => allocate(&[*src], &[]), + Instruction::DrainIfEnd { src } => allocate(&[*src], &[]), + Instruction::LoadVariable { dst, var_id: _ } => allocate(&[], &[*dst]), + Instruction::StoreVariable { var_id: _, src } => allocate(&[*src], &[]), + Instruction::DropVariable { var_id: _ } => Ok(()), + Instruction::LoadEnv { dst, key: _ } => allocate(&[], &[*dst]), + Instruction::LoadEnvOpt { dst, key: _ } => allocate(&[], &[*dst]), + Instruction::StoreEnv { key: _, src } => allocate(&[*src], &[]), + Instruction::PushPositional { src } => allocate(&[*src], &[]), + Instruction::AppendRest { src } => allocate(&[*src], &[]), + Instruction::PushFlag { name: _ } => Ok(()), + Instruction::PushShortFlag { short: _ } => Ok(()), + Instruction::PushNamed { name: _, src } => allocate(&[*src], &[]), + Instruction::PushShortNamed { short: _, src } => allocate(&[*src], &[]), + Instruction::PushParserInfo { name: _, info: _ } => Ok(()), + Instruction::RedirectOut { mode: _ } => Ok(()), + Instruction::RedirectErr { mode: _ } => Ok(()), + Instruction::CheckErrRedirected { src } => allocate(&[*src], &[*src]), + Instruction::OpenFile { + file_num: _, + path, + append: _, + } => allocate(&[*path], &[]), + Instruction::WriteFile { file_num: _, src } => allocate(&[*src], &[]), + Instruction::CloseFile { file_num: _ } => Ok(()), + Instruction::Call { + decl_id: _, + src_dst, + } => allocate(&[*src_dst], &[*src_dst]), + Instruction::StringAppend { src_dst, val } => allocate(&[*src_dst, *val], &[*src_dst]), + Instruction::GlobFrom { + src_dst, + no_expand: _, + } => allocate(&[*src_dst], &[*src_dst]), + Instruction::ListPush { src_dst, item } => allocate(&[*src_dst, *item], &[*src_dst]), + Instruction::ListSpread { src_dst, items } => { + allocate(&[*src_dst, *items], &[*src_dst]) + } + Instruction::RecordInsert { src_dst, key, val } => { + allocate(&[*src_dst, *key, *val], &[*src_dst]) + } + Instruction::RecordSpread { src_dst, items } => { + allocate(&[*src_dst, *items], &[*src_dst]) + } + Instruction::Not { src_dst } => allocate(&[*src_dst], &[*src_dst]), + Instruction::BinaryOp { + lhs_dst, + op: _, + rhs, + } => allocate(&[*lhs_dst, *rhs], &[*lhs_dst]), + Instruction::FollowCellPath { src_dst, path } => { + allocate(&[*src_dst, *path], &[*src_dst]) + } + Instruction::CloneCellPath { dst, src, path } => { + allocate(&[*src, *path], &[*src, *dst]) + } + Instruction::UpsertCellPath { + src_dst, + path, + new_value, + } => allocate(&[*src_dst, *path, *new_value], &[*src_dst]), + Instruction::Jump { index: _ } => Ok(()), + Instruction::BranchIf { cond, index: _ } => allocate(&[*cond], &[]), + Instruction::BranchIfEmpty { src, index: _ } => allocate(&[*src], &[*src]), + Instruction::Match { + pattern: _, + src, + index: _, + } => allocate(&[*src], &[*src]), + Instruction::CheckMatchGuard { src } => allocate(&[*src], &[*src]), + Instruction::Iterate { + dst, + stream, + end_index: _, + } => allocate(&[*stream], &[*dst, *stream]), + Instruction::OnError { index: _ } => Ok(()), + Instruction::OnErrorInto { index: _, dst } => allocate(&[], &[*dst]), + Instruction::PopErrorHandler => Ok(()), + Instruction::ReturnEarly { src } => allocate(&[*src], &[]), + Instruction::Return { src } => allocate(&[*src], &[]), + }; + + // Add more context to the error + match allocate_result { + Ok(()) => (), + Err(CompileError::RegisterUninitialized { reg_id, caller }) => { + return Err(CompileError::RegisterUninitializedWhilePushingInstruction { + reg_id, + caller, + instruction: format!("{:?}", instruction.item), + span: instruction.span, + }); + } + Err(err) => return Err(err), + } + + self.instructions.push(instruction.item); + self.spans.push(instruction.span); + self.ast.push(None); + self.comments.push(String::new()); + Ok(()) + } + + /// Set the AST of the last instruction. Separate method because it's rarely used. + pub(crate) fn set_last_ast(&mut self, ast_ref: Option) { + *self.ast.last_mut().expect("no last instruction") = ast_ref; + } + + /// Add a comment to the last instruction. + pub(crate) fn add_comment(&mut self, comment: impl std::fmt::Display) { + add_comment( + self.comments.last_mut().expect("no last instruction"), + comment, + ) + } + + /// Load a register with a literal. + pub(crate) fn load_literal( + &mut self, + reg_id: RegId, + literal: Spanned, + ) -> Result<(), CompileError> { + self.push( + Instruction::LoadLiteral { + dst: reg_id, + lit: literal.item, + } + .into_spanned(literal.span), + )?; + Ok(()) + } + + /// Allocate a new register and load a literal into it. + pub(crate) fn literal(&mut self, literal: Spanned) -> Result { + let reg_id = self.next_register()?; + self.load_literal(reg_id, literal)?; + Ok(reg_id) + } + + /// Deallocate a register and set it to `Empty`, if it is allocated + pub(crate) fn drop_reg(&mut self, reg_id: RegId) -> Result<(), CompileError> { + if self.is_allocated(reg_id) { + self.push(Instruction::Drop { src: reg_id }.into_spanned(Span::unknown()))?; + } + Ok(()) + } + + /// Set a register to `Empty`, but mark it as in-use, e.g. for input + pub(crate) fn load_empty(&mut self, reg_id: RegId) -> Result<(), CompileError> { + self.drop_reg(reg_id)?; + self.mark_register(reg_id) + } + + /// Drain the stream in a register (fully consuming it) + pub(crate) fn drain(&mut self, src: RegId, span: Span) -> Result<(), CompileError> { + self.push(Instruction::Drain { src }.into_spanned(span)) + } + + /// Add data to the `data` array and return a [`DataSlice`] referencing it. + pub(crate) fn data(&mut self, data: impl AsRef<[u8]>) -> Result { + let data = data.as_ref(); + let start = self.data.len(); + if data.is_empty() { + Ok(DataSlice::empty()) + } else if start + data.len() < u32::MAX as usize { + let slice = DataSlice { + start: start as u32, + len: data.len() as u32, + }; + self.data.extend_from_slice(data); + Ok(slice) + } else { + Err(CompileError::DataOverflow { + block_span: self.block_span, + }) + } + } + + /// Clone a register with a `clone` instruction. + pub(crate) fn clone_reg(&mut self, src: RegId, span: Span) -> Result { + let dst = self.next_register()?; + self.push(Instruction::Clone { dst, src }.into_spanned(span))?; + Ok(dst) + } + + /// Add a `branch-if` instruction + pub(crate) fn branch_if( + &mut self, + cond: RegId, + label_id: LabelId, + span: Span, + ) -> Result<(), CompileError> { + self.push( + Instruction::BranchIf { + cond, + index: label_id.0, + } + .into_spanned(span), + ) + } + + /// Add a `branch-if-empty` instruction + pub(crate) fn branch_if_empty( + &mut self, + src: RegId, + label_id: LabelId, + span: Span, + ) -> Result<(), CompileError> { + self.push( + Instruction::BranchIfEmpty { + src, + index: label_id.0, + } + .into_spanned(span), + ) + } + + /// Add a `jump` instruction + pub(crate) fn jump(&mut self, label_id: LabelId, span: Span) -> Result<(), CompileError> { + self.push(Instruction::Jump { index: label_id.0 }.into_spanned(span)) + } + + /// Add a `match` instruction + pub(crate) fn r#match( + &mut self, + pattern: Pattern, + src: RegId, + label_id: LabelId, + span: Span, + ) -> Result<(), CompileError> { + self.push( + Instruction::Match { + pattern: Box::new(pattern), + src, + index: label_id.0, + } + .into_spanned(span), + ) + } + + /// The index that the next instruction [`.push()`](Self::push)ed will have. + pub(crate) fn here(&self) -> usize { + self.instructions.len() + } + + /// Allocate a new file number, for redirection. + pub(crate) fn next_file_num(&mut self) -> Result { + let next = self.file_count; + self.file_count = self + .file_count + .checked_add(1) + .ok_or(CompileError::FileOverflow { + block_span: self.block_span, + })?; + Ok(next) + } + + /// Push a new loop state onto the builder. Creates new labels that must be set. + pub(crate) fn begin_loop(&mut self) -> Loop { + let loop_ = Loop { + break_label: self.label(None), + continue_label: self.label(None), + }; + self.loop_stack.push(loop_); + loop_ + } + + /// True if we are currently in a loop. + pub(crate) fn is_in_loop(&self) -> bool { + !self.loop_stack.is_empty() + } + + /// Add a loop breaking jump instruction. + pub(crate) fn push_break(&mut self, span: Span) -> Result<(), CompileError> { + let loop_ = self + .loop_stack + .last() + .ok_or_else(|| CompileError::NotInALoop { + msg: "`break` called from outside of a loop".into(), + span: Some(span), + })?; + self.jump(loop_.break_label, span) + } + + /// Add a loop continuing jump instruction. + pub(crate) fn push_continue(&mut self, span: Span) -> Result<(), CompileError> { + let loop_ = self + .loop_stack + .last() + .ok_or_else(|| CompileError::NotInALoop { + msg: "`continue` called from outside of a loop".into(), + span: Some(span), + })?; + self.jump(loop_.continue_label, span) + } + + /// Pop the loop state. Checks that the loop being ended is the same one that was expected. + pub(crate) fn end_loop(&mut self, loop_: Loop) -> Result<(), CompileError> { + let ended_loop = self + .loop_stack + .pop() + .ok_or_else(|| CompileError::NotInALoop { + msg: "end_loop() called outside of a loop".into(), + span: None, + })?; + + if ended_loop == loop_ { + Ok(()) + } else { + Err(CompileError::IncoherentLoopState { + block_span: self.block_span, + }) + } + } + + /// Mark an unreachable code path. Produces an error at runtime if executed. + #[allow(dead_code)] // currently unused, but might be used in the future. + pub(crate) fn unreachable(&mut self, span: Span) -> Result<(), CompileError> { + self.push(Instruction::Unreachable.into_spanned(span)) + } + + /// Consume the builder and produce the final [`IrBlock`]. + pub(crate) fn finish(mut self) -> Result { + // Add comments to label targets + for (index, label_target) in self.labels.iter().enumerate() { + if let Some(label_target) = label_target { + add_comment( + &mut self.comments[*label_target], + format_args!("label({index})"), + ); + } + } + + // Populate the actual target indices of labels into the instructions + for ((index, instruction), span) in + self.instructions.iter_mut().enumerate().zip(&self.spans) + { + if let Some(label_id) = instruction.branch_target() { + let target_index = self.labels.get(label_id).cloned().flatten().ok_or( + CompileError::UndefinedLabel { + label_id, + span: Some(*span), + }, + )?; + // Add a comment to the target index that we come from here + add_comment( + &mut self.comments[target_index], + format_args!("from({index}:)"), + ); + instruction.set_branch_target(target_index).map_err(|_| { + CompileError::SetBranchTargetOfNonBranchInstruction { + instruction: format!("{:?}", instruction), + span: *span, + } + })?; + } + } + + Ok(IrBlock { + instructions: self.instructions, + spans: self.spans, + data: self.data.into(), + ast: self.ast, + comments: self.comments.into_iter().map(|s| s.into()).collect(), + register_count: self + .register_allocation_state + .len() + .try_into() + .expect("register count overflowed in finish() despite previous checks"), + file_count: self.file_count, + }) + } +} + +/// Keeps track of the `break` and `continue` target labels for a loop. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) struct Loop { + pub(crate) break_label: LabelId, + pub(crate) continue_label: LabelId, +} + +/// Add a new comment to an existing one +fn add_comment(comment: &mut String, new_comment: impl std::fmt::Display) { + use std::fmt::Write; + write!( + comment, + "{}{}", + if comment.is_empty() { "" } else { ", " }, + new_comment + ) + .expect("formatting failed"); +} diff --git a/nushell/crates/nu-engine/src/compile/call.rs b/nushell/crates/nu-engine/src/compile/call.rs new file mode 100644 index 0000000..3729489 --- /dev/null +++ b/nushell/crates/nu-engine/src/compile/call.rs @@ -0,0 +1,272 @@ +use std::sync::Arc; + +use nu_protocol::{ + IntoSpanned, RegId, Span, Spanned, + ast::{Argument, Call, Expression, ExternalArgument}, + engine::StateWorkingSet, + ir::{Instruction, IrAstRef, Literal}, +}; + +use super::{BlockBuilder, CompileError, RedirectModes, compile_expression, keyword::*}; + +pub(crate) fn compile_call( + working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + call: &Call, + redirect_modes: RedirectModes, + io_reg: RegId, +) -> Result<(), CompileError> { + let decl = working_set.get_decl(call.decl_id); + + // Check if this call has --help - if so, just redirect to `help` + if call.named_iter().any(|(name, _, _)| name.item == "help") { + let name = working_set + .find_decl_name(call.decl_id) // check for name in scope + .and_then(|name| std::str::from_utf8(name).ok()) + .unwrap_or(decl.name()); // fall back to decl's name + return compile_help(working_set, builder, name.into_spanned(call.head), io_reg); + } + + // Try to figure out if this is a keyword call like `if`, and handle those specially + if decl.is_keyword() { + match decl.name() { + "if" => { + return compile_if(working_set, builder, call, redirect_modes, io_reg); + } + "match" => { + return compile_match(working_set, builder, call, redirect_modes, io_reg); + } + "const" => { + // This differs from the behavior of the const command, which adds the const value + // to the stack. Since `load-variable` also checks `engine_state` for the variable + // and will get a const value though, is it really necessary to do that? + return builder.load_empty(io_reg); + } + "alias" => { + // Alias does nothing + return builder.load_empty(io_reg); + } + "let" | "mut" => { + return compile_let(working_set, builder, call, redirect_modes, io_reg); + } + "try" => { + return compile_try(working_set, builder, call, redirect_modes, io_reg); + } + "loop" => { + return compile_loop(working_set, builder, call, redirect_modes, io_reg); + } + "while" => { + return compile_while(working_set, builder, call, redirect_modes, io_reg); + } + "for" => { + return compile_for(working_set, builder, call, redirect_modes, io_reg); + } + "break" => { + return compile_break(working_set, builder, call, redirect_modes, io_reg); + } + "continue" => { + return compile_continue(working_set, builder, call, redirect_modes, io_reg); + } + "return" => { + return compile_return(working_set, builder, call, redirect_modes, io_reg); + } + "def" | "export def" => { + return builder.load_empty(io_reg); + } + _ => (), + } + } + + // Keep AST if the decl needs it. + let requires_ast = decl.requires_ast_for_arguments(); + + // It's important that we evaluate the args first before trying to set up the argument + // state for the call. + // + // We could technically compile anything that isn't another call safely without worrying about + // the argument state, but we'd have to check all of that first and it just isn't really worth + // it. + enum CompiledArg<'a> { + Positional(RegId, Span, Option), + Named( + &'a str, + Option<&'a str>, + Option, + Span, + Option, + ), + Spread(RegId, Span, Option), + } + + let mut compiled_args = vec![]; + + for arg in &call.arguments { + let arg_reg = arg + .expr() + .map(|expr| { + let arg_reg = builder.next_register()?; + + compile_expression( + working_set, + builder, + expr, + RedirectModes::value(arg.span()), + None, + arg_reg, + )?; + + Ok(arg_reg) + }) + .transpose()?; + + let ast_ref = arg + .expr() + .filter(|_| requires_ast) + .map(|expr| IrAstRef(Arc::new(expr.clone()))); + + match arg { + Argument::Positional(_) | Argument::Unknown(_) => { + compiled_args.push(CompiledArg::Positional( + arg_reg.expect("expr() None in non-Named"), + arg.span(), + ast_ref, + )) + } + Argument::Named((name, short, _)) => compiled_args.push(CompiledArg::Named( + &name.item, + short.as_ref().map(|spanned| spanned.item.as_str()), + arg_reg, + arg.span(), + ast_ref, + )), + Argument::Spread(_) => compiled_args.push(CompiledArg::Spread( + arg_reg.expect("expr() None in non-Named"), + arg.span(), + ast_ref, + )), + } + } + + // Now that the args are all compiled, set up the call state (argument stack and redirections) + for arg in compiled_args { + match arg { + CompiledArg::Positional(reg, span, ast_ref) => { + builder.push(Instruction::PushPositional { src: reg }.into_spanned(span))?; + builder.set_last_ast(ast_ref); + } + CompiledArg::Named(name, short, Some(reg), span, ast_ref) => { + if !name.is_empty() { + let name = builder.data(name)?; + builder.push(Instruction::PushNamed { name, src: reg }.into_spanned(span))?; + } else { + let short = builder.data(short.unwrap_or(""))?; + builder + .push(Instruction::PushShortNamed { short, src: reg }.into_spanned(span))?; + } + builder.set_last_ast(ast_ref); + } + CompiledArg::Named(name, short, None, span, ast_ref) => { + if !name.is_empty() { + let name = builder.data(name)?; + builder.push(Instruction::PushFlag { name }.into_spanned(span))?; + } else { + let short = builder.data(short.unwrap_or(""))?; + builder.push(Instruction::PushShortFlag { short }.into_spanned(span))?; + } + builder.set_last_ast(ast_ref); + } + CompiledArg::Spread(reg, span, ast_ref) => { + builder.push(Instruction::AppendRest { src: reg }.into_spanned(span))?; + builder.set_last_ast(ast_ref); + } + } + } + + // Add any parser info from the call + for (name, info) in &call.parser_info { + let name = builder.data(name)?; + let info = Box::new(info.clone()); + builder.push(Instruction::PushParserInfo { name, info }.into_spanned(call.head))?; + } + + if let Some(mode) = redirect_modes.out { + builder.push(mode.map(|mode| Instruction::RedirectOut { mode }))?; + } + + if let Some(mode) = redirect_modes.err { + builder.push(mode.map(|mode| Instruction::RedirectErr { mode }))?; + } + + // The state is set up, so we can do the call into io_reg + builder.push( + Instruction::Call { + decl_id: call.decl_id, + src_dst: io_reg, + } + .into_spanned(call.head), + )?; + + Ok(()) +} + +pub(crate) fn compile_help( + working_set: &StateWorkingSet<'_>, + builder: &mut BlockBuilder, + decl_name: Spanned<&str>, + io_reg: RegId, +) -> Result<(), CompileError> { + let help_command_id = + working_set + .find_decl(b"help") + .ok_or_else(|| CompileError::MissingRequiredDeclaration { + decl_name: "help".into(), + span: decl_name.span, + })?; + + let name_data = builder.data(decl_name.item)?; + let name_literal = builder.literal(decl_name.map(|_| Literal::String(name_data)))?; + + builder.push(Instruction::PushPositional { src: name_literal }.into_spanned(decl_name.span))?; + + builder.push( + Instruction::Call { + decl_id: help_command_id, + src_dst: io_reg, + } + .into_spanned(decl_name.span), + )?; + + Ok(()) +} + +pub(crate) fn compile_external_call( + working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + head: &Expression, + args: &[ExternalArgument], + redirect_modes: RedirectModes, + io_reg: RegId, +) -> Result<(), CompileError> { + // Pass everything to run-external + let run_external_id = working_set + .find_decl(b"run-external") + .ok_or(CompileError::RunExternalNotFound { span: head.span })?; + + let mut call = Call::new(head.span); + call.decl_id = run_external_id; + + call.arguments.push(Argument::Positional(head.clone())); + + for arg in args { + match arg { + ExternalArgument::Regular(expr) => { + call.arguments.push(Argument::Positional(expr.clone())); + } + ExternalArgument::Spread(expr) => { + call.arguments.push(Argument::Spread(expr.clone())); + } + } + } + + compile_call(working_set, builder, &call, redirect_modes, io_reg) +} diff --git a/nushell/crates/nu-engine/src/compile/expression.rs b/nushell/crates/nu-engine/src/compile/expression.rs new file mode 100644 index 0000000..3fcbbac --- /dev/null +++ b/nushell/crates/nu-engine/src/compile/expression.rs @@ -0,0 +1,572 @@ +use super::{ + BlockBuilder, CompileError, RedirectModes, compile_binary_op, compile_block, compile_call, + compile_external_call, compile_load_env, +}; + +use nu_protocol::{ + ENV_VARIABLE_ID, IntoSpanned, RegId, Span, Value, + ast::{CellPath, Expr, Expression, ListItem, RecordItem, ValueWithUnit}, + engine::StateWorkingSet, + ir::{DataSlice, Instruction, Literal}, +}; + +pub(crate) fn compile_expression( + working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + expr: &Expression, + redirect_modes: RedirectModes, + in_reg: Option, + out_reg: RegId, +) -> Result<(), CompileError> { + let drop_input = |builder: &mut BlockBuilder| { + if let Some(in_reg) = in_reg { + if in_reg != out_reg { + builder.drop_reg(in_reg)?; + } + } + Ok(()) + }; + + let lit = |builder: &mut BlockBuilder, literal: Literal| { + drop_input(builder)?; + + builder + .push( + Instruction::LoadLiteral { + dst: out_reg, + lit: literal, + } + .into_spanned(expr.span), + ) + .map(|_| ()) + }; + + let ignore = |builder: &mut BlockBuilder| { + drop_input(builder)?; + builder.load_empty(out_reg) + }; + + let unexpected = |expr_name: &str| CompileError::UnexpectedExpression { + expr_name: expr_name.into(), + span: expr.span, + }; + + let move_in_reg_to_out_reg = |builder: &mut BlockBuilder| { + // Ensure that out_reg contains the input value, because a call only uses one register + if let Some(in_reg) = in_reg { + if in_reg != out_reg { + // Have to move in_reg to out_reg so it can be used + builder.push( + Instruction::Move { + dst: out_reg, + src: in_reg, + } + .into_spanned(expr.span), + )?; + } + } else { + // Will have to initialize out_reg with Empty first + builder.load_empty(out_reg)?; + } + Ok(()) + }; + + match &expr.expr { + Expr::AttributeBlock(ab) => compile_expression( + working_set, + builder, + &ab.item, + redirect_modes, + in_reg, + out_reg, + ), + Expr::Bool(b) => lit(builder, Literal::Bool(*b)), + Expr::Int(i) => lit(builder, Literal::Int(*i)), + Expr::Float(f) => lit(builder, Literal::Float(*f)), + Expr::Binary(bin) => { + let data_slice = builder.data(bin)?; + lit(builder, Literal::Binary(data_slice)) + } + Expr::Range(range) => { + // Compile the subexpressions of the range + let compile_part = |builder: &mut BlockBuilder, + part_expr: Option<&Expression>| + -> Result { + let reg = builder.next_register()?; + if let Some(part_expr) = part_expr { + compile_expression( + working_set, + builder, + part_expr, + RedirectModes::value(part_expr.span), + None, + reg, + )?; + } else { + builder.load_literal(reg, Literal::Nothing.into_spanned(expr.span))?; + } + Ok(reg) + }; + + drop_input(builder)?; + + let start = compile_part(builder, range.from.as_ref())?; + let step = compile_part(builder, range.next.as_ref())?; + let end = compile_part(builder, range.to.as_ref())?; + + // Assemble the range + builder.load_literal( + out_reg, + Literal::Range { + start, + step, + end, + inclusion: range.operator.inclusion, + } + .into_spanned(expr.span), + ) + } + Expr::Var(var_id) => { + drop_input(builder)?; + builder.push( + Instruction::LoadVariable { + dst: out_reg, + var_id: *var_id, + } + .into_spanned(expr.span), + )?; + Ok(()) + } + Expr::VarDecl(_) => Err(unexpected("VarDecl")), + Expr::Call(call) => { + move_in_reg_to_out_reg(builder)?; + + compile_call(working_set, builder, call, redirect_modes, out_reg) + } + Expr::ExternalCall(head, args) => { + move_in_reg_to_out_reg(builder)?; + + compile_external_call(working_set, builder, head, args, redirect_modes, out_reg) + } + Expr::Operator(_) => Err(unexpected("Operator")), + Expr::RowCondition(block_id) => lit(builder, Literal::RowCondition(*block_id)), + Expr::UnaryNot(subexpr) => { + drop_input(builder)?; + compile_expression( + working_set, + builder, + subexpr, + RedirectModes::value(subexpr.span), + None, + out_reg, + )?; + builder.push(Instruction::Not { src_dst: out_reg }.into_spanned(expr.span))?; + Ok(()) + } + Expr::BinaryOp(lhs, op, rhs) => { + if let Expr::Operator(operator) = op.expr { + drop_input(builder)?; + compile_binary_op( + working_set, + builder, + lhs, + operator.into_spanned(op.span), + rhs, + expr.span, + out_reg, + ) + } else { + Err(CompileError::UnsupportedOperatorExpression { span: op.span }) + } + } + Expr::Collect(var_id, expr) => { + let store_reg = if let Some(in_reg) = in_reg { + // Collect, clone, store + builder.push(Instruction::Collect { src_dst: in_reg }.into_spanned(expr.span))?; + builder.clone_reg(in_reg, expr.span)? + } else { + // Just store nothing in the variable + builder.literal(Literal::Nothing.into_spanned(Span::unknown()))? + }; + builder.push( + Instruction::StoreVariable { + var_id: *var_id, + src: store_reg, + } + .into_spanned(expr.span), + )?; + compile_expression(working_set, builder, expr, redirect_modes, in_reg, out_reg)?; + // Clean it up afterward + builder.push(Instruction::DropVariable { var_id: *var_id }.into_spanned(expr.span))?; + Ok(()) + } + Expr::Subexpression(block_id) => { + let block = working_set.get_block(*block_id); + compile_block(working_set, builder, block, redirect_modes, in_reg, out_reg) + } + Expr::Block(block_id) => lit(builder, Literal::Block(*block_id)), + Expr::Closure(block_id) => lit(builder, Literal::Closure(*block_id)), + Expr::MatchBlock(_) => Err(unexpected("MatchBlock")), // only for `match` keyword + Expr::List(items) => { + // Guess capacity based on items (does not consider spread as more than 1) + lit( + builder, + Literal::List { + capacity: items.len(), + }, + )?; + for item in items { + // Compile the expression of the item / spread + let reg = builder.next_register()?; + let expr = match item { + ListItem::Item(expr) | ListItem::Spread(_, expr) => expr, + }; + compile_expression( + working_set, + builder, + expr, + RedirectModes::value(expr.span), + None, + reg, + )?; + + match item { + ListItem::Item(_) => { + // Add each item using list-push + builder.push( + Instruction::ListPush { + src_dst: out_reg, + item: reg, + } + .into_spanned(expr.span), + )?; + } + ListItem::Spread(spread_span, _) => { + // Spread the list using list-spread + builder.push( + Instruction::ListSpread { + src_dst: out_reg, + items: reg, + } + .into_spanned(*spread_span), + )?; + } + } + } + Ok(()) + } + Expr::Table(table) => { + lit( + builder, + Literal::List { + capacity: table.rows.len(), + }, + )?; + + // Evaluate the columns + let column_registers = table + .columns + .iter() + .map(|column| { + let reg = builder.next_register()?; + compile_expression( + working_set, + builder, + column, + RedirectModes::value(column.span), + None, + reg, + )?; + Ok(reg) + }) + .collect::, CompileError>>()?; + + // Build records for each row + for row in table.rows.iter() { + let row_reg = builder.next_register()?; + builder.load_literal( + row_reg, + Literal::Record { + capacity: table.columns.len(), + } + .into_spanned(expr.span), + )?; + for (column_reg, item) in column_registers.iter().zip(row.iter()) { + let column_reg = builder.clone_reg(*column_reg, item.span)?; + let item_reg = builder.next_register()?; + compile_expression( + working_set, + builder, + item, + RedirectModes::value(item.span), + None, + item_reg, + )?; + builder.push( + Instruction::RecordInsert { + src_dst: row_reg, + key: column_reg, + val: item_reg, + } + .into_spanned(item.span), + )?; + } + builder.push( + Instruction::ListPush { + src_dst: out_reg, + item: row_reg, + } + .into_spanned(expr.span), + )?; + } + + // Free the column registers, since they aren't needed anymore + for reg in column_registers { + builder.drop_reg(reg)?; + } + + Ok(()) + } + Expr::Record(items) => { + lit( + builder, + Literal::Record { + capacity: items.len(), + }, + )?; + + for item in items { + match item { + RecordItem::Pair(key, val) => { + // Add each item using record-insert + let key_reg = builder.next_register()?; + let val_reg = builder.next_register()?; + compile_expression( + working_set, + builder, + key, + RedirectModes::value(key.span), + None, + key_reg, + )?; + compile_expression( + working_set, + builder, + val, + RedirectModes::value(val.span), + None, + val_reg, + )?; + builder.push( + Instruction::RecordInsert { + src_dst: out_reg, + key: key_reg, + val: val_reg, + } + .into_spanned(expr.span), + )?; + } + RecordItem::Spread(spread_span, expr) => { + // Spread the expression using record-spread + let reg = builder.next_register()?; + compile_expression( + working_set, + builder, + expr, + RedirectModes::value(expr.span), + None, + reg, + )?; + builder.push( + Instruction::RecordSpread { + src_dst: out_reg, + items: reg, + } + .into_spanned(*spread_span), + )?; + } + } + } + Ok(()) + } + Expr::Keyword(kw) => { + // keyword: just pass through expr, since commands that use it and are not being + // specially handled already are often just positional anyway + compile_expression( + working_set, + builder, + &kw.expr, + redirect_modes, + in_reg, + out_reg, + ) + } + Expr::ValueWithUnit(value_with_unit) => { + lit(builder, literal_from_value_with_unit(value_with_unit)?) + } + Expr::DateTime(dt) => lit(builder, Literal::Date(Box::new(*dt))), + Expr::Filepath(path, no_expand) => { + let val = builder.data(path)?; + lit( + builder, + Literal::Filepath { + val, + no_expand: *no_expand, + }, + ) + } + Expr::Directory(path, no_expand) => { + let val = builder.data(path)?; + lit( + builder, + Literal::Directory { + val, + no_expand: *no_expand, + }, + ) + } + Expr::GlobPattern(path, no_expand) => { + let val = builder.data(path)?; + lit( + builder, + Literal::GlobPattern { + val, + no_expand: *no_expand, + }, + ) + } + Expr::String(s) => { + let data_slice = builder.data(s)?; + lit(builder, Literal::String(data_slice)) + } + Expr::RawString(rs) => { + let data_slice = builder.data(rs)?; + lit(builder, Literal::RawString(data_slice)) + } + Expr::CellPath(path) => lit(builder, Literal::CellPath(Box::new(path.clone()))), + Expr::FullCellPath(full_cell_path) => { + if matches!(full_cell_path.head.expr, Expr::Var(ENV_VARIABLE_ID)) { + compile_load_env(builder, expr.span, &full_cell_path.tail, out_reg) + } else { + compile_expression( + working_set, + builder, + &full_cell_path.head, + // Only capture the output if there is a tail. This was a bit of a headscratcher + // as the parser emits a FullCellPath with no tail for subexpressions in + // general, which shouldn't be captured any differently than they otherwise + // would be. + if !full_cell_path.tail.is_empty() { + RedirectModes::value(expr.span) + } else { + redirect_modes + }, + in_reg, + out_reg, + )?; + // Only do the follow if this is actually needed + if !full_cell_path.tail.is_empty() { + let cell_path_reg = builder.literal( + Literal::CellPath(Box::new(CellPath { + members: full_cell_path.tail.clone(), + })) + .into_spanned(expr.span), + )?; + builder.push( + Instruction::FollowCellPath { + src_dst: out_reg, + path: cell_path_reg, + } + .into_spanned(expr.span), + )?; + } + Ok(()) + } + } + Expr::ImportPattern(_) => Err(unexpected("ImportPattern")), + Expr::Overlay(_) => Err(unexpected("Overlay")), + Expr::Signature(_) => ignore(builder), // no effect + Expr::StringInterpolation(exprs) | Expr::GlobInterpolation(exprs, _) => { + let mut exprs_iter = exprs.iter().peekable(); + + if exprs_iter + .peek() + .is_some_and(|e| matches!(e.expr, Expr::String(..) | Expr::RawString(..))) + { + // If the first expression is a string or raw string literal, just take it and build + // from that + compile_expression( + working_set, + builder, + exprs_iter.next().expect("peek() was Some"), + RedirectModes::value(expr.span), + None, + out_reg, + )?; + } else { + // Start with an empty string + lit(builder, Literal::String(DataSlice::empty()))?; + } + + // Compile each expression and append to out_reg + for expr in exprs_iter { + let scratch_reg = builder.next_register()?; + compile_expression( + working_set, + builder, + expr, + RedirectModes::value(expr.span), + None, + scratch_reg, + )?; + builder.push( + Instruction::StringAppend { + src_dst: out_reg, + val: scratch_reg, + } + .into_spanned(expr.span), + )?; + } + + // If it's a glob interpolation, change it to a glob + if let Expr::GlobInterpolation(_, no_expand) = expr.expr { + builder.push( + Instruction::GlobFrom { + src_dst: out_reg, + no_expand, + } + .into_spanned(expr.span), + )?; + } + + Ok(()) + } + Expr::Nothing => lit(builder, Literal::Nothing), + Expr::Garbage => Err(CompileError::Garbage { span: expr.span }), + } +} + +fn literal_from_value_with_unit(value_with_unit: &ValueWithUnit) -> Result { + let Expr::Int(int_value) = value_with_unit.expr.expr else { + return Err(CompileError::UnexpectedExpression { + expr_name: format!("{:?}", value_with_unit.expr), + span: value_with_unit.expr.span, + }); + }; + + match value_with_unit + .unit + .item + .build_value(int_value, Span::unknown()) + .map_err(|err| CompileError::InvalidLiteral { + msg: err.to_string(), + span: value_with_unit.expr.span, + })? { + Value::Filesize { val, .. } => Ok(Literal::Filesize(val)), + Value::Duration { val, .. } => Ok(Literal::Duration(val)), + other => Err(CompileError::InvalidLiteral { + msg: format!("bad value returned by Unit::build_value(): {other:?}"), + span: value_with_unit.unit.span, + }), + } +} diff --git a/nushell/crates/nu-engine/src/compile/keyword.rs b/nushell/crates/nu-engine/src/compile/keyword.rs new file mode 100644 index 0000000..971b8c7 --- /dev/null +++ b/nushell/crates/nu-engine/src/compile/keyword.rs @@ -0,0 +1,884 @@ +use nu_protocol::{ + IntoSpanned, RegId, Type, VarId, + ast::{Block, Call, Expr, Expression}, + engine::StateWorkingSet, + ir::Instruction, +}; + +use super::{BlockBuilder, CompileError, RedirectModes, compile_block, compile_expression}; + +/// Compile a call to `if` as a branch-if +pub(crate) fn compile_if( + working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + call: &Call, + redirect_modes: RedirectModes, + io_reg: RegId, +) -> Result<(), CompileError> { + // Pseudocode: + // + // %io_reg <- + // not %io_reg + // branch-if %io_reg, FALSE + // TRUE: ...... + // jump END + // FALSE: ...... OR drop %io_reg + // END: + let invalid = || CompileError::InvalidKeywordCall { + keyword: "if".into(), + span: call.head, + }; + + let condition = call.positional_nth(0).ok_or_else(invalid)?; + let true_block_arg = call.positional_nth(1).ok_or_else(invalid)?; + let else_arg = call.positional_nth(2); + + let true_block_id = true_block_arg.as_block().ok_or_else(invalid)?; + let true_block = working_set.get_block(true_block_id); + + let true_label = builder.label(None); + let false_label = builder.label(None); + let end_label = builder.label(None); + + let not_condition_reg = { + // Compile the condition first + let condition_reg = builder.next_register()?; + compile_expression( + working_set, + builder, + condition, + RedirectModes::value(condition.span), + None, + condition_reg, + )?; + + // Negate the condition - we basically only want to jump if the condition is false + builder.push( + Instruction::Not { + src_dst: condition_reg, + } + .into_spanned(call.head), + )?; + + condition_reg + }; + + // Set up a branch if the condition is false. + builder.branch_if(not_condition_reg, false_label, call.head)?; + builder.add_comment("if false"); + + // Compile the true case + builder.set_label(true_label, builder.here())?; + compile_block( + working_set, + builder, + true_block, + redirect_modes.clone(), + Some(io_reg), + io_reg, + )?; + + // Add a jump over the false case + builder.jump(end_label, else_arg.map(|e| e.span).unwrap_or(call.head))?; + builder.add_comment("end if"); + + // On the else side now, assert that io_reg is still valid + builder.set_label(false_label, builder.here())?; + builder.mark_register(io_reg)?; + + if let Some(else_arg) = else_arg { + let Expression { + expr: Expr::Keyword(else_keyword), + .. + } = else_arg + else { + return Err(invalid()); + }; + + if else_keyword.keyword.as_ref() != b"else" { + return Err(invalid()); + } + + let else_expr = &else_keyword.expr; + + match &else_expr.expr { + Expr::Block(block_id) => { + let false_block = working_set.get_block(*block_id); + compile_block( + working_set, + builder, + false_block, + redirect_modes, + Some(io_reg), + io_reg, + )?; + } + _ => { + // The else case supports bare expressions too, not only blocks + compile_expression( + working_set, + builder, + else_expr, + redirect_modes, + Some(io_reg), + io_reg, + )?; + } + } + } else { + // We don't have an else expression/block, so just set io_reg = Empty + builder.load_empty(io_reg)?; + } + + // Set the end label + builder.set_label(end_label, builder.here())?; + + Ok(()) +} + +/// Compile a call to `match` +pub(crate) fn compile_match( + working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + call: &Call, + redirect_modes: RedirectModes, + io_reg: RegId, +) -> Result<(), CompileError> { + // Pseudocode: + // + // %match_reg <- + // collect %match_reg + // match (pat1), %match_reg, PAT1 + // MATCH2: match (pat2), %match_reg, PAT2 + // FAIL: drop %io_reg + // drop %match_reg + // jump END + // PAT1: %guard_reg <- + // check-match-guard %guard_reg + // not %guard_reg + // branch-if %guard_reg, MATCH2 + // drop %match_reg + // <...expr...> + // jump END + // PAT2: drop %match_reg + // <...expr...> + // jump END + // END: + let invalid = || CompileError::InvalidKeywordCall { + keyword: "match".into(), + span: call.head, + }; + + let match_expr = call.positional_nth(0).ok_or_else(invalid)?; + + let match_block_arg = call.positional_nth(1).ok_or_else(invalid)?; + let match_block = match_block_arg.as_match_block().ok_or_else(invalid)?; + + let match_reg = builder.next_register()?; + + // Evaluate the match expression (patterns will be checked against this). + compile_expression( + working_set, + builder, + match_expr, + RedirectModes::value(match_expr.span), + None, + match_reg, + )?; + + // Important to collect it first + builder.push(Instruction::Collect { src_dst: match_reg }.into_spanned(match_expr.span))?; + + // Generate the `match` instructions. Guards are not used at this stage. + let mut match_labels = Vec::with_capacity(match_block.len()); + let mut next_labels = Vec::with_capacity(match_block.len()); + let end_label = builder.label(None); + + for (pattern, _) in match_block { + let match_label = builder.label(None); + match_labels.push(match_label); + builder.r#match( + pattern.pattern.clone(), + match_reg, + match_label, + pattern.span, + )?; + // Also add a label for the next match instruction or failure case + next_labels.push(builder.label(Some(builder.here()))); + } + + // Match fall-through to jump to the end, if no match + builder.load_empty(io_reg)?; + builder.drop_reg(match_reg)?; + builder.jump(end_label, call.head)?; + + // Generate each of the match expressions. Handle guards here, if present. + for (index, (pattern, expr)) in match_block.iter().enumerate() { + let match_label = match_labels[index]; + let next_label = next_labels[index]; + + // `io_reg` and `match_reg` are still valid at each of these branch targets + builder.mark_register(io_reg)?; + builder.mark_register(match_reg)?; + + // Set the original match instruction target here + builder.set_label(match_label, builder.here())?; + + // Handle guard, if present + if let Some(guard) = &pattern.guard { + let guard_reg = builder.next_register()?; + compile_expression( + working_set, + builder, + guard, + RedirectModes::value(guard.span), + None, + guard_reg, + )?; + builder + .push(Instruction::CheckMatchGuard { src: guard_reg }.into_spanned(guard.span))?; + builder.push(Instruction::Not { src_dst: guard_reg }.into_spanned(guard.span))?; + // Branch to the next match instruction if the branch fails to match + builder.branch_if( + guard_reg, + next_label, + // Span the branch with the next pattern, or the head if this is the end + match_block + .get(index + 1) + .map(|b| b.0.span) + .unwrap_or(call.head), + )?; + builder.add_comment("if match guard false"); + } + + // match_reg no longer needed, successful match + builder.drop_reg(match_reg)?; + + // Execute match right hand side expression + if let Expr::Block(block_id) = expr.expr { + let block = working_set.get_block(block_id); + compile_block( + working_set, + builder, + block, + redirect_modes.clone(), + Some(io_reg), + io_reg, + )?; + } else { + compile_expression( + working_set, + builder, + expr, + redirect_modes.clone(), + Some(io_reg), + io_reg, + )?; + } + + // Jump to the end after the match logic is done + builder.jump(end_label, call.head)?; + builder.add_comment("end match"); + } + + // Set the end destination + builder.set_label(end_label, builder.here())?; + + Ok(()) +} + +/// Compile a call to `let` or `mut` (just do store-variable) +pub(crate) fn compile_let( + working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + call: &Call, + _redirect_modes: RedirectModes, + io_reg: RegId, +) -> Result<(), CompileError> { + // Pseudocode: + // + // %io_reg <- ...... <- %io_reg + // store-variable $var, %io_reg + let invalid = || CompileError::InvalidKeywordCall { + keyword: "let".into(), + span: call.head, + }; + + let var_decl_arg = call.positional_nth(0).ok_or_else(invalid)?; + let block_arg = call.positional_nth(1).ok_or_else(invalid)?; + + let var_id = var_decl_arg.as_var().ok_or_else(invalid)?; + let block_id = block_arg.as_block().ok_or_else(invalid)?; + let block = working_set.get_block(block_id); + + let variable = working_set.get_variable(var_id); + + compile_block( + working_set, + builder, + block, + RedirectModes::value(call.head), + Some(io_reg), + io_reg, + )?; + + // If the variable is a glob type variable, we should cast it with GlobFrom + if variable.ty == Type::Glob { + builder.push( + Instruction::GlobFrom { + src_dst: io_reg, + no_expand: true, + } + .into_spanned(call.head), + )?; + } + + builder.push( + Instruction::StoreVariable { + var_id, + src: io_reg, + } + .into_spanned(call.head), + )?; + builder.add_comment("let"); + + // Don't forget to set io_reg to Empty afterward, as that's the result of an assignment + builder.load_empty(io_reg)?; + + Ok(()) +} + +/// Compile a call to `try`, setting an error handler over the evaluated block +pub(crate) fn compile_try( + working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + call: &Call, + redirect_modes: RedirectModes, + io_reg: RegId, +) -> Result<(), CompileError> { + // Pseudocode (literal block): + // + // on-error-into ERR, %io_reg // or without + // %io_reg <- <...block...> <- %io_reg + // write-to-out-dests %io_reg + // pop-error-handler + // jump END + // ERR: clone %err_reg, %io_reg + // store-variable $err_var, %err_reg // or without + // %io_reg <- <...catch block...> <- %io_reg // set to empty if no catch block + // END: + // + // with expression that can't be inlined: + // + // %closure_reg <- + // on-error-into ERR, %io_reg + // %io_reg <- <...block...> <- %io_reg + // write-to-out-dests %io_reg + // pop-error-handler + // jump END + // ERR: clone %err_reg, %io_reg + // push-positional %closure_reg + // push-positional %err_reg + // call "do", %io_reg + // END: + let invalid = || CompileError::InvalidKeywordCall { + keyword: "try".into(), + span: call.head, + }; + + let block_arg = call.positional_nth(0).ok_or_else(invalid)?; + let block_id = block_arg.as_block().ok_or_else(invalid)?; + let block = working_set.get_block(block_id); + + let catch_expr = match call.positional_nth(1) { + Some(kw_expr) => Some(kw_expr.as_keyword().ok_or_else(invalid)?), + None => None, + }; + let catch_span = catch_expr.map(|e| e.span).unwrap_or(call.head); + + let err_label = builder.label(None); + let end_label = builder.label(None); + + // We have two ways of executing `catch`: if it was provided as a literal, we can inline it. + // Otherwise, we have to evaluate the expression and keep it as a register, and then call `do`. + enum CatchType<'a> { + Block { + block: &'a Block, + var_id: Option, + }, + Closure { + closure_reg: RegId, + }, + } + + let catch_type = catch_expr + .map(|catch_expr| match catch_expr.as_block() { + Some(block_id) => { + let block = working_set.get_block(block_id); + let var_id = block.signature.get_positional(0).and_then(|v| v.var_id); + Ok(CatchType::Block { block, var_id }) + } + None => { + // We have to compile the catch_expr and use it as a closure + let closure_reg = builder.next_register()?; + compile_expression( + working_set, + builder, + catch_expr, + RedirectModes::value(catch_expr.span), + None, + closure_reg, + )?; + Ok(CatchType::Closure { closure_reg }) + } + }) + .transpose()?; + + // Put the error handler instruction. If we have a catch expression then we should capture the + // error. + if catch_type.is_some() { + builder.push( + Instruction::OnErrorInto { + index: err_label.0, + dst: io_reg, + } + .into_spanned(call.head), + )? + } else { + // Otherwise, we don't need the error value. + builder.push(Instruction::OnError { index: err_label.0 }.into_spanned(call.head))? + }; + + builder.add_comment("try"); + + // Compile the block + compile_block( + working_set, + builder, + block, + redirect_modes.clone(), + Some(io_reg), + io_reg, + )?; + + // Successful case: + // - write to the current output destinations + // - pop the error handler + if let Some(mode) = redirect_modes.out { + builder.push(mode.map(|mode| Instruction::RedirectOut { mode }))?; + } + + if let Some(mode) = redirect_modes.err { + builder.push(mode.map(|mode| Instruction::RedirectErr { mode }))?; + } + builder.push(Instruction::DrainIfEnd { src: io_reg }.into_spanned(call.head))?; + builder.push(Instruction::PopErrorHandler.into_spanned(call.head))?; + + // Jump over the failure case + builder.jump(end_label, catch_span)?; + + // This is the error handler + builder.set_label(err_label, builder.here())?; + + // Mark out register as likely not clean - state in error handler is not well defined + builder.mark_register(io_reg)?; + + // Now compile whatever is necessary for the error handler + match catch_type { + Some(CatchType::Block { block, var_id }) => { + // Error will be in io_reg + builder.mark_register(io_reg)?; + if let Some(var_id) = var_id { + // Take a copy of the error as $err, since it will also be input + let err_reg = builder.next_register()?; + builder.push( + Instruction::Clone { + dst: err_reg, + src: io_reg, + } + .into_spanned(catch_span), + )?; + builder.push( + Instruction::StoreVariable { + var_id, + src: err_reg, + } + .into_spanned(catch_span), + )?; + } + // Compile the block, now that the variable is set + compile_block( + working_set, + builder, + block, + redirect_modes, + Some(io_reg), + io_reg, + )?; + } + Some(CatchType::Closure { closure_reg }) => { + // We should call `do`. Error will be in io_reg + let do_decl_id = working_set.find_decl(b"do").ok_or_else(|| { + CompileError::MissingRequiredDeclaration { + decl_name: "do".into(), + span: call.head, + } + })?; + + // Take a copy of io_reg, because we pass it both as an argument and input + builder.mark_register(io_reg)?; + let err_reg = builder.next_register()?; + builder.push( + Instruction::Clone { + dst: err_reg, + src: io_reg, + } + .into_spanned(catch_span), + )?; + + // Push the closure and the error + builder + .push(Instruction::PushPositional { src: closure_reg }.into_spanned(catch_span))?; + builder.push(Instruction::PushPositional { src: err_reg }.into_spanned(catch_span))?; + + // Call `$err | do $closure $err` + builder.push( + Instruction::Call { + decl_id: do_decl_id, + src_dst: io_reg, + } + .into_spanned(catch_span), + )?; + } + None => { + // Just set out to empty. + builder.load_empty(io_reg)?; + } + } + + // This is the end - if we succeeded, should jump here + builder.set_label(end_label, builder.here())?; + + Ok(()) +} + +/// Compile a call to `loop` (via `jump`) +pub(crate) fn compile_loop( + working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + call: &Call, + _redirect_modes: RedirectModes, + io_reg: RegId, +) -> Result<(), CompileError> { + // Pseudocode: + // + // drop %io_reg + // LOOP: %io_reg <- ...... + // drain %io_reg + // jump %LOOP + // END: drop %io_reg + let invalid = || CompileError::InvalidKeywordCall { + keyword: "loop".into(), + span: call.head, + }; + + let block_arg = call.positional_nth(0).ok_or_else(invalid)?; + let block_id = block_arg.as_block().ok_or_else(invalid)?; + let block = working_set.get_block(block_id); + + let loop_ = builder.begin_loop(); + builder.load_empty(io_reg)?; + + builder.set_label(loop_.continue_label, builder.here())?; + + compile_block( + working_set, + builder, + block, + RedirectModes::default(), + None, + io_reg, + )?; + + // Drain the output, just like for a semicolon + builder.drain(io_reg, call.head)?; + + builder.jump(loop_.continue_label, call.head)?; + builder.add_comment("loop"); + + builder.set_label(loop_.break_label, builder.here())?; + builder.end_loop(loop_)?; + + // State of %io_reg is not necessarily well defined here due to control flow, so make sure it's + // empty. + builder.mark_register(io_reg)?; + builder.load_empty(io_reg)?; + + Ok(()) +} + +/// Compile a call to `while`, via branch instructions +pub(crate) fn compile_while( + working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + call: &Call, + _redirect_modes: RedirectModes, + io_reg: RegId, +) -> Result<(), CompileError> { + // Pseudocode: + // + // LOOP: %io_reg <- + // branch-if %io_reg, TRUE + // jump FALSE + // TRUE: %io_reg <- ...... + // drain %io_reg + // jump LOOP + // FALSE: drop %io_reg + let invalid = || CompileError::InvalidKeywordCall { + keyword: "while".into(), + span: call.head, + }; + + let cond_arg = call.positional_nth(0).ok_or_else(invalid)?; + let block_arg = call.positional_nth(1).ok_or_else(invalid)?; + let block_id = block_arg.as_block().ok_or_else(invalid)?; + let block = working_set.get_block(block_id); + + let loop_ = builder.begin_loop(); + builder.set_label(loop_.continue_label, builder.here())?; + + let true_label = builder.label(None); + + compile_expression( + working_set, + builder, + cond_arg, + RedirectModes::value(call.head), + None, + io_reg, + )?; + + builder.branch_if(io_reg, true_label, call.head)?; + builder.add_comment("while"); + builder.jump(loop_.break_label, call.head)?; + builder.add_comment("end while"); + + builder.set_label(true_label, builder.here())?; + + compile_block( + working_set, + builder, + block, + RedirectModes::default(), + None, + io_reg, + )?; + + // Drain the result, just like for a semicolon + builder.drain(io_reg, call.head)?; + + builder.jump(loop_.continue_label, call.head)?; + builder.add_comment("while"); + + builder.set_label(loop_.break_label, builder.here())?; + builder.end_loop(loop_)?; + + // State of %io_reg is not necessarily well defined here due to control flow, so make sure it's + // empty. + builder.mark_register(io_reg)?; + builder.load_empty(io_reg)?; + + Ok(()) +} + +/// Compile a call to `for` (via `iterate`) +pub(crate) fn compile_for( + working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + call: &Call, + _redirect_modes: RedirectModes, + io_reg: RegId, +) -> Result<(), CompileError> { + // Pseudocode: + // + // %stream_reg <- + // LOOP: iterate %io_reg, %stream_reg, END + // store-variable $var, %io_reg + // %io_reg <- <...block...> + // drain %io_reg + // jump LOOP + // END: drop %io_reg + let invalid = || CompileError::InvalidKeywordCall { + keyword: "for".into(), + span: call.head, + }; + + if call.get_named_arg("numbered").is_some() { + // This is deprecated and we don't support it. + return Err(invalid()); + } + + let var_decl_arg = call.positional_nth(0).ok_or_else(invalid)?; + let var_id = var_decl_arg.as_var().ok_or_else(invalid)?; + + let in_arg = call.positional_nth(1).ok_or_else(invalid)?; + let in_expr = in_arg.as_keyword().ok_or_else(invalid)?; + + let block_arg = call.positional_nth(2).ok_or_else(invalid)?; + let block_id = block_arg.as_block().ok_or_else(invalid)?; + let block = working_set.get_block(block_id); + + // Ensure io_reg is marked so we don't use it + builder.mark_register(io_reg)?; + + let stream_reg = builder.next_register()?; + + compile_expression( + working_set, + builder, + in_expr, + RedirectModes::value(in_expr.span), + None, + stream_reg, + )?; + + // Set up loop state + let loop_ = builder.begin_loop(); + builder.set_label(loop_.continue_label, builder.here())?; + + // This gets a value from the stream each time it's executed + // io_reg basically will act as our scratch register here + builder.push( + Instruction::Iterate { + dst: io_reg, + stream: stream_reg, + end_index: loop_.break_label.0, + } + .into_spanned(call.head), + )?; + builder.add_comment("for"); + + // Put the received value in the variable + builder.push( + Instruction::StoreVariable { + var_id, + src: io_reg, + } + .into_spanned(var_decl_arg.span), + )?; + + // Do the body of the block + compile_block( + working_set, + builder, + block, + RedirectModes::default(), + None, + io_reg, + )?; + + // Drain the output, just like for a semicolon + builder.drain(io_reg, call.head)?; + + // Loop back to iterate to get the next value + builder.jump(loop_.continue_label, call.head)?; + + // Set the end of the loop + builder.set_label(loop_.break_label, builder.here())?; + builder.end_loop(loop_)?; + + // We don't need stream_reg anymore, after the loop + // io_reg may or may not be empty, so be sure it is + builder.free_register(stream_reg)?; + builder.mark_register(io_reg)?; + builder.load_empty(io_reg)?; + + Ok(()) +} + +/// Compile a call to `break`. +pub(crate) fn compile_break( + _working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + call: &Call, + _redirect_modes: RedirectModes, + io_reg: RegId, +) -> Result<(), CompileError> { + if builder.is_in_loop() { + builder.load_empty(io_reg)?; + builder.push_break(call.head)?; + builder.add_comment("break"); + } else { + // Fall back to calling the command if we can't find the loop target statically + builder.push( + Instruction::Call { + decl_id: call.decl_id, + src_dst: io_reg, + } + .into_spanned(call.head), + )?; + } + Ok(()) +} + +/// Compile a call to `continue`. +pub(crate) fn compile_continue( + _working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + call: &Call, + _redirect_modes: RedirectModes, + io_reg: RegId, +) -> Result<(), CompileError> { + if builder.is_in_loop() { + builder.load_empty(io_reg)?; + builder.push_continue(call.head)?; + builder.add_comment("continue"); + } else { + // Fall back to calling the command if we can't find the loop target statically + builder.push( + Instruction::Call { + decl_id: call.decl_id, + src_dst: io_reg, + } + .into_spanned(call.head), + )?; + } + Ok(()) +} + +/// Compile a call to `return` as a `return-early` instruction. +/// +/// This is not strictly necessary, but it is more efficient. +pub(crate) fn compile_return( + working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + call: &Call, + _redirect_modes: RedirectModes, + io_reg: RegId, +) -> Result<(), CompileError> { + // Pseudocode: + // + // %io_reg <- + // return-early %io_reg + if let Some(arg_expr) = call.positional_nth(0) { + compile_expression( + working_set, + builder, + arg_expr, + RedirectModes::value(arg_expr.span), + None, + io_reg, + )?; + } else { + builder.load_empty(io_reg)?; + } + + // TODO: It would be nice if this could be `return` instead, but there is a little bit of + // behaviour remaining that still depends on `ShellError::Return` + builder.push(Instruction::ReturnEarly { src: io_reg }.into_spanned(call.head))?; + + // io_reg is supposed to remain allocated + builder.load_empty(io_reg)?; + + Ok(()) +} diff --git a/nushell/crates/nu-engine/src/compile/mod.rs b/nushell/crates/nu-engine/src/compile/mod.rs new file mode 100644 index 0000000..5995e83 --- /dev/null +++ b/nushell/crates/nu-engine/src/compile/mod.rs @@ -0,0 +1,218 @@ +use nu_protocol::{ + CompileError, IntoSpanned, RegId, Span, + ast::{Block, Expr, Pipeline, PipelineRedirection, RedirectionSource, RedirectionTarget}, + engine::StateWorkingSet, + ir::{Instruction, IrBlock, RedirectMode}, +}; + +mod builder; +mod call; +mod expression; +mod keyword; +mod operator; +mod redirect; + +use builder::BlockBuilder; +use call::*; +use expression::compile_expression; +use operator::*; +use redirect::*; + +const BLOCK_INPUT: RegId = RegId::new(0); + +/// Compile Nushell pipeline abstract syntax tree (AST) to internal representation (IR) instructions +/// for evaluation. +pub fn compile(working_set: &StateWorkingSet, block: &Block) -> Result { + let mut builder = BlockBuilder::new(block.span); + + let span = block.span.unwrap_or(Span::unknown()); + + compile_block( + working_set, + &mut builder, + block, + RedirectModes::caller(span), + Some(BLOCK_INPUT), + BLOCK_INPUT, + )?; + + // A complete block has to end with a `return` + builder.push(Instruction::Return { src: BLOCK_INPUT }.into_spanned(span))?; + + builder.finish() +} + +/// Compiles a [`Block`] in-place into an IR block. This can be used in a nested manner, for example +/// by [`compile_if()`][keyword::compile_if], where the instructions for the blocks for the if/else +/// are inlined into the top-level IR block. +fn compile_block( + working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + block: &Block, + redirect_modes: RedirectModes, + in_reg: Option, + out_reg: RegId, +) -> Result<(), CompileError> { + let span = block.span.unwrap_or(Span::unknown()); + let mut redirect_modes = Some(redirect_modes); + if !block.pipelines.is_empty() { + let last_index = block.pipelines.len() - 1; + for (index, pipeline) in block.pipelines.iter().enumerate() { + compile_pipeline( + working_set, + builder, + pipeline, + span, + // the redirect mode only applies to the last pipeline. + if index == last_index { + redirect_modes + .take() + .expect("should only take redirect_modes once") + } else { + RedirectModes::default() + }, + // input is only passed to the first pipeline. + if index == 0 { in_reg } else { None }, + out_reg, + )?; + + if index != last_index { + // Explicitly drain the out reg after each non-final pipeline, because that's how + // the semicolon functions. + if builder.is_allocated(out_reg) { + builder.push(Instruction::Drain { src: out_reg }.into_spanned(span))?; + } + builder.load_empty(out_reg)?; + } + } + Ok(()) + } else if in_reg.is_none() { + builder.load_empty(out_reg) + } else { + Ok(()) + } +} + +fn compile_pipeline( + working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + pipeline: &Pipeline, + fallback_span: Span, + redirect_modes: RedirectModes, + in_reg: Option, + out_reg: RegId, +) -> Result<(), CompileError> { + let mut iter = pipeline.elements.iter().peekable(); + let mut in_reg = in_reg; + let mut redirect_modes = Some(redirect_modes); + while let Some(element) = iter.next() { + let span = element.pipe.unwrap_or(fallback_span); + + // We have to get the redirection mode from either the explicit redirection in the pipeline + // element, or from the next expression if it's specified there. If this is the last + // element, then it's from whatever is passed in as the mode to use. + + let next_redirect_modes = if let Some(next_element) = iter.peek() { + let mut modes = redirect_modes_of_expression(working_set, &next_element.expr, span)?; + + // If there's a next element with no inherent redirection we always pipe out *unless* + // this is a single redirection of stderr to pipe (e>|) + if modes.out.is_none() + && !matches!( + element.redirection, + Some(PipelineRedirection::Single { + source: RedirectionSource::Stderr, + target: RedirectionTarget::Pipe { .. } + }) + ) + { + let pipe_span = next_element.pipe.unwrap_or(next_element.expr.span); + modes.out = Some(RedirectMode::Pipe.into_spanned(pipe_span)); + } + + modes + } else { + redirect_modes + .take() + .expect("should only take redirect_modes once") + }; + + let spec_redirect_modes = match &element.redirection { + Some(PipelineRedirection::Single { source, target }) => { + let mode = redirection_target_to_mode(working_set, builder, target)?; + match source { + RedirectionSource::Stdout => RedirectModes { + out: Some(mode), + err: None, + }, + RedirectionSource::Stderr => RedirectModes { + out: None, + err: Some(mode), + }, + RedirectionSource::StdoutAndStderr => RedirectModes { + out: Some(mode), + err: Some(mode), + }, + } + } + Some(PipelineRedirection::Separate { out, err }) => { + // In this case, out and err must not both be Pipe + assert!( + !matches!( + (out, err), + ( + RedirectionTarget::Pipe { .. }, + RedirectionTarget::Pipe { .. } + ) + ), + "for Separate redirection, out and err targets must not both be Pipe" + ); + let out = redirection_target_to_mode(working_set, builder, out)?; + let err = redirection_target_to_mode(working_set, builder, err)?; + RedirectModes { + out: Some(out), + err: Some(err), + } + } + None => RedirectModes { + out: None, + err: None, + }, + }; + + let redirect_modes = RedirectModes { + out: spec_redirect_modes.out.or(next_redirect_modes.out), + err: spec_redirect_modes.err.or(next_redirect_modes.err), + }; + + compile_expression( + working_set, + builder, + &element.expr, + redirect_modes.clone(), + in_reg, + out_reg, + )?; + + // only clean up the redirection if current element is not + // a subexpression. The subexpression itself already clean it. + if !is_subexpression(&element.expr.expr) { + // Clean up the redirection + finish_redirection(builder, redirect_modes, out_reg)?; + } + + // The next pipeline element takes input from this output + in_reg = Some(out_reg); + } + Ok(()) +} + +fn is_subexpression(expr: &Expr) -> bool { + match expr { + Expr::FullCellPath(inner) => { + matches!(&inner.head.expr, &Expr::Subexpression(..)) + } + Expr::Subexpression(..) => true, + _ => false, + } +} diff --git a/nushell/crates/nu-engine/src/compile/operator.rs b/nushell/crates/nu-engine/src/compile/operator.rs new file mode 100644 index 0000000..5e67410 --- /dev/null +++ b/nushell/crates/nu-engine/src/compile/operator.rs @@ -0,0 +1,379 @@ +use nu_protocol::{ + ENV_VARIABLE_ID, IntoSpanned, RegId, Span, Spanned, Value, + ast::{Assignment, Boolean, CellPath, Expr, Expression, Math, Operator, PathMember, Pattern}, + engine::StateWorkingSet, + ir::{Instruction, Literal}, +}; +use nu_utils::IgnoreCaseExt; + +use super::{BlockBuilder, CompileError, RedirectModes, compile_expression}; + +pub(crate) fn compile_binary_op( + working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + lhs: &Expression, + op: Spanned, + rhs: &Expression, + span: Span, + out_reg: RegId, +) -> Result<(), CompileError> { + if let Operator::Assignment(assign_op) = op.item { + if let Some(decomposed_op) = decompose_assignment(assign_op) { + // Compiling an assignment that uses a binary op with the existing value + compile_binary_op( + working_set, + builder, + lhs, + decomposed_op.into_spanned(op.span), + rhs, + span, + out_reg, + )?; + } else { + // Compiling a plain assignment, where the current left-hand side value doesn't matter + compile_expression( + working_set, + builder, + rhs, + RedirectModes::value(rhs.span), + None, + out_reg, + )?; + } + + compile_assignment(working_set, builder, lhs, op.span, out_reg)?; + + // Load out_reg with Nothing, as that's the result of an assignment + builder.load_literal(out_reg, Literal::Nothing.into_spanned(op.span)) + } else { + // Not an assignment: just do the binary op + let lhs_reg = out_reg; + + compile_expression( + working_set, + builder, + lhs, + RedirectModes::value(lhs.span), + None, + lhs_reg, + )?; + + match op.item { + // `and` / `or` are short-circuiting, use `match` to avoid running the RHS if LHS is + // the correct value. Be careful to support and/or on non-boolean values + Operator::Boolean(bool_op @ Boolean::And) + | Operator::Boolean(bool_op @ Boolean::Or) => { + // `and` short-circuits on false, and `or` short-circuits on true. + let short_circuit_value = match bool_op { + Boolean::And => false, + Boolean::Or => true, + Boolean::Xor => unreachable!(), + }; + + // Before match against lhs_reg, it's important to collect it first to get a concrete value if there is a subexpression. + builder.push(Instruction::Collect { src_dst: lhs_reg }.into_spanned(lhs.span))?; + // Short-circuit to return `lhs_reg`. `match` op does not consume `lhs_reg`. + let short_circuit_label = builder.label(None); + builder.r#match( + Pattern::Value(Value::bool(short_circuit_value, op.span)), + lhs_reg, + short_circuit_label, + op.span, + )?; + + // If the match failed then this was not the short-circuit value, so we have to run + // the RHS expression + let rhs_reg = builder.next_register()?; + compile_expression( + working_set, + builder, + rhs, + RedirectModes::value(rhs.span), + None, + rhs_reg, + )?; + + // It may seem intuitive that we can just return RHS here, but we do have to + // actually execute the binary-op in case this is not a boolean + builder.push( + Instruction::BinaryOp { + lhs_dst: lhs_reg, + op: Operator::Boolean(bool_op), + rhs: rhs_reg, + } + .into_spanned(op.span), + )?; + + // In either the short-circuit case or other case, the result is in lhs_reg = + // out_reg + builder.set_label(short_circuit_label, builder.here())?; + } + _ => { + // Any other operator, via `binary-op` + let rhs_reg = builder.next_register()?; + + compile_expression( + working_set, + builder, + rhs, + RedirectModes::value(rhs.span), + None, + rhs_reg, + )?; + + builder.push( + Instruction::BinaryOp { + lhs_dst: lhs_reg, + op: op.item, + rhs: rhs_reg, + } + .into_spanned(op.span), + )?; + } + } + + if lhs_reg != out_reg { + builder.push( + Instruction::Move { + dst: out_reg, + src: lhs_reg, + } + .into_spanned(op.span), + )?; + } + + builder.push(Instruction::Span { src_dst: out_reg }.into_spanned(span))?; + + Ok(()) + } +} + +/// The equivalent plain operator to use for an assignment, if any +pub(crate) fn decompose_assignment(assignment: Assignment) -> Option { + match assignment { + Assignment::Assign => None, + Assignment::AddAssign => Some(Operator::Math(Math::Add)), + Assignment::SubtractAssign => Some(Operator::Math(Math::Subtract)), + Assignment::MultiplyAssign => Some(Operator::Math(Math::Multiply)), + Assignment::DivideAssign => Some(Operator::Math(Math::Divide)), + Assignment::ConcatenateAssign => Some(Operator::Math(Math::Concatenate)), + } +} + +/// Compile assignment of the value in a register to a left-hand expression +pub(crate) fn compile_assignment( + working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + lhs: &Expression, + assignment_span: Span, + rhs_reg: RegId, +) -> Result<(), CompileError> { + match lhs.expr { + Expr::Var(var_id) => { + // Double check that the variable is supposed to be mutable + if !working_set.get_variable(var_id).mutable { + return Err(CompileError::AssignmentRequiresMutableVar { span: lhs.span }); + } + + builder.push( + Instruction::StoreVariable { + var_id, + src: rhs_reg, + } + .into_spanned(assignment_span), + )?; + Ok(()) + } + Expr::FullCellPath(ref path) => match (&path.head, &path.tail) { + ( + Expression { + expr: Expr::Var(var_id), + .. + }, + _, + ) if *var_id == ENV_VARIABLE_ID => { + // This will be an assignment to an environment variable. + let Some(PathMember::String { val: key, .. }) = path.tail.first() else { + return Err(CompileError::CannotReplaceEnv { span: lhs.span }); + }; + + // Some env vars can't be set by Nushell code. + const AUTOMATIC_NAMES: &[&str] = &["PWD", "FILE_PWD", "CURRENT_FILE"]; + if AUTOMATIC_NAMES.iter().any(|name| key.eq_ignore_case(name)) { + return Err(CompileError::AutomaticEnvVarSetManually { + envvar_name: "PWD".into(), + span: lhs.span, + }); + } + + let key_data = builder.data(key)?; + + let val_reg = if path.tail.len() > 1 { + // Get the current value of the head and first tail of the path, from env + let head_reg = builder.next_register()?; + + // We could use compile_load_env, but this shares the key data... + // Always use optional, because it doesn't matter if it's already there + builder.push( + Instruction::LoadEnvOpt { + dst: head_reg, + key: key_data, + } + .into_spanned(lhs.span), + )?; + + // Default to empty record so we can do further upserts + let default_label = builder.label(None); + let upsert_label = builder.label(None); + builder.branch_if_empty(head_reg, default_label, assignment_span)?; + builder.jump(upsert_label, assignment_span)?; + + builder.set_label(default_label, builder.here())?; + builder.load_literal( + head_reg, + Literal::Record { capacity: 0 }.into_spanned(lhs.span), + )?; + + // Do the upsert on the current value to incorporate rhs + builder.set_label(upsert_label, builder.here())?; + compile_upsert_cell_path( + builder, + (&path.tail[1..]).into_spanned(lhs.span), + head_reg, + rhs_reg, + assignment_span, + )?; + + head_reg + } else { + // Path has only one tail, so we don't need the current value to do an upsert, + // just set it directly to rhs + rhs_reg + }; + + // Finally, store the modified env variable + builder.push( + Instruction::StoreEnv { + key: key_data, + src: val_reg, + } + .into_spanned(assignment_span), + )?; + Ok(()) + } + (_, tail) if tail.is_empty() => { + // If the path tail is empty, we can really just treat this as if it were an + // assignment to the head + compile_assignment(working_set, builder, &path.head, assignment_span, rhs_reg) + } + _ => { + // Just a normal assignment to some path + let head_reg = builder.next_register()?; + + // Compile getting current value of the head expression + compile_expression( + working_set, + builder, + &path.head, + RedirectModes::value(path.head.span), + None, + head_reg, + )?; + + // Upsert the tail of the path into the old value of the head expression + compile_upsert_cell_path( + builder, + path.tail.as_slice().into_spanned(lhs.span), + head_reg, + rhs_reg, + assignment_span, + )?; + + // Now compile the assignment of the updated value to the head + compile_assignment(working_set, builder, &path.head, assignment_span, head_reg) + } + }, + Expr::Garbage => Err(CompileError::Garbage { span: lhs.span }), + _ => Err(CompileError::AssignmentRequiresVar { span: lhs.span }), + } +} + +/// Compile an upsert-cell-path instruction, with known literal members +pub(crate) fn compile_upsert_cell_path( + builder: &mut BlockBuilder, + members: Spanned<&[PathMember]>, + src_dst: RegId, + new_value: RegId, + span: Span, +) -> Result<(), CompileError> { + let path_reg = builder.literal( + Literal::CellPath( + CellPath { + members: members.item.to_vec(), + } + .into(), + ) + .into_spanned(members.span), + )?; + builder.push( + Instruction::UpsertCellPath { + src_dst, + path: path_reg, + new_value, + } + .into_spanned(span), + )?; + Ok(()) +} + +/// Compile the correct sequence to get an environment variable + follow a path on it +pub(crate) fn compile_load_env( + builder: &mut BlockBuilder, + span: Span, + path: &[PathMember], + out_reg: RegId, +) -> Result<(), CompileError> { + match path { + [] => builder.push( + Instruction::LoadVariable { + dst: out_reg, + var_id: ENV_VARIABLE_ID, + } + .into_spanned(span), + )?, + [PathMember::Int { span, .. }, ..] => { + return Err(CompileError::AccessEnvByInt { span: *span }); + } + [ + PathMember::String { + val: key, optional, .. + }, + tail @ .., + ] => { + let key = builder.data(key)?; + + builder.push(if *optional { + Instruction::LoadEnvOpt { dst: out_reg, key }.into_spanned(span) + } else { + Instruction::LoadEnv { dst: out_reg, key }.into_spanned(span) + })?; + + if !tail.is_empty() { + let path = builder.literal( + Literal::CellPath(Box::new(CellPath { + members: tail.to_vec(), + })) + .into_spanned(span), + )?; + builder.push( + Instruction::FollowCellPath { + src_dst: out_reg, + path, + } + .into_spanned(span), + )?; + } + } + } + Ok(()) +} diff --git a/nushell/crates/nu-engine/src/compile/redirect.rs b/nushell/crates/nu-engine/src/compile/redirect.rs new file mode 100644 index 0000000..02011fb --- /dev/null +++ b/nushell/crates/nu-engine/src/compile/redirect.rs @@ -0,0 +1,159 @@ +use nu_protocol::{ + IntoSpanned, OutDest, RegId, Span, Spanned, + ast::{Expression, RedirectionTarget}, + engine::StateWorkingSet, + ir::{Instruction, RedirectMode}, +}; + +use super::{BlockBuilder, CompileError, compile_expression}; + +#[derive(Default, Clone)] +pub(crate) struct RedirectModes { + pub(crate) out: Option>, + pub(crate) err: Option>, +} + +impl RedirectModes { + pub(crate) fn value(span: Span) -> Self { + RedirectModes { + out: Some(RedirectMode::Value.into_spanned(span)), + err: None, + } + } + + pub(crate) fn caller(span: Span) -> RedirectModes { + RedirectModes { + out: Some(RedirectMode::Caller.into_spanned(span)), + err: Some(RedirectMode::Caller.into_spanned(span)), + } + } +} + +pub(crate) fn redirection_target_to_mode( + working_set: &StateWorkingSet, + builder: &mut BlockBuilder, + target: &RedirectionTarget, +) -> Result, CompileError> { + Ok(match target { + RedirectionTarget::File { + expr, + append, + span: redir_span, + } => { + let file_num = builder.next_file_num()?; + let path_reg = builder.next_register()?; + compile_expression( + working_set, + builder, + expr, + RedirectModes::value(*redir_span), + None, + path_reg, + )?; + builder.push( + Instruction::OpenFile { + file_num, + path: path_reg, + append: *append, + } + .into_spanned(*redir_span), + )?; + RedirectMode::File { file_num }.into_spanned(*redir_span) + } + RedirectionTarget::Pipe { span } => RedirectMode::Pipe.into_spanned(*span), + }) +} + +pub(crate) fn redirect_modes_of_expression( + working_set: &StateWorkingSet, + expression: &Expression, + redir_span: Span, +) -> Result { + let (out, err) = expression.expr.pipe_redirection(working_set); + Ok(RedirectModes { + out: out + .map(|r| r.into_spanned(redir_span)) + .map(out_dest_to_redirect_mode) + .transpose()?, + err: err + .map(|r| r.into_spanned(redir_span)) + .map(out_dest_to_redirect_mode) + .transpose()?, + }) +} + +/// Finish the redirection for an expression, writing to and closing files as necessary +pub(crate) fn finish_redirection( + builder: &mut BlockBuilder, + modes: RedirectModes, + out_reg: RegId, +) -> Result<(), CompileError> { + if let Some(Spanned { + item: RedirectMode::File { file_num }, + span, + }) = modes.out + { + // If out is a file and err is a pipe, we must not consume the expression result - + // that is actually the err, in that case. + if !matches!( + modes.err, + Some(Spanned { + item: RedirectMode::Pipe, + .. + }) + ) { + builder.push( + Instruction::WriteFile { + file_num, + src: out_reg, + } + .into_spanned(span), + )?; + builder.load_empty(out_reg)?; + } + builder.push(Instruction::CloseFile { file_num }.into_spanned(span))?; + } + + match modes.err { + Some(Spanned { + item: RedirectMode::File { file_num }, + span, + }) => { + // Close the file, unless it's the same as out (in which case it was already closed) + if !modes.out.is_some_and(|out_mode| match out_mode.item { + RedirectMode::File { + file_num: out_file_num, + } => file_num == out_file_num, + _ => false, + }) { + builder.push(Instruction::CloseFile { file_num }.into_spanned(span))?; + } + } + Some(Spanned { + item: RedirectMode::Pipe, + span, + }) => { + builder.push(Instruction::CheckErrRedirected { src: out_reg }.into_spanned(span))?; + } + _ => (), + } + + Ok(()) +} + +pub(crate) fn out_dest_to_redirect_mode( + out_dest: Spanned, +) -> Result, CompileError> { + let span = out_dest.span; + out_dest + .map(|out_dest| match out_dest { + OutDest::Pipe => Ok(RedirectMode::Pipe), + OutDest::PipeSeparate => Ok(RedirectMode::PipeSeparate), + OutDest::Value => Ok(RedirectMode::Value), + OutDest::Null => Ok(RedirectMode::Null), + OutDest::Print => Ok(RedirectMode::Print), + OutDest::Inherit => Err(CompileError::InvalidRedirectMode { span }), + OutDest::File(_) => Err(CompileError::InvalidRedirectMode { span }), + }) + .transpose() +} diff --git a/nushell/crates/nu-engine/src/documentation.rs b/nushell/crates/nu-engine/src/documentation.rs new file mode 100644 index 0000000..36f4a30 --- /dev/null +++ b/nushell/crates/nu-engine/src/documentation.rs @@ -0,0 +1,599 @@ +use crate::eval_call; +use nu_protocol::{ + Category, Config, Example, IntoPipelineData, PipelineData, PositionalArg, Signature, Span, + SpanId, Spanned, SyntaxShape, Type, Value, + ast::{Argument, Call, Expr, Expression, RecordItem}, + debugger::WithoutDebug, + engine::CommandType, + engine::{Command, EngineState, Stack, UNKNOWN_SPAN_ID}, + record, +}; +use nu_utils::terminal_size; +use std::{collections::HashMap, fmt::Write}; + +/// ANSI style reset +const RESET: &str = "\x1b[0m"; +/// ANSI set default color (as set in the terminal) +const DEFAULT_COLOR: &str = "\x1b[39m"; + +pub fn get_full_help( + command: &dyn Command, + engine_state: &EngineState, + stack: &mut Stack, +) -> String { + // Precautionary step to capture any command output generated during this operation. We + // internally call several commands (`table`, `ansi`, `nu-highlight`) and get their + // `PipelineData` using this `Stack`, any other output should not be redirected like the main + // execution. + let stack = &mut stack.start_collect_value(); + + let signature = engine_state + .get_signature(command) + .update_from_command(command); + + get_documentation( + &signature, + &command.examples(), + engine_state, + stack, + command.is_keyword(), + ) +} + +/// Syntax highlight code using the `nu-highlight` command if available +fn nu_highlight_string(code_string: &str, engine_state: &EngineState, stack: &mut Stack) -> String { + if let Some(highlighter) = engine_state.find_decl(b"nu-highlight", &[]) { + let decl = engine_state.get_decl(highlighter); + + let call = Call::new(Span::unknown()); + + if let Ok(output) = decl.run( + engine_state, + stack, + &(&call).into(), + Value::string(code_string, Span::unknown()).into_pipeline_data(), + ) { + let result = output.into_value(Span::unknown()); + if let Ok(s) = result.and_then(Value::coerce_into_string) { + return s; // successfully highlighted string + } + } + } + code_string.to_string() +} + +fn get_documentation( + sig: &Signature, + examples: &[Example], + engine_state: &EngineState, + stack: &mut Stack, + is_parser_keyword: bool, +) -> String { + let nu_config = stack.get_config(engine_state); + + // Create ansi colors + let mut help_style = HelpStyle::default(); + help_style.update_from_config(engine_state, &nu_config); + let help_section_name = &help_style.section_name; + let help_subcolor_one = &help_style.subcolor_one; + + let cmd_name = &sig.name; + let mut long_desc = String::new(); + + let desc = &sig.description; + if !desc.is_empty() { + long_desc.push_str(desc); + long_desc.push_str("\n\n"); + } + + let extra_desc = &sig.extra_description; + if !extra_desc.is_empty() { + long_desc.push_str(extra_desc); + long_desc.push_str("\n\n"); + } + + if !sig.search_terms.is_empty() { + let _ = write!( + long_desc, + "{help_section_name}Search terms{RESET}: {help_subcolor_one}{}{RESET}\n\n", + sig.search_terms.join(", "), + ); + } + + let _ = write!( + long_desc, + "{help_section_name}Usage{RESET}:\n > {}\n", + sig.call_signature() + ); + + // TODO: improve the subcommand name resolution + // issues: + // - Aliases are included + // - https://github.com/nushell/nushell/issues/11657 + // - Subcommands are included violating module scoping + // - https://github.com/nushell/nushell/issues/11447 + // - https://github.com/nushell/nushell/issues/11625 + let mut subcommands = vec![]; + let signatures = engine_state.get_signatures_and_declids(true); + for (sig, decl_id) in signatures { + let command_type = engine_state.get_decl(decl_id).command_type(); + + // Don't display removed/deprecated commands in the Subcommands list + if sig.name.starts_with(&format!("{cmd_name} ")) + && !matches!(sig.category, Category::Removed) + { + // If it's a plugin, alias, or custom command, display that information in the help + if command_type == CommandType::Plugin + || command_type == CommandType::Alias + || command_type == CommandType::Custom + { + subcommands.push(format!( + " {help_subcolor_one}{} {help_section_name}({}){RESET} - {}", + sig.name, command_type, sig.description + )); + } else { + subcommands.push(format!( + " {help_subcolor_one}{}{RESET} - {}", + sig.name, sig.description + )); + } + } + } + + if !subcommands.is_empty() { + let _ = write!(long_desc, "\n{help_section_name}Subcommands{RESET}:\n"); + subcommands.sort(); + long_desc.push_str(&subcommands.join("\n")); + long_desc.push('\n'); + } + + if !sig.named.is_empty() { + long_desc.push_str(&get_flags_section(sig, &help_style, |v| { + nu_highlight_string(&v.to_parsable_string(", ", &nu_config), engine_state, stack) + })) + } + + if !sig.required_positional.is_empty() + || !sig.optional_positional.is_empty() + || sig.rest_positional.is_some() + { + let _ = write!(long_desc, "\n{help_section_name}Parameters{RESET}:\n"); + for positional in &sig.required_positional { + write_positional( + &mut long_desc, + positional, + PositionalKind::Required, + &help_style, + &nu_config, + engine_state, + stack, + ); + } + for positional in &sig.optional_positional { + write_positional( + &mut long_desc, + positional, + PositionalKind::Optional, + &help_style, + &nu_config, + engine_state, + stack, + ); + } + + if let Some(rest_positional) = &sig.rest_positional { + write_positional( + &mut long_desc, + rest_positional, + PositionalKind::Rest, + &help_style, + &nu_config, + engine_state, + stack, + ); + } + } + + fn get_term_width() -> usize { + if let Ok((w, _h)) = terminal_size() { + w as usize + } else { + 80 + } + } + + if !is_parser_keyword && !sig.input_output_types.is_empty() { + if let Some(decl_id) = engine_state.find_decl(b"table", &[]) { + // FIXME: we may want to make this the span of the help command in the future + let span = Span::unknown(); + let mut vals = vec![]; + for (input, output) in &sig.input_output_types { + vals.push(Value::record( + record! { + "input" => Value::string(input.to_string(), span), + "output" => Value::string(output.to_string(), span), + }, + span, + )); + } + + let caller_stack = &mut Stack::new().collect_value(); + if let Ok(result) = eval_call::( + engine_state, + caller_stack, + &Call { + decl_id, + head: span, + arguments: vec![Argument::Named(( + Spanned { + item: "width".to_string(), + span: Span::unknown(), + }, + None, + Some(Expression::new_unknown( + Expr::Int(get_term_width() as i64 - 2), // padding, see below + Span::unknown(), + Type::Int, + )), + ))], + parser_info: HashMap::new(), + }, + PipelineData::Value(Value::list(vals, span), None), + ) { + if let Ok((str, ..)) = result.collect_string_strict(span) { + let _ = writeln!(long_desc, "\n{help_section_name}Input/output types{RESET}:"); + for line in str.lines() { + let _ = writeln!(long_desc, " {line}"); + } + } + } + } + } + + if !examples.is_empty() { + let _ = write!(long_desc, "\n{help_section_name}Examples{RESET}:"); + } + + for example in examples { + long_desc.push('\n'); + long_desc.push_str(" "); + long_desc.push_str(example.description); + + if !nu_config.use_ansi_coloring.get(engine_state) { + let _ = write!(long_desc, "\n > {}\n", example.example); + } else { + let code_string = nu_highlight_string(example.example, engine_state, stack); + let _ = write!(long_desc, "\n > {code_string}\n"); + }; + + if let Some(result) = &example.result { + let mut table_call = Call::new(Span::unknown()); + if example.example.ends_with("--collapse") { + // collapse the result + table_call.add_named(( + Spanned { + item: "collapse".to_string(), + span: Span::unknown(), + }, + None, + None, + )) + } else { + // expand the result + table_call.add_named(( + Spanned { + item: "expand".to_string(), + span: Span::unknown(), + }, + None, + None, + )) + } + table_call.add_named(( + Spanned { + item: "width".to_string(), + span: Span::unknown(), + }, + None, + Some(Expression::new_unknown( + Expr::Int(get_term_width() as i64 - 2), + Span::unknown(), + Type::Int, + )), + )); + + let table = engine_state + .find_decl("table".as_bytes(), &[]) + .and_then(|decl_id| { + engine_state + .get_decl(decl_id) + .run( + engine_state, + stack, + &(&table_call).into(), + PipelineData::Value(result.clone(), None), + ) + .ok() + }); + + for item in table.into_iter().flatten() { + let _ = writeln!( + long_desc, + " {}", + item.to_expanded_string("", &nu_config) + .replace('\n', "\n ") + .trim() + ); + } + } + } + + long_desc.push('\n'); + + if !nu_config.use_ansi_coloring.get(engine_state) { + nu_utils::strip_ansi_string_likely(long_desc) + } else { + long_desc + } +} + +fn update_ansi_from_config( + ansi_code: &mut String, + engine_state: &EngineState, + nu_config: &Config, + theme_component: &str, +) { + if let Some(color) = &nu_config.color_config.get(theme_component) { + let caller_stack = &mut Stack::new().collect_value(); + let span = Span::unknown(); + let span_id = UNKNOWN_SPAN_ID; + + let argument_opt = get_argument_for_color_value(nu_config, color, span, span_id); + + // Call ansi command using argument + if let Some(argument) = argument_opt { + if let Some(decl_id) = engine_state.find_decl(b"ansi", &[]) { + if let Ok(result) = eval_call::( + engine_state, + caller_stack, + &Call { + decl_id, + head: span, + arguments: vec![argument], + parser_info: HashMap::new(), + }, + PipelineData::Empty, + ) { + if let Ok((str, ..)) = result.collect_string_strict(span) { + *ansi_code = str; + } + } + } + } + } +} + +fn get_argument_for_color_value( + nu_config: &Config, + color: &Value, + span: Span, + span_id: SpanId, +) -> Option { + match color { + Value::Record { val, .. } => { + let record_exp: Vec = (**val) + .iter() + .map(|(k, v)| { + RecordItem::Pair( + Expression::new_existing( + Expr::String(k.clone()), + span, + span_id, + Type::String, + ), + Expression::new_existing( + Expr::String(v.clone().to_expanded_string("", nu_config)), + span, + span_id, + Type::String, + ), + ) + }) + .collect(); + + Some(Argument::Positional(Expression::new_existing( + Expr::Record(record_exp), + Span::unknown(), + UNKNOWN_SPAN_ID, + Type::Record( + [ + ("fg".to_string(), Type::String), + ("attr".to_string(), Type::String), + ] + .into(), + ), + ))) + } + Value::String { val, .. } => Some(Argument::Positional(Expression::new_existing( + Expr::String(val.clone()), + Span::unknown(), + UNKNOWN_SPAN_ID, + Type::String, + ))), + _ => None, + } +} + +/// Contains the settings for ANSI colors in help output +/// +/// By default contains a fixed set of (4-bit) colors +/// +/// Can reflect configuration using [`HelpStyle::update_from_config`] +pub struct HelpStyle { + section_name: String, + subcolor_one: String, + subcolor_two: String, +} + +impl Default for HelpStyle { + fn default() -> Self { + HelpStyle { + // default: green + section_name: "\x1b[32m".to_string(), + // default: cyan + subcolor_one: "\x1b[36m".to_string(), + // default: light blue + subcolor_two: "\x1b[94m".to_string(), + } + } +} + +impl HelpStyle { + /// Pull colors from the [`Config`] + /// + /// Uses some arbitrary `shape_*` settings, assuming they are well visible in the terminal theme. + /// + /// Implementation detail: currently executes `ansi` command internally thus requiring the + /// [`EngineState`] for execution. + /// See for details + pub fn update_from_config(&mut self, engine_state: &EngineState, nu_config: &Config) { + update_ansi_from_config( + &mut self.section_name, + engine_state, + nu_config, + "shape_string", + ); + update_ansi_from_config( + &mut self.subcolor_one, + engine_state, + nu_config, + "shape_external", + ); + update_ansi_from_config( + &mut self.subcolor_two, + engine_state, + nu_config, + "shape_block", + ); + } +} + +/// Make syntax shape presentable by stripping custom completer info +fn document_shape(shape: &SyntaxShape) -> &SyntaxShape { + match shape { + SyntaxShape::CompleterWrapper(inner_shape, _) => inner_shape, + _ => shape, + } +} + +#[derive(PartialEq)] +enum PositionalKind { + Required, + Optional, + Rest, +} + +fn write_positional( + long_desc: &mut String, + positional: &PositionalArg, + arg_kind: PositionalKind, + help_style: &HelpStyle, + nu_config: &Config, + engine_state: &EngineState, + stack: &mut Stack, +) { + let help_subcolor_one = &help_style.subcolor_one; + let help_subcolor_two = &help_style.subcolor_two; + + // Indentation + long_desc.push_str(" "); + if arg_kind == PositionalKind::Rest { + long_desc.push_str("..."); + } + match &positional.shape { + SyntaxShape::Keyword(kw, shape) => { + let _ = write!( + long_desc, + "{help_subcolor_one}\"{}\" + {RESET}<{help_subcolor_two}{}{RESET}>", + String::from_utf8_lossy(kw), + document_shape(shape), + ); + } + _ => { + let _ = write!( + long_desc, + "{help_subcolor_one}{}{RESET} <{help_subcolor_two}{}{RESET}>", + positional.name, + document_shape(&positional.shape), + ); + } + }; + if !positional.desc.is_empty() || arg_kind == PositionalKind::Optional { + let _ = write!(long_desc, ": {}", positional.desc); + } + if arg_kind == PositionalKind::Optional { + if let Some(value) = &positional.default_value { + let _ = write!( + long_desc, + " (optional, default: {})", + nu_highlight_string( + &value.to_parsable_string(", ", nu_config), + engine_state, + stack + ) + ); + } else { + long_desc.push_str(" (optional)"); + }; + } + long_desc.push('\n'); +} + +pub fn get_flags_section( + signature: &Signature, + help_style: &HelpStyle, + mut value_formatter: F, // format default Value (because some calls cant access config or nu-highlight) +) -> String +where + F: FnMut(&nu_protocol::Value) -> String, +{ + let help_section_name = &help_style.section_name; + let help_subcolor_one = &help_style.subcolor_one; + let help_subcolor_two = &help_style.subcolor_two; + + let mut long_desc = String::new(); + let _ = write!(long_desc, "\n{help_section_name}Flags{RESET}:\n"); + for flag in &signature.named { + // Indentation + long_desc.push_str(" "); + // Short flag shown before long flag + if let Some(short) = flag.short { + let _ = write!(long_desc, "{help_subcolor_one}-{}{RESET}", short); + if !flag.long.is_empty() { + let _ = write!(long_desc, "{DEFAULT_COLOR},{RESET} "); + } + } + if !flag.long.is_empty() { + let _ = write!(long_desc, "{help_subcolor_one}--{}{RESET}", flag.long); + } + if flag.required { + long_desc.push_str(" (required parameter)") + } + // Type/Syntax shape info + if let Some(arg) = &flag.arg { + let _ = write!( + long_desc, + " <{help_subcolor_two}{}{RESET}>", + document_shape(arg) + ); + } + if !flag.desc.is_empty() { + let _ = write!(long_desc, ": {}", flag.desc); + } + if let Some(value) = &flag.default_value { + let _ = write!(long_desc, " (default: {})", &value_formatter(value)); + } + long_desc.push('\n'); + } + long_desc +} diff --git a/nushell/crates/nu-engine/src/env.rs b/nushell/crates/nu-engine/src/env.rs new file mode 100644 index 0000000..e02d762 --- /dev/null +++ b/nushell/crates/nu-engine/src/env.rs @@ -0,0 +1,431 @@ +use crate::ClosureEvalOnce; +use nu_path::canonicalize_with; +use nu_protocol::{ + ShellError, Span, Type, Value, VarId, + ast::Expr, + engine::{Call, EngineState, Stack, StateWorkingSet}, + shell_error::io::{IoError, IoErrorExt, NotFound}, +}; +use std::{ + collections::HashMap, + path::{Path, PathBuf}, + sync::Arc, +}; + +pub const ENV_CONVERSIONS: &str = "ENV_CONVERSIONS"; + +enum ConversionError { + ShellError(ShellError), + CellPathError, +} + +impl From for ConversionError { + fn from(value: ShellError) -> Self { + Self::ShellError(value) + } +} + +/// Translate environment variables from Strings to Values. +pub fn convert_env_vars( + stack: &mut Stack, + engine_state: &EngineState, + conversions: &Value, +) -> Result<(), ShellError> { + let conversions = conversions.as_record()?; + for (key, conversion) in conversions.into_iter() { + if let Some((case_preserve_env_name, val)) = + stack.get_env_var_insensitive(engine_state, key) + { + match val.get_type() { + Type::String => {} + _ => continue, + } + + let conversion = conversion + .as_record()? + .get("from_string") + .ok_or(ShellError::MissingRequiredColumn { + column: "from_string", + span: conversion.span(), + })? + .as_closure()?; + + let new_val = ClosureEvalOnce::new(engine_state, stack, conversion.clone()) + .debug(false) + .run_with_value(val.clone())? + .into_value(val.span())?; + + stack.add_env_var(case_preserve_env_name.to_string(), new_val); + } + } + Ok(()) +} + +/// Translate environment variables from Strings to Values. Requires config to be already set up in +/// case the user defined custom env conversions in config.nu. +/// +/// It returns Option instead of Result since we do want to translate all the values we can and +/// skip errors. This function is called in the main() so we want to keep running, we cannot just +/// exit. +pub fn convert_env_values( + engine_state: &mut EngineState, + stack: &mut Stack, +) -> Result<(), ShellError> { + let mut error = None; + + let mut new_scope = HashMap::new(); + + let env_vars = engine_state.render_env_vars(); + + for (name, val) in env_vars { + if let Value::String { .. } = val { + // Only run from_string on string values + match get_converted_value(engine_state, stack, name, val, "from_string") { + Ok(v) => { + let _ = new_scope.insert(name.to_string(), v); + } + Err(ConversionError::ShellError(e)) => error = error.or(Some(e)), + Err(ConversionError::CellPathError) => { + let _ = new_scope.insert(name.to_string(), val.clone()); + } + } + } else { + // Skip values that are already converted (not a string) + let _ = new_scope.insert(name.to_string(), val.clone()); + } + } + + error = error.or_else(|| ensure_path(engine_state, stack)); + + if let Ok(last_overlay_name) = &stack.last_overlay_name() { + if let Some(env_vars) = Arc::make_mut(&mut engine_state.env_vars).get_mut(last_overlay_name) + { + for (k, v) in new_scope { + env_vars.insert(k, v); + } + } else { + error = error.or_else(|| { + Some(ShellError::NushellFailedHelp { msg: "Last active overlay not found in permanent state.".into(), help: "This error happened during the conversion of environment variables from strings to Nushell values.".into() }) + }); + } + } else { + error = error.or_else(|| { + Some(ShellError::NushellFailedHelp { msg: "Last active overlay not found in stack.".into(), help: "This error happened during the conversion of environment variables from strings to Nushell values.".into() }) + }); + } + + if let Some(err) = error { + Err(err) + } else { + Ok(()) + } +} + +/// Translate one environment variable from Value to String +/// +/// Returns Ok(None) if the env var is not +pub fn env_to_string( + env_name: &str, + value: &Value, + engine_state: &EngineState, + stack: &Stack, +) -> Result { + match get_converted_value(engine_state, stack, env_name, value, "to_string") { + Ok(v) => Ok(v.coerce_into_string()?), + Err(ConversionError::ShellError(e)) => Err(e), + Err(ConversionError::CellPathError) => match value.coerce_string() { + Ok(s) => Ok(s), + Err(_) => { + if env_name.to_lowercase() == "path" { + // Try to convert PATH/Path list to a string + match value { + Value::List { vals, .. } => { + let paths: Vec = vals + .iter() + .filter_map(|v| v.coerce_str().ok()) + .map(|s| nu_path::expand_tilde(&*s).to_string_lossy().into_owned()) + .collect(); + + std::env::join_paths(paths.iter().map(AsRef::::as_ref)) + .map(|p| p.to_string_lossy().to_string()) + .map_err(|_| ShellError::EnvVarNotAString { + envvar_name: env_name.to_string(), + span: value.span(), + }) + } + _ => Err(ShellError::EnvVarNotAString { + envvar_name: env_name.to_string(), + span: value.span(), + }), + } + } else { + Err(ShellError::EnvVarNotAString { + envvar_name: env_name.to_string(), + span: value.span(), + }) + } + } + }, + } +} + +/// Translate all environment variables from Values to Strings +pub fn env_to_strings( + engine_state: &EngineState, + stack: &Stack, +) -> Result, ShellError> { + let env_vars = stack.get_env_vars(engine_state); + let mut env_vars_str = HashMap::new(); + for (env_name, val) in env_vars { + match env_to_string(&env_name, &val, engine_state, stack) { + Ok(val_str) => { + env_vars_str.insert(env_name, val_str); + } + Err(ShellError::EnvVarNotAString { .. }) => {} // ignore non-string values + Err(e) => return Err(e), + } + } + + Ok(env_vars_str) +} + +/// Returns the current working directory as a String, which is guaranteed to be canonicalized. +/// Unlike `current_dir_str_const()`, this also considers modifications to the current working directory made on the stack. +/// +/// Returns an error if $env.PWD doesn't exist, is not a String, or is not an absolute path. +#[deprecated(since = "0.92.3", note = "please use `EngineState::cwd()` instead")] +pub fn current_dir_str(engine_state: &EngineState, stack: &Stack) -> Result { + #[allow(deprecated)] + current_dir(engine_state, stack).map(|path| path.to_string_lossy().to_string()) +} + +/// Returns the current working directory as a String, which is guaranteed to be canonicalized. +/// +/// Returns an error if $env.PWD doesn't exist, is not a String, or is not an absolute path. +#[deprecated(since = "0.92.3", note = "please use `EngineState::cwd()` instead")] +pub fn current_dir_str_const(working_set: &StateWorkingSet) -> Result { + #[allow(deprecated)] + current_dir_const(working_set).map(|path| path.to_string_lossy().to_string()) +} + +/// Returns the current working directory, which is guaranteed to be canonicalized. +/// Unlike `current_dir_const()`, this also considers modifications to the current working directory made on the stack. +/// +/// Returns an error if $env.PWD doesn't exist, is not a String, or is not an absolute path. +#[deprecated(since = "0.92.3", note = "please use `EngineState::cwd()` instead")] +pub fn current_dir(engine_state: &EngineState, stack: &Stack) -> Result { + let cwd = engine_state.cwd(Some(stack))?; + // `EngineState::cwd()` always returns absolute path. + // We're using `canonicalize_with` instead of `fs::canonicalize()` because + // we still need to simplify Windows paths. "." is safe because `cwd` should + // be an absolute path already. + canonicalize_with(&cwd, ".").map_err(|err| { + ShellError::Io(IoError::new_internal_with_path( + err.not_found_as(NotFound::Directory), + "Could not canonicalize current dir", + nu_protocol::location!(), + PathBuf::from(cwd), + )) + }) +} + +/// Returns the current working directory, which is guaranteed to be canonicalized. +/// +/// Returns an error if $env.PWD doesn't exist, is not a String, or is not an absolute path. +#[deprecated(since = "0.92.3", note = "please use `EngineState::cwd()` instead")] +pub fn current_dir_const(working_set: &StateWorkingSet) -> Result { + let cwd = working_set.permanent_state.cwd(None)?; + // `EngineState::cwd()` always returns absolute path. + // We're using `canonicalize_with` instead of `fs::canonicalize()` because + // we still need to simplify Windows paths. "." is safe because `cwd` should + // be an absolute path already. + canonicalize_with(&cwd, ".").map_err(|err| { + ShellError::Io(IoError::new_internal_with_path( + err.not_found_as(NotFound::Directory), + "Could not canonicalize current dir", + nu_protocol::location!(), + PathBuf::from(cwd), + )) + }) +} + +/// Get the contents of path environment variable as a list of strings +pub fn path_str( + engine_state: &EngineState, + stack: &Stack, + span: Span, +) -> Result { + let (pathname, pathval) = match stack.get_env_var_insensitive(engine_state, "path") { + Some((_, v)) => Ok((if cfg!(windows) { "Path" } else { "PATH" }, v)), + None => Err(ShellError::EnvVarNotFoundAtRuntime { + envvar_name: if cfg!(windows) { + "Path".to_string() + } else { + "PATH".to_string() + }, + span, + }), + }?; + + env_to_string(pathname, pathval, engine_state, stack) +} + +pub const DIR_VAR_PARSER_INFO: &str = "dirs_var"; +pub fn get_dirs_var_from_call(stack: &Stack, call: &Call) -> Option { + call.get_parser_info(stack, DIR_VAR_PARSER_INFO) + .and_then(|x| { + if let Expr::Var(id) = x.expr { + Some(id) + } else { + None + } + }) +} + +/// This helper function is used to find files during eval +/// +/// First, the actual current working directory is selected as +/// a) the directory of a file currently being parsed +/// b) current working directory (PWD) +/// +/// Then, if the file is not found in the actual cwd, NU_LIB_DIRS is checked. +/// If there is a relative path in NU_LIB_DIRS, it is assumed to be relative to the actual cwd +/// determined in the first step. +/// +/// Always returns an absolute path +pub fn find_in_dirs_env( + filename: &str, + engine_state: &EngineState, + stack: &Stack, + dirs_var: Option, +) -> Result, ShellError> { + // Choose whether to use file-relative or PWD-relative path + let cwd = if let Some(pwd) = stack.get_env_var(engine_state, "FILE_PWD") { + match env_to_string("FILE_PWD", pwd, engine_state, stack) { + Ok(cwd) => { + if Path::new(&cwd).is_absolute() { + cwd + } else { + return Err(ShellError::GenericError { + error: "Invalid current directory".into(), + msg: format!( + "The 'FILE_PWD' environment variable must be set to an absolute path. Found: '{cwd}'" + ), + span: Some(pwd.span()), + help: None, + inner: vec![], + }); + } + } + Err(e) => return Err(e), + } + } else { + engine_state.cwd_as_string(Some(stack))? + }; + + let check_dir = |lib_dirs: Option<&Value>| -> Option { + if let Ok(p) = canonicalize_with(filename, &cwd) { + return Some(p); + } + let path = Path::new(filename); + if !path.is_relative() { + return None; + } + + lib_dirs? + .as_list() + .ok()? + .iter() + .map(|lib_dir| -> Option { + let dir = lib_dir.to_path().ok()?; + let dir_abs = canonicalize_with(dir, &cwd).ok()?; + canonicalize_with(filename, dir_abs).ok() + }) + .find(Option::is_some) + .flatten() + }; + + let lib_dirs = dirs_var.and_then(|var_id| engine_state.get_var(var_id).const_val.as_ref()); + // TODO: remove (see #8310) + let lib_dirs_fallback = stack.get_env_var(engine_state, "NU_LIB_DIRS"); + + Ok(check_dir(lib_dirs).or_else(|| check_dir(lib_dirs_fallback))) +} + +fn get_converted_value( + engine_state: &EngineState, + stack: &Stack, + name: &str, + orig_val: &Value, + direction: &str, +) -> Result { + let conversion = stack + .get_env_var(engine_state, ENV_CONVERSIONS) + .ok_or(ConversionError::CellPathError)? + .as_record()? + .get(name) + .ok_or(ConversionError::CellPathError)? + .as_record()? + .get(direction) + .ok_or(ConversionError::CellPathError)? + .as_closure()?; + + Ok( + ClosureEvalOnce::new(engine_state, stack, conversion.clone()) + .debug(false) + .run_with_value(orig_val.clone())? + .into_value(orig_val.span())?, + ) +} + +fn ensure_path(engine_state: &EngineState, stack: &mut Stack) -> Option { + let mut error = None; + + // If PATH/Path is still a string, force-convert it to a list + if let Some((preserve_case_name, value)) = stack.get_env_var_insensitive(engine_state, "Path") { + let span = value.span(); + match value { + Value::String { val, .. } => { + // Force-split path into a list + let paths = std::env::split_paths(val) + .map(|p| Value::string(p.to_string_lossy().to_string(), span)) + .collect(); + + stack.add_env_var(preserve_case_name.to_string(), Value::list(paths, span)); + } + Value::List { vals, .. } => { + // Must be a list of strings + if !vals.iter().all(|v| matches!(v, Value::String { .. })) { + error = error.or_else(|| { + Some(ShellError::GenericError { + error: format!( + "Incorrect {preserve_case_name} environment variable value" + ), + msg: format!("{preserve_case_name} must be a list of strings"), + span: Some(span), + help: None, + inner: vec![], + }) + }); + } + } + + val => { + // All other values are errors + let span = val.span(); + + error = error.or_else(|| { + Some(ShellError::GenericError { + error: format!("Incorrect {preserve_case_name} environment variable value"), + msg: format!("{preserve_case_name} must be a list of strings"), + span: Some(span), + help: None, + inner: vec![], + }) + }); + } + } + } + + error +} diff --git a/nushell/crates/nu-engine/src/eval.rs b/nushell/crates/nu-engine/src/eval.rs new file mode 100644 index 0000000..6fecf9d --- /dev/null +++ b/nushell/crates/nu-engine/src/eval.rs @@ -0,0 +1,651 @@ +use crate::eval_ir_block; +#[allow(deprecated)] +use crate::get_full_help; +use nu_protocol::{ + BlockId, Config, DataSource, ENV_VARIABLE_ID, IntoPipelineData, PipelineData, PipelineMetadata, + ShellError, Span, Value, VarId, + ast::{Assignment, Block, Call, Expr, Expression, ExternalArgument, PathMember}, + debugger::DebugContext, + engine::{Closure, EngineState, Stack}, + eval_base::Eval, +}; +use nu_utils::IgnoreCaseExt; +use std::sync::Arc; + +pub fn eval_call( + engine_state: &EngineState, + caller_stack: &mut Stack, + call: &Call, + input: PipelineData, +) -> Result { + engine_state.signals().check(call.head)?; + let decl = engine_state.get_decl(call.decl_id); + + if !decl.is_known_external() && call.named_iter().any(|(flag, _, _)| flag.item == "help") { + let help = get_full_help(decl, engine_state, caller_stack); + Ok(Value::string(help, call.head).into_pipeline_data()) + } else if let Some(block_id) = decl.block_id() { + let block = engine_state.get_block(block_id); + + let mut callee_stack = caller_stack.gather_captures(engine_state, &block.captures); + + // Rust does not check recursion limits outside of const evaluation. + // But nu programs run in the same process as the shell. + // To prevent a stack overflow in user code from crashing the shell, + // we limit the recursion depth of function calls. + // Picked 50 arbitrarily, should work on all architectures. + let maximum_call_stack_depth: u64 = engine_state.config.recursion_limit as u64; + callee_stack.recursion_count += 1; + if callee_stack.recursion_count > maximum_call_stack_depth { + callee_stack.recursion_count = 0; + return Err(ShellError::RecursionLimitReached { + recursion_limit: maximum_call_stack_depth, + span: block.span, + }); + } + + for (param_idx, (param, required)) in decl + .signature() + .required_positional + .iter() + .map(|p| (p, true)) + .chain( + decl.signature() + .optional_positional + .iter() + .map(|p| (p, false)), + ) + .enumerate() + { + let var_id = param + .var_id + .expect("internal error: all custom parameters must have var_ids"); + + if let Some(arg) = call.positional_nth(param_idx) { + let result = eval_expression::(engine_state, caller_stack, arg)?; + let param_type = param.shape.to_type(); + if required && !result.is_subtype_of(¶m_type) { + return Err(ShellError::CantConvert { + to_type: param.shape.to_type().to_string(), + from_type: result.get_type().to_string(), + span: result.span(), + help: None, + }); + } + callee_stack.add_var(var_id, result); + } else if let Some(value) = ¶m.default_value { + callee_stack.add_var(var_id, value.to_owned()); + } else { + callee_stack.add_var(var_id, Value::nothing(call.head)); + } + } + + if let Some(rest_positional) = decl.signature().rest_positional { + let mut rest_items = vec![]; + + for result in call.rest_iter_flattened( + decl.signature().required_positional.len() + + decl.signature().optional_positional.len(), + |expr| eval_expression::(engine_state, caller_stack, expr), + )? { + rest_items.push(result); + } + + let span = if let Some(rest_item) = rest_items.first() { + rest_item.span() + } else { + call.head + }; + + callee_stack.add_var( + rest_positional + .var_id + .expect("Internal error: rest positional parameter lacks var_id"), + Value::list(rest_items, span), + ) + } + + for named in decl.signature().named { + if let Some(var_id) = named.var_id { + let mut found = false; + for call_named in call.named_iter() { + if let (Some(spanned), Some(short)) = (&call_named.1, named.short) { + if spanned.item == short.to_string() { + if let Some(arg) = &call_named.2 { + let result = eval_expression::(engine_state, caller_stack, arg)?; + + callee_stack.add_var(var_id, result); + } else if let Some(value) = &named.default_value { + callee_stack.add_var(var_id, value.to_owned()); + } else { + callee_stack.add_var(var_id, Value::bool(true, call.head)) + } + found = true; + } + } else if call_named.0.item == named.long { + if let Some(arg) = &call_named.2 { + let result = eval_expression::(engine_state, caller_stack, arg)?; + + callee_stack.add_var(var_id, result); + } else if let Some(value) = &named.default_value { + callee_stack.add_var(var_id, value.to_owned()); + } else { + callee_stack.add_var(var_id, Value::bool(true, call.head)) + } + found = true; + } + } + + if !found { + if named.arg.is_none() { + callee_stack.add_var(var_id, Value::bool(false, call.head)) + } else if let Some(value) = named.default_value { + callee_stack.add_var(var_id, value); + } else { + callee_stack.add_var(var_id, Value::nothing(call.head)) + } + } + } + } + + let result = + eval_block_with_early_return::(engine_state, &mut callee_stack, block, input); + + if block.redirect_env { + redirect_env(engine_state, caller_stack, &callee_stack); + } + + result + } else { + // We pass caller_stack here with the knowledge that internal commands + // are going to be specifically looking for global state in the stack + // rather than any local state. + decl.run(engine_state, caller_stack, &call.into(), input) + } +} + +/// Redirect the environment from callee to the caller. +pub fn redirect_env(engine_state: &EngineState, caller_stack: &mut Stack, callee_stack: &Stack) { + // Grab all environment variables from the callee + let caller_env_vars = caller_stack.get_env_var_names(engine_state); + + // remove env vars that are present in the caller but not in the callee + // (the callee hid them) + for var in caller_env_vars.iter() { + if !callee_stack.has_env_var(engine_state, var) { + caller_stack.remove_env_var(engine_state, var); + } + } + + // add new env vars from callee to caller + for (var, value) in callee_stack.get_stack_env_vars() { + caller_stack.add_env_var(var, value); + } + + // set config to callee config, to capture any updates to that + caller_stack.config.clone_from(&callee_stack.config); +} + +fn eval_external( + engine_state: &EngineState, + stack: &mut Stack, + head: &Expression, + args: &[ExternalArgument], + input: PipelineData, +) -> Result { + let decl_id = engine_state + .find_decl("run-external".as_bytes(), &[]) + .ok_or(ShellError::ExternalNotSupported { + span: head.span(&engine_state), + })?; + + let command = engine_state.get_decl(decl_id); + + let mut call = Call::new(head.span(&engine_state)); + + call.add_positional(head.clone()); + + for arg in args { + match arg { + ExternalArgument::Regular(expr) => call.add_positional(expr.clone()), + ExternalArgument::Spread(expr) => call.add_spread(expr.clone()), + } + } + + command.run(engine_state, stack, &(&call).into(), input) +} + +pub fn eval_expression( + engine_state: &EngineState, + stack: &mut Stack, + expr: &Expression, +) -> Result { + let stack = &mut stack.start_collect_value(); + ::eval::(engine_state, stack, expr) +} + +/// Checks the expression to see if it's a internal or external call. If so, passes the input +/// into the call and gets out the result +/// Otherwise, invokes the expression +/// +/// It returns PipelineData with a boolean flag, indicating if the external failed to run. +/// The boolean flag **may only be true** for external calls, for internal calls, it always to be false. +pub fn eval_expression_with_input( + engine_state: &EngineState, + stack: &mut Stack, + expr: &Expression, + mut input: PipelineData, +) -> Result { + match &expr.expr { + Expr::Call(call) => { + input = eval_call::(engine_state, stack, call, input)?; + } + Expr::ExternalCall(head, args) => { + input = eval_external(engine_state, stack, head, args, input)?; + } + + Expr::Collect(var_id, expr) => { + input = eval_collect::(engine_state, stack, *var_id, expr, input)?; + } + + Expr::Subexpression(block_id) => { + let block = engine_state.get_block(*block_id); + // FIXME: protect this collect with ctrl-c + input = eval_subexpression::(engine_state, stack, block, input)?; + } + + Expr::FullCellPath(full_cell_path) => match &full_cell_path.head { + Expression { + expr: Expr::Subexpression(block_id), + span, + .. + } => { + let block = engine_state.get_block(*block_id); + + if !full_cell_path.tail.is_empty() { + let stack = &mut stack.start_collect_value(); + // FIXME: protect this collect with ctrl-c + input = eval_subexpression::(engine_state, stack, block, input)? + .into_value(*span)? + .follow_cell_path(&full_cell_path.tail)? + .into_owned() + .into_pipeline_data() + } else { + input = eval_subexpression::(engine_state, stack, block, input)?; + } + } + _ => { + input = eval_expression::(engine_state, stack, expr)?.into_pipeline_data(); + } + }, + + _ => { + input = eval_expression::(engine_state, stack, expr)?.into_pipeline_data(); + } + }; + + Ok(input) +} + +pub fn eval_block_with_early_return( + engine_state: &EngineState, + stack: &mut Stack, + block: &Block, + input: PipelineData, +) -> Result { + match eval_block::(engine_state, stack, block, input) { + Err(ShellError::Return { span: _, value }) => Ok(PipelineData::Value(*value, None)), + x => x, + } +} + +pub fn eval_block( + engine_state: &EngineState, + stack: &mut Stack, + block: &Block, + input: PipelineData, +) -> Result { + let result = eval_ir_block::(engine_state, stack, block, input); + if let Err(err) = &result { + stack.set_last_error(err); + } + result +} + +pub fn eval_collect( + engine_state: &EngineState, + stack: &mut Stack, + var_id: VarId, + expr: &Expression, + input: PipelineData, +) -> Result { + // Evaluate the expression with the variable set to the collected input + let span = input.span().unwrap_or(Span::unknown()); + + let metadata = match input.metadata() { + // Remove the `FilePath` metadata, because after `collect` it's no longer necessary to + // check where some input came from. + Some(PipelineMetadata { + data_source: DataSource::FilePath(_), + content_type: None, + }) => None, + other => other, + }; + + let input = input.into_value(span)?; + + stack.add_var(var_id, input.clone()); + + let result = eval_expression_with_input::( + engine_state, + stack, + expr, + // We still have to pass it as input + input.into_pipeline_data_with_metadata(metadata), + ); + + stack.remove_var(var_id); + + result +} + +pub fn eval_subexpression( + engine_state: &EngineState, + stack: &mut Stack, + block: &Block, + input: PipelineData, +) -> Result { + eval_block::(engine_state, stack, block, input) +} + +pub fn eval_variable( + engine_state: &EngineState, + stack: &Stack, + var_id: VarId, + span: Span, +) -> Result { + match var_id { + // $nu + nu_protocol::NU_VARIABLE_ID => { + if let Some(val) = engine_state.get_constant(var_id) { + Ok(val.clone()) + } else { + Err(ShellError::VariableNotFoundAtRuntime { span }) + } + } + // $env + ENV_VARIABLE_ID => { + let env_vars = stack.get_env_vars(engine_state); + let env_columns = env_vars.keys(); + let env_values = env_vars.values(); + + let mut pairs = env_columns + .map(|x| x.to_string()) + .zip(env_values.cloned()) + .collect::>(); + + pairs.sort_by(|a, b| a.0.cmp(&b.0)); + + Ok(Value::record(pairs.into_iter().collect(), span)) + } + var_id => stack.get_var(var_id, span), + } +} + +struct EvalRuntime; + +impl Eval for EvalRuntime { + type State<'a> = &'a EngineState; + + type MutState = Stack; + + fn get_config(engine_state: Self::State<'_>, stack: &mut Stack) -> Arc { + stack.get_config(engine_state) + } + + fn eval_var( + engine_state: &EngineState, + stack: &mut Stack, + var_id: VarId, + span: Span, + ) -> Result { + eval_variable(engine_state, stack, var_id, span) + } + + fn eval_call( + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _: Span, + ) -> Result { + // FIXME: protect this collect with ctrl-c + eval_call::(engine_state, stack, call, PipelineData::empty())?.into_value(call.head) + } + + fn eval_external_call( + engine_state: &EngineState, + stack: &mut Stack, + head: &Expression, + args: &[ExternalArgument], + _: Span, + ) -> Result { + let span = head.span(&engine_state); + // FIXME: protect this collect with ctrl-c + eval_external(engine_state, stack, head, args, PipelineData::empty())?.into_value(span) + } + + fn eval_collect( + engine_state: &EngineState, + stack: &mut Stack, + var_id: VarId, + expr: &Expression, + ) -> Result { + // It's a little bizarre, but the expression can still have some kind of result even with + // nothing input + eval_collect::(engine_state, stack, var_id, expr, PipelineData::empty())? + .into_value(expr.span) + } + + fn eval_subexpression( + engine_state: &EngineState, + stack: &mut Stack, + block_id: BlockId, + span: Span, + ) -> Result { + let block = engine_state.get_block(block_id); + // FIXME: protect this collect with ctrl-c + eval_subexpression::(engine_state, stack, block, PipelineData::empty())?.into_value(span) + } + + fn regex_match( + engine_state: &EngineState, + op_span: Span, + lhs: &Value, + rhs: &Value, + invert: bool, + expr_span: Span, + ) -> Result { + lhs.regex_match(engine_state, op_span, rhs, invert, expr_span) + } + + fn eval_assignment( + engine_state: &EngineState, + stack: &mut Stack, + lhs: &Expression, + rhs: &Expression, + assignment: Assignment, + op_span: Span, + _expr_span: Span, + ) -> Result { + let rhs = eval_expression::(engine_state, stack, rhs)?; + + let rhs = match assignment { + Assignment::Assign => rhs, + Assignment::AddAssign => { + let lhs = eval_expression::(engine_state, stack, lhs)?; + lhs.add(op_span, &rhs, op_span)? + } + Assignment::SubtractAssign => { + let lhs = eval_expression::(engine_state, stack, lhs)?; + lhs.sub(op_span, &rhs, op_span)? + } + Assignment::MultiplyAssign => { + let lhs = eval_expression::(engine_state, stack, lhs)?; + lhs.mul(op_span, &rhs, op_span)? + } + Assignment::DivideAssign => { + let lhs = eval_expression::(engine_state, stack, lhs)?; + lhs.div(op_span, &rhs, op_span)? + } + Assignment::ConcatenateAssign => { + let lhs = eval_expression::(engine_state, stack, lhs)?; + lhs.concat(op_span, &rhs, op_span)? + } + }; + + match &lhs.expr { + Expr::Var(var_id) | Expr::VarDecl(var_id) => { + let var_info = engine_state.get_var(*var_id); + if var_info.mutable { + stack.add_var(*var_id, rhs); + Ok(Value::nothing(lhs.span(&engine_state))) + } else { + Err(ShellError::AssignmentRequiresMutableVar { + lhs_span: lhs.span(&engine_state), + }) + } + } + Expr::FullCellPath(cell_path) => { + match &cell_path.head.expr { + Expr::Var(var_id) | Expr::VarDecl(var_id) => { + // The $env variable is considered "mutable" in Nushell. + // As such, give it special treatment here. + let is_env = var_id == &ENV_VARIABLE_ID; + if is_env || engine_state.get_var(*var_id).mutable { + let mut lhs = + eval_expression::(engine_state, stack, &cell_path.head)?; + if is_env { + // Reject attempts to assign to the entire $env + if cell_path.tail.is_empty() { + return Err(ShellError::CannotReplaceEnv { + span: cell_path.head.span(&engine_state), + }); + } + + // Updating environment variables should be case-preserving, + // so we need to figure out the original key before we do anything. + let (key, span) = match &cell_path.tail[0] { + PathMember::String { val, span, .. } => (val.to_string(), span), + PathMember::Int { val, span, .. } => (val.to_string(), span), + }; + let original_key = if let Value::Record { val: record, .. } = &lhs { + record + .iter() + .rev() + .map(|(k, _)| k) + .find(|x| x.eq_ignore_case(&key)) + .cloned() + .unwrap_or(key) + } else { + key + }; + + // Retrieve the updated environment value. + lhs.upsert_data_at_cell_path(&cell_path.tail, rhs)?; + let value = lhs.follow_cell_path(&[{ + let mut pm = cell_path.tail[0].clone(); + pm.make_insensitive(); + pm + }])?; + + // Reject attempts to set automatic environment variables. + if is_automatic_env_var(&original_key) { + return Err(ShellError::AutomaticEnvVarSetManually { + envvar_name: original_key, + span: *span, + }); + } + + let is_config = original_key == "config"; + + stack.add_env_var(original_key, value.into_owned()); + + // Trigger the update to config, if we modified that. + if is_config { + stack.update_config(engine_state)?; + } + } else { + lhs.upsert_data_at_cell_path(&cell_path.tail, rhs)?; + stack.add_var(*var_id, lhs); + } + Ok(Value::nothing(cell_path.head.span(&engine_state))) + } else { + Err(ShellError::AssignmentRequiresMutableVar { + lhs_span: lhs.span(&engine_state), + }) + } + } + _ => Err(ShellError::AssignmentRequiresVar { + lhs_span: lhs.span(&engine_state), + }), + } + } + _ => Err(ShellError::AssignmentRequiresVar { + lhs_span: lhs.span(&engine_state), + }), + } + } + + fn eval_row_condition_or_closure( + engine_state: &EngineState, + stack: &mut Stack, + block_id: BlockId, + span: Span, + ) -> Result { + let captures = engine_state + .get_block(block_id) + .captures + .iter() + .map(|(id, span)| { + stack + .get_var(*id, *span) + .or_else(|_| { + engine_state + .get_var(*id) + .const_val + .clone() + .ok_or(ShellError::VariableNotFoundAtRuntime { span: *span }) + }) + .map(|var| (*id, var)) + }) + .collect::>()?; + + Ok(Value::closure(Closure { block_id, captures }, span)) + } + + fn eval_overlay(engine_state: &EngineState, span: Span) -> Result { + let name = String::from_utf8_lossy(engine_state.get_span_contents(span)).to_string(); + + Ok(Value::string(name, span)) + } + + fn unreachable(engine_state: &EngineState, expr: &Expression) -> Result { + Ok(Value::nothing(expr.span(&engine_state))) + } +} + +/// Returns whether a string, when used as the name of an environment variable, +/// is considered an automatic environment variable. +/// +/// An automatic environment variable cannot be assigned to by user code. +/// Current there are three of them: $env.PWD, $env.FILE_PWD, $env.CURRENT_FILE +pub(crate) fn is_automatic_env_var(var: &str) -> bool { + let names = ["PWD", "FILE_PWD", "CURRENT_FILE"]; + names.iter().any(|&name| { + if cfg!(windows) { + name.eq_ignore_case(var) + } else { + name.eq(var) + } + }) +} diff --git a/nushell/crates/nu-engine/src/eval_helpers.rs b/nushell/crates/nu-engine/src/eval_helpers.rs new file mode 100644 index 0000000..92b74d4 --- /dev/null +++ b/nushell/crates/nu-engine/src/eval_helpers.rs @@ -0,0 +1,93 @@ +use crate::{ + eval_block, eval_block_with_early_return, eval_expression, eval_expression_with_input, + eval_ir_block, eval_subexpression, +}; +use nu_protocol::{ + PipelineData, ShellError, Value, + ast::{Block, Expression}, + debugger::{WithDebug, WithoutDebug}, + engine::{EngineState, Stack}, +}; + +/// Type of eval_block() function +pub type EvalBlockFn = + fn(&EngineState, &mut Stack, &Block, PipelineData) -> Result; + +/// Type of eval_ir_block() function +pub type EvalIrBlockFn = + fn(&EngineState, &mut Stack, &Block, PipelineData) -> Result; + +/// Type of eval_block_with_early_return() function +pub type EvalBlockWithEarlyReturnFn = + fn(&EngineState, &mut Stack, &Block, PipelineData) -> Result; + +/// Type of eval_expression() function +pub type EvalExpressionFn = fn(&EngineState, &mut Stack, &Expression) -> Result; + +/// Type of eval_expression_with_input() function +pub type EvalExpressionWithInputFn = + fn(&EngineState, &mut Stack, &Expression, PipelineData) -> Result; + +/// Type of eval_subexpression() function +pub type EvalSubexpressionFn = + fn(&EngineState, &mut Stack, &Block, PipelineData) -> Result; + +/// Helper function to fetch `eval_block()` with the correct type parameter based on whether +/// engine_state is configured with or without a debugger. +pub fn get_eval_block(engine_state: &EngineState) -> EvalBlockFn { + if engine_state.is_debugging() { + eval_block:: + } else { + eval_block:: + } +} + +/// Helper function to fetch `eval_ir_block()` with the correct type parameter based on whether +/// engine_state is configured with or without a debugger. +pub fn get_eval_ir_block(engine_state: &EngineState) -> EvalIrBlockFn { + if engine_state.is_debugging() { + eval_ir_block:: + } else { + eval_ir_block:: + } +} + +/// Helper function to fetch `eval_block_with_early_return()` with the correct type parameter based +/// on whether engine_state is configured with or without a debugger. +pub fn get_eval_block_with_early_return(engine_state: &EngineState) -> EvalBlockWithEarlyReturnFn { + if engine_state.is_debugging() { + eval_block_with_early_return:: + } else { + eval_block_with_early_return:: + } +} + +/// Helper function to fetch `eval_expression()` with the correct type parameter based on whether +/// engine_state is configured with or without a debugger. +pub fn get_eval_expression(engine_state: &EngineState) -> EvalExpressionFn { + if engine_state.is_debugging() { + eval_expression:: + } else { + eval_expression:: + } +} + +/// Helper function to fetch `eval_expression_with_input()` with the correct type parameter based +/// on whether engine_state is configured with or without a debugger. +pub fn get_eval_expression_with_input(engine_state: &EngineState) -> EvalExpressionWithInputFn { + if engine_state.is_debugging() { + eval_expression_with_input:: + } else { + eval_expression_with_input:: + } +} + +/// Helper function to fetch `eval_subexpression()` with the correct type parameter based on whether +/// engine_state is configured with or without a debugger. +pub fn get_eval_subexpression(engine_state: &EngineState) -> EvalSubexpressionFn { + if engine_state.is_debugging() { + eval_subexpression:: + } else { + eval_subexpression:: + } +} diff --git a/nushell/crates/nu-engine/src/eval_ir.rs b/nushell/crates/nu-engine/src/eval_ir.rs new file mode 100644 index 0000000..b3c6d0d --- /dev/null +++ b/nushell/crates/nu-engine/src/eval_ir.rs @@ -0,0 +1,1616 @@ +use std::{borrow::Cow, fs::File, sync::Arc}; + +use nu_path::{expand_path, expand_path_with}; +use nu_protocol::{ + DataSource, DeclId, ENV_VARIABLE_ID, Flag, IntoPipelineData, IntoSpanned, ListStream, OutDest, + PipelineData, PipelineMetadata, PositionalArg, Range, Record, RegId, ShellError, Signals, + Signature, Span, Spanned, Type, Value, VarId, + ast::{Bits, Block, Boolean, CellPath, Comparison, Math, Operator}, + debugger::DebugContext, + engine::{ + Argument, Closure, EngineState, ErrorHandler, Matcher, Redirection, Stack, StateWorkingSet, + }, + ir::{Call, DataSlice, Instruction, IrAstRef, IrBlock, Literal, RedirectMode}, + shell_error::io::IoError, +}; +use nu_utils::IgnoreCaseExt; + +use crate::{ + ENV_CONVERSIONS, convert_env_vars, eval::is_automatic_env_var, eval_block_with_early_return, +}; + +/// Evaluate the compiled representation of a [`Block`]. +pub fn eval_ir_block( + engine_state: &EngineState, + stack: &mut Stack, + block: &Block, + input: PipelineData, +) -> Result { + // Rust does not check recursion limits outside of const evaluation. + // But nu programs run in the same process as the shell. + // To prevent a stack overflow in user code from crashing the shell, + // we limit the recursion depth of function calls. + let maximum_call_stack_depth: u64 = engine_state.config.recursion_limit as u64; + if stack.recursion_count > maximum_call_stack_depth { + return Err(ShellError::RecursionLimitReached { + recursion_limit: maximum_call_stack_depth, + span: block.span, + }); + } + + if let Some(ir_block) = &block.ir_block { + D::enter_block(engine_state, block); + + let args_base = stack.arguments.get_base(); + let error_handler_base = stack.error_handlers.get_base(); + + // Allocate and initialize registers. I've found that it's not really worth trying to avoid + // the heap allocation here by reusing buffers - our allocator is fast enough + let mut registers = Vec::with_capacity(ir_block.register_count as usize); + for _ in 0..ir_block.register_count { + registers.push(PipelineData::Empty); + } + + // Initialize file storage. + let mut files = vec![None; ir_block.file_count as usize]; + + let result = eval_ir_block_impl::( + &mut EvalContext { + engine_state, + stack, + data: &ir_block.data, + block_span: &block.span, + args_base, + error_handler_base, + redirect_out: None, + redirect_err: None, + matches: vec![], + registers: &mut registers[..], + files: &mut files[..], + }, + ir_block, + input, + ); + + stack.error_handlers.leave_frame(error_handler_base); + stack.arguments.leave_frame(args_base); + + D::leave_block(engine_state, block); + + result + } else { + // FIXME blocks having IR should not be optional + Err(ShellError::GenericError { + error: "Can't evaluate block in IR mode".into(), + msg: "block is missing compiled representation".into(), + span: block.span, + help: Some("the IrBlock is probably missing due to a compilation error".into()), + inner: vec![], + }) + } +} + +/// All of the pointers necessary for evaluation +struct EvalContext<'a> { + engine_state: &'a EngineState, + stack: &'a mut Stack, + data: &'a Arc<[u8]>, + /// The span of the block + block_span: &'a Option, + /// Base index on the argument stack to reset to after a call + args_base: usize, + /// Base index on the error handler stack to reset to after a call + error_handler_base: usize, + /// State set by redirect-out + redirect_out: Option, + /// State set by redirect-err + redirect_err: Option, + /// Scratch space to use for `match` + matches: Vec<(VarId, Value)>, + /// Intermediate pipeline data storage used by instructions, indexed by RegId + registers: &'a mut [PipelineData], + /// Holds open files used by redirections + files: &'a mut [Option>], +} + +impl<'a> EvalContext<'a> { + /// Replace the contents of a register with a new value + #[inline] + fn put_reg(&mut self, reg_id: RegId, new_value: PipelineData) { + // log::trace!("{reg_id} <- {new_value:?}"); + self.registers[reg_id.get() as usize] = new_value; + } + + /// Borrow the contents of a register. + #[inline] + fn borrow_reg(&self, reg_id: RegId) -> &PipelineData { + &self.registers[reg_id.get() as usize] + } + + /// Replace the contents of a register with `Empty` and then return the value that it contained + #[inline] + fn take_reg(&mut self, reg_id: RegId) -> PipelineData { + // log::trace!("<- {reg_id}"); + std::mem::replace( + &mut self.registers[reg_id.get() as usize], + PipelineData::Empty, + ) + } + + /// Clone data from a register. Must be collected first. + fn clone_reg(&mut self, reg_id: RegId, error_span: Span) -> Result { + match &self.registers[reg_id.get() as usize] { + PipelineData::Empty => Ok(PipelineData::Empty), + PipelineData::Value(val, meta) => Ok(PipelineData::Value(val.clone(), meta.clone())), + _ => Err(ShellError::IrEvalError { + msg: "Must collect to value before using instruction that clones from a register" + .into(), + span: Some(error_span), + }), + } + } + + /// Clone a value from a register. Must be collected first. + fn clone_reg_value(&mut self, reg_id: RegId, fallback_span: Span) -> Result { + match self.clone_reg(reg_id, fallback_span)? { + PipelineData::Empty => Ok(Value::nothing(fallback_span)), + PipelineData::Value(val, _) => Ok(val), + _ => unreachable!("clone_reg should never return stream data"), + } + } + + /// Take and implicitly collect a register to a value + fn collect_reg(&mut self, reg_id: RegId, fallback_span: Span) -> Result { + let data = self.take_reg(reg_id); + let span = data.span().unwrap_or(fallback_span); + data.into_value(span) + } + + /// Get a string from data or produce evaluation error if it's invalid UTF-8 + fn get_str(&self, slice: DataSlice, error_span: Span) -> Result<&'a str, ShellError> { + std::str::from_utf8(&self.data[slice]).map_err(|_| ShellError::IrEvalError { + msg: format!("data slice does not refer to valid UTF-8: {slice:?}"), + span: Some(error_span), + }) + } +} + +/// Eval an IR block on the provided slice of registers. +fn eval_ir_block_impl( + ctx: &mut EvalContext<'_>, + ir_block: &IrBlock, + input: PipelineData, +) -> Result { + if !ctx.registers.is_empty() { + ctx.registers[0] = input; + } + + // Program counter, starts at zero. + let mut pc = 0; + let need_backtrace = ctx.engine_state.get_env_var("NU_BACKTRACE").is_some(); + + while pc < ir_block.instructions.len() { + let instruction = &ir_block.instructions[pc]; + let span = &ir_block.spans[pc]; + let ast = &ir_block.ast[pc]; + + D::enter_instruction(ctx.engine_state, ir_block, pc, ctx.registers); + + let result = eval_instruction::(ctx, instruction, span, ast, need_backtrace); + + D::leave_instruction( + ctx.engine_state, + ir_block, + pc, + ctx.registers, + result.as_ref().err(), + ); + + match result { + Ok(InstructionResult::Continue) => { + pc += 1; + } + Ok(InstructionResult::Branch(next_pc)) => { + pc = next_pc; + } + Ok(InstructionResult::Return(reg_id)) => { + return Ok(ctx.take_reg(reg_id)); + } + Err( + err @ (ShellError::Return { .. } + | ShellError::Continue { .. } + | ShellError::Break { .. }), + ) => { + // These block control related errors should be passed through + return Err(err); + } + Err(err) => { + if let Some(error_handler) = ctx.stack.error_handlers.pop(ctx.error_handler_base) { + // If an error handler is set, branch there + prepare_error_handler(ctx, error_handler, Some(err.into_spanned(*span))); + pc = error_handler.handler_index; + } else if need_backtrace { + let err = ShellError::into_chainned(err, *span); + return Err(err); + } else { + return Err(err); + } + } + } + } + + // Fell out of the loop, without encountering a Return. + Err(ShellError::IrEvalError { + msg: format!( + "Program counter out of range (pc={pc}, len={len})", + len = ir_block.instructions.len(), + ), + span: *ctx.block_span, + }) +} + +/// Prepare the context for an error handler +fn prepare_error_handler( + ctx: &mut EvalContext<'_>, + error_handler: ErrorHandler, + error: Option>, +) { + if let Some(reg_id) = error_handler.error_register { + if let Some(error) = error { + // Stack state has to be updated for stuff like LAST_EXIT_CODE + ctx.stack.set_last_error(&error.item); + // Create the error value and put it in the register + ctx.put_reg( + reg_id, + error + .item + .into_value(&StateWorkingSet::new(ctx.engine_state), error.span) + .into_pipeline_data(), + ); + } else { + // Set the register to empty + ctx.put_reg(reg_id, PipelineData::Empty); + } + } +} + +/// The result of performing an instruction. Describes what should happen next +#[derive(Debug)] +enum InstructionResult { + Continue, + Branch(usize), + Return(RegId), +} + +/// Perform an instruction +fn eval_instruction( + ctx: &mut EvalContext<'_>, + instruction: &Instruction, + span: &Span, + ast: &Option, + need_backtrace: bool, +) -> Result { + use self::InstructionResult::*; + + // See the docs for `Instruction` for more information on what these instructions are supposed + // to do. + match instruction { + Instruction::Unreachable => Err(ShellError::IrEvalError { + msg: "Reached unreachable code".into(), + span: Some(*span), + }), + Instruction::LoadLiteral { dst, lit } => load_literal(ctx, *dst, lit, *span), + Instruction::LoadValue { dst, val } => { + ctx.put_reg(*dst, Value::clone(val).into_pipeline_data()); + Ok(Continue) + } + Instruction::Move { dst, src } => { + let val = ctx.take_reg(*src); + ctx.put_reg(*dst, val); + Ok(Continue) + } + Instruction::Clone { dst, src } => { + let data = ctx.clone_reg(*src, *span)?; + ctx.put_reg(*dst, data); + Ok(Continue) + } + Instruction::Collect { src_dst } => { + let data = ctx.take_reg(*src_dst); + let value = collect(data, *span)?; + ctx.put_reg(*src_dst, value); + Ok(Continue) + } + Instruction::Span { src_dst } => { + let data = ctx.take_reg(*src_dst); + let spanned = data.with_span(*span); + ctx.put_reg(*src_dst, spanned); + Ok(Continue) + } + Instruction::Drop { src } => { + ctx.take_reg(*src); + Ok(Continue) + } + Instruction::Drain { src } => { + let data = ctx.take_reg(*src); + drain(ctx, data) + } + Instruction::DrainIfEnd { src } => { + let data = ctx.take_reg(*src); + let res = { + let stack = &mut ctx + .stack + .push_redirection(ctx.redirect_out.clone(), ctx.redirect_err.clone()); + data.drain_to_out_dests(ctx.engine_state, stack)? + }; + ctx.put_reg(*src, res); + Ok(Continue) + } + Instruction::LoadVariable { dst, var_id } => { + let value = get_var(ctx, *var_id, *span)?; + ctx.put_reg(*dst, value.into_pipeline_data()); + Ok(Continue) + } + Instruction::StoreVariable { var_id, src } => { + let value = ctx.collect_reg(*src, *span)?; + ctx.stack.add_var(*var_id, value); + Ok(Continue) + } + Instruction::DropVariable { var_id } => { + ctx.stack.remove_var(*var_id); + Ok(Continue) + } + Instruction::LoadEnv { dst, key } => { + let key = ctx.get_str(*key, *span)?; + if let Some(value) = get_env_var_case_insensitive(ctx, key) { + let new_value = value.clone().into_pipeline_data(); + ctx.put_reg(*dst, new_value); + Ok(Continue) + } else { + // FIXME: using the same span twice, shouldn't this really be + // EnvVarNotFoundAtRuntime? There are tests that depend on CantFindColumn though... + Err(ShellError::CantFindColumn { + col_name: key.into(), + span: Some(*span), + src_span: *span, + }) + } + } + Instruction::LoadEnvOpt { dst, key } => { + let key = ctx.get_str(*key, *span)?; + let value = get_env_var_case_insensitive(ctx, key) + .cloned() + .unwrap_or(Value::nothing(*span)); + ctx.put_reg(*dst, value.into_pipeline_data()); + Ok(Continue) + } + Instruction::StoreEnv { key, src } => { + let key = ctx.get_str(*key, *span)?; + let value = ctx.collect_reg(*src, *span)?; + + let key = get_env_var_name_case_insensitive(ctx, key); + + if !is_automatic_env_var(&key) { + let is_config = key == "config"; + let update_conversions = key == ENV_CONVERSIONS; + + ctx.stack.add_env_var(key.into_owned(), value.clone()); + + if is_config { + ctx.stack.update_config(ctx.engine_state)?; + } + if update_conversions { + convert_env_vars(ctx.stack, ctx.engine_state, &value)?; + } + Ok(Continue) + } else { + Err(ShellError::AutomaticEnvVarSetManually { + envvar_name: key.into(), + span: *span, + }) + } + } + Instruction::PushPositional { src } => { + let val = ctx.collect_reg(*src, *span)?.with_span(*span); + ctx.stack.arguments.push(Argument::Positional { + span: *span, + val, + ast: ast.clone().map(|ast_ref| ast_ref.0), + }); + Ok(Continue) + } + Instruction::AppendRest { src } => { + let vals = ctx.collect_reg(*src, *span)?.with_span(*span); + ctx.stack.arguments.push(Argument::Spread { + span: *span, + vals, + ast: ast.clone().map(|ast_ref| ast_ref.0), + }); + Ok(Continue) + } + Instruction::PushFlag { name } => { + let data = ctx.data.clone(); + ctx.stack.arguments.push(Argument::Flag { + data, + name: *name, + short: DataSlice::empty(), + span: *span, + }); + Ok(Continue) + } + Instruction::PushShortFlag { short } => { + let data = ctx.data.clone(); + ctx.stack.arguments.push(Argument::Flag { + data, + name: DataSlice::empty(), + short: *short, + span: *span, + }); + Ok(Continue) + } + Instruction::PushNamed { name, src } => { + let val = ctx.collect_reg(*src, *span)?.with_span(*span); + let data = ctx.data.clone(); + ctx.stack.arguments.push(Argument::Named { + data, + name: *name, + short: DataSlice::empty(), + span: *span, + val, + ast: ast.clone().map(|ast_ref| ast_ref.0), + }); + Ok(Continue) + } + Instruction::PushShortNamed { short, src } => { + let val = ctx.collect_reg(*src, *span)?.with_span(*span); + let data = ctx.data.clone(); + ctx.stack.arguments.push(Argument::Named { + data, + name: DataSlice::empty(), + short: *short, + span: *span, + val, + ast: ast.clone().map(|ast_ref| ast_ref.0), + }); + Ok(Continue) + } + Instruction::PushParserInfo { name, info } => { + let data = ctx.data.clone(); + ctx.stack.arguments.push(Argument::ParserInfo { + data, + name: *name, + info: info.clone(), + }); + Ok(Continue) + } + Instruction::RedirectOut { mode } => { + ctx.redirect_out = eval_redirection(ctx, mode, *span, RedirectionStream::Out)?; + Ok(Continue) + } + Instruction::RedirectErr { mode } => { + ctx.redirect_err = eval_redirection(ctx, mode, *span, RedirectionStream::Err)?; + Ok(Continue) + } + Instruction::CheckErrRedirected { src } => match ctx.borrow_reg(*src) { + #[cfg(feature = "os")] + PipelineData::ByteStream(stream, _) + if matches!(stream.source(), nu_protocol::ByteStreamSource::Child(_)) => + { + Ok(Continue) + } + _ => Err(ShellError::GenericError { + error: "Can't redirect stderr of internal command output".into(), + msg: "piping stderr only works on external commands".into(), + span: Some(*span), + help: None, + inner: vec![], + }), + }, + Instruction::OpenFile { + file_num, + path, + append, + } => { + let path = ctx.collect_reg(*path, *span)?; + let file = open_file(ctx, &path, *append)?; + ctx.files[*file_num as usize] = Some(file); + Ok(Continue) + } + Instruction::WriteFile { file_num, src } => { + let src = ctx.take_reg(*src); + let file = ctx + .files + .get(*file_num as usize) + .cloned() + .flatten() + .ok_or_else(|| ShellError::IrEvalError { + msg: format!("Tried to write to file #{file_num}, but it is not open"), + span: Some(*span), + })?; + let is_external = if let PipelineData::ByteStream(stream, ..) = &src { + stream.source().is_external() + } else { + false + }; + if let Err(err) = src.write_to(file.as_ref()) { + if is_external { + ctx.stack.set_last_error(&err); + } + Err(err)? + } else { + Ok(Continue) + } + } + Instruction::CloseFile { file_num } => { + if ctx.files[*file_num as usize].take().is_some() { + Ok(Continue) + } else { + Err(ShellError::IrEvalError { + msg: format!("Tried to close file #{file_num}, but it is not open"), + span: Some(*span), + }) + } + } + Instruction::Call { decl_id, src_dst } => { + let input = ctx.take_reg(*src_dst); + let mut result = eval_call::(ctx, *decl_id, *span, input)?; + if need_backtrace { + match &mut result { + PipelineData::ByteStream(s, ..) => s.push_caller_span(*span), + PipelineData::ListStream(s, ..) => s.push_caller_span(*span), + _ => (), + }; + } + ctx.put_reg(*src_dst, result); + Ok(Continue) + } + Instruction::StringAppend { src_dst, val } => { + let string_value = ctx.collect_reg(*src_dst, *span)?; + let operand_value = ctx.collect_reg(*val, *span)?; + let string_span = string_value.span(); + + let mut string = string_value.into_string()?; + let operand = if let Value::String { val, .. } = operand_value { + // Small optimization, so we don't have to copy the string *again* + val + } else { + operand_value.to_expanded_string(", ", ctx.engine_state.get_config()) + }; + string.push_str(&operand); + + let new_string_value = Value::string(string, string_span); + ctx.put_reg(*src_dst, new_string_value.into_pipeline_data()); + Ok(Continue) + } + Instruction::GlobFrom { src_dst, no_expand } => { + let string_value = ctx.collect_reg(*src_dst, *span)?; + let glob_value = if matches!(string_value, Value::Glob { .. }) { + // It already is a glob, so don't touch it. + string_value + } else { + // Treat it as a string, then cast + let string = string_value.into_string()?; + Value::glob(string, *no_expand, *span) + }; + ctx.put_reg(*src_dst, glob_value.into_pipeline_data()); + Ok(Continue) + } + Instruction::ListPush { src_dst, item } => { + let list_value = ctx.collect_reg(*src_dst, *span)?; + let item = ctx.collect_reg(*item, *span)?; + let list_span = list_value.span(); + let mut list = list_value.into_list()?; + list.push(item); + ctx.put_reg(*src_dst, Value::list(list, list_span).into_pipeline_data()); + Ok(Continue) + } + Instruction::ListSpread { src_dst, items } => { + let list_value = ctx.collect_reg(*src_dst, *span)?; + let items = ctx.collect_reg(*items, *span)?; + let list_span = list_value.span(); + let items_span = items.span(); + let mut list = list_value.into_list()?; + list.extend( + items + .into_list() + .map_err(|_| ShellError::CannotSpreadAsList { span: items_span })?, + ); + ctx.put_reg(*src_dst, Value::list(list, list_span).into_pipeline_data()); + Ok(Continue) + } + Instruction::RecordInsert { src_dst, key, val } => { + let record_value = ctx.collect_reg(*src_dst, *span)?; + let key = ctx.collect_reg(*key, *span)?; + let val = ctx.collect_reg(*val, *span)?; + let record_span = record_value.span(); + let mut record = record_value.into_record()?; + + let key = key.coerce_into_string()?; + if let Some(old_value) = record.insert(&key, val) { + return Err(ShellError::ColumnDefinedTwice { + col_name: key, + second_use: *span, + first_use: old_value.span(), + }); + } + + ctx.put_reg( + *src_dst, + Value::record(record, record_span).into_pipeline_data(), + ); + Ok(Continue) + } + Instruction::RecordSpread { src_dst, items } => { + let record_value = ctx.collect_reg(*src_dst, *span)?; + let items = ctx.collect_reg(*items, *span)?; + let record_span = record_value.span(); + let items_span = items.span(); + let mut record = record_value.into_record()?; + // Not using .extend() here because it doesn't handle duplicates + for (key, val) in items + .into_record() + .map_err(|_| ShellError::CannotSpreadAsRecord { span: items_span })? + { + if let Some(first_value) = record.insert(&key, val) { + return Err(ShellError::ColumnDefinedTwice { + col_name: key, + second_use: *span, + first_use: first_value.span(), + }); + } + } + ctx.put_reg( + *src_dst, + Value::record(record, record_span).into_pipeline_data(), + ); + Ok(Continue) + } + Instruction::Not { src_dst } => { + let bool = ctx.collect_reg(*src_dst, *span)?; + let negated = !bool.as_bool()?; + ctx.put_reg( + *src_dst, + Value::bool(negated, bool.span()).into_pipeline_data(), + ); + Ok(Continue) + } + Instruction::BinaryOp { lhs_dst, op, rhs } => binary_op(ctx, *lhs_dst, op, *rhs, *span), + Instruction::FollowCellPath { src_dst, path } => { + let data = ctx.take_reg(*src_dst); + let path = ctx.take_reg(*path); + if let PipelineData::Value(Value::CellPath { val: path, .. }, _) = path { + let value = data.follow_cell_path(&path.members, *span)?; + ctx.put_reg(*src_dst, value.into_pipeline_data()); + Ok(Continue) + } else if let PipelineData::Value(Value::Error { error, .. }, _) = path { + Err(*error) + } else { + Err(ShellError::TypeMismatch { + err_message: "expected cell path".into(), + span: path.span().unwrap_or(*span), + }) + } + } + Instruction::CloneCellPath { dst, src, path } => { + let value = ctx.clone_reg_value(*src, *span)?; + let path = ctx.take_reg(*path); + if let PipelineData::Value(Value::CellPath { val: path, .. }, _) = path { + let value = value.follow_cell_path(&path.members)?; + ctx.put_reg(*dst, value.into_owned().into_pipeline_data()); + Ok(Continue) + } else if let PipelineData::Value(Value::Error { error, .. }, _) = path { + Err(*error) + } else { + Err(ShellError::TypeMismatch { + err_message: "expected cell path".into(), + span: path.span().unwrap_or(*span), + }) + } + } + Instruction::UpsertCellPath { + src_dst, + path, + new_value, + } => { + let data = ctx.take_reg(*src_dst); + let metadata = data.metadata(); + // Change the span because we're modifying it + let mut value = data.into_value(*span)?; + let path = ctx.take_reg(*path); + let new_value = ctx.collect_reg(*new_value, *span)?; + if let PipelineData::Value(Value::CellPath { val: path, .. }, _) = path { + value.upsert_data_at_cell_path(&path.members, new_value)?; + ctx.put_reg(*src_dst, value.into_pipeline_data_with_metadata(metadata)); + Ok(Continue) + } else if let PipelineData::Value(Value::Error { error, .. }, _) = path { + Err(*error) + } else { + Err(ShellError::TypeMismatch { + err_message: "expected cell path".into(), + span: path.span().unwrap_or(*span), + }) + } + } + Instruction::Jump { index } => Ok(Branch(*index)), + Instruction::BranchIf { cond, index } => { + let data = ctx.take_reg(*cond); + let data_span = data.span(); + let val = match data { + PipelineData::Value(Value::Bool { val, .. }, _) => val, + PipelineData::Value(Value::Error { error, .. }, _) => { + return Err(*error); + } + _ => { + return Err(ShellError::TypeMismatch { + err_message: "expected bool".into(), + span: data_span.unwrap_or(*span), + }); + } + }; + if val { + Ok(Branch(*index)) + } else { + Ok(Continue) + } + } + Instruction::BranchIfEmpty { src, index } => { + let is_empty = matches!( + ctx.borrow_reg(*src), + PipelineData::Empty | PipelineData::Value(Value::Nothing { .. }, _) + ); + + if is_empty { + Ok(Branch(*index)) + } else { + Ok(Continue) + } + } + Instruction::Match { + pattern, + src, + index, + } => { + let value = ctx.clone_reg_value(*src, *span)?; + ctx.matches.clear(); + if pattern.match_value(&value, &mut ctx.matches) { + // Match succeeded: set variables and branch + for (var_id, match_value) in ctx.matches.drain(..) { + ctx.stack.add_var(var_id, match_value); + } + Ok(Branch(*index)) + } else { + // Failed to match, put back original value + ctx.matches.clear(); + Ok(Continue) + } + } + Instruction::CheckMatchGuard { src } => { + if matches!( + ctx.borrow_reg(*src), + PipelineData::Value(Value::Bool { .. }, _) + ) { + Ok(Continue) + } else { + Err(ShellError::MatchGuardNotBool { span: *span }) + } + } + Instruction::Iterate { + dst, + stream, + end_index, + } => eval_iterate(ctx, *dst, *stream, *end_index), + Instruction::OnError { index } => { + ctx.stack.error_handlers.push(ErrorHandler { + handler_index: *index, + error_register: None, + }); + Ok(Continue) + } + Instruction::OnErrorInto { index, dst } => { + ctx.stack.error_handlers.push(ErrorHandler { + handler_index: *index, + error_register: Some(*dst), + }); + Ok(Continue) + } + Instruction::PopErrorHandler => { + ctx.stack.error_handlers.pop(ctx.error_handler_base); + Ok(Continue) + } + Instruction::ReturnEarly { src } => { + let val = ctx.collect_reg(*src, *span)?; + Err(ShellError::Return { + span: *span, + value: Box::new(val), + }) + } + Instruction::Return { src } => Ok(Return(*src)), + } +} + +/// Load a literal value into a register +fn load_literal( + ctx: &mut EvalContext<'_>, + dst: RegId, + lit: &Literal, + span: Span, +) -> Result { + let value = literal_value(ctx, lit, span)?; + ctx.put_reg(dst, PipelineData::Value(value, None)); + Ok(InstructionResult::Continue) +} + +fn literal_value( + ctx: &mut EvalContext<'_>, + lit: &Literal, + span: Span, +) -> Result { + Ok(match lit { + Literal::Bool(b) => Value::bool(*b, span), + Literal::Int(i) => Value::int(*i, span), + Literal::Float(f) => Value::float(*f, span), + Literal::Filesize(q) => Value::filesize(*q, span), + Literal::Duration(q) => Value::duration(*q, span), + Literal::Binary(bin) => Value::binary(&ctx.data[*bin], span), + Literal::Block(block_id) | Literal::RowCondition(block_id) | Literal::Closure(block_id) => { + let block = ctx.engine_state.get_block(*block_id); + let captures = block + .captures + .iter() + .map(|(var_id, span)| get_var(ctx, *var_id, *span).map(|val| (*var_id, val))) + .collect::, ShellError>>()?; + Value::closure( + Closure { + block_id: *block_id, + captures, + }, + span, + ) + } + Literal::Range { + start, + step, + end, + inclusion, + } => { + let start = ctx.collect_reg(*start, span)?; + let step = ctx.collect_reg(*step, span)?; + let end = ctx.collect_reg(*end, span)?; + let range = Range::new(start, step, end, *inclusion, span)?; + Value::range(range, span) + } + Literal::List { capacity } => Value::list(Vec::with_capacity(*capacity), span), + Literal::Record { capacity } => Value::record(Record::with_capacity(*capacity), span), + Literal::Filepath { + val: path, + no_expand, + } => { + let path = ctx.get_str(*path, span)?; + if *no_expand { + Value::string(path, span) + } else { + let path = expand_path(path, true); + Value::string(path.to_string_lossy(), span) + } + } + Literal::Directory { + val: path, + no_expand, + } => { + let path = ctx.get_str(*path, span)?; + if path == "-" { + Value::string("-", span) + } else if *no_expand { + Value::string(path, span) + } else { + let path = expand_path(path, true); + Value::string(path.to_string_lossy(), span) + } + } + Literal::GlobPattern { val, no_expand } => { + Value::glob(ctx.get_str(*val, span)?, *no_expand, span) + } + Literal::String(s) => Value::string(ctx.get_str(*s, span)?, span), + Literal::RawString(s) => Value::string(ctx.get_str(*s, span)?, span), + Literal::CellPath(path) => Value::cell_path(CellPath::clone(path), span), + Literal::Date(dt) => Value::date(**dt, span), + Literal::Nothing => Value::nothing(span), + }) +} + +fn binary_op( + ctx: &mut EvalContext<'_>, + lhs_dst: RegId, + op: &Operator, + rhs: RegId, + span: Span, +) -> Result { + let lhs_val = ctx.collect_reg(lhs_dst, span)?; + let rhs_val = ctx.collect_reg(rhs, span)?; + + // Handle binary op errors early + if let Value::Error { error, .. } = lhs_val { + return Err(*error); + } + if let Value::Error { error, .. } = rhs_val { + return Err(*error); + } + + // We only have access to one span here, but the generated code usually adds a `span` + // instruction to set the output span to the right span. + let op_span = span; + + let result = match op { + Operator::Comparison(cmp) => match cmp { + Comparison::Equal => lhs_val.eq(op_span, &rhs_val, span)?, + Comparison::NotEqual => lhs_val.ne(op_span, &rhs_val, span)?, + Comparison::LessThan => lhs_val.lt(op_span, &rhs_val, span)?, + Comparison::GreaterThan => lhs_val.gt(op_span, &rhs_val, span)?, + Comparison::LessThanOrEqual => lhs_val.lte(op_span, &rhs_val, span)?, + Comparison::GreaterThanOrEqual => lhs_val.gte(op_span, &rhs_val, span)?, + Comparison::RegexMatch => { + lhs_val.regex_match(ctx.engine_state, op_span, &rhs_val, false, span)? + } + Comparison::NotRegexMatch => { + lhs_val.regex_match(ctx.engine_state, op_span, &rhs_val, true, span)? + } + Comparison::In => lhs_val.r#in(op_span, &rhs_val, span)?, + Comparison::NotIn => lhs_val.not_in(op_span, &rhs_val, span)?, + Comparison::Has => lhs_val.has(op_span, &rhs_val, span)?, + Comparison::NotHas => lhs_val.not_has(op_span, &rhs_val, span)?, + Comparison::StartsWith => lhs_val.starts_with(op_span, &rhs_val, span)?, + Comparison::EndsWith => lhs_val.ends_with(op_span, &rhs_val, span)?, + }, + Operator::Math(mat) => match mat { + Math::Add => lhs_val.add(op_span, &rhs_val, span)?, + Math::Subtract => lhs_val.sub(op_span, &rhs_val, span)?, + Math::Multiply => lhs_val.mul(op_span, &rhs_val, span)?, + Math::Divide => lhs_val.div(op_span, &rhs_val, span)?, + Math::FloorDivide => lhs_val.floor_div(op_span, &rhs_val, span)?, + Math::Modulo => lhs_val.modulo(op_span, &rhs_val, span)?, + Math::Pow => lhs_val.pow(op_span, &rhs_val, span)?, + Math::Concatenate => lhs_val.concat(op_span, &rhs_val, span)?, + }, + Operator::Boolean(bl) => match bl { + Boolean::Or => lhs_val.or(op_span, &rhs_val, span)?, + Boolean::Xor => lhs_val.xor(op_span, &rhs_val, span)?, + Boolean::And => lhs_val.and(op_span, &rhs_val, span)?, + }, + Operator::Bits(bit) => match bit { + Bits::BitOr => lhs_val.bit_or(op_span, &rhs_val, span)?, + Bits::BitXor => lhs_val.bit_xor(op_span, &rhs_val, span)?, + Bits::BitAnd => lhs_val.bit_and(op_span, &rhs_val, span)?, + Bits::ShiftLeft => lhs_val.bit_shl(op_span, &rhs_val, span)?, + Bits::ShiftRight => lhs_val.bit_shr(op_span, &rhs_val, span)?, + }, + Operator::Assignment(_asg) => { + return Err(ShellError::IrEvalError { + msg: "can't eval assignment with the `binary-op` instruction".into(), + span: Some(span), + }); + } + }; + + ctx.put_reg(lhs_dst, PipelineData::Value(result, None)); + + Ok(InstructionResult::Continue) +} + +/// Evaluate a call +fn eval_call( + ctx: &mut EvalContext<'_>, + decl_id: DeclId, + head: Span, + input: PipelineData, +) -> Result { + let EvalContext { + engine_state, + stack: caller_stack, + args_base, + redirect_out, + redirect_err, + .. + } = ctx; + + let args_len = caller_stack.arguments.get_len(*args_base); + let decl = engine_state.get_decl(decl_id); + + // Set up redirect modes + let mut caller_stack = caller_stack.push_redirection(redirect_out.take(), redirect_err.take()); + + let result = (|| { + if let Some(block_id) = decl.block_id() { + // If the decl is a custom command + let block = engine_state.get_block(block_id); + + // check types after acquiring block to avoid unnecessarily cloning Signature + check_input_types(&input, &block.signature, head)?; + + // Set up a callee stack with the captures and move arguments from the stack into variables + let mut callee_stack = caller_stack.gather_captures(engine_state, &block.captures); + + gather_arguments( + engine_state, + block, + &mut caller_stack, + &mut callee_stack, + *args_base, + args_len, + head, + )?; + + // Add one to the recursion count, so we don't recurse too deep. Stack overflows are not + // recoverable in Rust. + callee_stack.recursion_count += 1; + + let result = + eval_block_with_early_return::(engine_state, &mut callee_stack, block, input); + + // Move environment variables back into the caller stack scope if requested to do so + if block.redirect_env { + redirect_env(engine_state, &mut caller_stack, &callee_stack); + } + + result + } else { + check_input_types(&input, &decl.signature(), head)?; + // FIXME: precalculate this and save it somewhere + let span = Span::merge_many( + std::iter::once(head).chain( + caller_stack + .arguments + .get_args(*args_base, args_len) + .iter() + .flat_map(|arg| arg.span()), + ), + ); + + let call = Call { + decl_id, + head, + span, + args_base: *args_base, + args_len, + }; + + // Run the call + decl.run(engine_state, &mut caller_stack, &(&call).into(), input) + } + })(); + + drop(caller_stack); + + // Important that this runs, to reset state post-call: + ctx.stack.arguments.leave_frame(ctx.args_base); + ctx.redirect_out = None; + ctx.redirect_err = None; + + result +} + +fn find_named_var_id( + sig: &Signature, + name: &[u8], + short: &[u8], + span: Span, +) -> Result { + sig.named + .iter() + .find(|n| { + if !n.long.is_empty() { + n.long.as_bytes() == name + } else { + // It's possible to only have a short name and no long name + n.short + .is_some_and(|s| s.encode_utf8(&mut [0; 4]).as_bytes() == short) + } + }) + .ok_or_else(|| ShellError::IrEvalError { + msg: format!( + "block does not have an argument named `{}`", + String::from_utf8_lossy(name) + ), + span: Some(span), + }) + .and_then(|flag| expect_named_var_id(flag, span)) +} + +fn expect_named_var_id(arg: &Flag, span: Span) -> Result { + arg.var_id.ok_or_else(|| ShellError::IrEvalError { + msg: format!( + "block signature is missing var id for named arg `{}`", + arg.long + ), + span: Some(span), + }) +} + +fn expect_positional_var_id(arg: &PositionalArg, span: Span) -> Result { + arg.var_id.ok_or_else(|| ShellError::IrEvalError { + msg: format!( + "block signature is missing var id for positional arg `{}`", + arg.name + ), + span: Some(span), + }) +} + +/// Move arguments from the stack into variables for a custom command +fn gather_arguments( + engine_state: &EngineState, + block: &Block, + caller_stack: &mut Stack, + callee_stack: &mut Stack, + args_base: usize, + args_len: usize, + call_head: Span, +) -> Result<(), ShellError> { + let mut positional_iter = block + .signature + .required_positional + .iter() + .map(|p| (p, true)) + .chain( + block + .signature + .optional_positional + .iter() + .map(|p| (p, false)), + ); + + // Arguments that didn't get consumed by required/optional + let mut rest = vec![]; + + // If we encounter a spread, all further positionals should go to rest + let mut always_spread = false; + + for arg in caller_stack.arguments.drain_args(args_base, args_len) { + match arg { + Argument::Positional { span, val, .. } => { + // Don't check next positional arg if we encountered a spread previously + let next = (!always_spread).then(|| positional_iter.next()).flatten(); + if let Some((positional_arg, required)) = next { + let var_id = expect_positional_var_id(positional_arg, span)?; + if required { + // By checking the type of the bound variable rather than converting the + // SyntaxShape here, we might be able to save some allocations and effort + let variable = engine_state.get_var(var_id); + check_type(&val, &variable.ty)?; + } + callee_stack.add_var(var_id, val); + } else { + rest.push(val); + } + } + Argument::Spread { vals, .. } => { + if let Value::List { vals, .. } = vals { + rest.extend(vals); + // All further positional args should go to spread + always_spread = true; + } else if let Value::Error { error, .. } = vals { + return Err(*error); + } else { + return Err(ShellError::CannotSpreadAsList { span: vals.span() }); + } + } + Argument::Flag { + data, + name, + short, + span, + } => { + let var_id = find_named_var_id(&block.signature, &data[name], &data[short], span)?; + callee_stack.add_var(var_id, Value::bool(true, span)) + } + Argument::Named { + data, + name, + short, + span, + val, + .. + } => { + let var_id = find_named_var_id(&block.signature, &data[name], &data[short], span)?; + callee_stack.add_var(var_id, val) + } + Argument::ParserInfo { .. } => (), + } + } + + // Add the collected rest of the arguments if a spread argument exists + if let Some(rest_arg) = &block.signature.rest_positional { + let rest_span = rest.first().map(|v| v.span()).unwrap_or(call_head); + let var_id = expect_positional_var_id(rest_arg, rest_span)?; + callee_stack.add_var(var_id, Value::list(rest, rest_span)); + } + + // Check for arguments that haven't yet been set and set them to their defaults + for (positional_arg, _) in positional_iter { + let var_id = expect_positional_var_id(positional_arg, call_head)?; + callee_stack.add_var( + var_id, + positional_arg + .default_value + .clone() + .unwrap_or(Value::nothing(call_head)), + ); + } + + for named_arg in &block.signature.named { + if let Some(var_id) = named_arg.var_id { + // For named arguments, we do this check by looking to see if the variable was set yet on + // the stack. This assumes that the stack's variables was previously empty, but that's a + // fair assumption for a brand new callee stack. + if !callee_stack.vars.iter().any(|(id, _)| *id == var_id) { + let val = if named_arg.arg.is_none() { + Value::bool(false, call_head) + } else if let Some(value) = &named_arg.default_value { + value.clone() + } else { + Value::nothing(call_head) + }; + callee_stack.add_var(var_id, val); + } + } + } + + Ok(()) +} + +/// Type check helper. Produces `CantConvert` error if `val` is not compatible with `ty`. +fn check_type(val: &Value, ty: &Type) -> Result<(), ShellError> { + match val { + Value::Error { error, .. } => Err(*error.clone()), + _ if val.is_subtype_of(ty) => Ok(()), + _ => Err(ShellError::CantConvert { + to_type: ty.to_string(), + from_type: val.get_type().to_string(), + span: val.span(), + help: None, + }), + } +} + +/// Type check pipeline input against command's input types +fn check_input_types( + input: &PipelineData, + signature: &Signature, + head: Span, +) -> Result<(), ShellError> { + let io_types = &signature.input_output_types; + + // If a command doesn't have any input/output types, then treat command input type as any + if io_types.is_empty() { + return Ok(()); + } + + // If a command only has a nothing input type, then allow any input data + if io_types.iter().all(|(intype, _)| intype == &Type::Nothing) { + return Ok(()); + } + + match input { + // early return error directly if detected + PipelineData::Value(Value::Error { error, .. }, ..) => return Err(*error.clone()), + // bypass run-time typechecking for custom types + PipelineData::Value(Value::Custom { .. }, ..) => return Ok(()), + _ => (), + } + + // Check if the input type is compatible with *any* of the command's possible input types + if io_types + .iter() + .any(|(command_type, _)| input.is_subtype_of(command_type)) + { + return Ok(()); + } + + let mut input_types = io_types + .iter() + .map(|(input, _)| input.to_string()) + .collect::>(); + + let expected_string = match input_types.len() { + 0 => { + return Err(ShellError::NushellFailed { + msg: "Command input type strings is empty, despite being non-zero earlier" + .to_string(), + }); + } + 1 => input_types.swap_remove(0), + 2 => input_types.join(" and "), + _ => { + input_types + .last_mut() + .expect("Vector with length >2 has no elements") + .insert_str(0, "and "); + input_types.join(", ") + } + }; + + match input { + PipelineData::Empty => Err(ShellError::PipelineEmpty { dst_span: head }), + _ => Err(ShellError::OnlySupportsThisInputType { + exp_input_type: expected_string, + wrong_type: input.get_type().to_string(), + dst_span: head, + src_span: input.span().unwrap_or(Span::unknown()), + }), + } +} + +/// Get variable from [`Stack`] or [`EngineState`] +fn get_var(ctx: &EvalContext<'_>, var_id: VarId, span: Span) -> Result { + match var_id { + // $env + ENV_VARIABLE_ID => { + let env_vars = ctx.stack.get_env_vars(ctx.engine_state); + let env_columns = env_vars.keys(); + let env_values = env_vars.values(); + + let mut pairs = env_columns + .map(|x| x.to_string()) + .zip(env_values.cloned()) + .collect::>(); + + pairs.sort_by(|a, b| a.0.cmp(&b.0)); + + Ok(Value::record(pairs.into_iter().collect(), span)) + } + _ => ctx.stack.get_var(var_id, span).or_else(|err| { + // $nu is handled by getting constant + if let Some(const_val) = ctx.engine_state.get_constant(var_id).cloned() { + Ok(const_val.with_span(span)) + } else { + Err(err) + } + }), + } +} + +/// Get an environment variable, case-insensitively +fn get_env_var_case_insensitive<'a>(ctx: &'a mut EvalContext<'_>, key: &str) -> Option<&'a Value> { + // Read scopes in order + for overlays in ctx + .stack + .env_vars + .iter() + .rev() + .chain(std::iter::once(&ctx.engine_state.env_vars)) + { + // Read overlays in order + for overlay_name in ctx.stack.active_overlays.iter().rev() { + let Some(map) = overlays.get(overlay_name) else { + // Skip if overlay doesn't exist in this scope + continue; + }; + let hidden = ctx.stack.env_hidden.get(overlay_name); + let is_hidden = |key: &str| hidden.is_some_and(|hidden| hidden.contains(key)); + + if let Some(val) = map + // Check for exact match + .get(key) + // Skip when encountering an overlay where the key is hidden + .filter(|_| !is_hidden(key)) + .or_else(|| { + // Check to see if it exists at all in the map, with a different case + map.iter().find_map(|(k, v)| { + // Again, skip something that's hidden + (k.eq_ignore_case(key) && !is_hidden(k)).then_some(v) + }) + }) + { + return Some(val); + } + } + } + // Not found + None +} + +/// Get the existing name of an environment variable, case-insensitively. This is used to implement +/// case preservation of environment variables, so that changing an environment variable that +/// already exists always uses the same case. +fn get_env_var_name_case_insensitive<'a>(ctx: &mut EvalContext<'_>, key: &'a str) -> Cow<'a, str> { + // Read scopes in order + ctx.stack + .env_vars + .iter() + .rev() + .chain(std::iter::once(&ctx.engine_state.env_vars)) + .flat_map(|overlays| { + // Read overlays in order + ctx.stack + .active_overlays + .iter() + .rev() + .filter_map(|name| overlays.get(name)) + }) + .find_map(|map| { + // Use the hashmap first to try to be faster? + if map.contains_key(key) { + Some(Cow::Borrowed(key)) + } else { + map.keys().find(|k| k.eq_ignore_case(key)).map(|k| { + // it exists, but with a different case + Cow::Owned(k.to_owned()) + }) + } + }) + // didn't exist. + .unwrap_or(Cow::Borrowed(key)) +} + +/// Helper to collect values into [`PipelineData`], preserving original span and metadata +/// +/// The metadata is removed if it is the file data source, as that's just meant to mark streams. +fn collect(data: PipelineData, fallback_span: Span) -> Result { + let span = data.span().unwrap_or(fallback_span); + let metadata = match data.metadata() { + // Remove the `FilePath` metadata, because after `collect` it's no longer necessary to + // check where some input came from. + Some(PipelineMetadata { + data_source: DataSource::FilePath(_), + content_type: None, + }) => None, + other => other, + }; + let value = data.into_value(span)?; + Ok(PipelineData::Value(value, metadata)) +} + +/// Helper for drain behavior. +fn drain(ctx: &mut EvalContext<'_>, data: PipelineData) -> Result { + use self::InstructionResult::*; + match data { + PipelineData::ByteStream(stream, ..) => { + let span = stream.span(); + let callback_spans = stream.get_caller_spans().clone(); + if let Err(mut err) = stream.drain() { + ctx.stack.set_last_error(&err); + if callback_spans.is_empty() { + return Err(err); + } else { + for s in callback_spans { + err = ShellError::EvalBlockWithInput { + span: s, + sources: vec![err], + } + } + return Err(err); + } + } else { + ctx.stack.set_last_exit_code(0, span); + } + } + PipelineData::ListStream(stream, ..) => { + let callback_spans = stream.get_caller_spans().clone(); + if let Err(mut err) = stream.drain() { + if callback_spans.is_empty() { + return Err(err); + } else { + for s in callback_spans { + err = ShellError::EvalBlockWithInput { + span: s, + sources: vec![err], + } + } + return Err(err); + } + } + } + PipelineData::Value(..) | PipelineData::Empty => {} + } + Ok(Continue) +} + +enum RedirectionStream { + Out, + Err, +} + +/// Open a file for redirection +fn open_file(ctx: &EvalContext<'_>, path: &Value, append: bool) -> Result, ShellError> { + let path_expanded = + expand_path_with(path.as_str()?, ctx.engine_state.cwd(Some(ctx.stack))?, true); + let mut options = File::options(); + if append { + options.append(true); + } else { + options.write(true).truncate(true); + } + let file = options + .create(true) + .open(&path_expanded) + .map_err(|err| IoError::new(err, path.span(), path_expanded))?; + Ok(Arc::new(file)) +} + +/// Set up a [`Redirection`] from a [`RedirectMode`] +fn eval_redirection( + ctx: &mut EvalContext<'_>, + mode: &RedirectMode, + span: Span, + which: RedirectionStream, +) -> Result, ShellError> { + match mode { + RedirectMode::Pipe => Ok(Some(Redirection::Pipe(OutDest::Pipe))), + RedirectMode::PipeSeparate => Ok(Some(Redirection::Pipe(OutDest::PipeSeparate))), + RedirectMode::Value => Ok(Some(Redirection::Pipe(OutDest::Value))), + RedirectMode::Null => Ok(Some(Redirection::Pipe(OutDest::Null))), + RedirectMode::Inherit => Ok(Some(Redirection::Pipe(OutDest::Inherit))), + RedirectMode::Print => Ok(Some(Redirection::Pipe(OutDest::Print))), + RedirectMode::File { file_num } => { + let file = ctx + .files + .get(*file_num as usize) + .cloned() + .flatten() + .ok_or_else(|| ShellError::IrEvalError { + msg: format!("Tried to redirect to file #{file_num}, but it is not open"), + span: Some(span), + })?; + Ok(Some(Redirection::File(file))) + } + RedirectMode::Caller => Ok(match which { + RedirectionStream::Out => ctx.stack.pipe_stdout().cloned().map(Redirection::Pipe), + RedirectionStream::Err => ctx.stack.pipe_stderr().cloned().map(Redirection::Pipe), + }), + } +} + +/// Do an `iterate` instruction. This can be called repeatedly to get more values from an iterable +fn eval_iterate( + ctx: &mut EvalContext<'_>, + dst: RegId, + stream: RegId, + end_index: usize, +) -> Result { + let mut data = ctx.take_reg(stream); + if let PipelineData::ListStream(list_stream, _) = &mut data { + // Modify the stream, taking one value off, and branching if it's empty + if let Some(val) = list_stream.next_value() { + ctx.put_reg(dst, val.into_pipeline_data()); + ctx.put_reg(stream, data); // put the stream back so it can be iterated on again + Ok(InstructionResult::Continue) + } else { + ctx.put_reg(dst, PipelineData::Empty); + Ok(InstructionResult::Branch(end_index)) + } + } else { + // Convert the PipelineData to an iterator, and wrap it in a ListStream so it can be + // iterated on + let metadata = data.metadata(); + let span = data.span().unwrap_or(Span::unknown()); + ctx.put_reg( + stream, + PipelineData::ListStream( + ListStream::new(data.into_iter(), span, Signals::EMPTY), + metadata, + ), + ); + eval_iterate(ctx, dst, stream, end_index) + } +} + +/// Redirect environment from the callee stack to the caller stack +fn redirect_env(engine_state: &EngineState, caller_stack: &mut Stack, callee_stack: &Stack) { + // TODO: make this more efficient + // Grab all environment variables from the callee + let caller_env_vars = caller_stack.get_env_var_names(engine_state); + + // remove env vars that are present in the caller but not in the callee + // (the callee hid them) + for var in caller_env_vars.iter() { + if !callee_stack.has_env_var(engine_state, var) { + caller_stack.remove_env_var(engine_state, var); + } + } + + // add new env vars from callee to caller + for (var, value) in callee_stack.get_stack_env_vars() { + caller_stack.add_env_var(var, value); + } + + // set config to callee config, to capture any updates to that + caller_stack.config.clone_from(&callee_stack.config); +} diff --git a/nushell/crates/nu-engine/src/exit.rs b/nushell/crates/nu-engine/src/exit.rs new file mode 100644 index 0000000..396b3ef --- /dev/null +++ b/nushell/crates/nu-engine/src/exit.rs @@ -0,0 +1,37 @@ +use std::sync::atomic::Ordering; + +use nu_protocol::engine::EngineState; + +/// Exit the process or clean jobs if appropriate. +/// +/// Drops `tag` and exits the current process if there are no running jobs, or if `exit_warning_given` is true. +/// When running in an interactive session, warns the user if there +/// were jobs and sets `exit_warning_given` instead, returning `tag` itself in that case. +/// +// Currently, this `tag` argument exists mostly so that a LineEditor can be dropped before exiting the process. +pub fn cleanup_exit(tag: T, engine_state: &EngineState, exit_code: i32) -> T { + let mut jobs = engine_state.jobs.lock().expect("failed to lock job table"); + + if engine_state.is_interactive + && jobs.iter().next().is_some() + && !engine_state.exit_warning_given.load(Ordering::SeqCst) + { + let job_count = jobs.iter().count(); + + println!("There are still background jobs running ({}).", job_count); + + println!("Running `exit` a second time will kill all of them."); + + engine_state + .exit_warning_given + .store(true, Ordering::SeqCst); + + return tag; + } + + let _ = jobs.kill_all(); + + drop(tag); + + std::process::exit(exit_code); +} diff --git a/nushell/crates/nu-engine/src/glob_from.rs b/nushell/crates/nu-engine/src/glob_from.rs new file mode 100644 index 0000000..7753c63 --- /dev/null +++ b/nushell/crates/nu-engine/src/glob_from.rs @@ -0,0 +1,117 @@ +use nu_glob::MatchOptions; +use nu_path::{canonicalize_with, expand_path_with}; +use nu_protocol::{NuGlob, ShellError, Signals, Span, Spanned, shell_error::io::IoError}; +use std::{ + fs, + path::{Component, Path, PathBuf}, +}; + +/// This function is like `nu_glob::glob` from the `glob` crate, except it is relative to a given cwd. +/// +/// It returns a tuple of two values: the first is an optional prefix that the expanded filenames share. +/// This prefix can be removed from the front of each value to give an approximation of the relative path +/// to the user +/// +/// The second of the two values is an iterator over the matching filepaths. +#[allow(clippy::type_complexity)] +pub fn glob_from( + pattern: &Spanned, + cwd: &Path, + span: Span, + options: Option, + signals: Signals, +) -> Result< + ( + Option, + Box> + Send>, + ), + ShellError, +> { + let no_glob_for_pattern = matches!(pattern.item, NuGlob::DoNotExpand(_)); + let pattern_span = pattern.span; + let (prefix, pattern) = if nu_glob::is_glob(pattern.item.as_ref()) { + // Pattern contains glob, split it + let mut p = PathBuf::new(); + let path = PathBuf::from(&pattern.item.as_ref()); + let components = path.components(); + let mut counter = 0; + + for c in components { + if let Component::Normal(os) = c { + if nu_glob::is_glob(os.to_string_lossy().as_ref()) { + break; + } + } + p.push(c); + counter += 1; + } + + let mut just_pattern = PathBuf::new(); + for c in counter..path.components().count() { + if let Some(comp) = path.components().nth(c) { + just_pattern.push(comp); + } + } + if no_glob_for_pattern { + just_pattern = PathBuf::from(nu_glob::Pattern::escape(&just_pattern.to_string_lossy())); + } + + // Now expand `p` to get full prefix + let path = expand_path_with(p, cwd, pattern.item.is_expand()); + let escaped_prefix = PathBuf::from(nu_glob::Pattern::escape(&path.to_string_lossy())); + + (Some(path), escaped_prefix.join(just_pattern)) + } else { + let path = PathBuf::from(&pattern.item.as_ref()); + let path = expand_path_with(path, cwd, pattern.item.is_expand()); + let is_symlink = match fs::symlink_metadata(&path) { + Ok(attr) => attr.file_type().is_symlink(), + Err(_) => false, + }; + + if is_symlink { + (path.parent().map(|parent| parent.to_path_buf()), path) + } else { + let path = match canonicalize_with(path.clone(), cwd) { + Ok(p) if nu_glob::is_glob(p.to_string_lossy().as_ref()) => { + // our path might contain glob metacharacters too. + // in such case, we need to escape our path to make + // glob work successfully + PathBuf::from(nu_glob::Pattern::escape(&p.to_string_lossy())) + } + Ok(p) => p, + Err(err) => { + return Err(IoError::new(err, pattern_span, path).into()); + } + }; + (path.parent().map(|parent| parent.to_path_buf()), path) + } + }; + + let pattern = pattern.to_string_lossy().to_string(); + let glob_options = options.unwrap_or_default(); + + let glob = nu_glob::glob_with(&pattern, glob_options, signals).map_err(|e| { + nu_protocol::ShellError::GenericError { + error: "Error extracting glob pattern".into(), + msg: e.to_string(), + span: Some(span), + help: None, + inner: vec![], + } + })?; + + Ok(( + prefix, + Box::new(glob.map(move |x| match x { + Ok(v) => Ok(v), + Err(e) => Err(nu_protocol::ShellError::GenericError { + error: "Error extracting glob pattern".into(), + msg: e.to_string(), + span: Some(span), + help: None, + inner: vec![], + }), + })), + )) +} diff --git a/nushell/crates/nu-engine/src/lib.rs b/nushell/crates/nu-engine/src/lib.rs new file mode 100644 index 0000000..0c920b8 --- /dev/null +++ b/nushell/crates/nu-engine/src/lib.rs @@ -0,0 +1,28 @@ +#![doc = include_str!("../README.md")] +mod call_ext; +mod closure_eval; +pub mod column; +pub mod command_prelude; +mod compile; +pub mod documentation; +pub mod env; +mod eval; +mod eval_helpers; +mod eval_ir; +pub mod exit; +mod glob_from; +pub mod scope; + +pub use call_ext::CallExt; +pub use closure_eval::*; +pub use column::get_columns; +pub use compile::compile; +pub use documentation::get_full_help; +pub use env::*; +pub use eval::{ + eval_block, eval_block_with_early_return, eval_call, eval_expression, + eval_expression_with_input, eval_subexpression, eval_variable, redirect_env, +}; +pub use eval_helpers::*; +pub use eval_ir::eval_ir_block; +pub use glob_from::glob_from; diff --git a/nushell/crates/nu-engine/src/scope.rs b/nushell/crates/nu-engine/src/scope.rs new file mode 100644 index 0000000..576a1a4 --- /dev/null +++ b/nushell/crates/nu-engine/src/scope.rs @@ -0,0 +1,575 @@ +use nu_protocol::{ + DeclId, ModuleId, Signature, Span, SyntaxShape, Type, Value, VarId, + ast::Expr, + engine::{Command, EngineState, Stack, Visibility}, + record, +}; +use std::{cmp::Ordering, collections::HashMap}; + +pub struct ScopeData<'e, 's> { + engine_state: &'e EngineState, + stack: &'s Stack, + vars_map: HashMap<&'e Vec, &'e VarId>, + decls_map: HashMap<&'e Vec, &'e DeclId>, + modules_map: HashMap<&'e Vec, &'e ModuleId>, + visibility: Visibility, +} + +impl<'e, 's> ScopeData<'e, 's> { + pub fn new(engine_state: &'e EngineState, stack: &'s Stack) -> Self { + Self { + engine_state, + stack, + vars_map: HashMap::new(), + decls_map: HashMap::new(), + modules_map: HashMap::new(), + visibility: Visibility::new(), + } + } + + pub fn populate_vars(&mut self) { + for overlay_frame in self.engine_state.active_overlays(&[]) { + self.vars_map.extend(&overlay_frame.vars); + } + } + + // decls include all commands, i.e., normal commands, aliases, and externals + pub fn populate_decls(&mut self) { + for overlay_frame in self.engine_state.active_overlays(&[]) { + self.decls_map.extend(&overlay_frame.decls); + self.visibility.merge_with(overlay_frame.visibility.clone()); + } + } + + pub fn populate_modules(&mut self) { + for overlay_frame in self.engine_state.active_overlays(&[]) { + self.modules_map.extend(&overlay_frame.modules); + } + } + + pub fn collect_vars(&self, span: Span) -> Vec { + let mut vars = vec![]; + + for (var_name, var_id) in &self.vars_map { + let var_name = Value::string(String::from_utf8_lossy(var_name).to_string(), span); + + let var = self.engine_state.get_var(**var_id); + let var_type = Value::string(var.ty.to_string(), span); + let is_const = Value::bool(var.const_val.is_some(), span); + + let var_value = self + .stack + .get_var(**var_id, span) + .ok() + .or(var.const_val.clone()) + .unwrap_or(Value::nothing(span)); + + let var_id_val = Value::int(var_id.get() as i64, span); + + vars.push(Value::record( + record! { + "name" => var_name, + "type" => var_type, + "value" => var_value, + "is_const" => is_const, + "var_id" => var_id_val, + }, + span, + )); + } + + sort_rows(&mut vars); + vars + } + + pub fn collect_commands(&self, span: Span) -> Vec { + let mut commands = vec![]; + + for (command_name, decl_id) in &self.decls_map { + if self.visibility.is_decl_id_visible(decl_id) + && !self.engine_state.get_decl(**decl_id).is_alias() + { + let decl = self.engine_state.get_decl(**decl_id); + let signature = decl.signature(); + + let examples = decl + .examples() + .into_iter() + .map(|x| { + Value::record( + record! { + "description" => Value::string(x.description, span), + "example" => Value::string(x.example, span), + "result" => x.result.unwrap_or(Value::nothing(span)), + }, + span, + ) + }) + .collect(); + + let attributes = decl + .attributes() + .into_iter() + .map(|(name, value)| { + Value::record( + record! { + "name" => Value::string(name, span), + "value" => value, + }, + span, + ) + }) + .collect(); + + let record = record! { + "name" => Value::string(String::from_utf8_lossy(command_name), span), + "category" => Value::string(signature.category.to_string(), span), + "signatures" => self.collect_signatures(&signature, span), + "description" => Value::string(decl.description(), span), + "examples" => Value::list(examples, span), + "attributes" => Value::list(attributes, span), + "type" => Value::string(decl.command_type().to_string(), span), + "is_sub" => Value::bool(decl.is_sub(), span), + "is_const" => Value::bool(decl.is_const(), span), + "creates_scope" => Value::bool(signature.creates_scope, span), + "extra_description" => Value::string(decl.extra_description(), span), + "search_terms" => Value::string(decl.search_terms().join(", "), span), + "decl_id" => Value::int(decl_id.get() as i64, span), + }; + + commands.push(Value::record(record, span)) + } + } + + sort_rows(&mut commands); + + commands + } + + fn collect_signatures(&self, signature: &Signature, span: Span) -> Value { + let mut sigs = signature + .input_output_types + .iter() + .map(|(input_type, output_type)| { + ( + input_type.to_shape().to_string(), + Value::list( + self.collect_signature_entries(input_type, output_type, signature, span), + span, + ), + ) + }) + .collect::>(); + + // Until we allow custom commands to have input and output types, let's just + // make them Type::Any Type::Any so they can show up in our `scope commands` + // a little bit better. If sigs is empty, we're pretty sure that we're dealing + // with a custom command. + if sigs.is_empty() { + let any_type = &Type::Any; + sigs.push(( + any_type.to_shape().to_string(), + Value::list( + self.collect_signature_entries(any_type, any_type, signature, span), + span, + ), + )); + } + sigs.sort_unstable_by(|(k1, _), (k2, _)| k1.cmp(k2)); + // For most commands, input types are not repeated in + // `input_output_types`, i.e. each input type has only one associated + // output type. Furthermore, we want this to always be true. However, + // there are currently some exceptions, such as `hash sha256` which + // takes in string but may output string or binary depending on the + // presence of the --binary flag. In such cases, the "special case" + // signature usually comes later in the input_output_types, so this will + // remove them from the record. + sigs.dedup_by(|(k1, _), (k2, _)| k1 == k2); + Value::record(sigs.into_iter().collect(), span) + } + + fn collect_signature_entries( + &self, + input_type: &Type, + output_type: &Type, + signature: &Signature, + span: Span, + ) -> Vec { + let mut sig_records = vec![]; + + // input + sig_records.push(Value::record( + record! { + "parameter_name" => Value::nothing(span), + "parameter_type" => Value::string("input", span), + "syntax_shape" => Value::string(input_type.to_shape().to_string(), span), + "is_optional" => Value::bool(false, span), + "short_flag" => Value::nothing(span), + "description" => Value::nothing(span), + "custom_completion" => Value::nothing(span), + "parameter_default" => Value::nothing(span), + }, + span, + )); + + // required_positional + for req in &signature.required_positional { + let custom = extract_custom_completion_from_arg(self.engine_state, &req.shape); + + sig_records.push(Value::record( + record! { + "parameter_name" => Value::string(&req.name, span), + "parameter_type" => Value::string("positional", span), + "syntax_shape" => Value::string(req.shape.to_string(), span), + "is_optional" => Value::bool(false, span), + "short_flag" => Value::nothing(span), + "description" => Value::string(&req.desc, span), + "custom_completion" => Value::string(custom, span), + "parameter_default" => Value::nothing(span), + }, + span, + )); + } + + // optional_positional + for opt in &signature.optional_positional { + let custom = extract_custom_completion_from_arg(self.engine_state, &opt.shape); + let default = if let Some(val) = &opt.default_value { + val.clone() + } else { + Value::nothing(span) + }; + + sig_records.push(Value::record( + record! { + "parameter_name" => Value::string(&opt.name, span), + "parameter_type" => Value::string("positional", span), + "syntax_shape" => Value::string(opt.shape.to_string(), span), + "is_optional" => Value::bool(true, span), + "short_flag" => Value::nothing(span), + "description" => Value::string(&opt.desc, span), + "custom_completion" => Value::string(custom, span), + "parameter_default" => default, + }, + span, + )); + } + + // rest_positional + if let Some(rest) = &signature.rest_positional { + let name = if rest.name == "rest" { "" } else { &rest.name }; + let custom = extract_custom_completion_from_arg(self.engine_state, &rest.shape); + + sig_records.push(Value::record( + record! { + "parameter_name" => Value::string(name, span), + "parameter_type" => Value::string("rest", span), + "syntax_shape" => Value::string(rest.shape.to_string(), span), + "is_optional" => Value::bool(true, span), + "short_flag" => Value::nothing(span), + "description" => Value::string(&rest.desc, span), + "custom_completion" => Value::string(custom, span), + // rest_positional does have default, but parser prohibits specifying it?! + "parameter_default" => Value::nothing(span), + }, + span, + )); + } + + // named flags + for named in &signature.named { + let flag_type; + + // Skip the help flag + if named.long == "help" { + continue; + } + + let mut custom_completion_command_name: String = "".to_string(); + let shape = if let Some(arg) = &named.arg { + flag_type = Value::string("named", span); + custom_completion_command_name = + extract_custom_completion_from_arg(self.engine_state, arg); + Value::string(arg.to_string(), span) + } else { + flag_type = Value::string("switch", span); + Value::nothing(span) + }; + + let short_flag = if let Some(c) = named.short { + Value::string(c, span) + } else { + Value::nothing(span) + }; + + let default = if let Some(val) = &named.default_value { + val.clone() + } else { + Value::nothing(span) + }; + + sig_records.push(Value::record( + record! { + "parameter_name" => Value::string(&named.long, span), + "parameter_type" => flag_type, + "syntax_shape" => shape, + "is_optional" => Value::bool(!named.required, span), + "short_flag" => short_flag, + "description" => Value::string(&named.desc, span), + "custom_completion" => Value::string(custom_completion_command_name, span), + "parameter_default" => default, + }, + span, + )); + } + + // output + sig_records.push(Value::record( + record! { + "parameter_name" => Value::nothing(span), + "parameter_type" => Value::string("output", span), + "syntax_shape" => Value::string(output_type.to_shape().to_string(), span), + "is_optional" => Value::bool(false, span), + "short_flag" => Value::nothing(span), + "description" => Value::nothing(span), + "custom_completion" => Value::nothing(span), + "parameter_default" => Value::nothing(span), + }, + span, + )); + + sig_records + } + + pub fn collect_externs(&self, span: Span) -> Vec { + let mut externals = vec![]; + + for (command_name, decl_id) in &self.decls_map { + let decl = self.engine_state.get_decl(**decl_id); + + if decl.is_known_external() { + let record = record! { + "name" => Value::string(String::from_utf8_lossy(command_name), span), + "description" => Value::string(decl.description(), span), + "decl_id" => Value::int(decl_id.get() as i64, span), + }; + + externals.push(Value::record(record, span)) + } + } + + sort_rows(&mut externals); + externals + } + + pub fn collect_aliases(&self, span: Span) -> Vec { + let mut aliases = vec![]; + + for (decl_name, decl_id) in self.engine_state.get_decls_sorted(false) { + if self.visibility.is_decl_id_visible(&decl_id) { + let decl = self.engine_state.get_decl(decl_id); + if let Some(alias) = decl.as_alias() { + let aliased_decl_id = if let Expr::Call(wrapped_call) = &alias.wrapped_call.expr + { + Value::int(wrapped_call.decl_id.get() as i64, span) + } else { + Value::nothing(span) + }; + + let expansion = String::from_utf8_lossy( + self.engine_state.get_span_contents(alias.wrapped_call.span), + ); + + aliases.push(Value::record( + record! { + "name" => Value::string(String::from_utf8_lossy(&decl_name), span), + "expansion" => Value::string(expansion, span), + "description" => Value::string(alias.description(), span), + "decl_id" => Value::int(decl_id.get() as i64, span), + "aliased_decl_id" => aliased_decl_id, + }, + span, + )); + } + } + } + + sort_rows(&mut aliases); + // aliases.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal)); + aliases + } + + fn collect_module(&self, module_name: &[u8], module_id: &ModuleId, span: Span) -> Value { + let module = self.engine_state.get_module(*module_id); + + let all_decls = module.decls(); + + let mut export_commands: Vec = all_decls + .iter() + .filter_map(|(name_bytes, decl_id)| { + let decl = self.engine_state.get_decl(*decl_id); + + if !decl.is_alias() && !decl.is_known_external() { + Some(Value::record( + record! { + "name" => Value::string(String::from_utf8_lossy(name_bytes), span), + "decl_id" => Value::int(decl_id.get() as i64, span), + }, + span, + )) + } else { + None + } + }) + .collect(); + + let mut export_aliases: Vec = all_decls + .iter() + .filter_map(|(name_bytes, decl_id)| { + let decl = self.engine_state.get_decl(*decl_id); + + if decl.is_alias() { + Some(Value::record( + record! { + "name" => Value::string(String::from_utf8_lossy(name_bytes), span), + "decl_id" => Value::int(decl_id.get() as i64, span), + }, + span, + )) + } else { + None + } + }) + .collect(); + + let mut export_externs: Vec = all_decls + .iter() + .filter_map(|(name_bytes, decl_id)| { + let decl = self.engine_state.get_decl(*decl_id); + + if decl.is_known_external() { + Some(Value::record( + record! { + "name" => Value::string(String::from_utf8_lossy(name_bytes), span), + "decl_id" => Value::int(decl_id.get() as i64, span), + }, + span, + )) + } else { + None + } + }) + .collect(); + + let mut export_submodules: Vec = module + .submodules() + .iter() + .map(|(name_bytes, submodule_id)| self.collect_module(name_bytes, submodule_id, span)) + .collect(); + + let mut export_consts: Vec = module + .consts() + .iter() + .map(|(name_bytes, var_id)| { + Value::record( + record! { + "name" => Value::string(String::from_utf8_lossy(name_bytes), span), + "type" => Value::string(self.engine_state.get_var(*var_id).ty.to_string(), span), + "var_id" => Value::int(var_id.get() as i64, span), + }, + span, + ) + }) + .collect(); + + sort_rows(&mut export_commands); + sort_rows(&mut export_aliases); + sort_rows(&mut export_externs); + sort_rows(&mut export_submodules); + sort_rows(&mut export_consts); + + let (module_desc, module_extra_desc) = self + .engine_state + .build_module_desc(*module_id) + .unwrap_or_default(); + + Value::record( + record! { + "name" => Value::string(String::from_utf8_lossy(module_name), span), + "commands" => Value::list(export_commands, span), + "aliases" => Value::list(export_aliases, span), + "externs" => Value::list(export_externs, span), + "submodules" => Value::list(export_submodules, span), + "constants" => Value::list(export_consts, span), + "has_env_block" => Value::bool(module.env_block.is_some(), span), + "description" => Value::string(module_desc, span), + "extra_description" => Value::string(module_extra_desc, span), + "module_id" => Value::int(module_id.get() as i64, span), + "file" => Value::string(module.file.clone().map_or("unknown".to_string(), |(p, _)| p.path().to_string_lossy().to_string()), span), + }, + span, + ) + } + + pub fn collect_modules(&self, span: Span) -> Vec { + let mut modules = vec![]; + + for (module_name, module_id) in &self.modules_map { + modules.push(self.collect_module(module_name, module_id, span)); + } + + modules.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal)); + modules + } + + pub fn collect_engine_state(&self, span: Span) -> Value { + let num_env_vars = self + .engine_state + .env_vars + .values() + .map(|overlay| overlay.len() as i64) + .sum(); + + Value::record( + record! { + "source_bytes" => Value::int(self.engine_state.next_span_start() as i64, span), + "num_vars" => Value::int(self.engine_state.num_vars() as i64, span), + "num_decls" => Value::int(self.engine_state.num_decls() as i64, span), + "num_blocks" => Value::int(self.engine_state.num_blocks() as i64, span), + "num_modules" => Value::int(self.engine_state.num_modules() as i64, span), + "num_env_vars" => Value::int(num_env_vars, span), + }, + span, + ) + } +} + +fn extract_custom_completion_from_arg(engine_state: &EngineState, shape: &SyntaxShape) -> String { + match shape { + SyntaxShape::CompleterWrapper(_, custom_completion_decl_id) => { + let custom_completion_command = engine_state.get_decl(*custom_completion_decl_id); + let custom_completion_command_name: &str = custom_completion_command.name(); + custom_completion_command_name.to_string() + } + _ => "".to_string(), + } +} + +fn sort_rows(decls: &mut [Value]) { + decls.sort_by(|a, b| match (a, b) { + (Value::Record { val: rec_a, .. }, Value::Record { val: rec_b, .. }) => { + // Comparing the first value from the record + // It is expected that the first value is the name of the entry (command, module, alias, etc.) + match (rec_a.values().next(), rec_b.values().next()) { + (Some(val_a), Some(val_b)) => match (val_a, val_b) { + (Value::String { val: str_a, .. }, Value::String { val: str_b, .. }) => { + str_a.cmp(str_b) + } + _ => Ordering::Equal, + }, + _ => Ordering::Equal, + } + } + _ => Ordering::Equal, + }); +} diff --git a/nushell/crates/nu-explore/.gitignore b/nushell/crates/nu-explore/.gitignore new file mode 100644 index 0000000..4c234e5 --- /dev/null +++ b/nushell/crates/nu-explore/.gitignore @@ -0,0 +1,22 @@ +/target +/scratch +**/*.rs.bk +history.txt +tests/fixtures/nuplayground +crates/*/target + +# Debian/Ubuntu +debian/.debhelper/ +debian/debhelper-build-stamp +debian/files +debian/nu.substvars +debian/nu/ + +# macOS junk +.DS_Store + +# JetBrains' IDE items +.idea/* + +# VSCode's IDE items +.vscode/* diff --git a/nushell/crates/nu-explore/Cargo.toml b/nushell/crates/nu-explore/Cargo.toml new file mode 100644 index 0000000..0f876d7 --- /dev/null +++ b/nushell/crates/nu-explore/Cargo.toml @@ -0,0 +1,37 @@ +[package] +authors = ["The Nushell Project Developers"] +description = "Nushell table pager" +repository = "https://github.com/nushell/nushell/tree/main/crates/nu-explore" +edition = "2024" +license = "MIT" +name = "nu-explore" +version = "0.105.2" + +[lib] +bench = false + +[lints] +workspace = true + +[dependencies] +nu-protocol = { path = "../nu-protocol", version = "0.105.2" } +nu-parser = { path = "../nu-parser", version = "0.105.2" } +nu-path = { path = "../nu-path", version = "0.105.2" } +nu-color-config = { path = "../nu-color-config", version = "0.105.2" } +nu-engine = { path = "../nu-engine", version = "0.105.2" } +nu-table = { path = "../nu-table", version = "0.105.2" } +nu-json = { path = "../nu-json", version = "0.105.2" } +nu-utils = { path = "../nu-utils", version = "0.105.2" } +nu-ansi-term = { workspace = true } +nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.105.2" } + +anyhow = { workspace = true } +log = { workspace = true } +strip-ansi-escapes = { workspace = true } +crossterm = { workspace = true } +ratatui = { workspace = true } +ansi-str = { workspace = true } +unicode-width = { workspace = true } +lscolors = { workspace = true, default-features = false, features = [ + "nu-ansi-term", +] } diff --git a/nushell/crates/nu-explore/LICENSE b/nushell/crates/nu-explore/LICENSE new file mode 100644 index 0000000..ae174e8 --- /dev/null +++ b/nushell/crates/nu-explore/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 - 2023 The Nushell Project Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/nushell/crates/nu-explore/README.md b/nushell/crates/nu-explore/README.md new file mode 100644 index 0000000..d18a576 --- /dev/null +++ b/nushell/crates/nu-explore/README.md @@ -0,0 +1,5 @@ +Implementation of the interactive `explore` command pager. + +## Internal Nushell crate + +This crate implements components of Nushell and is not designed to support plugin authors or other users directly. diff --git a/nushell/crates/nu-explore/src/commands/expand.rs b/nushell/crates/nu-explore/src/commands/expand.rs new file mode 100644 index 0000000..8c6ad06 --- /dev/null +++ b/nushell/crates/nu-explore/src/commands/expand.rs @@ -0,0 +1,77 @@ +use super::ViewCommand; +use crate::{ + nu_common::{self, collect_input}, + views::{Preview, ViewConfig}, +}; +use anyhow::Result; +use nu_color_config::StyleComputer; +use nu_protocol::{ + Value, + engine::{EngineState, Stack}, +}; + +#[derive(Default, Clone)] +pub struct ExpandCmd; + +impl ExpandCmd { + pub fn new() -> Self { + Self + } +} + +impl ExpandCmd { + pub const NAME: &'static str = "expand"; +} + +impl ViewCommand for ExpandCmd { + type View = Preview; + + fn name(&self) -> &'static str { + Self::NAME + } + + fn description(&self) -> &'static str { + "" + } + + fn parse(&mut self, _: &str) -> Result<()> { + Ok(()) + } + + fn spawn( + &mut self, + engine_state: &EngineState, + stack: &mut Stack, + value: Option, + _: &ViewConfig, + ) -> Result { + if let Some(value) = value { + let value_as_string = convert_value_to_string(value, engine_state, stack)?; + Ok(Preview::new(&value_as_string)) + } else { + Ok(Preview::new("")) + } + } +} + +fn convert_value_to_string( + value: Value, + engine_state: &EngineState, + stack: &mut Stack, +) -> Result { + let (cols, vals) = collect_input(value.clone())?; + + let has_no_head = cols.is_empty() || (cols.len() == 1 && cols[0].is_empty()); + let has_single_value = vals.len() == 1 && vals[0].len() == 1; + if !has_no_head && has_single_value { + let config = stack.get_config(engine_state); + Ok(vals[0][0].to_abbreviated_string(&config)) + } else { + let config = engine_state.get_config(); + let style_computer = StyleComputer::from_config(engine_state, stack); + let table = + nu_common::try_build_table(value, engine_state.signals(), config, style_computer); + + Ok(table) + } +} diff --git a/nushell/crates/nu-explore/src/commands/help.rs b/nushell/crates/nu-explore/src/commands/help.rs new file mode 100644 index 0000000..47cba18 --- /dev/null +++ b/nushell/crates/nu-explore/src/commands/help.rs @@ -0,0 +1,113 @@ +use super::ViewCommand; +use crate::views::{Preview, ViewConfig}; +use anyhow::Result; +use nu_ansi_term::Color; +use nu_protocol::{ + Value, + engine::{EngineState, Stack}, +}; + +use std::sync::LazyLock; + +#[derive(Debug, Default, Clone)] +pub struct HelpCmd {} + +impl HelpCmd { + pub const NAME: &'static str = "help"; + pub fn view() -> Preview { + Preview::new(&HELP_MESSAGE) + } +} + +static HELP_MESSAGE: LazyLock = LazyLock::new(|| { + let title = nu_ansi_term::Style::new().bold().underline(); + let code = nu_ansi_term::Style::new().bold().fg(Color::Blue); + + // There is probably a nicer way to do this formatting inline + format!( + r#"{} +Explore helps you dynamically navigate through your data! + +{} +Launch Explore by piping data into it: {} + + Move around: Use the cursor keys +Drill down into records+tables: Press to select a cell, move around with cursor keys, press again + Go back/up a level: Press or "q" + Transpose (flip rows+columns): Press "t" + Expand (show all nested data): Press "e" + Open this help page : Type ":help" then + Open an interactive REPL: Type ":try" then + Run a Nushell command: Type ":nu " then . The data currently being explored is piped into it. + Scroll up: Press "Page Up", Ctrl+B, or Alt+V + Scroll down: Press "Page Down", Ctrl+F, or Ctrl+V + Exit Explore: Type ":q" then , or Ctrl+D. Alternately, press or "q" until Explore exits + +{} +Most commands support search via regular expressions. + +You can type "/" and type a pattern you want to search on. Then hit and you will see the search results. + +To go to the next hit use "" key. You also can do a reverse search by using "?" instead of "/". +"#, + title.paint("Explore"), + title.paint("Basics"), + code.paint("ls | explore"), + title.paint("Search") + ) +}); + +// TODO: search help could use some updating... search results get shown immediately after typing, don't need to press Enter +// const HELP_MESSAGE: &str = r#"# Explore + +// Explore helps you dynamically navigate through your data + +// ## Basics + +// Move around: Use the cursor keys +// Drill down into records+tables: Press to select a cell, move around with cursor keys, then press again +// Go back/up a level: Press +// Transpose data (flip rows and columns): Press "t" +// Expand data (show all nested data): Press "e" +// Open this help page : Type ":help" then +// Open an interactive REPL: Type ":try" then +// Scroll up/down: Use the "Page Up" and "Page Down" keys +// Exit Explore: Type ":q" then , or Ctrl+D. Alternately, press until Explore exits + +// ## Search + +// Most commands support search via regular expressions. + +// You can type "/" and type a pattern you want to search on. +// Then hit and you will see the search results. + +// To go to the next hit use "" key. + +// You also can do a reverse search by using "?" instead of "/". +// "#; + +impl ViewCommand for HelpCmd { + type View = Preview; + + fn name(&self) -> &'static str { + Self::NAME + } + + fn description(&self) -> &'static str { + "" + } + + fn parse(&mut self, _: &str) -> Result<()> { + Ok(()) + } + + fn spawn( + &mut self, + _: &EngineState, + _: &mut Stack, + _: Option, + _: &ViewConfig, + ) -> Result { + Ok(HelpCmd::view()) + } +} diff --git a/nushell/crates/nu-explore/src/commands/mod.rs b/nushell/crates/nu-explore/src/commands/mod.rs new file mode 100644 index 0000000..3010949 --- /dev/null +++ b/nushell/crates/nu-explore/src/commands/mod.rs @@ -0,0 +1,56 @@ +use crate::views::ViewConfig; + +use super::pager::{Pager, Transition}; +use anyhow::Result; +use nu_protocol::{ + Value, + engine::{EngineState, Stack}, +}; + +mod expand; +mod help; +mod nu; +mod quit; +mod table; +mod r#try; + +pub use expand::ExpandCmd; +pub use help::HelpCmd; +pub use nu::NuCmd; +pub use quit::QuitCmd; +pub use table::TableCmd; +pub use r#try::TryCmd; + +pub trait SimpleCommand { + fn name(&self) -> &'static str; + + fn description(&self) -> &'static str; + + fn parse(&mut self, args: &str) -> Result<()>; + + fn react( + &mut self, + engine_state: &EngineState, + stack: &mut Stack, + pager: &mut Pager<'_>, + value: Option, + ) -> Result; +} + +pub trait ViewCommand { + type View; + + fn name(&self) -> &'static str; + + fn description(&self) -> &'static str; + + fn parse(&mut self, args: &str) -> Result<()>; + + fn spawn( + &mut self, + engine_state: &EngineState, + stack: &mut Stack, + value: Option, + config: &ViewConfig, + ) -> Result; +} diff --git a/nushell/crates/nu-explore/src/commands/nu.rs b/nushell/crates/nu-explore/src/commands/nu.rs new file mode 100644 index 0000000..c788ca9 --- /dev/null +++ b/nushell/crates/nu-explore/src/commands/nu.rs @@ -0,0 +1,123 @@ +use super::ViewCommand; +use crate::{ + nu_common::{collect_pipeline, has_simple_value, run_command_with_value}, + pager::Frame, + views::{Layout, Orientation, Preview, RecordView, View, ViewConfig}, +}; +use anyhow::Result; +use nu_protocol::{ + PipelineData, Value, + engine::{EngineState, Stack}, +}; +use ratatui::layout::Rect; + +#[derive(Debug, Default, Clone)] +pub struct NuCmd { + command: String, +} + +impl NuCmd { + pub fn new() -> Self { + Self { + command: String::new(), + } + } + + pub const NAME: &'static str = "nu"; +} + +impl ViewCommand for NuCmd { + type View = NuView; + + fn name(&self) -> &'static str { + Self::NAME + } + + fn description(&self) -> &'static str { + "" + } + + fn parse(&mut self, args: &str) -> Result<()> { + args.trim().clone_into(&mut self.command); + + Ok(()) + } + + fn spawn( + &mut self, + engine_state: &EngineState, + stack: &mut Stack, + value: Option, + config: &ViewConfig, + ) -> Result { + let value = value.unwrap_or_default(); + + let pipeline = run_command_with_value(&self.command, &value, engine_state, stack)?; + + let is_record = matches!(pipeline, PipelineData::Value(Value::Record { .. }, ..)); + + let (columns, values) = collect_pipeline(pipeline)?; + + if let Some(value) = has_simple_value(&values) { + let text = value.to_abbreviated_string(&engine_state.config); + return Ok(NuView::Preview(Preview::new(&text))); + } + + let mut view = RecordView::new(columns, values, config.explore_config.clone()); + + if is_record { + view.set_top_layer_orientation(Orientation::Left); + } + + Ok(NuView::Records(Box::new(view))) + } +} + +pub enum NuView { + Records(Box), + Preview(Preview), +} + +impl View for NuView { + fn draw(&mut self, f: &mut Frame, area: Rect, cfg: ViewConfig<'_>, layout: &mut Layout) { + match self { + NuView::Records(v) => v.draw(f, area, cfg, layout), + NuView::Preview(v) => v.draw(f, area, cfg, layout), + } + } + + fn handle_input( + &mut self, + engine_state: &EngineState, + stack: &mut Stack, + layout: &Layout, + info: &mut crate::pager::ViewInfo, + key: crossterm::event::KeyEvent, + ) -> crate::pager::Transition { + match self { + NuView::Records(v) => v.handle_input(engine_state, stack, layout, info, key), + NuView::Preview(v) => v.handle_input(engine_state, stack, layout, info, key), + } + } + + fn show_data(&mut self, i: usize) -> bool { + match self { + NuView::Records(v) => v.show_data(i), + NuView::Preview(v) => v.show_data(i), + } + } + + fn collect_data(&self) -> Vec { + match self { + NuView::Records(v) => v.collect_data(), + NuView::Preview(v) => v.collect_data(), + } + } + + fn exit(&mut self) -> Option { + match self { + NuView::Records(v) => v.exit(), + NuView::Preview(v) => v.exit(), + } + } +} diff --git a/nushell/crates/nu-explore/src/commands/quit.rs b/nushell/crates/nu-explore/src/commands/quit.rs new file mode 100644 index 0000000..fa0e9ca --- /dev/null +++ b/nushell/crates/nu-explore/src/commands/quit.rs @@ -0,0 +1,38 @@ +use super::SimpleCommand; +use crate::pager::{Pager, Transition}; +use anyhow::Result; +use nu_protocol::{ + Value, + engine::{EngineState, Stack}, +}; + +#[derive(Default, Clone)] +pub struct QuitCmd; + +impl QuitCmd { + pub const NAME: &'static str = "quit"; +} + +impl SimpleCommand for QuitCmd { + fn name(&self) -> &'static str { + Self::NAME + } + + fn description(&self) -> &'static str { + "" + } + + fn parse(&mut self, _: &str) -> Result<()> { + Ok(()) + } + + fn react( + &mut self, + _: &EngineState, + _: &mut Stack, + _: &mut Pager<'_>, + _: Option, + ) -> Result { + Ok(Transition::Exit) + } +} diff --git a/nushell/crates/nu-explore/src/commands/table.rs b/nushell/crates/nu-explore/src/commands/table.rs new file mode 100644 index 0000000..e035b76 --- /dev/null +++ b/nushell/crates/nu-explore/src/commands/table.rs @@ -0,0 +1,75 @@ +use super::ViewCommand; +use crate::{ + nu_common::collect_input, + views::{Orientation, RecordView, ViewConfig}, +}; +use anyhow::Result; +use nu_protocol::{ + Value, + engine::{EngineState, Stack}, +}; + +#[derive(Debug, Default, Clone)] +pub struct TableCmd { + // todo: add arguments to override config right from CMD + settings: TableSettings, +} + +#[derive(Debug, Default, Clone)] +struct TableSettings { + orientation: Option, + turn_on_cursor_mode: bool, +} + +impl TableCmd { + pub fn new() -> Self { + Self::default() + } + + pub const NAME: &'static str = "table"; +} + +impl ViewCommand for TableCmd { + type View = RecordView; + + fn name(&self) -> &'static str { + Self::NAME + } + + fn description(&self) -> &'static str { + "" + } + + fn parse(&mut self, _: &str) -> Result<()> { + Ok(()) + } + + fn spawn( + &mut self, + _: &EngineState, + _: &mut Stack, + value: Option, + config: &ViewConfig, + ) -> Result { + let value = value.unwrap_or_default(); + let is_record = matches!(value, Value::Record { .. }); + + let (columns, data) = collect_input(value)?; + + let mut view = RecordView::new(columns, data, config.explore_config.clone()); + + if is_record { + view.set_top_layer_orientation(Orientation::Left); + } + + if let Some(o) = self.settings.orientation { + view.set_top_layer_orientation(o); + } + + if self.settings.turn_on_cursor_mode { + view.set_cursor_mode(); + } + + Ok(view) + } +} diff --git a/nushell/crates/nu-explore/src/commands/try.rs b/nushell/crates/nu-explore/src/commands/try.rs new file mode 100644 index 0000000..926438b --- /dev/null +++ b/nushell/crates/nu-explore/src/commands/try.rs @@ -0,0 +1,55 @@ +use super::ViewCommand; +use crate::views::{TryView, ViewConfig}; +use anyhow::Result; +use nu_protocol::{ + Value, + engine::{EngineState, Stack}, +}; + +#[derive(Debug, Default, Clone)] +pub struct TryCmd { + command: String, +} + +impl TryCmd { + pub fn new() -> Self { + Self { + command: String::new(), + } + } + + pub const NAME: &'static str = "try"; +} + +impl ViewCommand for TryCmd { + type View = TryView; + + fn name(&self) -> &'static str { + Self::NAME + } + + fn description(&self) -> &'static str { + "" + } + + fn parse(&mut self, args: &str) -> Result<()> { + args.trim().clone_into(&mut self.command); + + Ok(()) + } + + fn spawn( + &mut self, + engine_state: &EngineState, + stack: &mut Stack, + value: Option, + config: &ViewConfig, + ) -> Result { + let value = value.unwrap_or_default(); + let mut view = TryView::new(value, config.explore_config.clone()); + view.init(self.command.clone()); + view.try_run(engine_state, stack)?; + + Ok(view) + } +} diff --git a/nushell/crates/nu-explore/src/default_context.rs b/nushell/crates/nu-explore/src/default_context.rs new file mode 100644 index 0000000..4d80375 --- /dev/null +++ b/nushell/crates/nu-explore/src/default_context.rs @@ -0,0 +1,17 @@ +use nu_protocol::engine::{EngineState, StateWorkingSet}; + +use crate::explore::*; + +pub fn add_explore_context(mut engine_state: EngineState) -> EngineState { + let delta = { + let mut working_set = StateWorkingSet::new(&engine_state); + working_set.add_decl(Box::new(Explore)); + working_set.render() + }; + + if let Err(err) = engine_state.merge_delta(delta) { + eprintln!("Error creating explore command context: {err:?}"); + } + + engine_state +} diff --git a/nushell/crates/nu-explore/src/explore.rs b/nushell/crates/nu-explore/src/explore.rs new file mode 100644 index 0000000..8bbb7f2 --- /dev/null +++ b/nushell/crates/nu-explore/src/explore.rs @@ -0,0 +1,271 @@ +use crate::{ + PagerConfig, run_pager, + util::{create_lscolors, create_map}, +}; +use nu_ansi_term::{Color, Style}; +use nu_color_config::{StyleComputer, get_color_map}; +use nu_engine::command_prelude::*; +use nu_protocol::Config; + +/// A `less` like program to render a [`Value`] as a table. +#[derive(Clone)] +pub struct Explore; + +impl Command for Explore { + fn name(&self) -> &str { + "explore" + } + + fn description(&self) -> &str { + "Explore acts as a table pager, just like `less` does for text." + } + + fn signature(&self) -> nu_protocol::Signature { + // todo: Fix error message when it's empty + // if we set h i short flags it panics???? + + Signature::build("explore") + .input_output_types(vec![(Type::Any, Type::Any)]) + .named( + "head", + SyntaxShape::Boolean, + "Show or hide column headers (default true)", + None, + ) + .switch("index", "Show row indexes when viewing a list", Some('i')) + .switch( + "tail", + "Start with the viewport scrolled to the bottom", + Some('t'), + ) + .switch( + "peek", + "When quitting, output the value of the cell the cursor was on", + Some('p'), + ) + .category(Category::Viewers) + } + + fn extra_description(&self) -> &str { + r#"Press `:` then `h` to get a help menu."# + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let show_head: bool = call.get_flag(engine_state, stack, "head")?.unwrap_or(true); + let show_index: bool = call.has_flag(engine_state, stack, "index")?; + let tail: bool = call.has_flag(engine_state, stack, "tail")?; + let peek_value: bool = call.has_flag(engine_state, stack, "peek")?; + + let nu_config = stack.get_config(engine_state); + let style_computer = StyleComputer::from_config(engine_state, stack); + + let mut explore_config = ExploreConfig::from_nu_config(&nu_config); + explore_config.table.show_header = show_head; + explore_config.table.show_index = show_index; + explore_config.table.separator_style = lookup_color(&style_computer, "separator"); + + let lscolors = create_lscolors(engine_state, stack); + let cwd = engine_state.cwd(Some(stack)).map_or(String::new(), |path| { + path.to_str().unwrap_or("").to_string() + }); + + let config = PagerConfig::new( + &nu_config, + &explore_config, + &style_computer, + &lscolors, + peek_value, + tail, + &cwd, + ); + + let result = run_pager(engine_state, &mut stack.clone(), input, config); + + match result { + Ok(Some(value)) => Ok(PipelineData::Value(value, None)), + Ok(None) => Ok(PipelineData::Value(Value::default(), None)), + Err(err) => { + let shell_error = match err.downcast::() { + Ok(e) => e, + Err(e) => ShellError::GenericError { + error: e.to_string(), + msg: "".into(), + span: None, + help: None, + inner: vec![], + }, + }; + + Ok(PipelineData::Value( + Value::error(shell_error, call.head), + None, + )) + } + } + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Explore the system host information record", + example: r#"sys host | explore"#, + result: None, + }, + Example { + description: "Explore the output of `ls` without column names", + example: r#"ls | explore --head false"#, + result: None, + }, + Example { + description: "Explore a list of Markdown files' contents, with row indexes", + example: r#"glob *.md | each {|| open } | explore --index"#, + result: None, + }, + Example { + description: "Explore a JSON file, then save the last visited sub-structure to a file", + example: r#"open file.json | explore --peek | to json | save part.json"#, + result: None, + }, + ] + } +} + +#[derive(Debug, Clone)] +pub struct ExploreConfig { + pub table: TableConfig, + pub selected_cell: Style, + pub status_info: Style, + pub status_success: Style, + pub status_warn: Style, + pub status_error: Style, + pub status_bar_background: Style, + pub status_bar_text: Style, + pub cmd_bar_text: Style, + pub cmd_bar_background: Style, + pub highlight: Style, + /// if true, the explore view will immediately try to run the command as it is typed + pub try_reactive: bool, +} + +impl Default for ExploreConfig { + fn default() -> Self { + Self { + table: TableConfig::default(), + selected_cell: color(None, Some(Color::LightBlue)), + status_info: color(None, None), + status_success: color(Some(Color::Black), Some(Color::Green)), + status_warn: color(None, None), + status_error: color(Some(Color::White), Some(Color::Red)), + status_bar_background: color( + Some(Color::Rgb(29, 31, 33)), + Some(Color::Rgb(196, 201, 198)), + ), + status_bar_text: color(None, None), + cmd_bar_text: color(Some(Color::Rgb(196, 201, 198)), None), + cmd_bar_background: color(None, None), + highlight: color(Some(Color::Black), Some(Color::Yellow)), + try_reactive: false, + } + } +} +impl ExploreConfig { + /// take the default explore config and update it with relevant values from the nu config + pub fn from_nu_config(config: &Config) -> Self { + let mut ret = Self::default(); + + ret.table.column_padding_left = config.table.padding.left; + ret.table.column_padding_right = config.table.padding.right; + + let explore_cfg_hash_map = config.explore.clone(); + let colors = get_color_map(&explore_cfg_hash_map); + + if let Some(s) = colors.get("status_bar_text") { + ret.status_bar_text = *s; + } + + if let Some(s) = colors.get("status_bar_background") { + ret.status_bar_background = *s; + } + + if let Some(s) = colors.get("command_bar_text") { + ret.cmd_bar_text = *s; + } + + if let Some(s) = colors.get("command_bar_background") { + ret.cmd_bar_background = *s; + } + + if let Some(s) = colors.get("command_bar_background") { + ret.cmd_bar_background = *s; + } + + if let Some(s) = colors.get("selected_cell") { + ret.selected_cell = *s; + } + + if let Some(hm) = explore_cfg_hash_map.get("status").and_then(create_map) { + let colors = get_color_map(&hm); + + if let Some(s) = colors.get("info") { + ret.status_info = *s; + } + + if let Some(s) = colors.get("success") { + ret.status_success = *s; + } + + if let Some(s) = colors.get("warn") { + ret.status_warn = *s; + } + + if let Some(s) = colors.get("error") { + ret.status_error = *s; + } + } + + if let Some(hm) = explore_cfg_hash_map.get("try").and_then(create_map) { + if let Some(reactive) = hm.get("reactive") { + if let Ok(b) = reactive.as_bool() { + ret.try_reactive = b; + } + } + } + + ret + } +} + +#[derive(Debug, Default, Clone, Copy)] +pub struct TableConfig { + pub separator_style: Style, + pub show_index: bool, + pub show_header: bool, + pub column_padding_left: usize, + pub column_padding_right: usize, +} + +const fn color(foreground: Option, background: Option) -> Style { + Style { + background, + foreground, + is_blink: false, + is_bold: false, + is_dimmed: false, + is_hidden: false, + is_italic: false, + is_reverse: false, + is_strikethrough: false, + is_underline: false, + prefix_with_reset: false, + } +} + +fn lookup_color(style_computer: &StyleComputer, key: &str) -> nu_ansi_term::Style { + style_computer.compute(key, &Value::nothing(Span::unknown())) +} diff --git a/nushell/crates/nu-explore/src/lib.rs b/nushell/crates/nu-explore/src/lib.rs new file mode 100644 index 0000000..a73ea14 --- /dev/null +++ b/nushell/crates/nu-explore/src/lib.rs @@ -0,0 +1,131 @@ +#![doc = include_str!("../README.md")] +mod commands; +mod default_context; +mod explore; +mod nu_common; +mod pager; +mod registry; +mod views; + +use anyhow::Result; +use commands::{ExpandCmd, HelpCmd, NuCmd, QuitCmd, TableCmd, TryCmd}; +use crossterm::terminal::size; +pub use default_context::add_explore_context; +pub use explore::Explore; +use explore::ExploreConfig; +use nu_common::{collect_pipeline, has_simple_value}; +use nu_protocol::{ + PipelineData, Value, + engine::{EngineState, Stack}, +}; +use pager::{Page, Pager, PagerConfig}; +use registry::CommandRegistry; +use views::{BinaryView, Orientation, Preview, RecordView}; + +mod util { + pub use super::nu_common::{create_lscolors, create_map}; +} + +fn run_pager( + engine_state: &EngineState, + stack: &mut Stack, + input: PipelineData, + config: PagerConfig, +) -> Result> { + let mut p = Pager::new(config.clone()); + let commands = create_command_registry(); + + let is_record = matches!(input, PipelineData::Value(Value::Record { .. }, ..)); + let is_binary = matches!( + input, + PipelineData::Value(Value::Binary { .. }, ..) | PipelineData::ByteStream(..) + ); + + if is_binary { + p.show_message("For help type :help"); + + let view = binary_view(input, config.explore_config)?; + return p.run(engine_state, stack, Some(view), commands); + } + + let (columns, data) = collect_pipeline(input)?; + + let has_no_input = columns.is_empty() && data.is_empty(); + if has_no_input { + return p.run(engine_state, stack, help_view(), commands); + } + + p.show_message("For help type :help"); + + if let Some(value) = has_simple_value(&data) { + let text = value.to_abbreviated_string(config.nu_config); + let view = Some(Page::new(Preview::new(&text), false)); + return p.run(engine_state, stack, view, commands); + } + + let view = create_record_view(columns, data, is_record, config); + p.run(engine_state, stack, view, commands) +} + +fn create_record_view( + columns: Vec, + data: Vec>, + // wait, why would we use RecordView for something that isn't a record? + is_record: bool, + config: PagerConfig, +) -> Option { + let mut view = RecordView::new(columns, data, config.explore_config.clone()); + if is_record { + view.set_top_layer_orientation(Orientation::Left); + } + + if config.tail { + if let Ok((w, h)) = size() { + view.tail(w, h); + } + } + + Some(Page::new(view, true)) +} + +fn help_view() -> Option { + Some(Page::new(HelpCmd::view(), false)) +} + +fn binary_view(input: PipelineData, config: &ExploreConfig) -> Result { + let data = match input { + PipelineData::Value(Value::Binary { val, .. }, _) => val, + PipelineData::ByteStream(bs, _) => bs.into_bytes()?, + _ => unreachable!("checked beforehand"), + }; + + let view = BinaryView::new(data, config); + + Ok(Page::new(view, true)) +} + +fn create_command_registry() -> CommandRegistry { + let mut registry = CommandRegistry::new(); + create_commands(&mut registry); + create_aliases(&mut registry); + + registry +} + +fn create_commands(registry: &mut CommandRegistry) { + registry.register_command_view(NuCmd::new(), true); + registry.register_command_view(TableCmd::new(), true); + + registry.register_command_view(ExpandCmd::new(), false); + registry.register_command_view(TryCmd::new(), false); + registry.register_command_view(HelpCmd::default(), false); + + registry.register_command_reactive(QuitCmd); +} + +fn create_aliases(registry: &mut CommandRegistry) { + registry.create_aliases("h", HelpCmd::NAME); + registry.create_aliases("e", ExpandCmd::NAME); + registry.create_aliases("q", QuitCmd::NAME); + registry.create_aliases("q!", QuitCmd::NAME); +} diff --git a/nushell/crates/nu-explore/src/nu_common/command.rs b/nushell/crates/nu-explore/src/nu_common/command.rs new file mode 100644 index 0000000..c86c686 --- /dev/null +++ b/nushell/crates/nu-explore/src/nu_common/command.rs @@ -0,0 +1,119 @@ +use nu_engine::eval_block; +use nu_parser::parse; +use nu_protocol::{ + OutDest, PipelineData, ShellError, Value, + debugger::WithoutDebug, + engine::{EngineState, Redirection, Stack, StateWorkingSet}, +}; +use std::sync::Arc; + +pub fn run_command_with_value( + command: &str, + input: &Value, + engine_state: &EngineState, + stack: &mut Stack, +) -> Result { + if is_ignored_command(command) { + return Err(ShellError::GenericError { + error: "Command ignored".to_string(), + msg: "the command is ignored".to_string(), + span: None, + help: None, + inner: vec![], + }); + } + + let pipeline = PipelineData::Value(input.clone(), None); + let pipeline = run_nu_command(engine_state, stack, command, pipeline)?; + if let PipelineData::Value(Value::Error { error, .. }, ..) = pipeline { + Err(ShellError::GenericError { + error: "Error from pipeline".to_string(), + msg: error.to_string(), + span: None, + help: None, + inner: vec![*error], + }) + } else { + Ok(pipeline) + } +} + +pub fn run_nu_command( + engine_state: &EngineState, + stack: &mut Stack, + cmd: &str, + current: PipelineData, +) -> std::result::Result { + let mut engine_state = engine_state.clone(); + eval_source2(&mut engine_state, stack, cmd.as_bytes(), "", current) +} + +pub fn is_ignored_command(command: &str) -> bool { + let ignore_list = ["clear", "explore", "exit"]; + + for cmd in ignore_list { + if command.starts_with(cmd) { + return true; + } + } + + false +} + +fn eval_source2( + engine_state: &mut EngineState, + stack: &mut Stack, + source: &[u8], + fname: &str, + input: PipelineData, +) -> Result { + let (mut block, delta) = { + let mut working_set = StateWorkingSet::new(engine_state); + let output = parse( + &mut working_set, + Some(fname), // format!("entry #{}", entry_num) + source, + false, + ); + + if let Some(err) = working_set.parse_errors.first() { + return Err(ShellError::GenericError { + error: "Parse error".to_string(), + msg: err.to_string(), + span: None, + help: None, + inner: vec![], + }); + } + + (output, working_set.render()) + }; + + // We need to merge different info other wise things like PIPEs etc will not work. + if let Err(err) = engine_state.merge_delta(delta) { + return Err(ShellError::GenericError { + error: "Merge error".to_string(), + msg: err.to_string(), + span: None, + help: None, + inner: vec![err], + }); + } + + // eval_block outputs all expressions except the last to STDOUT; + // we don't won't that. + // + // So we LITERALLY ignore all expressions except the LAST. + if block.len() > 1 { + let range = ..block.pipelines.len() - 1; + // Note: `make_mut` will mutate `&mut block: &mut Arc` + // for the outer fn scope `eval_block` + Arc::make_mut(&mut block).pipelines.drain(range); + } + + let stack = &mut stack.push_redirection( + Some(Redirection::Pipe(OutDest::PipeSeparate)), + Some(Redirection::Pipe(OutDest::PipeSeparate)), + ); + eval_block::(engine_state, stack, &block, input) +} diff --git a/nushell/crates/nu-explore/src/nu_common/lscolor.rs b/nushell/crates/nu-explore/src/nu_common/lscolor.rs new file mode 100644 index 0000000..7a3400d --- /dev/null +++ b/nushell/crates/nu-explore/src/nu_common/lscolor.rs @@ -0,0 +1,129 @@ +use std::path::Path; + +use super::NuText; +use lscolors::LsColors; +use nu_ansi_term::{Color, Style}; +use nu_engine::env_to_string; +use nu_path::{expand_path_with, expand_to_real_path}; +use nu_protocol::engine::{EngineState, Stack}; +use nu_utils::get_ls_colors; + +pub fn create_lscolors(engine_state: &EngineState, stack: &Stack) -> LsColors { + let colors = stack + .get_env_var(engine_state, "LS_COLORS") + .and_then(|v| env_to_string("LS_COLORS", v, engine_state, stack).ok()); + + get_ls_colors(colors) +} + +/// Colorizes any columns named "name" in the table using LS_COLORS +pub fn lscolorize(header: &[String], data: &mut [Vec], cwd: &str, lscolors: &LsColors) { + for (col, col_name) in header.iter().enumerate() { + if col_name != "name" { + continue; + } + + for row in data.iter_mut() { + let (path, text_style) = &mut row[col]; + + let style = get_path_style(path, cwd, lscolors); + if let Some(style) = style { + *text_style = text_style.style(style); + } + } + } +} + +fn get_path_style(path: &str, cwd: &str, ls_colors: &LsColors) -> Option

^A7jF4&w?*{dN*uZRV^4j z@OeB~5ayzL`raa(P0io?c0UeJz_fMeI?arebi*aR(xgI+A14~iXbuBKX(RP%D!2S{ zUY5lbb&I^zJqsaBAjDmDjGJ4aVf^;c>TLkbIWYo_v#s%We!kWLF~Ice&; z>Kcs08V_kyd-W<`G2OKZs0y1e+6rt7dOVEJFv-bqfKVFJQX1*H-gs4-+fXhsx>`mI zytLMBzDhSn+~MwIQkpJ)SefuxHRCxTD_uRT+@>>gY^pbmO|(5Rwfnm`%7h!G7HK4@ zIu0$7)>8dG;kJ$coK4ff>V)iBb*A3Y+7lKHDkIA|TILsnxK=dG%YVlbSIf<@cy3>p zo@oy6?^Pz2JiBSC6A7T#dhfmj6I9AJ_qEXpd=Z5i!11$G+x9Sj`O4hiD|I9_>qVnb z;9p2+7qz=!c(AMHtBovRHwzb1>UU+X%w73nTqwkgPL4?x;G>xkUkQ5}vUv)L0KGeo z6n=PC__=8~o+IbtC+vhaix^D%$lwWv2+ZrNOnQcCKBmIqcOs1+V5tMM_9j4?X%l!> z9~oNSf3Ah4XZ7hU6xVzFYG`25E%I%|YIa7BjrF74dds{F698-ZV2rk4HOFr&hi;$t zt-w^4p;ys?6(2me%2KsNfKFBXQNP^(L)2S_MHMaX+k1u?7`i)$ZiY_j?glA`?(UMI zyBh?CF6mapp;JUaq*NNjAVp06obx;H^?u)<_qx`z?&p5W98@>!n(3%qH>rd)K0dah zPu`R_q-ZXsYiTaS8K8ruBiK3$lZ=`#9y50Hl%E$`E|Jdr?KXlSANPzO&FJ0Z2RN|0 z6!u*V8C^NMqxH4J1S$1}HD&sbwJ$^7p3mB>pTDpkezi6Io}T!?8uVq0{Cex9y&}f; z!T=BQZAWB`hk;7?$y^`Bg!KM|+4iI}12ukv$+v)+@0T;;d$Zz!bJ7exo!b-FStk?Q z3*W!YN?i8Nm7UeAzD~Sj3|>Y*;zzxqe4oNUa|NAA``UuP^NPcw!eM9fQt3TMM*!<= z_p72hvSJ^VT3@vV+xHLl_x&9YelmW-wUZ&S18A6J?b*;ij*{lRA1-XUo9zx?_^2S6 zTIrHs23H=bs!L?s!6B8OjLvsSCl1;wrJhyBF(rI?Q~CAnH>IbdvdnzW8(ebM-8{=Z znZcHqAec4qz@%Q9Mz?>V$ z!A;o`{cqO(^ez0W3=_zMCG^@yl^=<<*uXHZE@6QFJ8M7t3I2#}M~ayn#<~D2+QDsU z)nn{)*4bd=3)V`w>ocKN#NS5~o*)ek#R2vyW7_-A)Y@@_0FrCIr0?fGC535Ut;K~; zZ%!gp>}PNlX_p0gAK=izOtO0mb8-4mKyPN+W+2PbXsO&LfePb4B#2OK@XPbuO zg|d#=$HLdxF73~ZYd9QO5pH`Pel;)c`Xjjd&L|u*6Ct<4F3|pX3Ou|M+T3j7n9!pUBZBHvCDJrtAmL zsM>&)T5bA?`oh`|+7n;nm_mBk5})sz9*ODB)TXHP6u|&_yn4_V$JZ@SBOdkt3EI_e z=uDTZQlh#8lv`?k>WOo0C9uiG;p?gyaMPMTr> z^bN~h2c(?hcww?&fnC14+LeFkAfo^0+;Gc_j-3Gu#MKF z%^z!o`5h(^`(%rDYhi>p6A1U}h_0HUBdoBV9^`GjfINP!F9Co;sca#pS_txvxe9 z?-t2(ybTm!j0)JzKFEZ-cODAthx?!N#Ya8wHWR))8R9};HK=5W#-^MjJDREH&Lq=|xaQEx2Bc(O@w`Q&_!n_7eZ*JTAg|UPT7n96Ma3sIu}EkV%=Ac0(URCiTF^o@K{Yi> zo``aLGjj{~eI;xs=Ryi9pI5=}>|!!;&4i35yEnBu9^lV<8`Q3CdA#t-CTm~)gY$%l zOlg|gfr$Z=*07uKL4AT&l1`TX&3qJlvbv| zqDBd;i7V>)-Omm-ok9#(I+=-OFl1Q^-sEkeyQ!ge)9pIyaRsan>-J78mF+<3--pv} zXZ?66oSn|MR4tl4YNjLKIi0;k{R%$^?$>Zs6m2#=H_L0Od)ZCk*<5WN;i14t7|ErX z|Ez!6R1+QtmNgDPI5bFX@<}#+d35@vm)fsxbsUV@&1HxH*eDJ0%h1qKal%^SF-Nuf ze5Qz7aDhI)A|}g7vzis>1vBYezX=PYCw@j)1z}6>LrKp(IzDF!@Mgwm!Qy8!WB_cP zJ$Lp>sV3M=`j z2>?apf%Hq1VK5Q^hM4B(wIWSdrg0cpo|akAoU~%NMw=)P7IHCWW`XYUUONA5SA-|2C>a7^ogm2pY?7HB0G*Spd%zm$7&k(~ zUU1xFU&Z>VlHdCaV91goh6bS2EU)3Xx04r`eN72kmc0C^Qs7vOjHhiGXp2$~X80sx z#3;;;jREB9F5*d3rsI~$a1BqInq;e!_*hgKvH$k=QkC@x%QQRQj}dcA*N}VZm2%;~ z`=m_!ja-46p;6L4PDK(M=_6l9!KFy4Y63!n^8HR!xZX%7v5NTsGZ=1D(v}ZFDVk3# zC+QhX)Qs=VmZB++Vpj@{9=O)WW?xfhGd{c`FhOTC57#|khB`zq z`{L)Z&mGxPTFm-BB^adzKyq-RG>?E_M4s=ZQ3|dXrAWugt6w%DRIN^ZG9b%Q(?(je zUh}t_M)hRV6L}22f60M&7gPGrd1`ROzN8%G>H$%>3-Q}5t=1Ka7LjY+j&X^C@d+L_ zj(hWws$dm)4i4}WzpR+1eMGqUJX7}E^urH06>Xke(iWDlDUynWYyKi1wA~1VCWB|d^5}p#aVyRJPiRu{H zox;!E_+02M5NkwkwsTGmyptoJzC8bUnxZR%O!bUztU;+?#}m}ew`#7cW~`-gcgpc8 zq7Hu$gSq(dy2*UL6_VJK0?hYokGH(qn#oKYXzu26~OyOpv0@wi70|XW`X2y~|mJP&^ z8D{;6^D?UP=^}UeO;D4!NP+vjQ}x*S3)89Yl_RS$Nx=;_+Z##Eg$L6p76Wk1in zUySJgJ(GVEjD2TER}`ov~NuhylsJ8uL4Bv!W- zw=Cal+{_*%R`hx~pgI?a3;SFPe<5f?vy-ARhy+*oZrO7$;h5%(L1oJl;&1;%L|tu3 znA^!E<#q&cSICZtWv^aN^VDn6(T~Z!8)7@-<%J+xCAAKdNeu`@^vB|9h)S9KR4L3V z4GyqPGH0%BW}ht*u;A%Je?3e6tJTb6-I-aZe#4gx9iElxtnGFf`~1Oo9O(u4uyd+T z6{_xGb>qo#pY_lw zE^7NkD!AhHxTU^L>zVG)mM-L$y30C5!9ExI`L^x6FBcArJT99qEY~G3e^KrHh(g{T>hxq|7inH zj!m7o*8BbXj~1b#Ih7JQO(|?ud-xxcPP5Fj@bAQDmY=D=I3dJ-u8W;&;ONo0K%-3} z1#cKpOzC`TY|2|tHHz=|HN$O=;@=dJoRX|xqM2Abzq%^P^%TYZ!_5L47DNvxx{l>k z*yP(AsFFW6KJhsX@sTm&V-EWc$)!|#O^wWWt|ljw9g4kd77sX@iu)$zmLV_}+ufiE zB57c7QcI|&v*GMo@nZL5M_&b58(^Fto%rbVg^97A4>pT3I7(BR z@^#yY}0*im*w-_N`Ssd{o3G6T^EfeOQ^ zeT(Gst+^00oinfYM2SElXfNQgXcXtEXwcN?#7%Eqqew0Wn&WC!-G7h#JV#O>%0&G5 z-gs=@pp=Psx%pXHE$Cil%*PO9+=yloG$ba&sfG z7m&*AeI_x=CI$|rIiutTlxE+JK}!G?tGJ2%cXR)@n!;bwkpfC@>`eZsvb zkVI3UZ6+?q8z75q3a8oAx+@)f1WYj|#Bvz$y$R~Rea(_mrg;o=@+6=9EOFx9me ze|Q$89r*Uad$FVtanndMJ6mvOk=hDxVn&8|$e(dFSIrBt9J`?lTkkR6PO#)VGWt)2 z@;SBq{Z0VMm_VGU;8Bg>H&&seY@t6j^z>{9>{`U&TaTzyVK-Mgp;rSZaP|uZ{7-$ zzjn(fbqV~OuyDy2#dc5sxzK0Z+V^fAco>(AOQTg}?95cHj>xS|*q@D`E_5DG)ymb0 zdvNI4_^k=O`~>!HqPg>3v-nIVl)T#CA~ByqEa>0wt4HPgvD?+z$63uB{@bxnvC03; zThO`4O`$+iB0-(*z*2w0l*8&M5@Fx@M*CV>ztY|( zIwT<_lrH)xb-;egnda4L!jFLHx3q_So-ZVq*ZHEq z4nzk!&I}uxA=FHyILx@UO*JP?)qf=MJDb}ivN$-Kn^&9n$0xUt;1c6e)_4wcyZU{i zg3rDRZ3|5ppo+PZHe6;Wn-AhYW*~Ntbdho%>E@pjggQ3Z2e`O0w99N0`MuL& z{Uk|1Y7s+E{Giqx$`R_aYoYX3(*7bVLB;QkAv0R(!r753!2Sj@zy3hY#QwGSCFam) zHOYIs!JTrB>-l8Pm5Xo7xG$jL2h-570&udAR#}q+XkpZru5yyyMu3>2!oq4X|Wyj$)t`Sqm5h;ssAJ?Ln$Ib*Zf+Q!U z2O?Z+8WVSm%bYtJk57)3zH!AgSX%k~jDg^n!njRA$XL3Q*oHyZv62M)xQrEnC=D7~ zoZAoHo|SrsesuQH>lGP_qe*B0tbX9HR} zgEa*tTDe)(m;~HB_SC$wAxc4>eAT*qd7c7?HWppnMqBUFKQ$~AIlhN%MN?{-N=-#R zJogyhv)lB~bL3VP$e2gh^@Kjm!PnR?Sn0-^ra@WDHW#%tN9ecdj{@s0k}#dt zL0-n;767CD8MB8sqb;|{I}l^i5)e7?ey(e=y;Nzuy`J=Z^6{Z})z6R@iX>fkzdES{UVhg)w<|{rf9abv ztgp9DP;JGhFHcf#x<9@p&NGr&`5xl#j zHNe`g5|9kp*<}01_wq*P_)j{&wjM!99-H|BhU6(X1-}%**yt_i)B~?gwCvS+sw4ymGqV5d7H8c=bW|o+wyE z)h~YIe_f+#p92fjEMLO0ooFnYuvmpZmzd;xMI%HandMd|`*j6r{MYBzn10*FlgzgP z+uR{GQc=UdjH5R-GiPX>0aPYgLR);1Tw7~=E1@z09%{ohGpN%d@)3BeH*@Q5I8$d^ ze|s!25yRuJ^K+5@GX9hFNUZipir*8nf41J2y!;*(X+~Au_IF!n_%-fx435>m>&?To z8<*H7z{~KBPFZelk0g^!HLDLrfhNHHO}3J|mu;+;{MYyyqlQu0$C>U|Y;AppLkZ2$ z2FVnbFE^{@`p27RpPN=Vld`PPbA!3lTt!KNZ;8oY(%1y>h$!ND2 ziEOmp>y5Xsu{P1I??-5F7qA~(;jQ23mSL-%k!rra)`fnTiu!J>JxIji+U;RpI>(@%XLzlyW5d-N?8m25Hk=Nt|q!`8%lHszA1-Ll7|7Ggy8^hm!^-CvAlZ$Bq1V$+WP&@)T?j`hn z3yFMH*v3dBLNZARY_%XMj+p_-I-ueaq2fNpq2#U z5=cCSfP>gW7F6P+uOEV%5*DjLi7*_zK@c%5TE_Hs26D5Y7IRO0YAJF9*hRe4>q@bg z4$aeGxJD5H+Ay|0sv1b#e2D1y5C`&E<#U1Qam4I|Fijw{m({bN#NQb2W83}Vd>+>q zUub&P<};;3^_wh2*BWX`i`Km8z8}vuTIBZ=Z1#OxK?{$!ds$zfzUY;#U8IZH+5d>4g#pmCd(4Nt{XJdD5SyITG)E*fJi#+}L^ImviE^s+!1i&sEm<~Jl-6xc= zk&3Zpt1fYYC(3cg1B=!uFj3f+=j5yetv}vc(v!IP$+f$36N?kJ3UeYu@(qQHVN3}K z%W^bR;k($CI*^WQIEFZ1CD&&s<2OV752T#oT1uq#k;+N^A4pkkn(!ZxGAVcVs>TD` z|B%uR#J!ZJpuHKGro{Nr2$jN){k8<8(4O)NA95M||8bNVovTXJBV=#zn8?Xqk1uQ?-;G-w=_a=KNO==1zRWwIS8Y zFl8rNRZ`&@%huOwIMf+MP!<$`Jv><4qKlhyS~^0e*@CvbIC|JnMYy%mRm9VJST|02 zzSEF^_h0go#q)`9bp74CHmH<F!PMUQ9Yd5F68$ugsn^@Ls=@wCx4!v({9Cw9jAs zHjkVg25}RubB2Utajjp{|Mc)3?3UnE#0g~QL^kWH>F_r`AM1bGocYy5*gM{w;lgE9 zxcuqVba#la+l-7=*96^je&N<-E1NI%xf11u)12{myp22xkv2;l(@%RA*jMN`I<$oZ zc3S@m69%su^L@QsHGjm2TsG!1oR$Ac5f{8ZVlEJ};Zmh_gQN5d?7C`IMHsprV6Epn z3(9*SxfXW(D)giO%dbC5^>OsWc9Y0qQY$(}t2et@3O-=~&L2eVV`DC&@S`%{#qi@w zoGj@Bf?FeOe81?dyNJ`_#F3zmmX}1bkIn@N#6Nd^%!>T>>}=$hLgjp<%-Prv@89QB z%rPz(GeWPUt`@n@eqSw%cKo?s8@K!Webe`K^wCBr@yPziD+vt6!a*R;*WEy0u>6V> zE9US`he6EWoAL*bkH9otDJ*gP$_ay+f&_F!A2%+iJ8t0Pyr-f&R}?60OLRxC zbiX}~Z1<6yw+2WsIHq;1l&$MvXk)(unGZbPQibIa=V}#si$3shCW$0&S`xYhSN%pZ zWroL!;$CGV54$h}Kh9;3ksA*luC6BZ*F*zSDEgp)tv{A2ll&eA(s>)?II@!iKraUS zfs`t)Gff|Gw}7N*&`hUl;}!>DNYV!HLC>_H2CNcawG~4GMjSDe+<_yN$5K4ElQ^PkY_g^A-GV4!LQ7%1J3 z*+)YNZppA&W=GdqE|xFY-%6nL_YqtQj{pFXQWt5jk%#hOy@au7VTp+r>#7iN z98k}Dd5DHoI~6YCVE`pL2dqcu@yscx7QbI`f&W&QQGDRUD^f0QSK1Vkm&1r1l9ux^ zyVY6!(6K-s5KH47XD*&8OAP?_JHCT-DMzQ}KRHr$WfPE^2TG7}W3>$(_jZH(nSwjM zok2Gxw5rx)P=@~K$a)-uhoOmIX)a~%XPEPD6m*twQk zu`F3t5;x{;c8x5gDq2fsHQhmE&)28+Nc;ZVM#ktqzS!YdUugFB)fx2p^-27-7L+GN z5hPo;M=DEe1BC1_u3R<@ytGBJ<;@pI7l{i^seKE*S$U1?gd%snBbbAFA>&ohdxS+> z*}k!SHhX2?)84Mu*|Fnb=}gp;UZh}&M|9BI!xfLBSD39 zztM#%0jA@0hx?osnImsu;4cU~Req=q77T9L?CH#jkC_F2v4a)1QzEzF7XJ(S9ZqXl zs4vq%O@+iF$U#aXQdH^=B?SR`oR4u<^p4iy?Xd#RFPiwZ6IOUY9T8t9-*0X_a-1N5 z+ccJLSqh&IN>I!;RkCCoPFh1L;8;8|5S?*t$R@+D=21|D?iB^Fci@>BPggBmA9VLr zwdEK^&k4UaQj3`&K%Xjyg7Q!L2e>X$>IvEbTAIW@TwdFlIB6MUCeZ*b`_Jw24niz8 zYV;VduOaU?@?pA)eE;mTEe`S@foHJf_3iI1`EXS9Ppd=DoLLJ96nxC>P2O?dhlU`b zI9zU{vhC*p6~p~K>ZF6aCQ1E3MHq&Uf$*0*yN_6`b=B98^HKXh&MnGg`zYGxV3ou6 zVO)(+4EVngK7J1DA<;DDh z(YVFCXz$%E=^sXNy#N9+k@&rWS=q9L@rpFHXNK9jlJk!pUVB*YSnb7U-?p9^r%aE4EpbRa zLE&X%!1PNv8MjLDXhU*8uwW-eGPh|O%oc`#-K>Gx4DD1;qJOxA?7D{TbBWUxy0x#w z7=_)zKP*YGOj7@wBDS0|ETMEiS0wNoMfM&hs?1PJ`uXACc)Ccj-2btBQPhNf1Ujz9 z+=WT#Y3d%!ba;KBKR2ION=A(YAeduN=9~<@06n@g*3)>5n#qzZbSe>vYJsu9mdt(# zLb_j4F0 zK{ZA9GC6g%SJpMDw-OmNfsA*QOb|pa@&+lHOCI(nSHWLKS&2eDmLi*yCBU9|(hw&C zL-@@PM|YZjwTark+QB83%7ZkIRXA^yjXKDlS{9zK=1-w@K@xpI9V<+u*dLafdzbYv zKKCoEsItzwVvICV%5{(3ZGMi?^rV-IZEkj02zbwE^#@c~{;I3iiR}O;0*~A>!6ik7%W_bBAn<6W_DmWa% zN*;+Juw#WP(iXVQ2$?!?(8h6m+$*s&W*ueY>{R4*zbI7_Vb_LBdyH}VfOUG!)%vaq z?Ngsv_L|TKvVa0So^^}qlLroiNiTwub=d)FLu>^MHGNLB-vFW|KpCe=tw&X0jWzZo znC)9Y@)1~23L@CYih%S840TuXI0HGHLY$Q3pJ%Jy(I);4NCpD=_BQU4qu}U|HC6oq zf}J5K!Yf32La*icH0f4u~L!XD5+w6-Y1FOSpCB9=M$ngZG zOKXHZ6li%R=y@eT=#bclE`rbWT>GTN5l=)SYVSwwOjK%>)9R)I>nufO>Q@TeL_udD zJa#c$`<%+*bBWol3tZ=eswP6rgR z`*QRPv82kG?@y2PbDN_Jg=ZVR23rd0IaI%UU`>{H!1W1^-)zwnB%Xqyz62j%OI`19 zle!dNU-}NtU;k!`a&@uE+Fw20bv#(!ETHh;px>cS!{G&>h=wz9N1?(lEY<;4?4Hze zYXHIf+$>n3(9BuQ6i_s4y`=l?pZ#aX?{|S=`ngGypELF-kltjvO-HW37Tko$#YR2T zu7CCgl5+tk>0k}%zhG!GWMZqsBZUIBTfq(Z`Ww_f6iYbSGlIDI14b*|T#4{RHMZnF zjv!}?<2;M|3BQ;=l`&pRgtDd2_u-~EtBga-S}m6F=PvBQMui+&WH}A^{SR}i3*X>d zt?)Ve&(QC-TGh^4wL`5bxSjgy2SHyX&uH%80LJD-+~(1)7?-efi$7)&YD>NZwpCNM zU&48FQM{!Ml|HxGy{Q&JVYU3m62NHdL&sQk$HI(!)lW7eoa352Ss*?BcUNk+@uV;8zd?Aqszhx zYAUwTAjjW^S=uW8{@?l7i{PA`C?0hxtJw*mn+aiQ$6iNAdh99bH9XlhM+J2)0(gcX zA0|dl5|TmpcFGB==xWKuXqC)^?d5FQ;7lG)rmm>$?dS3a1Z+))z|c%vbjF{$JNb9i zu+L|W1AwBG0jZ}h@iR1gyU@PnyLj2yS!ML>$Cga+l36~+)($DX{;Oe#jsgZ?h4;Ij z?YW{j-FjWz2KwDHZ`{C~?gb(2X~k8O!|oMRp6H^CFbjcqK>;mO9_`qZT~jDdYq$O> ztkfiG?)lJnUpz4(@Np`N$q=vE2GUr*Hq@W)vl524A>K32j2T|DR*jgCN8VT1OO)MX zU#VwDzJoV5uq<}Rwk{M7M#n1ubiVKI^sAu+0XZML44$%tY^yKraQfIEys~?OyfPh0&-eM5T zShsgwGaEZ_M{h|J<8RWbDgivT{pphBK_jp863u9n-UYyG_5zZtsj z>`CzXmolE#-g(*B50EelR6;=sv8BFLgu^snt( zt!n!{8k#2qD+mpZ!ilo*i{ZkKEr!>-hTTXOq=t57;1pKqjZjL3E1C|x6e0hsh<&#a z{?_enJK<)oQG^od^xeD7;3l1?k_7D$w(ug00c+AF2)O$8|J5ft0Kh~!=7`#FtV5KGja z-iL$e4~UvJT*`Id^t*N@m&Yf?xTil7{{49C0K|~c#4fMO*ZqCl5G~X6AmcrEIQ8wO zs|etSDKyMSEjnc)-tLf;RGxm>qVq|n9gJm!5isA9!EdX6ENs`cyp9#|u?Ss)T+HE$ z#P`s5J$OQu`zK`$7x2JY#v@$;U(A9;=E}Pins#vGNuGs>#LHUd0&xfL1xV_pp0%FC zl5_A(5hQK;$ z^Wi=2mt~rX*1Kpyw01s;Vrxy?a~;qFMaZG}XKTaH1M(zywk|aB{4TSnbvvihz-JQD zLxRs^&-o?-Pv@h$jC$T@;tHm(0&lHbGppX=4b2?8MS8uo1V*Ktx^C@!|7Fg>G>woe zI1!vN)^9yiGIi|Jw_vX)!!mX&Uopb7zR^z|HzlS-egY}5#93kj1fs4>@NU9#YUD|N z51Lvll04E^Mx$V3v9+bL%4+Q-t~bvu;3N!>o-q;M%c7n&e_>B_V;!lyI2HeFcdq1C zv_AYtiuNrD@n|mPZZ6c6gb75Z{gX;5myGWXS#N!w_-LL?7gCBiKT4Rw_+kFR{8K|X zrKu5)dDorTw?#t-B`Wn#>T*JP3cjU*M%1CC6nX~vraXF&K{RnnG(66F1$LjnLO-z1 zwwp;`ZM8<4)OU8Ef;|9h2lSQnTwQ|Z(^Cr5zOC5Z-4od z@dP<*hkP7MzD;}d6B~0n(MPdWZz#gp^Lo+nd07cfcgglKoJF}jxAZ@oz%k#=OG~Mr z%$C4@u?_Q-xdpKg{Uz2F$$UCX-5$O(UdXW=`4Srzoav*^Y2Rmj6TT@xT3j+cj>)g(-?~rwl4yFw~L29r44MUK{SC$ zK#;q8iyvl3DIP*8=(N7HtCB)^_ctA81Q18oSkf4}p&UV2WHd?FC;mu{dn^K$vy+QN zWwBB}gYfk1LrQqv&E+0;?JX9A?a6ed3!G*v@e_%lsXeI0Y%D04gBv~05LqDq%SI~q zvqh)pR`I+^J#VueuAvu^O7M8gR^Ea`ZmyRjW|@WK zVblJ8OL7yyd8}Jvcyr@>Fk2|(`tP^Y#E=i|EzfwIyEi0+%E&!c?pa`(OS1%5_MIG{ zzu-_+?E3M;-^km~)hofRR}p7znJy`UsDpBbv6&0} zl<^|dJCzBPp66798jze-ve)yS%H-#zoaCUHO+QsC>mZ{SkVgr+02>vlYK~fpoBw37 zw(1eV2d6qikQfqVG?5lY5unAXA?MTIIl@P%om9u~)|teKX6eU(6;Z_hq6}w& z_9ZSM(PDCzbgzU#Aq4bfXNoyAfmR6)s%hdP7ldo?6i5HNI4-@oO)y#P0Q;fJEjFVx zXF2)$Oh>m|bWZsA*lN19S16VXw#22ohge$BN2Q9?bHVT2s^VBGOiZ7AHx8Ju zIG;5b!VA{sr?>hs7oww=Sil0u|Mu3tf}yw-@EJ_bke=VV!L2H5!=Y6?KqoQV(R1vS zINhug$1=0S*5TE#K?#oZAPyRSf^M>RHhDUBB(^-XBnP>KBj@A9tn$Vi+0=4n_PK~> z>6(Wc`hG(Mtj7GPdy03q%b6jV9{{jzZfZ04D#7-o8dJUgxn-0dznq(B$uP%iBj<6| zZBXMvEvWNw9bR#tMs=y{X1-f^%BmRZrn5?z;-M&+T_^6TRt- z)(iP_acS6)$?{wsH&9oEP+1R#1z_NX`c`y>0s88sCb}jLM5sPf!-o?Arlz@ZXacFB zD7(~XDO+7r-PvcTP2WZfI0Uo9NNFm!K_0ecz-$M{JAdEhU!~lTP(5-7YK&K1x=5xe z#_rs+2=yA`=cPp|;V=iPz8PASec!Bh{AJ+mUt}@=I;0{VcXy5Jx&H(Zjiu3Rx-99X zhvLNPoKWqZ=D5gx9VJG~FafSt_y-@4A>;$F|8^1CKh%YTc1B;SV@p#s4pV+yvw%~YdP)__uh=bf&hTVl9eel zMT4QKdH_tog8v<(#>nnZLn{yfo8x%>bj-5r~sYmy!~jh_uCD-f$aCgNMer>adqtO)o<86 zA8v`f@;It5-+a1jo8ULjkd#%HkM^|Xx`1V^ll&(?dZ63wE^=^tE?u~zNf)$S;qJ^jS~X=#8>JsSd5J!V2T#?LuW61 z;jPWAbNivg{4UlOvI$D0;g6JrMfJG~0N&N#zgbU!JZ27k=<3}bio4Tp-^&~)qND&-r=a(pbu@m3mjUTwc z^B+hxMOnP>Za<#}?@&9+sTW{Q=~6NN-BImFnKR~mVL~(0Ilg<%hd0PW`%Eooq^%nc zLVq(1`0jwSw%$xnzniT%rV~n@~ot$roQYg#y3_>e!3)#>8h)BH(ea+jPvIK&Vb)c z+V1Vqzy;zbwZ?-d%|?u?nYu%MX8qqE6=>WO}=<9hGvh2w({B1BYyiv z;cP#Fq*gLW3Q%QR`i?gK~1D7F7SJ1`y{M44s1cxb+#JOJEl{7l+$ z-xSyyUcjil(8MwY=dllzd9kBzNy(Rfy$yEZ^)yD~sB-JCKT-+d8k^FY5`|K(`XoOS z|NGUs>W2vl0%mG>0TDdukJ-F=Q?U>+PVX(KL4q{k9EfA4PU;6&jhQ)M>hd@l!e=!! z1LI7MXGm!kDYVP|yD$unA~AUT;a6exUhjtgT6v%N{^|k^D!LIc{LP@<4@jnA{4^fQ zU{y?X45kpGM3*Fd8rJ&0asDHyVMz=NyDLpN7EFp`giG|~evD60K=yg?wZ>8-d}M&#zx5sLzm-+u<`;i3*kCY;UId@cUG3njFKG`K5kBSKtRNrATfrViJeS4`6++c zC<_RcR}*b)*reqXHFh~b`j#>Vk&Nq*l9^WU^O>?wh7eP%Ja8+M zz@0h^DokkV=-^BFvy(DQ%Z2@%I9?M`&w^Vc3J5!-=KD?8gr(#yO$IhAdym30*YV0= zskv^rb%R9tmbeK~sUn&%Jh0ve3(9HR zE~w|n|81$$JE%RROZ4oi&ahMV^M(1%b)AudhTcCqqh3VuB`E_83pZ$rN8$7n6zOEr zxgsh#Q%@G|{O0wl7bXZ6%zl%iCv;O-$k-k-&|K&)^JkC!Ngj_P5pWmsQz5qo;o3Yb zNLR(b9VLITORfMa=%6W3mM-W@kl64l(0DWThF@>r2EID1izi(8m~BL}w{YV+GxifD zF^J0kQ@?|Bk<&w}M7JW>Pety{MV|JrKHYg0_>xZT$?1QGWUtzgJpQ~;t3n>*&SNtx zo`RrBFrrENMD--UBneGpcbS^8K{NhoC@n{-(8d4?UASQ{|Bom&l{TxSv<%MmZ{YoWL7OAD> z-b4{&d8Z6Dmp`ASUz=dc8lx#cNNr3@VNQfi4k^5}G34o+J76zNYkD&O5SqNjkahcH zDYpPPNq_$k8ZU~%wPso^sX#nX5Fx~UzflpHPa6}!^jUNKpA}RHrM<+84>3#mwaat{ zV$Moo3FEH13QxU$SalQ5EIXS2^X_Mg!V6}lujs#@n5}|R05C3CgaxF?f@_G*MzY|< zDZA5FDOaGIa$Y21Sac3qh{4qYFhjDv;p->H)|mw3ri&@(aGE?gT}y{F-|_+0u>MIb z6HHaFoIfT|4D0qemZ-Ut^B~_`jX+-N7b!~Knb?+5zBSk|Els{8qEnKWR=b()`npSQ zvsV5WTP~(vS%%%gx=uZ!PP42|o3&ndvu;Q8oq@wUFu>_V%4up`@8-^d6QNw3!(qj0 z7W$UM;WG!XH4G(CAC2L05aD!Uef!Y60rJ8un=r$sZ`qcx(UT12B_i3kEL3@79#0Mk z;I?A{!_S7yRW)&oY+H)&zQP{&a3wZXL@5Ixq&^jra5&6>c~IuTs~k%ArsTAy)Trik z8EjgemaM(lY`kW3n&!MY+yY~s@(A(Bgv}Bw@v@qh>}tx4L8g0qs0YAXZCqDF*ALWh z)^~3<#H~Bi!<$>0w>)3m3q-FGK>HD$*L z+8PHz8?0Gh@KC06((*`eAh`0cCU_PscXGi|}&2Y5$uuL)(dPegF*kqtk|6=<>VF zBm2N9eYu~zb~^j`B0r?DbU#LPcWR1|lJ+ORN77*Jj;5|#VTrh@JmKH!7X00fpzoQX zXuT2G>kWHUmGbDI{84+Ws9cZe1GY3&gwcu;WN&Ch5{NhIbSOXry!uc+$ZP<2QOE0 zXVsGd`xglb6`e{s6^Y2h!Z7DDshvn|sCkK)q4PdYk}a5xuo5k*HMC8>y@qd`#tK|s+x{O|jC?$>*}JKvcX;_|8lqJZqwZynpYM|N&U(Ra0vQFZ@8bokv!b1=F43jxbH3dU8&AB!l?|i8* z_dnzEI4kkpZmyEJ8j>XJC85kT8rUsxMf!Ewq~+c9D>#CV`leus^0bzAvR^ zvha21@U0RmLw&yC15e;K^YOubDS(7?{Di)?| zo;8VbE#2B97n)r1=iS5?=mC8YLYyKAf?~RLT(BJwZ73%!2$MLNcz~tIccy?vP820g zu-8w}3h8%O!m`%%sxf+*SaTBclLmxH?#q-G+``$+k#LXUZ7Z5rN0fMsVW}n6rxTls zZYtsW6DoD1kJjk{57JLbr|N2I>R&E5^3!zlhlphEJ)6k*hM#-Mc=Orr%`QVb<@%p* zsIGB+U5Scdjl?flV!glS+asOvBVDIcRozg1FX-qge5`wU982fb6l$7rI$nvBM8~r9 z(Xw}B*Bp%X4wBCvhP;H#7(O;Mq4h8&PhHNNL<~_j{LT@ZVX0f1ejj=^6OpShKi}Cf zqoOgYc9|=?XQZ{!$3SKLkZo3~;>@Hz^cj4$U2l@kmFZSAQ$W z_6=rtGiJ{qX79_Cqi$wD7xT=Gw?7Xh_^OY{}BXpgSA1a<0{6epImq?_Gcnih)Z$f%&`@8F=ob6|d_OwqvHUT?fq z9ei>xsp_d!maao>7pK&`xzW}F_{d!KN0Pj1nF7~4sRz}+wbhaB$q9?y@$G6SB)**@ zx7>83k9sRG)I1ilmM{a$UqKaSewLS26)(swuQs68%ay+!lMJ~Kz9_`QgQa7LRSmZl zboD>WZ;l%RNh6;tGb5Ja#qOR9=gsFfwf|MI+U@r$dE~c3MTd|Ub4ZCu3eJeQA?b1f zU(wS$B>wSTgh?6gX$SL(cmA>$T(_M<2KXM{zJ>9%iLm+~+^v_x|8e-1k#w@L`7P6- zRp+LaP~yK7OY_bY^hz>j#im$b#&bm@^8IZQtdna}GSkW)FPp%`6u+mzc-rTpfsKH@7|^G2_9u$NX9|TK8{@~ z6CAP4r)8?q{LlmffuebFnpFG!%&dewDti+1M!V6bImjzVGO7vL=F?_X11v43QPYT> z5hcOjZe))blnl(`3;5Qg$?0J0 zSth&;&QJ}dr>N^9`qpE9JQK4BBOXSR)9oBftE0dhdx`0(WQ}19%a`Av$bSc+jvJfT zIW_bA;0>~ja7p0E31>>88(^&lZm5CiJkGJ3>?S;lL9^;#RPyZ2ff%;BLbn{-x+1R= zL4?_%aGX}CfEoFE7+I}(eHn?F`@Au|88C)wUMcz%N#2wADN2$nnEnA3@q>@oBX3Ri z(qb(NfP}qOMV1{aQY_#IGWi~x*Kpx(g(t81H9}Ag)sV55garMLivV#tQ>dFgyyo6v zH986Pn#X$6PfN(|+qPAu{HARxiTO3%((?&6pWF1m?OEdgK+;D>af6DV+oN;La&_$5 zp6@*=Y3s*lb1;^G`jYovyraWLQ=f0%A)%{gL&q8`1o%2}h<77CJNXsVprUvOo;8-# ztjuYSKj4`3-6!?`q=L zF&!03gGMN5yH>TH#%roHBvS*ln$_qSOu`CbN_W*BW_E{IHb^n8>)$kHUw*ZsC}n7B z38z&OC?{FM)1NEE`pd}TLV{9D(y&VLZ2Uhsf6PBzG5p6=?ef$G~#3 zGA)z-U%%77rRo3Q?^L+Mwofk8M(8lNX&91PnJ>ICMw*@CUc)C_3*6l1W5hv8TMX_` zTDF;6W1DoPsG<`LE{3Iv>nCjV^9AE~V{Vkb{kT=R={|5)x~Jx}&uzvEkeS+aP$v$* zd1!c?#JS?~P(W&w1=EqD&1ryyUc~TOOC`&}-TBzyBdEJ&)Eod0;6MWi@}Sf-@7fkb4YFwHfTduz|MtLW1=tX zIPYr8wEEr_E#_a%C1Iy+!(L8-T)HaTsC)R-PAG1R{$k;o&u@Jb^tC?1nbr)Ij{G#} zrn}#tUGY~|fV+cu2dnfXdsIh2`u2_Hn7n5keV>diGHWN?iC;d>K%4$SC12Opz~|2wTK(_p zf%SHbOkU%LEhi>Uu|`+0$Ukncv)-HDP<=R@}lzo*~5yLZ!RU;6yj z@AapJhf|+>exJYgp>D@f`Z*^70HCKI7{fP2ASXez!UNi4g*crEG|sST9GyRHl;A5v zJ_b!oShT9&<{!a`K}MbS_`wl^w2{IPQ$o8rDuB* zQo;arJ0Vb>n0dG@MC2bOMxayOs1Rf(IB>+NNt%ZPPJ*L0sxj$}2^E1Px>7z!qt071 ztyBW!&dZ^BbQr{lAbDoh0}|IMwL5X8KczOI1QPqJj5bgw6Q8!Cn{f^*}z*}J*4uwaiN!m@$9Dv*fAA` z>Ou4w;M+bmcU7cs8WRS{bX(HzozGA1KFzy7bYSq6;zfSJX&svie%$*IydaofqLl5~ zMS4m0>JImpn4GVXBjz+qeM}ws*w-$+1oAe@$#2DHd=+^msEiwi)sMg3CDC1-ate^b zvLc8{x_$)8hexp>eb+$s(hjFo=&)%RRgAWR>-2>!1PyvjqH&>7-hQx%WY&m_+e?I6 zMvYK0yCm?SUQ+i}OZ%8gBS#=JUyK05!mmJR=g_pNn0>vxj?^FBUN5$htLOx$|T zZ0$Pm)kX3T*v6S*A0y8j31e)|9RXCpi6tx})n0mp!1l)chHhcH)#2e^8y(HxBXX{G z_^K~EVSp$a}v}prfFiM;ynw-}#xu%MYrpgFN*1PP>5{bl8G=FJq z779zDXO0@tkm%Ohpfcn0&SCcht9aA2vhvc4@G@j*i$-0~5#~)Jl8Eh8qd@{U<$_Xy z5xfLf?72o9gJu<@xy$#sv8P$1?B7Y!vqn|pV%SFp(fd`Jb55_3 zK=!2{FmOZ_D`J4EH2=Yed(Mz}5MZa<3$+^Lr4y({UYO>kFv}N)L z2p)orxjo>@G2&X{KLQ*L{zk>U#uXR6$vlYW_#zCoP$0D&8M|#cYL#c;89{23qz%f7 zx3$Uey{0|!@eUUmw+%;Szr<&iU5kCRwXDpqDM(#WWNr#$9(rW+Y5AUkI`ZHr-gAjQ zSMka^aM^C1l&ciKIUU}rRcvJ$zh({nj+2DBz0fc6(7;XNO9C}0ATivz@{_jxI;o+^ zn(o8H#E|YMmsvxUPz=o}{?GIi_|m5M6Ej`UaZV|SaKz}k3fQNC|7L%U4KH3Qp}g?^ z&;|tek&sNU<@Ljls;OV6GpgN%77T5N~KAzGGdP3Lk?DMgS{EI%Uh|*0c?F# zc!#AD*#Emyzcv%biOABZ##&C+y2BozlYVmDBzB^1HkKMp9eEz$)28E$xfOU?S72>P zWu`|4>K7?ykaVhptw6!4&a3Jf?9`9Aj2`FIUVQ#DTxy@#E!R%35TorHs~X1pLjuS+ zcO?jLo%OCwy-IuXIwHGX#c;&XkP=ZTI<%XbTxXc$`G*zr@XOvS85GO^(RTr#rMieZ zTk0L^RU@q{CY1C}K)|FY6f+)06}YQ0b5zG#NVUK}Ga2C(oWT*I29Honw}X+s4P*!p zj(3=u<6%!v6@2G~o~cuy*557x42_l@jNbVfy-!O`>fOszns*)Ya%(aI*_a5u^D=)$ z4L1MaP0hJph}>{ydltIOmFy1U_a=7F*F^BIc#A`;y&aBO8-U1}gaq!;h-}S1Bj&%A zc_Ia0sv0IxNffrTZ{24>;uA@XF?*GIA?zYPr!>umdnOGuU#CBsGA_@}&D9~kd_(D7 z`Ww`i(`2w`9(8MKTQQ$Rte-$d@+W;yUwWaw^E_4?FK{(61n|H7_|x_6VjjF@j(dAS zxIR*u1DN36?A}7GCfM$Sm~iq^^OC=7&Xj3*2-KnL$>VYZ2x~H=B$&2R(_~S0t|bfZ zvjQizg_HTr)d$WgM8cuTSv8ub-^8q71Jx$&S(F1JWGqUIRD4e}l35C&M zq>N2>MHpuT_cFoOQ(LZD$G(uKtgb3lRN+D#3tn-m>g5L?y|_vdmr5~LzjNos)5 zT;@n4e<|$|DS<_4*<9fwe;NM~YSUa<7Yn|z=?tBNQE3T<RbExG>LY}w2m8$8oo9$g|{Y6k<{&kcQ?oV26<+rsd$v|5AIJ&6SoVA!{ ztxKr{C2iw}v~lRT3P24Ld*>)eWNC$pOTGGb=PFLvQAh=8Vh zjOzF#H@dD{k&9wIq?kResy!cYJdoKo#T7J|Ljq)&Z~qnbHH%XScvpuVb9`>-H^a=o z`-4ujE+!tSt%UB$ze%DTlxJI1s0tP}2cVU@`^hYU0=Pgr7J8P^pk=LKk3bNoAZv9; z(BV^Jnoj_uuED3CHj~pI89ss$c^%H6$6?DD`#PxyoWQ;1I=b^?MDxwDu@0iNVE^fl zyDOw>(V9E)8m{^8@2>~_Yr7>-(y>5)BB*QG!hOO~vMKZQShE(i!kRG?c*@y@ z;O`2OSLsDMhilMmQZxX>X}@_FBM}@GvXD(Vlk z7Xc;dRWr7QK!y7Dhw?MquW;?kzr&ReN>t@TAmVmx@1^Ctf;EXcfSw^OI;}p1ONXR5pQ$*E^l*-bvD)X3&(jSib@)7i zSPn*)I+&E+nXbIQ<}eFdAEV}q@93EykZqxcPb51?|2xxhDCJQZC)>vH;2bb#6jRSR zr{g*8S9*r>H5~U4PUjbZ)tr!j5Sz3MOcQD05xW$GYHw5(Yct~9;n<2bF6$hn96%^ zZKjN9&NdZJCz{|HAD&2TkBQf96p!7sz9d_#X3_ z`%<{&Qn(_)>+YWcrz@YytJ^ttwCCx!N>T=Fh~b;sS5AOV+XH4#{fi5*JLlTmz5808 zanVSaF%Fgz0yy9Y+IKm;zgAu-0F!iuyX%k~O;SgMAF7(M^n-!YwCWk2xQ>Vejp#x% zK5%3aAg4TZtcuD4it}78T&9(zlk*FpD){dpHo*;gITvOX7e-@VH9Hq&=c;SA0{Xy( zHN%CDd!w?tO1_D=wPWK|jI4#_5OaSKX9|o9dBAmI&UeE5W zL5|&{nyevF>XBqCr2Hcc{Da)vcf3dZmd5;XGA3V@w%US}D(;2oNocv(2<_Ira2IA( z)J+-D?X$aAI!9UYy@vC{mxNx8-jb0SU2;w#KK+0-eKlQRPXAAPIFOZi-~HGzb9Y)A zHFTje%YWbLhpYY<@<*7t_s}MbepAaF0jq`DY-fQSzgkCQ#^f4p8#%AF7f`3V+L3bz zqEUlydsu%j$}rpe^XYkie$e4I z{fpUHlqsWf=hTa#(#q9sPhTC+k{7$N2f~Z@4hjSjq29a1>XqG+pUD-b+(*y;TNzgS z%9rw0>%SjQRm0+oYMm#!WF7{3KJ88#{KYJU<@9Po?Rn3k&SL9Be}@;5;vjISGFrL) zv?2VVN&~$99{oWghfk=TdQX;+UfJHWxKzhsk$n;@D4K+VStbJRq8U%gCKq}Ecf}@C zgMf?kr>;8b93V!Z{eL^40GM!{tqzT6@sS+rE$a_y<|FkzS$hmp@BkG}>#8}tW&$kk zWPrvD8jD!Oa8@DDT=~Fi&7Uk8Swr1HxhTZ|v7(f`bY@rkZnOw|q`}hIcE9xc2)3kC zb%2#1Ob=P1Q!`bS#)UN)l`7r;&3_?#xYFrKq*izdmBN8QVD!?|QiL-Ax_?12C}xT) zjLNRelb9L801OwQTx(I8hCnnc;Vh-GsB3SUTr4brv;T8$QqE6^{E@8-iSI}T2UQl~ zx(2F~GLGB-x6Cd8X;7_J%X{|Yi)#!mBN|BH_PoIHvfxR2A)pC1wekp_M-Tu0xja87 z^56kdPE)~D^p_OAXirz4=DhYVNs@)Ek)}8{9jP7CY1ICKPz*qc7&?Fi3g=r|+hU=a zGC8n(dBOb#9Qo_bCefG^S8W)pkartEMrON{t!1v^9`gl{5&QvuYu;H zAu7_G(v!f$zZl9Jyj?$=aH;AB5W{ZuZ4DhRUaC9-$V9kX)jbwcds zg-oNVaFV@-9I#xxjYnDjJ3IdYrdwdqe&`@O3xA^qz)Bbq0_0e08YmPGQsb$A>xH8r zWE$}k3=ZCYHp3a>Fu>x=)uiliI34G%8}hOr7#nuY80awx@(6zdYuK#sgqaC#Zm3e( zwQuQ>FS~QPUnRD4-waD0r~#CVA3w*@o`jw)KMGdm_}0DbSn{oxa`g=FD0`we=1iwR zpQpbRW6hgoaP={dCUKI5$VL3qlY_LSlsHR-a>{MTmoO$^Gkoi%7E!R$@;t_v?ud zQIrpT_R?uYG>GGU@r>;w+@lS#+Drd7$#o#0rkjehIC2)+w2vTX*Cfr8**gCpuq$lH^<0-F!Wn3k= zMvx?iRr}LwJ6~#9n-rT3GqQ=~dMLX|r+6KH={PH|2^boTm~SErZQw$hLGPFl|nW+^#=k_+waRf+%3Jr(`4)dIOk8uzz%jl^{xX+-v{26sPY~?V|PUR?+ zESUHv)m!?;H5(@O%Z%2=z3LH6<1=?5-K3`;D4HT_$%Sza_Q?5!=a)i!lM01_S=Lo|2~bYS+hM>^H?Z+ zFf?(SdeFd~aDQye(#VRP0Yfu+6q^BYCNc7fRUeNplJtnv^|YKrQb%$saP67Ys#KTl zhA?Mw2MIv5p?b}`W?8;s<@EP6Rk6|R=C-F1WN4V4wy)_7)VW@X*UC7^4o+g|Z1Pih zUn2stn1E-r_#jqm?6kV*kaF6fze890Y1{ID38sgguckt{Nmn^jtB;kvE%^wbK{N!n z1;vYUfwp*XvMsI%1at1umi6<={0#4A(YBSVK}(LOd{k^Y=Oh-71DEI|4 z>ma>iU<{i>FPS>)5dL;xoUm9H1*JP+;jE+f9rp?LIZ$?S0{fnklR#U+N*q;qiEcaT zfoecq>GD3d@C@Mw8NJ?(P?}MzWd$XC_*7U9!;pw69J<7`uukY(cRtFBstA|j*U!pb zV@_Lx<2-y2vQ5hnRF+}9W!%(Z=W;wrV7!6#eSh$Trd(XR6A^`@sSHg-ds7snY{sU@ zqG#3qZO|%-Tg~`|hj?=0)9)2Tyh*kWZ7o*G7Sg&erb>VphxzeJdfHaQB4xC?RkFIX zG<}PWv+C4mV$#q`MoITa(ooO>>A!Jr$+ZQZ8 zXtT|}B&(ACT2&cEa&J0@+S^;ZNU68ceeUEY^g?5iJx2KZ+`)^}hZB_dN_>6PIX9hy z`!v>m|KBpQK9*j{Mk3Y!DI*)6Z!yYBsQ|V-5a49eA%%6;Q|Eg{X) zI8vn}7aFr}>DhmQy5bquS6f1lE=k+*f^%lH?r>zGi7dWu-!kwS$H$wF!|s$63sDg& zMEBKWdGNT?zn|n?#48uBVi!ti0Ln(-;-4{yDKK$2A@M4KF$oYh-=IVO2yxKVoTUaQ zJA>+IQp01kc6YVVXhDo-m>?!2YSTobvX7=pJCyP^UK5mPOWKH&a*eO+A z2dR`8&`*&%(m-7J!%EUVBcVVcmaLz8gGb22NL7^qrS+2|<%E zNKbp@c@Y4zKi*(Ja(Fibd4{>+n8Zi>eJKe=)m{B&;A$@e%BJF}`{BAI2zrU7TV?g{PlJGLafr|F;FAj0|;%t?~a-j2Qj2gv+( zY0`Yb;6a`h4X9kLER2YA=f18FB)CC3m|}*FzT7cE16&3AW|}(<+u7XTf>73cD@ww5 zxHT1jfgT+-BWM6v6OO&6N~X`>#68yM6(3Lfrs{7qi+(9BTL{3ZcvQy~Z%k{8#5ZOSiNjg=E$H{C$JQJov`KU6l)};%nYV4X;j{YwGGI z=es3$a^piNQUy->gB2;ukGEWL$z}IYBpfJWbCon>)un_niXF;ov89o*8lo0Aj1PF) zDC*Dz&R5aYy?~@!ioDzDSk$7zM~^fEv_ih#0H5i53Q&hS!kgFB;G2P$Y5n+u?+$I zKoejyqD`i$TtBbyjo;dY-wGgT^H&2IBMjY;CBOj4fQZB%vkjZ6CAtY-wi<=(qQwLd zH?)oawHO^^O%hzCICAa6z?M)MQ;ryc3%z+={3T7}nlUi3AccZWGi*7Zcm`>AG+G7bfGk2Y)j+q^)&4oJislrJ4vK2+1i>fNgbSz zlsf2dC59^B3q{EEk`4(>vEu2t2T28;?S0|mI)hHAO7bLUFhI6Mwkuf7hFzDjDy?&0N&aSC$7Hwb@ek|iJ?1$9crDb}-P@(1Jx0fRdZ&<8zDwxFbQd3V1VxS!>maKMgq~yUQwM%bmqAv@ayGc@MT1 zII918tH6*ajRwczz&b?-q0S){|`hhQM?#Ou-NPsBeV z99aX7Mi0rfZ_KeDjfBDkQQ_iA;pCdJ3KOwk_8unPi!<1dGxv@+H#3>4c?XNJ*t34H zDB^6?W5wovTO=kWE-8uIx;o1{3+AI;j!LO(NcqCzDu+q!n@F7qKFLFB3Cf4QGs4|A z33&;9Qm82`^WA@pfpNuK7lO}_;LrTkFl$FcC2^7cP%c1Ycshldr}0|IPqu7&Q`k-+ zV=SC+-I$+aQlPd{Anl`>sQEbJ&10Of#^_B@(wo983gnWNP%-hK2(4e-aFFZB+T7d7 z-7hQ~d2OjE$W9)VE>QelJ(weeKNz;bQ;i^`#hI0#?29y|-JD$|YclrEucg|onU1Y` zh!H}HsAO-|j-)>EK3igLsw$w#Y+bAmowNe*PdW{i1!J4id^61ak)BO;YSoRwzV#|1 z7An5dF}|pT$!sfu`Yhi-=vgkc0kZPTZ7Yu^iRUSMG|gDsSKV8D1F)8n6sA$u$5WyY zOun}M^KH{PQ~%y1j>0_s^i%C>^05$zE>7|3C-WhLLJ7K?9l`h2Ih(l=sSDvn#m}B6 zbSv_jPW@7&j6c)rR=O#Pd%6?H-^1+!)=9nBfBMY2MarE>S@yiBG%(dIgrWF(QN_-i z5<2jU&gQDxdp1~xsl9G~3G!+gn|;rlC))I$()<4OxFP#dKo&yIXns|DBFV7f?8CE{ zN{xRq>fd|_Hj10PA_3a`pnpi(-uG<>H?&bx6;B;bL$=%ek9eh#b2hCQ@3W_(;Mwi8 z+3BrW=|LE|>)YRk_H@X0w}!Uc3v-?K8(;ih^Q(R8L!4^)xz!~c(|qjK^;oR+jp9OQ zx;jMO>UFld&E3!n8Kfo$MoD=pBEFsU2inA@iPyFJc~|>qrEg3A-7eoszqq`+IP(Vx z?}Gi`M}B)BGsBzEx>CNe;*j3v6ZWC^sKCR%+eg{@;eQzXi{4R=?wLO?zV)seD8DiO zPklna=STIL<;X{4oq?a#uQn(K=v-e<{dpyo-a7Zfe0%0~i1J#LeV?xO%Wu@5PmSy- zYy61*HB>%?+4lrBnT;<@eH5-2c!d{qoF@t&dx_Pr$Nw8CI~;i}Hp=C?W~dw>`h8P6 zU<+rwi!t8rFW8Ks*(tcQW0;{x>4R|nzUBR0EJNa;fmo}gNizoFZHqSEcQ4J$eYsb7 zwd5SN@5w1+nvsNac;@Bt`X1^9_1a;#(lmwg$UUp2qkzT!(IvsHZ`PuGSr_O$WnRu@ zWlN*sc?ZO4Kno8Ne^X`pa<%!b3TEQtYs$Z`V?W{rVg|gr1MVI@6!>w}iT%k+YZpm+ zTktI-N>@t(g0gl!R*;lcd#a+Hd1}b7ETDRZek!!*dAimmBK_n@@OB`hmpCjj^WC=q z-ppnm>P6Zse3&Yq1qG@-IX8!;1)CrJW@a@JAw1QiCKApfr_(JhqZ)de2jqNUu64 zTk`&`(fdX^0z=K`9zVjPzwfQ0<~SZafA2sz`%8FHI+vR!bT5=oE)Z+)>B?Kq}6B!)A`m;mG=6_by-Hminu&4&1w=0%ShrWOs+5(fs7)NqUU` z2s06%X}O&x2xWR%7V+_vstwck2H>V}f{MNRIU98O?&C z^^u?H)V^O1EZH%TC^yGQju`=~fF5)Y~*Zz}BWrC#o&(u#K>c1o4A8DUe zw|a7zDe=rfr{F(w3szMu7GdtHW%?%EBIzBGR5ol6n%M05MXSvK$4Bo;Z`~+9w#Ss8 z)n<#L09)?pN)#cMiDS4**aMZnX?e=eaWkru#R-gGk z{j_c$*7o@|j)aoiuBIL^MId+9GaD~} zEYbRYGEC{Z*$u>>yNUt~n{>_Sj%=65e744mh3?JTTb?(``#ti?5Ldy+m^Ih5Yb%!p z*bPK=Iqf}PYF%rlu>0F}ZU8I;;1hzf6#>JAq`kW>DpREv7y6W2Q{kRP8&33R`t{=I zS2nbHBxygnQ{?4ZP$laP+xNE&$d@X0_%2Oj=pEci(HbOzq(}4y%A^Q7Z5msCo(I1+ z#u@a-Pao6A(mWyOH6qmuH6ijVRCxekgu}a;shpY;aWb?dTU3j(SYyS4MoH7(zXW zOxSsB|E`EDSBF=wKIbzC0Z@5&2fyXwXv+I!NQM-^vHlVB5L4^7IR$louDwUg#_@0I zrr!Pz$j{*atfb0(h}49x|~ZOlN!%y$meCtles+!)NL5r2lH zR$h!2p!#W|I`i_Fo*2$r`jeW&9*UQE;W#7wzRA2`S;Vo!;Go89MOFVeoOzg?Wg@yG zCEzxbm#jxIo7;4gP2iZ=&*>Xe23}Lh^#dP|8l}k&+nNmKGVS`>I@DaL^mq}7afPlC zkx{8RN%`EP->0JXVG|e7Uv)AD(aG))0aZ65%bIRBMM+Jr4mRDo*Zs>1(7mQ3O$0C1 zEHT_y(CqW}OYD<5f>_d2j>OFFv0wL*;eUwF58Yne-TtRmYUd` zO`A&H8-5b9zrv=O_ktjbc(Q~gF*Cs zs%yHMA6T!zK%`j=YAmI>psnEv^Mj@pSy>9!H24g%ANIP#tPVEe1Z z0%)d2`zTWaU_UpQh-oExxVM&v;7aX&yjc2L5fevIJv~DdB=l8`15|1=osJa>5<}QU zT=0@6LY={NmlRT*!8je2RBzeoGz)MgHao8?ag6~-^$9&q#u=;Up~yh@I%MP?6R!B3 z7$9f%3tI|}EBhK$Z`dyjuoTu`R|>iqr~z7mY{F^yKelh=1er2I~2XwTcoNus}4Y+xcxAM(ML*{0}r9hfnfb@bm-V%^x`kA^yDexg!3 z4rY1ygHG~T*fhTBO&eFwqoe4@To_(U%N8)>(MN`NV`D5JznESm*i*%FtSrnZwu81b#{)bK!2S+ldz1%eaUTg4ZOM&%L?!eP&dTYYK7titW z{QiHZ$5D@c97_kj3^1%cZSgOD-!?bec1zL5A~eQ_m}6dOM&nau>FA0}$HuQ1)BP`- zCwbzJ@GbZv+Y$7*A z?rxfqjN~t@0~n6iiF#J`{LM#X`%OMQAC_Mh$TI)$R0o%=P4MTCeD z&lD-^XWv8hj~fOvw2$1qi+UE$OEik5G4R}^{-x>+Xve?1o?!Hlf2TeOjxx6hi2S`& zp8>7m5S)|#N?%(1$}F3|lKxMj$@JJnVDL|3)Ir4fnS+|Cr;}+v+VAa)j1D11S8y#G>b$UaE`q zTm5Yg*?4xb^z=|WJy_@aq=gK&_{H$~!H*K+)&8@;7iX#5LHFNkEq;}F$idCmesmel*^Hg_=T$Q z1zaqe%F8)YRWBNbBWpj3MqR{cuf!Q{CZNbL(YzhmwnAvYdXw+CVZbHeNjAHCnZ zPj?Xu3M9473*1?bloJ4Kv#2!@LBF5r#8v^JmG0jWR1P{?X4i|?zgXza#QxzmeTEYP zBBJ=NSJd#-kL4nlk7NCB#dEpon6R?ou+pwJ0lo^6;w*`13!M2xatSoWj1CZYCQ)^k zakvl!5!4WZp#>3Kq47FTFQf!V&6<&Fm*nnulN@&vecSeR{s!~Ca(hHR7i}g-&8~^O zo2PY&ru3~Of8xwcf*>O$&=bke1xQRu20ZAsNBHxHFHxrSa7CiaziwEm!tqaEtvY#M*7KnPdh zfq@8l(=}AVnl~7U{+9(oijV7p3S<>18VUMG^pE9GP~G9jG0p|vjRpNW(xAYCYYI{k z0j+=l(UDUpLXEHF`K3J`L7+H?c zO%mU9Dc9`Ifw}Jpj z3Io-V9#L1|mUeDoDxspmS8H?<7~mrdr$>}iEcIbQi#)?gq; zAsi~XG8w^6?FJCaBkR&C`iA++u=yKLrSvm4NExy~Dc$k3L7><7prG!mMtF1AZz$33 z_YGk?eX&6BOS|U64fcT)0I37B%p$os`1yC5YU^3OuKT27d;nYIU(Em z?Wk0@o4w^ay25vSw|5(xd^Px%n?4o!{Fj5G*&xY1zVpBwc$T6QheQ%vyxkq#WZZaL z+NDV5l^6+1uq6DQO=-ZUq3X5HGqCfsLyB6}>-)pzRzevg2jR z;T^xn1wZD!4(uZ5P5$;GT~x+ahU$kwk|7R!`CH+y+xbEpS=8zIwai<2;<;4E%E&nH zR75`QyTmJz4!YPhUY=?%Kf~Mq_al~9g){3;7_F4tBRarPn~k^`+*~@vnR#nuu2hZuMp`{s{d>rL zvlf+AhI~tvQ2!v&=bfShC-B#rx8LZ9{nV69vH+%H6w0f#(zX($ zoh9yUDY9kDuf)6pU%yRHi($2Z#plL<7R3L#4uIik5(_lp#Z%ZY+O9>{?7yex(@i_5 zg<8X=-SFOXs|9&73+`oIp2;SD|3_lfQ(uI8MBN(gzGjrA^{_Xpa;G`^*G^$Q1T;vv zysC%NwkyT2gt~lTrhKxN3?k#%oM{WwktfsPl*0zYt?5tn?`y*3OjE>7-wo%@l(m<2 zDMH6VWGNr(*c6*sx0>Aek(ZwG5nFXxU1h}D5T%A{hQuxY3o-fyP4R;~$-h@h;VM0< z9rCbeaur>HB2{xoNV4dy_iy)J#pkb(NtgB_mAl=P2j0=WSX6FJcoQVryQ1T3ki2lW zCd2%r+!qh0FT(Ew2PO%~MInmGt0Lc?0rS@s<)o^Ujs4X>i7mo!AfzRR_pL;R&6jEj9|aM)GQmH1#@f+ZvEM!nBr{<`8_8Pfu4?A^ zjz4qBbD4A-n|Eu`d}09Ov~S7FJ75{F@86k0SCeHaA2(Ynp7fUv|0UobNQIq#%(c6< z@g_uM2cI^x`pT$DvHT;tOyDkKg=MnE|Hs;S1~n1?-G0-6&5-VZT)?5d%#WCTUMd?94~-Hqx8n)jDk*{gTrmD${hIuvh~4z)&V zy%;$@I#YdiQ@RGv-1mkrp-hQpwN)EijX^X2VuE)RGuT|;_Mo7 zJ(CFxVHKuSuF;({t6QMjgscm_R0WFzmO*YMSM^+g`{z zrDAH-ua`n(Cp4-js_bj^ss#7qAGD1-M1DVb2G-m;roD{UT%A&eKRJoq{&`hS&KG;? zWA#?Z_O>&`3S;t+0p5j4nZxLQ!BEM=hjL`-wJw;toY{VS=FICBCUOB^&D4H@C3lc? z%|8V=FBq)$ce4HiK1I405miJa!7a&75bC$FjOVR3vX1q-u~ytFVtMw>8*x z@m9}X`&DBWDt(f)LcQpL)eh8lR_`%YjagA_aQex+7QX2?aQF(%C|G2^oEpR2qACY$ zmJ@+V5SVu^*w|pY4^2w>Rnc(MTN3_^)a9EMwG2d^y0%9LujJHr#RA`)cyt2c5Q(|f za-bfg%RqwftHe?UpP1_1mpm9M;}_ue6YB2vFJ^U>x%tTENE?5mnfJJ-ti|M4>dU?= zUH0eU|Ne}(mkPaH`5J4?2fhl{moEgOo~Z(KJfdo6S3`XiHAG^^&0-V^>lq*vKS&CV zpc2B@*D9j#@`6%z_NnMe@c`7wDuPFoLXFlGO|4A|By^+Or6$q^3!G`0L2a#psU)s|CM8zlsy+xIr!z#xogmE`mp?OC0yCjeir zB|luFO*nWz*V-v!hHwL&Xh{Q7p)codF}u1$N4;P-&UbGLup^Vv37mF+e*510IELj= zr@u2Ya<4V@yUnCrjm$e7OBEcWiOXa#G1sgD=eTLPaOVV$tu~0mfr7hJEOMJ z(PkggxJ6VJ#*K;`1}r8H;C>1veW!ijmV1}$$+T7P#*DL`>9y3#%Favj+z8z<--z$k zBMl1V`us}eZH^nLfVFd0kb zlNXT*F`k<@ZY6RiM|~^)>0(Ly%|i1*CnKlhA7$#ig9j7FD%@Ms{CANlEsrD3QDt8f z3929JMeYf46Qo9@VgSq*>j}0rjTuSd!YLHXaHJbR8*GoEb@l7 z#@WfV^!)=NY%Bn7rhabZ@)1MaboRbm&u~WFe%98nwM~rBh z3KBPvB}KZ^;}4**t4zlBM<P7H|jVwZ;WlpqZ=E9{uUFM-&=7T5zNa9 zV{2sXEoiNW%xv4L+!Ynv8$?tW0K|nB_3>TOXk}hdlZiH6EG;%>a~lu8?WLhz&u0>_ zRLKD=`aBbybx-e#OIg!}+s39NS>Ed-+E+FXf#Afp=e`0mMb>Nsl?f2?7*XmLK5k}G z^TLG?KZ(c>^f$B7#yUvv4}K7nPm;-O)g&PA6B3dy`Zf$L96fV{`o4^4`#b$Zl?_Hs5cd%5X% zivc>#R}pn0(4jBTfgcs+kcn6f1hFz0qyud6#fDFk-S~Dhua%+W&cpLRoKNWLcw=IW zbS;yUjV^tA()2VHs@oPbbLjnfs90!HzK`i2beVRAPDwvlvPj^Rsi8@)vTJTg79%%F zwT2_jt)$QzqalwIIQ32KRO|F|_X!N_CqD2?39>QD{(BP;DRR8^iwdvnEaVIww7BBu zCS*dLzs=>Ref5~pyQ$|i_0B#8&WD`AqY&{k;H7tLXD4AMT8e<{D?VrqWdOzEsTk{u zD%g86XWVWE_&Y>)EXs$(1ZdI#9QbdD4svSdN%%P5 z(COPs%#NpMjhegA2ipUzRi%9F8YPG9EJ+zg&q?3e+x!U|ZelS%>NpTttq zbZ3hXG4KCA>_o{GeJtBA-eGv`oJYo6TXUHNV>ujtOz_hsEy<=8Us>lpRG@3kEC8!< zsyo@gh|3>e=XUv4iGJ-Bl=A_(j|NFTiS8IvGo24pjg%2yjfnAFSAJK$lr1|>HH5PgU$>iyN0Bv|S@ov2)k zrGFiHtiFNxRxs41&`CiL#W~Ey#&+dge`a*e@FRA1$S1&1XVCZ&%s)Luu{cQ^$4O~$#05Zh}NC8yCRWq3+RK151wZIM0$$XXLyn=eQYGlts~ zNkvYE#LzDSw<(qhc@;b|wGJ=xH(bCNUNTTI;`r&SLb~&TbO8p+VvAbMM7^=KV5jy{EdQM!P*L<$GbGHAU z)}50axZ*WgGtZ+ZCCK7G@Gh%Vt>lQYdpX+csI16VEo&i-?7{rXIfg?LiihM{@=4)V!jlfFYtC#qA*Ox=%pKTZZmw4oGUX+zSJ`o;la++u_bw}F9cDd)90`g4DMx;f zehGjHYScLG#3#St6N0>jR6fM=UU5xmsuBz0?Uuw zt8IH5*&}eQhtU!`Ez^3<0WSQ3(gGo70%1V{Mml_28fwGq69A*(vISWQnoG!e_6>Au zDEQS|Rh?Yhrmi5NW|v_&qkzO&YE_DGt1!?M)Y_~rP}LxCjVY`lZRM{jJmP&-+yT9Z zAquY}cDCVC_MJT*>Hauk6tgrtvnsl7ag_rwvhS3mAGwLa1Dm*%CHLAyBfq{{-;vzU znZ4?uVi6^hC&VaWi32%Reuo%o($0Z$$H8nWIw*FYUjuro#v%7Xax`6=U&-lMD)9G_ zUM0qq6x2_>N*{*DB*~Zp1KqTirp=8LM&?bgS9|FLS-yxSH{6FPY2Y<9q%`%_%D>I; zLl***x&@g!B;U;OX)ab8P~Q*cKh8>-wjBjy<&87sMcXQavdu9c7ueMnBW2AKFpAwt ziYeUc(PY^?548CV7j4|;!Na5`yv15^A+q2<+-``QXkH`ME(7E5L|} z6~2fIuY<^kN59y)dCWq=tn(iNG7<}m3Wwc|u=*UF=%Tjlc6-_5ubB;>wMwQAV-#%* zUT9uAZmlC$DrgQG+XSo-C@+!H%2X2POSFTNu^-`@F*)4dVV>$(VMe0ACGiFbYzM-| z^Vs?k%!ao~PE*XfFGuI*3~A_X8_r9^^wHG!j2cO!of_QfjV-(=@@&gra_G!zE}v_sNg_WR+DmMVc?0M@IK>lV$$873c3pKI-|M&}ZJBw^p+o30$p> zdsRnaRw#BoTH96Tu3mF*R%_qbWnZo~4YW-trvY##SOn|nU?Hdg>>*i~V^D?jfA^Kf zek4`YF@;86DN$W2_VOBe%cb81|B^@Ct2xi>(%u$0jaf(LSw$&1{@Vubb_c3K?lP_0?vrcu$hnGqD9!EH(r$ zH|4&0a9;Xs@@h>!$x)Xn9YQDxfn&)69cbqrOSd-n`#~KLCn-)d+UWO@NFrng#0P(q z=M~=N^ULyxjINkRq`$tDj-c9+G2?IWrxMI%Qqnaj-DPzqjBW9-N40uv6 znSLPz*$7$ssf7Dyn#r`nj#`O{#XbS-dWg7PxExbwEZ6pBqbD^Pnb z&CWzBGsUj0G`Ub`-Zg|&SEdBN1?a_g4l50W{|53a%@{8)Zi|O!svfmj5idyVc9|KC zcrJ7^4Spuz9s!9tb%vY-+z`_XGEur0I6wqc*Bb%dRydMj%OY-Th@lzj&YV%}5CmH5ZlLMHt znCQBYQbl~cV@oP%A|{d$r<{QcF7S9O7#-}DV3HW?kSJ%^mTR>Y>JC#0Qv zO%o;yZk9e+!SE*C{CB{03AI~d#O6z!rvQMgQx_m_>esZfngt*5&{8gpJrWdNLc`k zn-2TRB%M+{L7rcc+=F6z%drQ@yAo%u zx{tu0{8L=_2vzTzKOK`{XN`!AKBjQR5_?~OD5V{PHGQ*7xcbHHcO^|uv&2r0Yd%&q z&4V?K>&i%G=C;3rKW%-yRlK*-Ew)QAsa5~1Stn*OfLO|%Ncc^BKl~~#?{BIqumY)r z6vDAAI&zl3-dkhS4~qjj85g(gLD+L`sHY$-zwl=y@1rG5KxZcT*LaeH%wQ#H5x3Lr zW*=e+sAVCRgd@$bEM1l4%WKBF3BTj+6N*FX`2;dvyrj))`4liAyww>17kHD*qC)E) z^!27Gzd~sWgv<+Il+rf3AzFJ!Z&q?QoFMpt1{R#bK+VR8jI|1sK6v=d<)OUP++^%< z!Ygqgp)!~*TB2W2Vp=g!At4>o0`aEIipKUe@ zBtr<(ztrpUo=0^F9^nw#@Ax~ISg`_o0o9<)%K)|)Bm$O+QX*IFs==YEYqAOhDeGA& zUF=@J=t(y8z5e_QD(~wsn3fR>_ERnv2N8e`%ch?@#G6syq7tFK#VV78DwUUa$;Gj1 z@6SA(H1t0hDj!_`FQtESbfsn<>G%WNVGr@j4-@nn*CkFjhkw5#5TYbzrG_Dj0^&OY zQ+r+B!DYXibMSQ@bn^XFVM+8g4^PnPf?sD554-Fc61CDZZgcpNQ02rQn#M6C zdWr|rn=w@!y0JTlT?GVc3V+H9O+0*h1Y$OSI}sSa8fHNOd>_IDzDHzS)0O$|C17^@ zQTIZPf0^4vxcusKtqW`+{35V~tj&^v!t1zZQrbKsdg-n%QVl|XXTbRdNS>+m9}X2R-V1$el3uqZ68E3vE=Y4<&_^ zLZ48^5W6HMFQYybeaK{);5Ceiq+r4da-QXCXW{SdYTa`50WQ~ryQ-d?%Hg8ySj;}N z01Sr=$S0RKuvt$&oHmZ@#JqPb5PUJIfg2c5{nawG+*R;UI-=CQQp zR4%mF0>S?6s%wA#j>&)9-vfOaO*U@D-B*k~AxZ~zgQM_PYK-xTK@`j;N49ei8>A;h z@_PXhPH*lS6#MY>=ff7SzW-fK03<#%CZ`p=@;bwSKnh!25Q`7ng;XR0?0(3!0w@lQ z!PEz(ve61kkWhBVJY(Wi8(vBy!Tj%%`zc1k(6g{R$`RT*kA+e6KxSfcYZ3!N)v*)OD)Ax*_G5Y7h)y zJrJ^_OI6p6nqSY!YyzVJkYLm{)Mq~5qKvm+^K5j!fj|xBY>{aY_cG^U2z23tA_3Mc z8Tx-L;p&dDcU~_vZ-h2jgRH;9QHR*orAJ>JS!E>&qzaGDiv~;`Opr;=XUB0Vyj;&> z(1(|~m3*yRpSOl7gqHzdrz-% zXPC!=q9X@;nIwO8cuZiMj936nVrvq8E4eVgc+_xe*7L4Q(q zvVyXi z3^yDlqHhGo#N|~BUJjSJHs^gB`%{3z6LI1EcY*^CWu2>r6)0I4$@Qh zr6tnSV$*9+r=`9L%e-=Ea*&x-GLLL;I#aekvmr6wYwuD0nA$e4Eiw?|ulscBBpI2) zC)d|!syg&NS2U4yu%yuVE3CyRd>vwm>A)6%Z?=Lh0B0DojN z^5|;8Z*(Uj>hGVcmsbcd0Yu$`B~s-CUs+?J(k;=HQJhd7!9loLOALKKClS-(4b3{; zsEa?C>8%);*O^2trEDVHyl#lDttC!8ii_NJMLiq|A@c=uQQi(~Vd{Anb!x_X+#l5K zn)^85h~>(0BdBhqQBlZ5KZ<)IgQSnAO*|>Q-PE?BuAe*T*xV6KPdh9)CdF=;Y!^~? z!!V&jrtMjxpC3EZuHd+mR%@C!uIRVLp2p!uW^!N^4<|%uB0ecSD$$p%dMIhE>o8i zSePgo65;o2O3xcfr9Q#-i4r#R$G@^*OqE|cyWYU{V2D&FoL{z5=#{rwd(m<~zkGZB zEB~PO;>}Bb>MSf&B(R*!TTwuHv3@qRt-bU#NB_t6R8QR(=^P*Nq3Y}KBz;Hwag@$eJ^-!63?22Hw_G0D%S1Bi8OM~20WCl z;`wwaSK5-~;1*K38Zsmh527g4<1UiS6*BBOnhBaUFZJ+3k(tdcmXEcQ%OiwM*WSfN zZZ5h)!U;sG1=7$&%_o;5PGK*kC=-J^pE~{(wi#wNNwVr_oa)z9$Y~|cujpu64gpK( zfsDGR-ZZ_P0V^zDx1W^J78_+~Duesd&APuoi#8m`yo)r<3m|zY zHf|HU8#pYuypy()9uIm~HVSTV|8(;6Vc$fZDF{O^)xuBIDViN2iUoV%5pPQgO zJY&>~&W=)VOB*K4pCBK&9S0A=llBLCrQciMYj4&s3LyhvinQ~qboF2i zgaFXL)btHp?6r~{FDwo*5s^ItD726=@cV&axz7W{URu!%Q-opu_)Icg$*!$AuOp6l zD)KRYXUZpAFo__k&q~3=Y*}@_j(i2<3mh_ z_K~8b_!e6&ioE5Z{j>5}rbLMF4(?$rxvUM5Qp;crb@+W&`%grN<7{z^0wJt2U9HKw z#@DRT7}gEOgx22FGGl^0mHvTylg@7v4658?`xA}co+ z3#p8Bz+4N?lrR2q{X0UAD>rILdRg3?qDBvv{eALpd+<*=>wP{3Xc@zRuKCQQ zgDM*{Y=!W=1bEm(%qR83iAB?B%IjE|wDjBYpA_)jV5Y0L#B8nI) z8BM*iMZrG!Dro~jK1d;sqNE?8+{9CZw_`(L4NPcgl+_m92ng-$eHR!V$ucV_l7$@# zwsB^r*Fy;c*I$S=#RC0kZYu(}{7%o++-ieZjw~yZJ3~VWJ#?eL;P}WK@&61twA~ZWFKuIei&m`Qyjn38Jufra~bH3ai1X+NUcw>qBqe)YTPpERf z^O?&ys7v(^G8er0;r>Lp>s{%Cn2-LkB7qjLo7sc`4r;e(X@hl`mbrqXH7F~VS8-4h zA1f^j8h^v|@92pls7P98h@YUYpcA7)zZDVfpe(2{4O&+0R_8mhRry^w&4qa>gu(mo z%A{4g4${2RT_)?s5UrY#p1g$~0(7*1ndu<>5XrcL1=;W}<)RRX@x}Rd7!Iy<&a;xe(gy8yA*cAOd=u>+RZBaXud=ERKNbT5jD#-a|nh(icqGywwj z0AXr8f@(bT^!F?))Tv?xTw=*dApGQ0FiP$Xb!K7 zzseo*ul!@>86mPrNTm0oHcCV7)Kv&!M;)auDSLf~zvm!)7#b`rc_;9&$kp-O_Fv)f z&B%N$IziB>t>n5BHRoHEF6-!C9>=udd$*(ib<#rRt7Jh%>Mo0lE}SIG3}glbgEn)L zu)&A7ucuKrgWow~wzrx4kw6{(K__mu=P;>;W_j?iH0rwf3>7bkwiqI!U`HhpVc}@L zL)IgbC^90(?QCU$25>GqyXJ5qSD4ED=qAiF36@bQadCD)6cUC#+OED0pv$e&^W2k5 zeJJ9Az|3j$$}7FkoyY~Y@vnSrX}DSH0tURSIP}#KbVFdZeZ4Ne!sk3u2kbH zJ%B3Z`EHX6(Xkz5nuY`~N2o{iK@$q)JS;&^E5uG<^*c@tCERF15>G@wr(06wjRhl~ zh*Suxzw&9S*=*=KemW+s5iy+NuOV#%h=y-=&ku^!A+P=ZY;NjM$=DiF3u$(9MP!V$ zC`5jQz>#Aq%e@%Ro?ogo7%^tAfQ+T<-j(A+aWC!iAvJ`yP~y;7*;mohNU;63K*&Bg z>ezK)(>L;sQ_R$^$|?u7py1Rb7%<8ojL#;F?f#Qu04O0wTzP{PB~uUThKusY?93CB z1yu~)m~-kbn(W`zEG`zBk%Oj7bGO+|O z$lO)xTy|6jEq0E(9%v*WXrt-z*hQ3qZDg^=D zUkYFV`cv<>L;$p^$p!7a>I~!LW{>Fjv^F5dK~E@Ht@6+13o*sdM++}vRyG|)ntQ&Y5Q;4mbfI0WtBMx_;} zQ7v^$RnT?>+|4^Zs%iGK6915?Ax{Eg)hRe>?xdm6Vm93js5p(|*MhGs-3dYK zWLVfsQ3)i9AHHgeJs*-7p%iu5eujDQ78=%=Kw1QgDWr>vo>kw-4ypou&sTkC4&X&o zdJmP#IUlYZD%HCwUlY&KtFNZ2R7?jq)QI!IC`TlL8gK^DHi_4_*U~Y__*$G*h%*PuK>^T;3_qO)10;~oi`|L}K{pw!_)M?!| zN%l4y;3)biOQn8rI~A?Cw0!`-1$X5e)D_)VE{U8kN+4OUVOfGl_NP-0Hw|K3%)twF z2;(sKV>->aSZ2bSV$O<;-kosvZ2808^G&eq7Dz(JRmzaHK+TJ~o9DOf;24!d)F#ut zSH7~EC`k$4m>&{X2Tm%zuG1T?7z)hbCdUwc9dGJexm^&BpV#S}ML}gxvB#Qb3u$`I z&$h7wl@P%CtCP)jQ>2#K0d7plJlzVKv{^rWtYk%!q)HqL&Hx2t>Zy>zL{RUf1IY#E z@6a>AY={8%@*wsjlwVY3&=b^eMCT>9BHHV<@SkY;$8bGT5bP?|Bjnqigt!5B{Me@w zcK&tvv9?MxodB+EsGgYt8*?@4&tOdeCpJ|(!kFww%d?2B#Q{hN0O6Ih<;T^0a<*WD zRtDA(tDbkWPIS;Mv2oB!@&fz>f+T^xCg^xSy-huI*vj5Da~^CQXnC(uPQ5S`jPF$U z-Yhe~!U#6Y z;=}yp(p+hx24`};reh*3;cjj&3*@{`4iCK}@QlgT1;k`I0=rXUf`QD`HO4IU+B zJ6m-tK`2+A4@|O8 zy#=7=Fy>}RsO0{eObu+K zRaq#DK9t}=|I@62d@_@aZf~`J6dN=iObF9xJxPH$p8MpZl(Dx;@q-Rt;6KyY}dzHrceNrq{lx9!(GE*=h#ZXOA%ZGRvXCp@V} z8Z-SIqx|YvX7+{o<1%wbj2L(wpb+7TxW#9_9GKgS)i3!(E>cc?4S`=ZdrcX#WyjdI z_|smGt|kr(6J#uC7Gjja?vx$%%K+BWNP2b^cnDzg;-T#+myNPqMP6PsoYX_F!1MTC z&Gt>&3NG?0cWMUQj_t~+d3gMw*=Jv@Cn*3esjrb@EJkzL3;`JV9eU5JAH~y&S5Bcw z_jA-h5&QMdIOaGNg*=?vq0vG5Q|9zqM)PkCv0zseNg!kvDADh?kRwx_{wzwd@5^+s zEi;@wcZX~&lH^P|Q9%pbK11hPsEWH3s2JA#v{8i7cXnr+^gAa@oCEtxtCinO z3Uu$q7`m@kechk&eqQ0fx|dQYTWeZtb=%{*YN)|^SYF0OJwuvEJfz(0ic>RR*4cp; z9|#UVT@>e~HEAx1`7BM%AM$13Pw2_g3-bi2mXiDTPD$8lnarRhaeFXMa$D{fB+2w^ zxyFeEM=}!l8k?xnLL~SG|4qc15dokKC&ZG2w`OBV#Swu@Fzz}$_=Y+jj|GSlx1vcE zF$6FrzexZJF2Whz2SDdCMo85QII++hi5bJNUY}FfZK|Es{vq-@#?kBTRdQ!mQph-HifSKFR%a%@DwNT}AmjC!)$6fv$x+(a z7-qeY`E17?*+sa#+=QtPU-fsBOib23k9oG~R<@OsoDQ?CwOk^91qoQM@OD@d--?Z_ zZT#DcbZ(vcx-Or*29NR$;UsiUrbc^hQH#2rPZKPyzJve1{Q6xc9&4Gq^KuNbL8UGX zcJmpW6e=Ixe4CUbzr3=3|KOLQhVs%-qInN+V9)|UwnR8z{sk9oy#PsQ+7Jw2hzs@D zT$(KqO%to-%zjz_5-K$q-8y~UlzFks{J??9D8C%nV<=Q_(c_-gLxbPRbZ77OOo^sk zor?eHcUWu}Y-o4nkV!v@NA`Ia9o0@I+40xsvuj@+`-4O4=Bw|ig$Y)4DCJpKW-Mrl z->LLp`{W^!iF^0FIQf1+@0z9cM%VenW80>G=~f;5frkuo%MLOQUq+d3eR}^M7cV{V zm;0IOIC*}@`VKj2%P5*u`K`nE`O1Rv`RTWRyz_px@nbERV(nxj zLfgLH_X{Qa=e}40$BRio`{qSp+&GKaf`NHd*9gnA&B%`}WQw80@%X6F;+J=_El5>t zkdPayUXqvR+f~0per!K>+J`6KWd8Z*%WJ2rzmxMD{8iy^`|L%ZM!>G$P^b!!Fw)ng zUws@HLlC%+h8Zyn^XbR3STJ=er}NiuoF$A~eDJFXEY$h;7MyJBCT(*@97Dx>NzC{y zrrC`6%Wvi#Rjs+st>ohShg%?Kljxh@O8>GRqNs{Y;>1H9!$$cvxR_0o zjB+Z#!H3c!MW$&1IhDYGmxKzlS!Q}p)zW31h<=e-ZgWm`i)y`uJ+pb?Y)*~fl7I+> zoq6eLPOVyJo!s`3c{ycnoyr4m-jpJXYH_(L?N|Kf<;<4#luPvoCC8SnMQ=i_KAKGD)mZxrG?%+ zwQ2X+Sk2I9Xui?cG6(MxHGb-`*pS=Z)U@_IaCa*7zPE7}ug=%wjp^sl{ttVlWqUZ0 z=KXn5P3!J8AzQ!9pr>trx`6AR)UeCW%hz~~D|`LlT&oMBbb{RDy`3N5wzy808TNI3 zTI&w}n6CEx`JLx`0Ycfq40m>RlO=lET-F1r_h&L`!rFuwzVyYFMllnm^;He5_T0ac zD8VW1&OCnA;gty<_%rS9*YW69&-B48mF7q7S1(^0!jht7W&@z~UR%*5{1dBp$fw@C z659}TwGLjeWGtZR&k16UXSNfxp6uhggHY62oo!mleyx+&KfZc5pQP06v=|dDq5Yiaa$eQ;H^OMj>1IX`%M)}j zrC7s^94g3Vdu*QXI69{v?dL~mQtc%AlIB6#!!HMCl$#sFJ7HtW zO?RIW*t_q{h(x75me=xT*1Q?Qo24IiT(1pK3gZ3uSH42Pk`4=ozAIZ^1SEXoN*d$8 zZ=!Aj2si4b%Xf!Mp@=Qdvh0-xxB~&^;_k7h&j_SX?VG@gt%kmxL`aD5oO1a`Kk_^o zGUg{Xh1Gchl%$?6Mtf}zj*P;=Nxb=cX5!(;c6XbdbSH#dN~4|M;%H{7AUxFnz@m~b zFSI-ls|z-|y_iH9@fy{i3kT0Ce<%Qnr5JG_)wHO%S0GuyWC(s-e1QK9-i0JH?3nL;z=I~EWYiGj zqe0FsE0`Gs`umgX4G)1N2@9CKwG5T*0rmy1a>o$laH6B`$u`a@=<`*%HEq9O>^T4M z9=C1?RwHsjZh)kl#pg=<5RL4wrJ3&EvV{h8|UOvruRrkSR^$ow;Au^tZ zLzp-TbkE&mB@j&4HSRe)l9oFkOCeT**mJdLe7<>>R=7O`e?j~>%ALtKl|zH=5&hTm z6$x4&-^zs_6il+B8kF*)Irwu$h|fEU71J5LHO0<@-iAMWve|wLy9EPdU7w#q1?Q(hiDe)Ksz{=anJ8HxW(_w8nSeyt^6Zx@h1IwXo+S?&@G)s-|Vh~<3&Q8+sr zqBERJDLlzyz_lL6Nu|;#7>#Hw-Zn!2NA|s1a8BR3bWZq>?z>Et+BcDuATeY_3(iAx z?{FpP0*p^waz>GbDTa-{w})vpK`fVt(DaI#G)MQ0ZOz8(cN|ydB*_f;S@XSQY8_Tj z&%zXEpGeaBO|LfX3H7d2x30`F5H%`22)#qxTEU?-mYJ&4TfJTrSG@OlpkmZ&pD5vw(pbq<>DVmdk(gYsFs{y%VGN_2SU?!5=r5+6*W?m-Z63ujV zl#VPSxgA|1aZr6n39U|_v)wKE6;>n{#jV70t&;Su0S{Uaq9T zo0-PN`U%ono)veyE2uw^3k>RfxYCd}{DPU~Es)C$tefKXG4&1yafq2$(c;R1uqt)X zfkqt7At$-KBtiX^NjzuBK?Lyt5|QJHrE%boJOc5mLv1JW9Piw37Gm;Gq|)`9Kr*J_ z3>8Vg=vsm200e@=SNWH&;|qQki3#xEhs;YWUariUcssw028;EmI~1#mac^trD5Vd# zDNN_aL~1hN&oa|uBe6KaBBTM8i;()A;d~lSUUh#)2=m+_jdK}7?_F@y>qB~@_z zTh1irx0E#HA{80`ncd3OP952e0VD&jkJ$w6QAAn<3OFr@N5e4T{Y_1-CPfQzElbsN zpO(08FRHyutz@8~^`)P9PPBrF&1)Il108G?8HH^TiymTGJBV2HgbC4AtatnXMu0-` z>A+<8GgH^yG#h^&CVDLFH$f}Gx{j0e4qk(wn~-YJd!Vq5#YyKyr!ihS<3^*%db-_) zdweDz*~P@ueTNtD@`6kAv06fB87Y`EcgiX3ND--hjl=iOQi=4|C*S3axP#~ubz1!B z-OJIkQZ9F(yLa6mu=4X!YN#FoLGr&(Ao z;=qXfl{i6u$*H$kG3#e{B|CFkQw(G?^7A+E+;?)m8RVux5@=G5Sk6c#lI0*C%DQvN*M9zHv{GDzg=U?=e;|SbAom zU^E0R5x&T(pD}jjrnLz=ozC*NfS_HZc^kF<*05gR-P?Jxx-aHD`?#!x?@6OCZVuo< zMJ+OYl4PP8BpZ0j&z6*hSU@lCwu+7K-ExXKESYgT#XcvwR0he*FTVce6d?-|;YgIp z^LVY9)q!!;auG!W1Hh`<8qu_ zVcwl1f38gl;Jo{|)0PxP<0R!9K`5p@ir;bMK4-GI9dT{WzCE1r`FmH7wHFG6iGcFHlm!qHXDU9M7wc4$K30LgE1T%{Qi(n;jE0$!@QUuZBmG=WmJ!jG6EN_X2cb^fh z$xvR4vX%%kFD9}tbts@Cx5G+=l=Hg%2m?{i^C-;oc}M>_n?m%Acq%JsjFZCX8*^?) z+GjzA{g%8%JV`R1s92J6ijX?+#n;rDQL5^pE)pVi#KlVOuVdmLUQJ#;EY1`o!J(ww zf^eS#$ks8G=lQV49`vCFYi%LaP?C5U!M%Y{KCWfsQl||5`S3*#CE*BLlnABrB5LNz zam|S)0wRP=c$^U`w1MD7p=@y=5+Ws}Fd0}sQId66O6w{jhpjT_peLvQFr~vqxUNEY z<${7!mSwrXdm@mChX6EC%MKJz^Y1QnL>%Xrnprvu}eemqFtew^s+60pFqz|SLa;OA$iQINzS_Pe4BUMViD z%*$O_yIA2DQ)%nLT5`zVswsuE6B0Z(DT>MY5K*P=93^ah+aiXgNM7V=%q^n^J`K(4 zl?i6k25$*s7QC!(p%q`S6y@y|t2KN)_p17%FXCI)j6QZ;^1_v|&Xu^Ghp z8tT2KLY?p>bd`c3W3^SuOgUd`vAsgEy$zb>RocT}|YRUNsz8*UsFuP{f&C@9f_$-!GXk(A%`W+Vsi| zb`xkAQ*N&6wO8`yjh<>eUZojj0KICVuv2dOs{G7hrS2svX|w3r@7`w*xT5!dKZ_~? zQxjq)eX2f2w#a@FCPzLaUu)^yrW#FX5ipGcA+%|!v>8*VnWm{&L|WPZv^r2Bfd9cb z`2QRrbwFxhGJyViPGki@|NWe}Glc#Bc8V+be>;l)->3M`nz;UJO;`W5CImA2dUmD1 z7{8ufACaQHP*U?SR2(CRkAb8c2@Sutox{lgqVBD~q6**s-#r6E$IuN!H_|0BL$`E; zw4{R4p+k3f58WLCA`IO~Dj*<8hX{y@fO7ae&v$*#_lI-Vdd`pMFW7rs_qF!E_iJDG z>z$*!GX!F=QKHsY+J&dFYl}Yw-2$P^%&LQyT&-iri|ia1}UmUvI<}d{{1B8U>FLaZJyS%2?OxJ{=eLBDH_9A z6f;m;FPYH;9l>8{$!$WTm)SL(v;>hWH6|n2oLYxaP;=VDR~iSUG&4E^j1AoCP8q?* z*rkZjC>vcx5>f)F^C4IFOC(4}PS{LXanLY%(5q*q$7IWigduqaY9k$%m82|LUa@YD z0zjJsbZj~gx^fUki8iHW@`cRc|L=Ne{(r8AzkY>E#v?292q}X~r924_xh1L81La~I4DkP;7_T2L%<{il z8y}!nYlb1g4_Jopyy*eU++)&;b~UpM$3w_vs?kCiBXM|-6!>7MAuu6@3?(Lwe)$jp z*l?)*No7~eCS-q@M|)K zlZhwdvnd&j0?0U&wgf@7Y9&hCjTKO!0gISw-Hwg=tqnjxkMXKkaKKHeSr!+|ADw}~ z#!BHnWRUW7{@SAcXo(O8E3qxKCB)*w|H?hlna+eKi@tWi%3)(RgrzPk#xz>{V9l8h z{MrYrWv*4yZMA)!@fi~!pQG`cixo4YjedT0;C+nUa4_1qzW=c8Gn`--{*hs1| zWL)UQmrCltSiki0T#?F|d|tP&4{-3=Y?$1C!$G}xY5Ca%wYH=AD&=&ALXG9hrP}|%L5-is z;}u%@fqNQRJEoC#1JYXfqI@&0o}5LAnr|C7-qCyx^XAdx+w8a9YmFTDJwvx6?`d_W zyISmv<4JC0EpvqJLSK;Sye5zk-Ve+FLG)TO@0HnyN`pG<5R#6)!Dh{8a;CXr#-ECx zNmx$$eRKT$_9vK0r?*RMyPWq^62pzpiyggGvgdNL!aj$JUiM#R|F&OkwE7&}Z}Ro| z`jvFOdH46V<=vm6wJ%e}#f7rwzju5FUu)CJ|1CVS!Y(qO`1AXz<^@CbR@fsD5+Ztj z$GROsZu~I%MD0|)9YybZxE&3P;`$oHX3V7<%T-zZHIA?IkR^_@k83AE^rQ1mqU3%x ztIXVzEh!Lp$hDiIM9FQJpu$nJn@U+Yd;4 zmizNpLEs;kUj=1m|5y*S{q1=4s){xp(3qg%ugNIpfgNH9segA-d5qqD?V@RXpho>{5kneY8$9)EjzG9Kkuk9o8v^UvGtN7ziGuB zzpAo}$bz(WjWObR50_8(b1hnJ4Vz9ZeshCftX7LuH@5Bo(>LXR@t^17D*S%#wjbx+ z+=+iuC)hn7>Fqf{gkkArOlY9wrA+f>?P7#Jgdlqy#%lS}h>dfMdziB-_)9GcPky&x3sY`pA-@(OmDiD6NLDGAI)_J8*b>8+`68z0e2<5-Iv!WK-?H`rp zwL2!B-j@FyCHD#`T74Y!Ev<{Wj-k`$#cxsZ1z5>U;l`sK*{yuaqkAjiRj=RQ#8r@Q zq`S1iN_tN?NVoR<)W8m@iO>a(KK~tDZaB8Yzb@8k94xchYvt4@0v;O4OjH2zO)m^d zeW|tOu3BR<{pgFTM9h0QnXI3`g3tVR$cVZXI#hp|ggGnX#QQB?(fH#!yzjA77Ut9b)p5uU zWN5-my%^lEsW%T6VfThI8jJ27*$g?1Pl{T2PgP1D1m2u1GSCjuxy(68SlN6~t&Bq}s5J zC&B!n8~Ms`%sP4)cYB9C(V|!`0+q@jSEg&|FvPK?m+Yj52z(iV&G1dFFS2|VoDYwd z|2Ut(kK-9a=K2KzS1&=(vL(H$-(eUr9!kt1Npy86qwDVKo?TV|w+*pLABPesBs2l# zchOv4T!5km+;>NT_nL=cKXM+h^`Os9#r5u3? zfDhE71tUt^Vn2|v$o=U0xkg&XX0=Cmno5H zE=J3`u_5p$FsY3rp}?C^IgN29IzB_wfa9UEPQx1WWowgu4eiRja?pkiJ=SH*$i?}y zf?S>|srgkokmdI}P!2!?f&$pOJ2Z)(O9U`&z?2#=;tQb2KFApWox_+M&P$vxGbJi( zJ>QV6+X`c?#Y{(C(SLZbs#}jKJi7Ow%r1g7IMaQ7JF0Kr5s8OBMdl!%a&^Si86w$l z5Ln^soo&U0-}Eh5%qGn#+t5RRbfEKlmGy9fd125`0zst8TxQp3$Poyo3vpH3DHVXi z0+TI}2m9jfAZXL&xZ5ViMr`yohOnAz=zkP@-D> z{H?RP^ccFWIbMHT!)BFb^>^NYAGpX(v!*O2Mcz|^ms ztfXCrYCxRkmpN{oG1~VncCYxz`^~6_Xeq;hM)V*H?L~6o$mW9=c9@0KEOb5($sGB) z0`hv*=#M>flJcnmKUK^9RP~OR8u&akNG1)N&bQQH^O7FYe^77`(*j!N3AYT^ODFF< z$1~*uPATC8PMJ_SEPYtuPrgWoBAYyXTO{$iL7Cu3F08Hj_*I1-h3gnEr9fUJDZvg? zV(<`;Sm1tyq%l1z$g})D^_XKSmnF_g)R*qBl}TdH(#cNrn|Ct1SCv`OyKcX{{=~Rq za|W$KJGYwT)8t>P(fGE$nk~{kJoo{a&q2@9@McpJMeg8O_WVofe{Om{%Ju-MUDbVN zx)Y%-{BBx*o#Uvw6z!a;{gnwi;7K0G!Mhe;sK5Cs=sz>1K4eZrLyOv<@<4NscW^Vw z!iSg{FOFIrHfioD6;EOaHzU){!4s5W=52{X=1k>VZH?V+OfoNHemve6sXBqa-5>$$ z+B2m(m4HTP3S!Cr+8w+;zi#|(wW=do+>--$#3$Liqu3$`r);~A5}B6R2EM_?Mc=IG zS&oNE&(T_e65n};%SSQ9I0i{8OMgZf9QTf6bcM<4c=g<^%0?@C35&J%{p5Pm-Km^$ z%RQbSZFifo-@f^0CZNmWk=y3EjcTt3@0XX7WeyQMkqCGREZnx&4-;ie{(5qwu=?ri z;1jy1fN##>2$jt|&1fTt{)F%`7I`r|&hA0I7?6J|`DR>VJ(4;~5W& zS|t5rKs;iD`Uh)cs@nFl~&EXjR z48H~l63GC{bNt&SP$rV7Uo_IlKe9~(i4z*V;t;8e^t8zdv!mwsl8pAb)>Nb-CtEQM zxbN_WdvTS8hJG#yJ*xD5g(kFR!(-Pa^0NWbDtr<+u;`4TUWULwsGIWci{}dF{PrfG zxxj>7wYD}n$T`7wmgj*WeluEaa8BuADAX7&)e_|=_>kpL;`{Pk`JW9@t)Y@|g%X*t ze~&4%mLb=mTEfgZ*627{+?an^&NB!Kh()RI!STB(`Dp?CTV3M86i5$MBDq2$csu}~ zEqU>wmMMufU5Ucvz{yI|_v#qpm;@@@gt(62mC|RsY^JmoP`_RF`Brbzx5-_*d{o`Z zb!v15_S{~I!j>NsY1x4y-w@PC8$=Wo%QKa6L|3jXf>hl}-XXy%%&CeMbavmCHn5l$ z`z$3WJ9VKojYpm5MW@ESGgPc5Z9dxnHpWl7J6%*g!!qj?M4d{@ge=3ElV~rccP||> zhu{*k6f{ot`JNFMXtDB^Z zn<#WgcWDq_w%^<|V&d>A}ZEuB|1aWU!UoGCrQt2D75; z?$V*u(ouvGZEcED57*WzrPgGL*l~&DCtbB381cF63;jiSBMJWbY$8@q~x+M21<5=&Z?c%aaQ8F#&FsA612%?*=dPt3EpO86w1 zLS9{;T`j~sbVFSN$^K|bq4x3!_4v5vH%9F#OKtaBsSry&Gi_ZbMmoa9%4rSBjM9p<o&Q?>uR?-~vG_>|K?3>kf(wf#FDn|55Ev4#=xSKj% zn~1iXhC-W&YMQ)0Hpt^OKay%PDQlKpt686H+N`a=sBH%Gnqme8lD?zGaigQlFQUok zqp;ASqAP#~H8Z(Yl24Tp1l2L?wJ_Y~ah?bXy=!`RRGxHC+Nv+w8fex^deiE%)+(+^ zLlD+hp(tgTE}SBEK8A8sKlKgvdrM^D0t8KCyuQa}}%8E4` zBu93boseP+LY^8DFT!zIR-qsicold_x@{V5s4|9Ds??Ol_Ui6+A}U3<*I~tX)xDz} z=tc{-5u{4WjvIxKb?B&)94HZ4U~XA40bu_x;oDQ}*sVx4^cxd5>H5e*NVAR$bIDi#~&W;@?Y>)G0&+l8(QSeJ)G* zdlEp_oV4FAZ~*JRfA@al_C2c&2m!%ymBdF-;I^hWc<3YYc`Az^SAagj_vjEHHhy6T zZvo>DzEt`Dh~tr14d*VTsfb)L66*Q^hI02oR)nOe>!2>Sb2F~O zPwVYGyz7Cfc@k-PQ;IM*3g2WlpowWl9kJ2ic^1EPF;HkWar--IBMxA4#AKjNuHrBZ z;^p{)eyn}U)R58~lZ1ch<**AM;C8=0TEhW&YB|1|#yCS0enp{UHOKDk$Fh)PpLYC^ zPQ%X%#@*bZtv}2djhz~gyLl1@ch?5d2;txy-wq2U@zZ|##o{eaU_^>3RyAVVU-a|DqS{Nr@m7aA_@DjruVV379vjBZ?Ms`-cL$3+cG zC#`XZ*I94@S>-9Bc8ltJHuYNXnGrG>evXmf%9(@%?~06w-wSFy;%A=P9XZ#v-^UM_ z(ISxznSsC-7BY;iF;(o8R8DWZqIUUu+SLn(z3}IipOUNCdqZ_|9sk40>T*_GDB91Mu?5(Y^;MPiYr#=ukep{x>PKl(iAw3{9>rX z(0{K%rZe*7AEqwY5%3x@vW|ScYwnUa)zV;SOinuDT4CV6yqer0^E}hgCZs?}Xhu*M z_uIJ|2`FnEpG5h-_xUxx@wBY*S@^Vuw$BrE&nHcib#0P zpiKfyimAOG2pUj?G6^{PY_K!znuoDL$l)M9I8P*)j)f?eNe=2gqkyyZwVqUmV0)Xi z0V=ZTMJnqEal$iBQlkGI6PnA>>UE)iqWWZyQHbP3LuK1%Mg zi$_ntM*#?-iteK`*f(f!qxPTFev_r5t+*2-1gSg<7kLlYz_N4CiV*Sw#86m?u(8hdiHxBG zlF)%kBoR8_H&V_uB!bvowv%+=JbCkg2=v{;DG(xPJJD{3Zd;7_hcEx}Ed}B-`?r;X z+;H;!n0!L-r*@w0CWO0R3U*rjc6&m}m*$iw0n{R?{zku$3H=`)RzR`so0cSOTqX?JQLboPT-DH8( z14bGEz@u047X*@nBf&5}>Uo=CFk$r(j}6Ng29Vv=dr6zvVkib6{VOO8uf zKEJ1xC+4v^oNMrG_RYO7N4wfI5|j-hy#sS@GYe*OmUA0n9 z11w!HfzP>2!bzcvv@qu}|3^@KYCw@#6G78mthMN_l8-RN);zTQ^F z!zdNTt6|~2YC^Iu(=4hEcpqO*6%E$6RRCC?Ex;Ha;0*(@Ns`{vS1Q;YRQFqgc|(o6 zhH7+$iL^7gX}2!08U0*oLI*Es1G$hVI#P*~xs`?;b=$_S$2nkj#{)=~YuFjnku`(P zf@m}t9?FF2`0^13mT3|x7fnyNgnBM7tlWQhhhhxC(aCJr7? z0~}B0&n7uJN-u_fdj>ZdCCd}lzlA+>U2Kf7(^yWB<9vOqsn>-TM5YWTAGdTMeD8mOts!S0Aj9=70RSjmy#1b%INHr-E3^x zbr5Aw$7H#LWN)PMisO<_63QA!l2&_FQ7f};M+rgrTB@kwa-p2LB#rL}i*%3Y!t(>I zL44&w$JOD9o3SvjAAru2ke?r){-#{N6Rw9DJOpK8{wP&k0R(VK3+3h*?QH)+10vm5}~Z!=vn{9u>-J;Wo#_gdJ}| z(9~P}zj7cj9=$xd8Lc>;dL3V|4HDxtl;^C{ljtLDh(W9QAZ(=;e;HS~C= z4eDDg4`>k1&=@EIYnUaOtJ!Fa-|v=lMg~xYDzmfT!IWf!ZME;LFqH{IS4hNw_>d(< zYBMer2$zE_fMub`P?}8}R-MxSX9p%5tEoWHtmD6gK}RE#MImFB?9|Jw!E8{%^czj^ zM$iz?2V5oDV3v{ekXdm6)d1Z&KZ?FGcmiseD_RdFco_KO^gEvHSV|+~YG^C`P9JZ# zk0uPxQ6y*QQVoD!PCnCuiD0K-h)6mTS-2l@Nbl7=3FR>a!9wY5?6BjFb8x(`%jm1y zpUHhcVx;@p45Y8)YKp!srkzpaZE(?{@S@J#Cy0C`a8!^cS()NClUa|Jw$VA2UYWjH zt`}G0jimfzJi6)Qp<7yd56At?*!R^a9cw=2RSfGwA}!GH$(6{$t78>&&AGk`l4M$y zQ`@b75Tz`|_YC`Xu5KVB)JHp0O*zjZLRY*p>ZhBTrt;^$(dkb4i*MR87CfL~qn3v4 zL+n!$iAn;A?%06F=YI`rG1x#dAIsgC>HIC11av$0GVw58dm@>tv)}W1)|g;!ZT@Qf zjeV}%q@$Go^xv=FMF)Q;UK`=q+*5XSVvWX@=Z&HT+Qcl}R8@xP3eywo}V zo?u@9WvN)Bp52fOD zORlItbCHd>CCr2_h$m|cF&UyR_qT_d_uY%dI{a0LLKoe!u7$2k#~P#eJeQTy4WVLJ zwL)61W*^L#ik&jS{GVIQ%dVF^e0-XW62&pOlh3F;(0%fl^W^zk|M11r zdaK8ufBmEGuki-%c?%R7pY)x}Xa}XZ8;fR`OTFc;Tcu{aD@%Z&(Z2{%=ww4&_(bla zxy^1mzI(5i(ch~+QQj8e4QK~`Ja{S|%VnjV#Ok}Zbs3BF!SV*cj6AB6`!*Y-V=$F< z4!N5|?~Si79?>tWKJn=e2!X=)>?vL6!nvR#fY4SMl|>T>Qe65ygw?_bQ^J4FgXKrj z`azFVaGbHHF|UBn-xFL!_arC5d`>Nl?uql&dwXwjWRTX@}vhxwZD#r)-MN)G@A zNLvD6(rL+UCf<9MPq@c;Yh{=(1XG9t%wWk#q$UhRf?GEGgw|bmh%wJUf7`Z%=nXoW zf5|gS*XUl2T4NoP{y}^E(?5#Kac%d=pjh?er+>e?zl2n`N?6UO7ai*%RUa#qL{D~G z^eZNBZE51ae)>dqZKQFxuJmunRdy#kQGxWNLZ-z4g?fv2Y|z%!^AE$17#R~k;X)1z zHxc3L0ZjSuKJYokpkmC8efs*ftSC-j-}bv=>ik)pBm{S_u~ct<3TM3Yf0VqVBJ#cF zyotDcPq$;-qyS1}+Q}RQl!Nrp%Zl{Geh$T+U+fAOsIxFgU` z`kqR2sEVvTGQ7X$b5**O2x|b|-_P<7ERzHiUYJwIsz=)y^9}=s*|jP_K8Sy6Q?A05 z5^)=gnoAWiYysfFd^Kdupz|(FTwx%LA8a~dmqrBHPtgN!h z4?K*F@UJN1Qp3X?9W^D2Mk*EB(7hcR_oN?tDWf`QfQ-HAR%^{`_3D1Jgy(fy>oFLc zV^~|1RvrNz^InM#K}Y+fU{PJsiKTbNiL$jB& z$w9MCNwdQ;r7R`dGET`AKz$gBqHc~Dy`_Wehij}vzf)I@EF-C@AM?AKuCVW~+tt!K z&Ix=e7R;yoTQi1ut66p+VKfGW*OMSU(2vN-=Ytjh$2%&Rizh04A7?ocq1*gk5uOs4 zFzYtDT8~PxRJ!LPHpYq901m|i6%jfq?6>Nhj!yi0yNZ7;O=!Q8@967P!^40Bc&3kX0#NZ#BzY=QCWe~qT-t+~&Rl=YDzuYROgm`0Tqjt} z<;Qe@lJ+8=Hpa4O1AP+4!`}rImP<1p6_CIcKpQ?ibf4vnF9gDmLMI+fod1)Uaz(7e`ALx5@MGRn*Fo^|8EB@0dYL@4P=2A&p^)D|!A3 zHdae{a1;7;?isBZB@#8w7-~dsWm#9WTJ>Uqrx}7IeE5PcCj|6iC!5NhG;TvtC%9lN z*VH^jwZ@*ewt(^owbbWjUd9X+h7RK=>WO>F^5tZ3#x&`%Yo$hD+rnGdT(HGlq;`I2 zx;%+c{)*B{NenjRcP%RX!s}0ReX>RR^Cb@S9-Bp9^E;1#8tW|g+=QK zxXma%b-7B$Tcv>~egtRThXSA(hul{j^VGZ#jS>WoN*mp{Lv63IqXIGR-BrFothdQB z91OMGzD^p?B$~Zk{ugKTBG<_ObULhgIjJRsK9`I=HDkmfKU5N6s0Blqjo*rWe6>PI z0LRvu`Pdwy)0d)&3y@P4KD9&Zx>soaRj&NC9R1rWg%t$Hkc{(M{v1CZ6MYfW??_NM zk`{QS9}LkRtEej5$nnb*5A;w3O??^^QzqG0#aLdLs=z84=bte$sK$}6#i8XI$6JHs zE^Nehc^D}KN6DwffBa@jDwfrExIE8~&!mNa=J{Z^*g}L7OrQv+Qr2d+ib=^b=BN`F z=7zbA33;CZCxV3g5Y;_gXQNAPC5$I4QQ7 zn42@AC5M(QB?&7(okMJiM#}>`Ovvv(5q4VA+3umuwP)R9r5*4-8O22K?{Wl?x(&w? zIpA%32-D=r$4nN`xHsmAo-Nxd92JlnH+b#{^(XlGr3lGf^vzj>QTCy z5L%;!(94)SawS9OPsS$QsJ;|MX@kVSz@6_EsuvCGf05#ExMN?bQ`wgc_;x3jA*p0M zEC?%}Ry4VZPM2o;ot6oB=296c#P`7IKb!`}8_%&+7HILYgfrf;6IR zDT_HSTd1++>$ay%PKJQPvEoLT2vF(8gIBW8E`!ruKaqWd+kl(bD3n))m!G2(+l!#< zn@IQ>l21~Y-y=jrR=VyoWf5og_y3mR~(jL3*sI}b-OeB ziEp9IQ{j;NH=g_9In1|uF1X^K^kz%>X<^OZm^hTQpK@s|d)?-9Y zwuO~LC$yI4~~~CvcdAz<)!pJrBye@fX4GjgV=(ktippE2})(8bjxC{WfFED2y@GD z-?BPAkCs_0le;N{)3Q;pyPtVD{y6O_85#ekqDv3r@Cd9_POG#Kt_%nmcGPzsJa=cl zTTFf&{pku@L%k-&q9#kfp8j`jtUcN4=ne}u8QZ;ce}s$tV0h$Z4ZU@VCoN~UNENwy zl~@b+y5lh*JsV$so;0y1jg9wRZr}KvbMkLA@|ZtN zm@7hmJkpiRt`gV&Up|#8MGVHPDh{MYO!{5ad@2h?`VDD@f>f&g%U>M1Nww$0YBIhG zKMJIgh5Fq!3IwIXJdtpoic9Ruo8w{ApVc=tC|82IL7sIZpz)HY+5AFQ1g9+y=bc8~ zxN+BJUi~1g)0(+JpGM>32tIb^Ms$3`*T8yZjrPe_MZ2P32hxOtJ&Ik&!mFe;A6y#^ zLtj<6>CfLxlRa)RFES~?7d_G0ra3wi>v!Qy#C_wju&gmmHNfXaAh6oXtCHM4_^+W` z_t*XA8h=>7$W~m#r#0U@%a%dk&8!^XxygjnI9rgQ^<%c*1JHn#(v-6s0p8vE7GbBW zuW=-saEh`&7j*%aZer4J>+Poka{R7acyxk(#bE_CSHuYJC^h8xwHIS|mjZP-Hlu7y6Hf$?OPDZZ(K_=eB^rrvMIR7I>ky1n*|V&HIKCsTW?3A3<> z2!=`KEBiJlPmz1++pg?ex$qlwf4dgl9mAhnLapGY>t7IBg$5hZC;6QtoWWa?cax7q zhfHqohwqSOx3ixDZOek^Bsw=^R2P2V7QVUl{vx{c%>Gky+lS=8BONzl`6sIr+XD!x0X``K@kid{R$BxYZSEVYWe4+YIJ{nf|?SJ+ka!_0yBm?(^x zz?n{JE}L`MU<4kOu=}AWoRH6`S~k5I3XCSu5V{WgH-p6NAPi}It8--&5ex>c?nh~5 zqiGBhtp%~IXpMAnhJDfN?@U8Ec-XrW5}JvOdaU>a(D0^D`Z1*3=E3ThRm&L0vlHpf zODN+;Yht3DL4qQ9827`8@!RDRj5t<0di&pD^$)KPA@ptRhk|MnftF5(c;Bth_Zi^f ztDv+Mp55^@P9`?3KbM1*KT|+yiiyQLSy={HNcaqc06Zn9hK>XfIR%59$Wm_2_h!Qt z2*b#0@}1lxB`kgsJg473M~SBwC*Z;*J=3Q0Ihhh~10INO5<6J|^#C#MTgSythV{S+ zfY#wp_$Qy5z+Y!$!W3=YKMv;D#9sX(xM@)!D%i0AH{3--{l7Ah15XE+LPt6NAu(Wz zhq4Y&-~7>AnX^k|_{|(+Y)1W6c?x8MB=Asc{)&Bm#R7Uo^_QGMN0wsz0|OWnh6eE^ zNG!fsWF`l|f`@uj`f!$VHk~y+a`bbp{ZR`wEI}H(1mSNgEKU|YoaH+AqAb7lz2+X| zp4ltROBP0}Go2~v9}=)X#}I}t5z#gD{w5LgKUQao<7qv#%O`~Nlw$JtIqO?~p!Niq z&vd`;7qr?UKk!0i*2ZNW43BjS@foBKO9gzcF|)HtT-efTtRpMyT=v^bGa*P(+bm76 zV41E$BQjZ_t;Qt<98~brgo8{58&JDPE+SYCuUYjGla<^M;NuqL;D1c%8dPj%f z+Ln_ISo6YW)c}yZ0^L^?ycm3kckGj<@6Br9tiK8_IbyptvI}Avb7Kn94k;~nGM0q+ zJX3I={_)gt)L%boyuaGrOM)4RhJsibY;g0o$ay~dP83XMP~1Q3eh^yCYmXY}7_Ztu2oa4`KxSzXUxD?0*FB$L@P`HhY?=CmxmaAOO+ksyBdz1m zT}90vLJ?FiH4)|*E2nUNRE@B`ZJUMTrFo0XjO!p%I#yh#8s2_SvS^(19;B_yeLR9W zfb1YDxX^&$r>Iux5?P=@LDTxG^g}C(xGEreAe{X|l=KPxQZEi1+;77=4CuADMJDC^ z4qDortcAVasB-2>XE-SJErL{4;F}tvLM>(OhsHNcg;USrIHut95r`_0 zleS%!q}33f?PQk|a`xk^M%CcQc%o9>tl^u8tN$j94 znh?qeI3P4DA>d-OjR%9-Rd3O6Aja>G{p7<1aSR~Lld?t4tqm0Cp@|~6v!`Ae8mB{w zIg9iMG7{XY^=QUi95dj#O|n8x1I2HgNLuN)h%|@iuL^J15$3;pR%RM~2Mw4nyg5Y# zyk-JFPpK`)`Mpm#ueG9^9|x^+L>xYhFivWil-ZQm;9?Fkok9nFy;B7kE}H=eX|xS> z1d$!u87R118k#+L$2o$D5p=r4^fbI}^sqXi$<|m6%QG@?F3hT?hw%odQt;C2GJf{R zVQ4U7;w<1Y7)SGqXW*DJ%9&IR8#$;{4uafsb-@uYTnmBdt9KeBk;zzU=5phL3Sjd+ zq}0?bm?~|ArqdypJ62ODiJABX|Djk{y9IVoD3VBvnE_4BA;i2heU-Dt&HSS*da_Gm zwLDdWM+C{Va{=5aWZoub+Hee5uJ1^ax5vTG1aof>Ok?nkW?Ivn^eIPtxCXb!QM#y^qy9V9B3yqy zK$3nz>_Bu;VGru&Q~+Quq}JqS-p{d(p5}s+YoJl1)9l`fC}c(`(K|GEJ^gO{?Z43E z=Y*9F+}&>K9NEc_Ju`%=^XmR8Md@R>kLi898d8{e*X`G;^|DSTIyEfu1* zQhyrqS6P56L!Kaxx%ml3mb3mz%G>A0;uBgp{nm7d2sY}@59Q;8cO}A+nCPaguxP<% zBt+J8C;(poji6ZA8jPJKy+;X+*XZ_s-W*L1mq6!%45Wlx^NcSO zVOHglX_~TlR(^7&Fpi%IIgn_Qf~ zmg9 zD3Itm{%f_+BK+3orD~^?Z`BwDcmv(t@y}nan*I^vPWs*Z?JX*`rObyyZ~PJdQfC^{ zstkYfcb{A8*qcS&t*?x48>MG6xU`y5brVgg9?PZEiG@7frZHOuL)+)H1*V4v%!JWD zDEpuo8iTwpiT8Zx_-{O^61YW74!K_Zk)Mn@*ChqUQJf(B>vJND{^^k?xGs-I41W>W zw^AJiE%zVD&Mz?slxey+N01cThN>1TnCsZ$58V~rma8b@hXIu2ojKAHf*Ftszkn zoRvr3M^UL;asdil=osjx4hbVO_B{M@I*bvmp#CQVqz1QapNUpiIi<)uEu_+KFrFwZ z`QEbaH@~T;jcb5dy7*~*896+G0}w0`Kb~HYVTd48ur*R6l@rB)9S#V#kDi3)ARVy? znh_Lt3NlL|x?c3A5*?cc3%j`;kt2%uCCY|Ag0zS_&K89g_I2KrlG%9E`I{}pQY6z? zb1bA@Y)SNeNr_+Tx-e&ZlWjsWpq*icc$U%{?3T(7vRb=p z4tuxFJ9UM+MtC%{*F(1i6-#%+U9fO+Y8!!8OjEf;(;jubGeub(MM^eCxnowF^D_Ba z*o2JY@kSYaL8N>R#&nA5(=&T{V{HWEE**$PRobCGhgA;S;IIry4e$|8qB;lpAL-YPZx}nSHwT047$rDl@-QM zWIlO5&G;NW>_fkX)>Yvh*?pY$Imd=TXIky+a7>cdock4xY>0+m(il|~0TI8QZl{u8 zQtov5!86JTgSfcL;E^DOQTHYKAXhxsmtT@{I9W?M-z2SK_KqfLr6L0}D|K^#acYrN z>;QL8b#iBY{Tw7C(zP$$-@44ph6AF2Wt_qMuy{;t80dB)#?0}kuSL<6%buhMaYfbf zeO$PSADr^4(_FX`Ho2-rS(4WDcu`E*$m*C)tk|fpv1^A(`&O;)~xd@Z|;I$+{K;Tv21AmuDxK!=z;|okrkILBAyZ!?t~=H zIH`@oFygHC!*XAqB-+|WoZ70S<9y%akjl7#H4 zGQ#Y3!;|khl(3fuWD;!^)kc&G3VRzJ=&W5PbT~`(j5^PF`?G2joK*DamGzaBt(BCO z+TDjW+-sfPExb=lIWV89ISNWSBgY{xmPV{l=5uGtPjM)1pe`E2Uq*YB7x~y_+QXeH zFn10IN9^kJ_fsBEgXvHR-f2@y+7uU5lxwpJk@dp#Bo@Pfir@Z+H)*!-*LJH%>)mJE zc6ATN{}g2}#pX^|MN-_679(9-4uj$8~K@`H(2=;OFzygmoJC&ih1s$y~YPjgHLUlLv&zjcNl1|l< z>7U~?TK14nq@s5dtWhZ=Dg~I0TZ8VMo7LNS#OF!GZ!fKPDzgl@nJUl|m4(>*ox@j& zlo!9gghf7c+|IOwPXa`-25WhhmPM%pPwSF2N+T>l?%0e%?g>4I z{|Q37E(Phs^1T zgk{}!0-0W|=@|3dKBe)cCQVFu3WVd2tl|Qn_F~HP69T;@qnW`O4-NmsyGa$P)#7vS zAv-I3mjVp_)6lL64117W7XeX-pl94Fo|q(lyBdB6IdXleY+h&>yK3eZaoK?q+~U$_ z9-E^6clP!5hg!q1XfGaPTrcg0Ty1ha0vElW1f8P-onyW@(t)JYxmh@*tQF&d%qjopk%hijWOo(_kXtqwP* zY~*i0+zvlkp8LQ{lv=6Ie|?dB56n$v-eYnRtEZ;CT_Aslq2RcCHO zpnEYX^!=Ea6Qj%5teC-yq)S7pvRpg$LlVu1<8eiz~nO5j$dEeV}hKT`Z%ZE#qgs@hDV zFgj2FhwP*s%qSZTXHI*`PRS5!WJqSXhl~)wLE_pZV(t!zIDHo-ZhY2LLMPX>Y1L-_ zo&S>k;&*lSAO9a^K3tcL!@MI4e9QWwYb2Gi%QuWlj{+cqxar#IYC7NBCns}87_~*U z(@m|68?55Qz0xHpz6HdQ5l>UAr{06gufR_a2ib>kcl;Hr#Wu;NM~!av_Pj;oLa%5$ z=IKUA9_tOs(l`g^%>O8~l3yl)n@uv?{=A?3LG>hx_9G5qErNAdv99E&JH=d?(UQ!= zz}NQ$cb2U{_%9dx=e_iSt3^ ztj+pj`I7lM67tc8;*~AaMrDu*3G!a=ciIfQ+RQwh1yD(XWAlOJu@)#>YKh^rrS}T;?7u50Fas7~NdjgXb zN5ZGyC*Fd9SKOoVUVr4@d`>073v2>DY9+PJFTVbJE^d-(DUsLDW7J1`P)yUvAbw%? ze*u_4XTRsHDWROoMb(;AiOU(CH2-sdU8P6Eu9DHylDC3}KhuD;M59F5gk^{NVVH(- zn1_XUNsJhZQO+IYfk=FIXj2#>ySSWz+l$P2A_G_142b~L*o`$qjztia`&f$+*N_Re znIjpaA9-45#4lkvPahSO&xDoPL;zS@vR#zD4V(l~12z-@x20JDs4|$l2>p#W2K_pk zQv=$n_hRV7ABr`cyLC0&B={1po%jFuedl+4FB*Rjv7x<}I5$kCZFoGRduw;vrxCLk z<6W_r4X$6oRHtIB{R^gZxUJz(uI*Z|uNtt8hfP(1^Q8AsO7uB+^r;m4RMT0i*LdRz zL1I9gv{74nI6JnH8MSX4npF+Bmx_^}XmQ5`Iz0jKshe{PvAYc%Mzo#%BwWc0MF7Cv z7R#N##W8r>9UuxFdH3yt&|ScNlvYnbR~JIFi5V8ByS!%{yK@}7qbT&Uo4n6^jI5!% z7h3tsIm_W;q5HLhuiz=v+)K>!P~abeLA@^hf;jAWLm-{fG2N=t8aDBT)D`eCRGp`< zEYTU=b#+5By!c{4?U0PTV^IHnPPw{k+nb>XfZ8qN$`+Ztx!o1&Thh;699R9o3%keZ z)*Gl1T~wXWXoNd@58?5&0vw(tBwq2_n@}|14-A~tu%iE}iRN)0*V54E$R`B)uOg$Z zn&${ur|eik@b->xaq8YD*&dSb9{1z9@v`gA@;Td=eN2i!a)>h&E3!{Ee7}Dle8dHb zzi)t@sSL#a)YASzBtJl?8&QBD!2mbxQIb%QVMB%vs68`aK*c$M1_}m9@C%%T00uGO zdsPs_xn~m`rX=|9pGublqS$*SAizh11diP!qp=mc7cMhGIH!xC05ScZ7zls?9ry96*8Kmo#o6E&GLIDc3FmQW^gWVI%Tre|y`Ss!B$E^SUe8c)D6O2E=G-C+B z|L~)4J^(MXjIf3ZWQZ+d*egf?7_g|~7Gz7@WDk5SnN4vN|mS@s;Hxq5{@|IkW-GJjo6XGf=b{q>$TWstIePr>M6z$ zG%E3@Bfd&IEw$CY!c8~ceDkOPH?@niLKjIE(Cu*oBlqdfS+x9rOZ}^5!P0%m}A>2IT z{1X2L>UbEBk8oAxn->^*<1w@BJ%AhPouS`tD@-Y|$%nVw&w-CTc$VK1pLY2<#=O0n zZcm?}^QUS*0GiyRGDL}uW4|*%*Z`9?oQW@YFjI=t`UkK0RqP|9v)|bI7cz&aj&-iX zn)+ZQ!1s+%a(g?}bDq;!ui46u=eifeSX&Ar53Z1q7!UMjL8sKQ$EN8PSNT z??sPzLDXRt(-_BE z9YuIUASyACkF+F1DtSpq4ziGkOyv7AsmUYyQH;DRic&-=Mn>xJqCSQ;58joG?*XOJc^-n9Fn~m74j?j7gK4_#)#EtC`Jd zt`V8vqhvI-`OR>S6O-V4rZN%6Msg;xo7t1(I*B<%&cV`%=!9qR?0HX1<};Q2+ zxe==QLn0S!k3j!HQ2HrI09nX}5C}-a2LaTP*p%VG6o#*Py7N>>v?yE%sWf3gP5@D; zM1WV zG-@@-P();^sR1~(3Q(n-QINvajJEQl995_EF#0czzH_VFQt0a!CQP@NfpoF0uYd328#$rQ6nD29))<{?+6ePU9Jqb zx+UOXunL{A%2ttNjqOn>H_@}&5V`#7OEcApn`0znAcCWdq}YZV-{O^~!IMrq28D?> z@ntyZfdU@RaVW#?3?m6>#dExM-4-cH7){!Qp+IZazr?j3$N+>Kr~&_9gJ?h&{(#44 z|3bFW&at~QJkVe!)LaNbOku5ZFF(ZdzXPz~BVk3J_5y$a80euE`E|*aeg;$+Y4;f_ zjt`3?3S2e;@vD|JZiR2`!xPpRtUPAba}5?mijA#(vnN|n_5CAUuf`N4C z0)JwVieYto07AHf622?)(L^#SsOZGSOw9Z8k$Z z;u7Oi$uS%d00h8;e2~F%KE4lyKTMDn;DgHLJB$KA1&>{Utsrdq2RJ&AHlAU`0-H$3 zKK6l+bx4E5AeEInY60aFi-Bsy!pA8pBv@3>tO46l1T*j<3@iVj!yTER*>s}{6j`U* zF4BFSLpt48WDp{&H1=w%{;WJ{KNx!k6Dwt=jm>DQGuoPqt?vZDmS;#{0^-9;rquiE zV>e`Ee2ZJ)@|)M3QG+N749o}0gg-$O8q3cJbUk{(kaM#n-AcL{k*<(p_XTFnA!CbM z7K?=u#HG$>NfRx&=8tgPfg!`j<(-2&F=|{o)6?2?0g^qdT47h%k)AYQ3DW6LhkDed z_PB}Vy{QMgS0G*0v9|%l6*A9fYqQ|uFcM;r1Hix%@n}Rm;y{gn7hogU5CTlvu>}A^ zr8sKX1Uw3A@eV*?4fYU4hgeV$uCw*)1 ?uHX-B#K8X&2xhT~*Y0(&Gw{ebi%Zul zu@AFoRL2RTHbx!BpM#B+xdZdCzqFlgL_3!uA82*b+=3AS#K1`DzKL$xorQYfq7ITs zFUu*r!vKJX4f8UM6ad2(Zv-wb0?FCVDnea`Y`*gqT8c<8lGb}XA=oLgr%-q{K8mZ_ zC23m6H`ow$dH5;sZJ&sO&8C&rG2Q7&Ls#D10!!&BOzJw1&6{0y=&y#uE0gJ_29@Cg3)Fggp)@5Sm2@a6%UVfVK)DSlsJ{ zA`k=6fkFyEYRK#_uB5i6WGOOmAvka+yh8xkMFRiwz*s`($jU4uFi-R}yXVFeUt3J@Sb}!*>9v=^280Lp+(RrHC zjRvMBCP3U2CucLGfz%KtKARJfVXSjj|m7?zgV=isNFF#Kr^2QRLL&kP6 z$f9SSAaBPCq#y%CApNoM`mgXL>M{!kd^8gn3&0n9@P{S@b2Ne@Q19+`kJYM%(b}U7 zPb}f~qAt;)Y|cUyN5HbUp&gQ<-)_Jk(lH}m@@U{e7_a~f9HSk`Kw9RHe}!!)RHT_B3KB+03gEZ5FiSG576>}FBKC} zRIwrC(=Wqu9LJ+PYS2nDlrI10^DfUZBIXM#9<&)F^D_x@MiWm)4bm$!b02A}oyzLC zZWQsXM@J9MG?#FmQd4kNQwxoZMPD-?BB4W|R1)ixgzz&wdPgYe%AnE;DSn43h+*EI zAv?^(C0UaOL*izXq9n%c1xvI31^^Bc0(~4Y!Mt-4HIzGtaubX4K^;N>24KW+4H%f} zKoj%_78K$nlo}}1LJ#gk=@T$$Gd>DZYA!EnzVtKu<3;)rM;Gm83WPwPtQf_!EBNn0 z0)Phk1|CrDTK{*j=Q=dy(C1%Jr=s4Z6I7{P;eh0Pc z4@L|C|7-&PbVOJiCmOHs;cky-G~gHb0VR#IOz-003IHe6VGMz+va-M)P)bg#^AYRx zCto!g^VBT%v{y?<0NiW;_ySZVKvWF^RSj%akMUNG)hZ!%T}P-O1z_x;G%L=a$?8#a zrj-@<)p8Wz2P7aZl;Yur)j>-YKH_37>f$hzWJt#BHe>D={K59dX9W@hC%rT;qyjL* zV=$M>*qYJ;kXC7tlW6rq-JtATT|)soUZTJ^EQ5Jap%(`+d(opQ{bZ1hL>gEPza zMl+R2xivbdK?DEC)nC1~*dXF23jhJqZZ=IeK5#-Dx@Aj=uOP5CX(0yzGL++Rb*{j4 zA}Zn{`c+B6EF=5UBw#M}0s|&w;&wJ@PVG!hvQI6Z7A?A#Y_1|JzLRIcLM+HacKHHl z*P<=TMK0*VY4O5!udHO#s36Y=fAV1e1c0~>11!msGdu${M1wSLz%)=pHO3MxU_&-& zqkIDPQF`MyY=ctZggb8J9GqipD{VS>!#c3zO}0Z$LUd~T^Fz)fJ=WuV(-&T{qkIt& zL_{Qi0|0B=;SD;V640U9$ks=@l^=%?NEe1-lFP%~_SrVIcpTVaCa-NPZEsUcSQdd%S2E_MPQ3~iRg+56;0Hchk3mWJo~xNJdym zn8Zn-L`tT#PqDVOSiAat)&b%Sdn`Zs>rgHG%OPxNGa`-BDo zMNkOEPzW{^t#?u0#ZjmuQa*xwz1VPz_k!=^fBJJ5)5&?S?Nwq$V)g;-I z;YD6d`F!MMAL>CEvOs|W^4aKiZ6jDTF?jL*Ny6Zkfv+bt0Te$rI9ofIZw=yNGG=31 z*<=4eW>Q9ms7{7W+mwi&f@@S&vM5<*;%5T*N@;Kb_U^T3S|Pn<@XM;?4d_V{&c;}MSb$%|nrHQP4 z4oGwa06lq7d+x)6b9r-^$A@}a$B=oegZ!K}%mH`B2%NuGSpsF_K!>#49YJ9k%T zu^XGT*6FYrWK*svi?*nX%7l+L+ncDTs8_q6NU5^HN}OIhha$DMOFNHH`-}MOoxvRc+NxwDey=f`F`PIf(%ECcT}EV$d#G0kEJB{s13rK@GaZARu71 zTI;oH11s)9ORD%MuE-w}Vj-jqryzn30YNmb%+_(;ikAtz*L;!uQG)+>dU=A`S$Rxi zq$s-3vAP^WzWng+F5M+IeJTjdzzn_l!u`Mo-63=)`7SIx2}0ZNqQ21JzKoHD-NUpN z9Y&g!!@pfJTc!5cqg$H&qJO$DmYmQMCTu?xX#Vl#pV+<_Yuw=cIm z0L0*DlwtxDzzduPD|q;sl>Ke%D94Dx2D&OP$2k%Lu4MeY~cqLCzL7_HKU8 z#$6>2OUt-S=6&Z(#Y`6Iy*(!6Uh>_N@{GhX{m;>8Koa9>sMTN)jX_G?;D?#EC}C9= ztxUv$4PXd0ONS2i#!p0`VeyOC1yv_E3M{}3!p6>rq9vC~*2j^awgQ(j= z{M*JS+@Px5-s0Q{;{2=@EUduY5}N*sXaFP*bu)JIa~@3pZR&29SPG6Q8ueC>-b(gu ztW_e}`it3u6VmwRW82O0@gvkBg_t3UfD#OXJ%MgW8h8!n*0k~?Pb>Ir*6_~${xlq(AqASNFf z1C$F8&I+~gLreOEEIdG33Iz%*CIm1b;L1!(>_%Wncd9^u1AiJfi!@?x($uS4zZQ%< zdBezkEfcI3$E}tZqGWXX)CvGbhj8FwXPnJ0E~jg_<-dP+Ulu z8(^;5l)|MFp!Q6E8&N~dL;~=jSxq(prkr07MKu3WUk_rGlLOQgbBsJJ2$)|1``ss1 zOT8e_!4&BLqu_!F`SpQ4rv$)5X*LC50zSQ5H9#Xr={CUxQd#&+O$|_!%tSfH^8!{D z7D>@@8U@hfj{vF!8dn~+B92Hbp;KT1Io?BtfDJap;F!r_cbHPeuz|%K@PNaadCuMR zPj=~H24(@AQ3t?*p%n%ZJ4q^p+CB&URsjeg!zJkK<4z_u6?$l* ze3=PqVC;Q2-ay)cCuc%vu4);p)-~tda^vmfYpGLr99f-QOHI&_#8|x2 zxGVj)*GOWRdni7-Oq(&&7D32%McP&f;0^vHTadWF@JFsNNbA8(J5uz`5W5uxJLwhi zT8kP#NIfh@zLe&|7&`v&tJ@7kw;2D`y(J9uPd&}N@o7b$hdz43jtY#?ykH840X)5= zsJG;LFXXCuuwB7yc(WET8Q85VtS6d&wp>_DdCCm4q{6`n<^g%=Q$;#fDFgvX6QP!U zeqs)D}+xM<*~2hGX`#4#e&Nx%~eTuvSnb49YfRC(uwYG821=%=D2Yi|H&(AE<{S#Fs$b z3@IfBKn)%PDMqHbPk&z9A9v&zwEz|ml4b1L{>DhZ`ZZF3tSZPFapg6&0Z%G!^AEC8 zlog7}r9;gh_=P`uvNsCZ1V~r;NKdx)O9qlqT3tk;k8)Dagb1Jm z5`=;!`f)P>`0WN1ONx$=f*O$tks73%6r&j7j?@Wc04`7~UCz3>hQ##=SQ%tSAd(CO zAHRgA6*01eX73_t(^7A16|C(TAS?TEo1xKM;?6%h%bV4)6)z=ti= zaE1|B#{eauhC7O(2uW~*A2u{v9qPaa;1c0@yNiuKsv?1%;G-Fe*epD<_t$&;Hn?mU zZc;B6()V%gk!}AZqpMlA3Q1xKJdjZbG)RIP_qaoW6*5_ZXm3*A6M|o@)zo&pp#zmbhg{i;3@pTf8R&o+ zK`hjbB9^Wm#V`aKDlxia77oZlCbE$OK!9JgL$h`80*DOoL7@Pm5=@k`#$wFA;vt|4 z!)VMjG9iFCft9^d(-meqPV01I4#8~#{FGq!La)Ew#``$*J%AUYS0 zwDlo-V2uAi+%XG>D*8~3{^E5*m0gBx@@cjzj{)0A$x9aGe=kk7uF$Jq@ZeN_IwcS) zA>t1@xk$zufJI}lF(?BJzzT$R-5Xe`B6~t)(dVkzVF^(WUl?rJi>4SN3&N4L=?Nmt zdXPUBy=xOU(;di=!i|$Hm`TOZqtFaMulM1YEXef$bKnL(%pr;rlmm?eQS>t=5X1w> z!P4fi1yTJ*Z+qig-~1K;61dSRb~sc4i4a{mXyFrjCiBy)j+&1qC4qC#dAq0H&i16D zK3omtDlBI?Lkyr21Gom|pJI7_T;33va~#zDw4?yZ({cDcGHN8XY0y#1$T1b2rr~vI zd%pjMQt|LA=tlcWnD05PxDWouyK?iE zB!2k0ul=MZ;1=Z$`|uP%2W~Xlb*a64`hP$9;-7#2qVhif{||inha9_iG4}_68i)UV zX$MAMcNviVYSD((gg=-@hc@L=ec6N)w#xb|-v z(S(8#6ZtR{dLRnhG5}&=Bb-}m}%a}-5Fy%uK;XqS@KreO=N}GKEdpRV@KpaT{}>=G)qN6a zdJQRFV@Qh%Ig1sEdMrhif2TrT36ddcd}^~0bU6}NuoZH#6X5caE}@cOaS(Nb$KD+hRyD^G1vpOz>bw?-ZA97#Q@)g$dz|iirOVgdj4Y$rz(K9G4R; z8Bw5xc4+;`5DE~Q3_1|bm=61}5BRVS=`t6>SqmIAJUm%ml|duP&7ESRKEh7*JbO3~453e8>UXlg%fD3gX3Fp8c0Pq3KR67Y% z5+{M4KDA*5F#t)rq)iG;&_q^iU=N}|A4f$Ob}K8#V6h)CQJ$nBZsWTOkf)xYV6|L|UVKEF> zdKydNqiA7=Yta^O5f_hzrg)(j0}3i83aEw=09Q~C>#!zra1I29N#I!>0`MQb5D4;+ z0J1;}4Rew`@)}5E&LyAh3ZTWWZ4HAs_T%AA08@3uG)M~L!t`;U;@k{0eJwba8qC?=u)P3Dta1P02QNR8IccpvDrDOXJehV zcOBeG7xX$G^#LLs(o=AWZT?E1`uTa7%5g37A~E7oHVZGN5l#KDFkUiRl%Ss^G$JK( zA~HL(fuXZFJ0mrsC^@ntQ1Vp)V6H(*Bu3H*{zCt?SKB1uD78}JO;th>I}v+Z(j^G{ zpUT0k+9fB?s%H`qay$?k4rxE@v9WWd3o#-Ce6+&XTw}A+Q8_ml2a6@?-!CTL2Av2SgMz7^$8KDS3{BvH0U&-{p|^ z)Q~55qNFC3OeeA@MU>v>EBP@2l;gMx^rb$9n=3K7h#M_6>3i-Xh)lazHMX+@aYEQ2 z1s(7Q=)f$~=n%bQF6d&Wf|(P@+r08ZFZQBt`BD%F(=SN^Fp8%Z1Vf^IVZP9V7~=Xc z$U~5uYi$Tvd9DI6WDp(&E17hAyBljA9P$4O5a14y5DzR62)y+$G5|X8AUbeD7(?PM zJz*HW$!vC$HulI<`l>7kDL2e?E_V~KTlqlJ)I}TRxhudd^Wra90m7|#y0R;%7K^(z z6+bEUx{w4bnN(A?NOG^nG0a1#>`{p#;WRJB3x%_$=q+I`2P;kmmGLQwKJAo<4o(sB|aY$JDl``CuwOhln zMvL8T)!Gvzei`NM@uyF*MKvu2c5yEdwv#8=tNt(*^~JV9k#$RCBs%>qL*q#G_2 z&NhT{2T%i25GW_vmoI@8CzL`^>^J1RZlhX5Hx#u{w8?cfL}H+14}(NX#6)X{$(k%h zXIDi+a79^E%e=Eu_{)%FWB@wr88&;vHf5-M8pu_VBhIu(Y36j9T;ny9LvOP&Lja~y{OLwG<~;Gqbf`pQA~pj zpg%#@onqGEVolS8Lte5)<%AO3#17pwO5oHA;>| zC$|`$&I8R-9o%#6(#CR1vrP>{RomO^h`2XaWp!3*mEIDx-ZnN8A0crw(h^)1$Xf1bs+bES9;|oeKj1FeHsLASU}MViM3cO(OAYBS?uH0 z;{{Oj+oE+q2W585F#6P#;nM&>uHUScEm~zoCIk~~j}l-Z;@n}GC1BPn&A=l7Ax2;J zwJjyBU;MRK|7GI?rh@_zVH4)s=BQb?P-0;=3u9Jh!F@Nm97Fd7Rlss=F_p=Y-ww>%;O_=U-6q?T0Z0ecH>8W-n2Jk^HLgWwdXZ2Ox&k# zf_*RR#>DvW4UvG5)>4g#LT=_}ybhwvY0P%-7H{(g>kkfWz(jPjPb5viIR@v@9SF&bK_MU+?9S3xv#NEl=eNBxXviRz64>q1L zb=dt)SEoK&7xiTKbyY8y*cW(+)B&fMEyyN!8}Ao*ymEIJXF)W0dg2g$2dpSJc=rf+ zkYAOChj>h~^=`ea-Hd-EtCJIGr?EKtz88e{Zn`=DgNlDh&+ zA=0E8i~0o0)auKsSG8`% z=#(o~uO*>I{aV)J)Qe-unq|wh>e!8Fb!Kf_x2s*eZo}s7NLS)fgmCjVF!su$fGG7c zNjR9`*S>%Lo*6LEP(YS!LJC%t%Ng)myHIngJt&%@TF|ADBFt(!p#nPG{J9f0;vizh zj14-5ESYjjzkKlqpLsd+X5m|jTg3nm;`4lDep6hI5W+c#vyn*=PyoOIOV1(Nqg4Od zpaM(&z#$aCBm25$ZzL21{|_8v1+64cC{SNKdGj2)P8W{`5CflH0vwUd!~i!$8s!n|B-2(`3GGe|^-Ok_yJ)&NszfIRYS8WwqSY<7QI_qaI`ck%Jn3ESxBS=7gyOjZM_E^Ul30I-rq8535y8uDWe$ zSnpni^_an}R{_w==MDoBXhoYp z@m+@-af}362#ruZhro^;UMSiJw@v6wTPYIYhLw$$Xz8YjZ3|gpN%ZX3XOqo(V!52n zT2W$rboJGtV|~VHkQ5e5(RSEqh1^FYEd*1UIW52d8QPFwZ;ms*7X$x%3^QQhnk`Zo z?2nM+8Z1Bn%|ktZz-J5Ba!CITZ^$Gk83ak`*vCHb zu?}glpdhf3jXP>#q`3r4D4&BL0A!|)5p0fg{F~pfLT4lZVBj2+8Js0T2A60ZqZb2X z2MeI3GMG`uG4dDz0e&%yUl3yegph_M_!xkl_3S!SVuK{kVK<)vO>qK=L4%HQKxml_ zMESADj4H8@3f-#%P*{UKL;(dT*zs-#YMKcGH-T4;vXrMx<%zg>ORK35m+{k@)VM|( zWpS~KYiVES{^39W72pHr%Z><7Sjj3}Qfx$w$B^oj;1S0=~+stcvk5LzY!NWcQWP={l{_!|H$O;_70 zCNN1P8o>Uwau!MEh!|GJ{`HkCC(VdlNOS-wI7k|(bU~}e`irt6@T>@N05!s9fEJQL zo&ZaZIN=rm81;h;?jn!a+C$M(0j?Ja=)e@x0gV6Al2#)rJw?jsM3Dfbl`?F#RRAX7 zqyTglLIzP(GK{3UMiHd5&IRfSp>n+JKYKmZQlMlbI8GTr2dPKwe65A-2}aumXi zJOdAZ{p*lOZl*aI1MBkI3N5k{u>f&&E_-5hhY?S5B6{6bLINNFS3<)bc|6h53Q!1Q z3RcIRS#OWw;$vSHi>1H3-+XOpHTmK%$u2#nkXQ4n2?S7fvvO64%S2)y;c8{aod5*V zVHm?{u`Q;>qCwP%4JmZs59ru(LOkV-2mb#J9_GVG6g9#o7}3eMJamWvPMl)qx%rah zoT>plHJO4q<{ptKGeatpH=CX`G)%h58i`aEBz~!Gb{WgTjJ>wXA6^ zyq_7w0M~&~hgCdcE1R{N&;n1r!usK-F)f7(X`^oflvi;FV6h?+=GII@YWyXouvHV| zvat5~{37O5a)*4rM|9Lk*$gly1OIJM`aylW2}vm&M@a&W5b69)QJ2xUkEjscI5sis#r zUNWEn z7^={bu>&B4lj%C($v>&Pf>&#{J@_(T`wfnH1_8i;f>IrSAcm;}l;8OfhEM<~h%;zW z9%Xtzg1|e$8$G^DAZU3fKykj;=s*x*v4v=_DmaG{yA6cOv40CD$BVihq`a#cvieDl z%qy}aGqPmzym(s+u#qPdyfPG|x$eP~x$_eF@a zdx$F3kw!qc$QZANK&|#$LB&x)0g!-4a~1Gl2gg{hga9p>NjZm*Lpr=9SD^uT5Em-~ zFBB>WOw+WSc)E{>x?caG1PPe8mZBJcd%O|DnE6nYLu#XVm^=W;5By82`71#yi!y{2iJcgJnf9SOj6g78>kzI+T$^Z{=YeMKb2Cjp`cJU~1qeWYE6@n@c z7bB=sH~?J?5KIG*sX!6V14Wq1Mt&>8$?L|6;HAHCw|!Hu&r`B4+P_Q0LC{#jp&__T z62?YLE^2_Y%0K{BDmme}LiT_@cHp6mvWHiY!dvORg8;rHf{8PHlu=SWOX!DLYc+g=AQj3+XswppQn7v_?$G znTR^udja~fHzfc3oHGKgE5HX`=nn9>2Sa%iBJe+jL#;+oHb{|_ItaOXc!l{e0ZYTK z;&Zj4WCJ1ykn8vdZ@a~8s)Iy;hwrK=c8~%Ks04UuD*=E3OJWC9a+FEShfn~7Q23s? zYKJ%IfJ#6I>@kS0{K`Z*hIRl1K){6!i6c0RBTfkr!z;|gOiUy@sZ$%maRkTDqeLgG z#2vdI_|hdLG{;2oEZ1_&Xo5>9kjnyanYz5oC;7={00cc41~A$^)}YCy;665}f?tS- zH+cak82}l8g^81b%~%?Eh?hdCgEO$FHf#=L*cVCglRL1@pP)&(dlf&U6Nrq+yxhya zL=%Zb1}y)G17<)6Su}{w>IUr_u^Xs|VlV_Ws08&WL-)i7@-$EMm)#^1bo1)EHWwj8!-a71ry3i&g36#go>W@qF+E0|9}XIGcY{b$Xua>_IQsfnGY?y zxPw^6=6Q|{jSvMOgnICWGDDSg2nAS}5@9f>04M=w*oOv+f_izC{P2hWC`M`1fEuj_ zY)H&+frWjj2Vuy9zg$fhg;5X*fSQ_;W0epB#SGm&TsSF*=B{S7G&lD!Z z8mw?c3(cF%#~YT=^v2O-Lud(7*HbAhG}0+a(hnK{E0B$zn?i)-i~JCef6z40I*@OO z1SkO(52B1&A=HY9D=fU5mK0Yb;nsu5!m+`YDU>_n6B=oQr4)mpZ5_LlBjY_m7&OFC&Y}Rn(%&3SwaNN9YoS%xZx2=I7hfz0@U{@D& z*SjfK%J9}g#S4rT*8u4N4FnVG9GWS_);rr&d%Xw)fY%qB4n>rmuX8aigsn@H*4Fl{SmYE2?fxDW3V`# zXi8jwlQ@6{mCDqr&0D-c+q+%df_=ofWn8EQ3e9ZXxbRSCOQi3GTX?ci9MpdyK* zl1NYv%dHE=y5WggIX2Ws2fO*yw%UvUrQhH7wYr-UQX&v}In>mEP&?rN{r}-q($b zsU_dxkXi^8mh45}neblstqJF43!7lmkXT=~Fb>U7P^0*a|a(OkLIgV8%&P zkD>_C$bb*|2o(Fk5B+G>6nzeKItird+NB*|ZVZv@oi88+-+dio0;V^zXpvum5gDNo z8_^LQQ4j`k5Iw};ln@dkX|()6II=CtK!t~PV6=)*F7q(F+as?iMu;p)R9rpQj_nyS zA(M{SVGd4SyT~}YgaSMWAN#ybCqs)o*^@pgoS`I@-z*A6VHCM+%1QsJluHq(P3e?R z5uZ_6&O=FwYg>x&{o%wlV*5p6?||4J)XXF7w5%a9YEcMl@w;q6v zwOAv9FI))3z)v-(1eLPRP+KRNsh0~`Wmn0Ued!lS!$*y1FH_-&Os->1RZtSafOOCW z?G%GQsW&F;K`_z80@#?2VXq1MF_JNvggP)BYZ*&;8C0B^n!$jZ!M{W*4#Cr8A0FVZ z2x7}IvL6&O^990EZd!$4$98p^zQf$(WgEAd)chbr%4jr+@RaWYpEGs{G7i9xyx48Q zm%zE3@!8;G!2fzOTA!-l@@5n&P7z@>5 z9nX55qkxoi)?uZ;btTVMt zi=j+@j@E*;A8QQjV=>d063zb!APE>CLUW3T!ZHP7AX?4YWThYr8mC}2q&`Ngi5!@2 zK(L8WuJ))013QQeJ)n*=p-LOKxHS`)#@dC@>KRff8-fQMa*`c72p>|SBnhGswM`@9 zY$QU6C2FE4ilQlsjoG*&mF^1)zC0396ncEi++2yw0r5v5r&nHsT{b>(6AC zH+8HtozrAmCh_o>XR@Ta)+B4fCT-%TT%IRbz921bg^Iq202u0N`-UW77wZaU=$jVy zfF@}==Jk80cw%OYs3(oUr(V`49qOll3Mi1AMuS>Bg=z(ca;QFzs1JuN$GE7B+Nh2i z7?2Vv364K%R*M&-fpc(&S%8I$Qa9dC$Ao1TpCN{sswqOwDXa3S%?PTY;!@bjqk(IM zrJ{zWda9_Rw5sAMCLbXNgRzy7fINsU;aaPT)QagPLd81o_tHi;C$+K`V(|^EB5ZH* z<~&R6=MnCY$fAbHf`ZD5SybFRCp10vBu&tQ>A?RM;s5sQNplA&anfh*Gi@e=0PKb4 z(1n9!h|Vg8V+gP-OEf|!Aq1f<+d@zauLzfRFg|O;GAFJP!>$q2F6N>J>VmGsoGvVq z*?W<7d0Z|Mf9J9cukk9c6|`}droUIwfMGBPYVe0_K%RowrN;U+S1IAhz%KzHXAAoc z7zwZeD=_3{j8L2tAz&~EgD?q8yb80g3u_1lD*&p@FEI!iKXd07GwGp7^R!;?$`oZh z4|q;)T2E$Eu|`w&UQqaXSh;lxD3h{{1rv8A>G~G-7VeS?ai2(9}Bh{ zXmHEsI~RBMBd01{(-YwIv?~k2m#eK4XE&V?f#@*>0!w`;eI1Ka5p)(2bvkNH!C(18!(wcz5l(&E*lezHxE@p~VddDSLs(Cw;}XVvNaq3>_-)4q$c zRwRq*%;ro~@!UwjbJ=A}h!PzX_0%WgVS%gbr-oEX!$bO0`%%~YogjxqvIqW(f+{imWzGS`~Fm~dJIiPS1Sekoy zRY@Qkgrpw0(oQ)Plv-joIyH2xRK)g$7hF=3DU57PN(6DEeNUO?@K?wFT_qGbu-a5G zrmiG)tJXZ7wU7va?bnk*EDjvIuGeb@`85|p#S{9&2w;(D>>#B>Fd*%MX`jRB1k0TS z1c)No{4>5WJQ!LUO(<$+OB?cvF4A*-0)z19KOvOj?yUbsYHl3JlnvReSjq_;EI5`< zjH~Zp!cEWPMs6LlG=cq7C0>=X#4!Y#(kF?)jIwm}_)qTB-CFZtn6+Au9^&e@1`a?z z@HYVoRVy+t@yu!q z#e;tb7V(F>8CnV48%SAd%)jm}RJlWss1!w#vZ)imwTC3q@(iE!_2Ed;6Vkx&Zm^=& zNDye&qC)gunq{Upu?|pVO&NtA3{~TstdOb7!4Pmm*C2WxO2$FBAGI>mX0;`dQm^Bp zRWfO9-w_q2+$bqgdW}M&j4k9*i~_L4kyZ6!TGBHtAeEWoOqsZhdli{cGO)rg18)RU zYQI}uN)`C#p-k5R2F%h=MRtX4PO*HEp=~w^LMiBX$R4l-Ft~mjhvZXQ5E~#ua$o5h*%$T-xtT}+Pjgk`W zqr3gng}QJzu0BC0)5%0mbXmHkWmxoCJq`2ZgeFs6 zaZ(5H_xGfOVHWpg`e>1Att*B2++0|_BuK;7cN>5}8&TBy7sgZr7v8Xs5%%!FERrWe z!U7vg`&asH(v*UWlXdMG1%WX}V3$G!e@+oc*=5jnZT#bgLH!1JodZ~*zgSo4G`()I z?R{;R^d~7&+O(!I7jf1na5tC5VgqaIWxi-Es?s~0yQ6=iNY{2!<6VFgZ=KGo#1rj- zvdoEiFAd6`7L``V%YvBYQw(n-G^5Ejm;Rz?k#_KambW^r1yAeRB;fR>UWPHYi55ni z2$m2iT!mb{)R6`4xRUk;-wz_uj3uoeFC^dusyRJilW#uAoIXvYK9U8Kv`k2`FaltG zZFjJce)kH*=OF?HQmVcHyg_Dd07;DDn(X%opZLc{qtJBjWrQ{FVCv>6NRi;+nBzP@ zd(ymOxFYU?MBPde^sj%~eH+jMU1@ZMZ?b)O3J-HcfW@#{0->dqjEP*#i6`i*Q28xr z0*^YmJsLCtUvf-uK6Z98?!pr4$G~#U4YoxcR1$BLE};FN>Pa6(sf1pJ(Gb&A&47vm z&_HBk9s>ef#+d<)*bQdJKn&zEGM2;sL;^DyA}GAz^Dervym=tuyz%JRk$^SNk%)ps zzBuG2IrzR@;Ji!?(^Z`nbP0X;KV80o3`YMmN+$a3E#}zC!~0~&&1K|lR~zN_jgkubHaErf+6hQ z66=)98bsblTPR3Bl=!7aj%&M_c1)Pv-LmCC%*Gmk(>5pAFOa2!Q>Qanz~WihfaTjU zPf}LiiN=b>)(GOl>zJD%&w{H)lQ}`Rk_W}c329(5z&3GSVBz&W({8YHA-e1gla$d* z2*7x8DLwBKVvEm$4h9mma)tbhO=U8TuAdAj%zvsG zDrD*}8C0o;wNw8NeisaeRhx(tSTmn$5}ueTNO7y6B1*JP#ZP~&*NTx}@zup^Gc`Gb zSmG@kVq&u3Fb@2ttJH`huxhWNwJ;Gdl%|UE`P4jg?kEyZwcO8B+E_N{q}59UN?~#_ zKVdP=KFGB*xuI_s6vz6S%K2r0r)mD7!K)sXOcecZa$-BHZ!c4Nt;=ff9;qw2wGYh& zrdH1y?xFdF(DqFaA61c|p*O~5wAE)%BUNv zc*oBg#P4?S2u2&caNpX1W@&|~`s}gJK_CLK3Mbc zZ3ACb8%-+xWc<)QWl^-2Gp%ez!^hg^kJgskH+{%E{4gt<#Z@r9X=OXr^);Y~)$(`4 zDnq&dx0lMcl0xNUd~(5lMOH7x+a5bv)Q!&=bX+BrXg|e`48O&iUR8Z))e*Dg`J95_ zU2ML0pm2AUQX`q!y0GXB$d|FNzJeTR%iUy1Z;{)13<*WyrJWp27+UJ*28hBV7m?J)zgL%N=ID1~TTQUFQm%o;@>`d(ym1+` z{DNE5ICfAO5g1(_f3c%M<~q&5)?R1X^t|PF)ow+DTOLjylb6?Ayhp=wF0e#s-00dq zj?zkYtO$>=~vdw}tb;;hQa4+Bz0 z%i@TNd(f<Kn)6^ z^6alDlc)puMpz!E*YiW3)ME#AF2mBf+e`YaSIY1WhmrnHoDYYN=P zj=UD<4sI0B#o*jok%ogJ8^;cKg?HW)2+t`O zWfCGKtrP&7B^fwPiu-U435EWN{Y!uJ0RhA-QcEB~+7u#nERI0PE@N7ea5Oi5=l_Gu zf_%pQ#{)=#EKKe0=ho|tKdEX$v6N4RluLvj5*{{|85_=M7-S}k8_i1vDzdlFaiFvp zVJVd|%^)0wYyl@pF&=O|&TYAT^%3mIOb>tvMm96SV8{nw4Fn^q429+DRfz4{RnxtKY*&{h*O7> zbDX*q`{9~Zw4?YW3eTvu4P9J9wQ2{MX6Dg{=27>_DF!#Q(a^H?+(Q9_K>;%?UN}jN zU2_>u3kr0Fye@R}TP1dlNbtds3hu%NiS+kA6geDnk;Ei}%mMaiSfRd9sQ!;ml^olz zTd6cwWlFDJJ?afAIQ#MVuZhSP-1QW^d0Ya9$%Esp-AxI8`Uq80{Fc!! zBuh+ZyVvNBMLx+0AcH|z`q)N%44zIV2XYjHBkmzf`|-Z&hd@Hs8%J1vP#*^^kyTl@ zk!}KF7RG7*#cs^^Aj&Q!%D!gCvQA#dIC8}aUU?wOX)emysVdIr&|WoNTCsv`s9=O$ z%PxwjE`(;Ry*zY`wBdAwCs-}QZmc{;eexi-!caEl@W=~Dw(?sV>60;@kumWzPCtcz zzjmM@UCq1~yF`z$%L5lndS<1K@cF9F+Rmi%0-;JX_6_-oNha+yBkQb8(rxPCDz54V zmUAbGh@nUHe70|dbGT(VRoOvyJ2}huOGwN+Y^I+^;i>Y+p_2eBRV2jO3rAFiz~Pw3 zzFJ!=R|hG6!qMftD*WJo*uY4op3<-xd{8E9b^qX4yk5uASiCQ;AWQRW{E2Y7poC(zR-{Bo3p!R2=v{F2MR7*$7o6fE^Q67Kj6L^ ztj(d4ehq{v-NXZLp%0utz?z~QOr12Ic&LKr2C%=r0if6N0>h!6>4!-WJ5TCDUSF4U*nc`5NB4I4QaQLe^%o{X4+jI-Q5Hu| z@v^WuQg6(X|LO06Z`4W=E&<0g&zS>=eJrMes}x1@pL-(YT=kfr>;o++puQCFH00Iz z4DII}`i(kzVEXQrn>m>Vp#sLuz$G@}B@Sh?j?FyYCl~nWc>xxA$EAf;*^^RrbAIh^^h)h@P*T&C)>@vF&6Tn+M*`SjHB&nP(5 zr--b}G&ay8w!0Q?xE6?>Qw=b=-Eo&Atc3xzS!9&(@s^OtS_&#wr20_!RF+J%m&6FL zWD8eb+;JpRex*gcO=&rcu5lDaJktwZV zcnsy7uH&1Js|jbM$F`&_(&c@@$^&$#Wmzt`n6BmxuAi|ZrSUo1*t~-*9kviKIf~P>Xf%t0wl$ENIp5_-a z{Z2Lp*R5ieai-!=rSLgZX?AJ1#+_|e|c&_0^m{_OVk(Uj0J+MC6FJ=gh-27db? z*TW;6*Y(GUHP_u&*-mrvPEWN??VqCZQ}l>`)|Vn9K`tU2ptp z82EbIB*L%is|U+G+_usgjIG~aD3v2z(tnk&hYy5g%NuNU1T=N#xVyzM5p9=tc2{1? zy5!f>-p_K>3^G)^2CfckT&+R*sl*p}*3YOX8yW?&ol~+AYkE5>MiEvwb?(}+u331|*OgKo)J37otE~4YuA`>mdUb)s@-iYLQVF%XNcoxd5=Xo~<3iy)e`CGf!&bi_sh8kmY_R30 z#8EV-qTT02A0`cWL;v4>;VYBDszF+8b^Pdyj2JYD@{IhYYOu;{t^vbX~7^^V!Pco z0`&F#f9B7^U#-jbeak#&b`RM1m7d>rWOdX$VG}$y`)8ize5xYFm^nKELcv|{)L89T ziJgYNpz9WCt^1)PeEz97`7`G8KK97I@JBEYvsHVJi`?x~?c}L{<)5u^cC*$mxnjZz zo;0D+&8chuVi}&VzZl(ATLr+3u(@Hu;IP}7Nm6_`kAU!3O`A!_Vl(JI-!)mtCK5A* zH2X3F7{QYKL^u?OWVx^r0p`$ZM@a?5r8v^`@iMa!03Q1-%VY--g8Cp{IcexQ5ouU# zth4mcXc0vvSaJTN#7Gdx|6XK07DUQX2}@MDX^(3Wn*OhdM7gVZclb@(M3-)6#=4yb zq8lj?`kTA(MpeZf$}h?6!t{I{jAIdBX;@5Cq1F2ceiORFHy&(_e&(T#a8onB9f~LP zb^zej`E+Itc}^Q2F04$S;Gj^Z2NY}cW|$vu=Gyd@sKlP5K6zi-G12}<0k7%BTD{en z_13?KZ+j6r(n5>VFufX+3`|M!)-Q~08r8p8tYhFohliUgB>rlB(@^@7@3qMHGu~6H`oIWf@z*KS?*+NR zz@+6T$ysh?!Cp?}ZyjDJm+wkCEF2Z&`!X`h5NiDC#+m4uk-52-trnXSf!;y#UV0)8 z@e*S!1XSkhohnj>fURS_Y8<-?a?XBSOcq1`PwdsA;o7S!B!72q#6Tz_-19O_8I<@o zI}+pM@0RyM`HDhLl$p3D?ewH7`@#5Yid^5pyWf23%Zvc!`w8LSNxeu*>PHP)NU$FD zI^QB6oVoyP7?xKxD9CIsoG=J#jNdzDz9)asG#SuG>nHo~;7=h=h3~ z)6m>zOqfvm`;Z0q@W<;+w<4Lsw?{w^wmsjvU?H}@XYvqk~-%T9FXKo#HEK)EY|dyF7S zN5(&EE5M*xj?Uu~{^ZHAVkG@UaztAfWhBc7+*DJhq)(}PsSB2zpY^BQ9L6ld=p1+siZYz)?K}FvXmtEJ0zkK$C6xsn02nDN*g&`>*ip=2 zI*6gDa3wNI2MWR0S4CJSU8JWuO@T!Lc_h7mg{lkVf(Uah7prOtYjfiqLb!=8Gol!n zi-stStm0SCtC>EIsB4lZWB`Hyyqe^0qAes0pt1;ke=kKE51PWp#~X!ATIt818Z+8T zzcw1fN4jDT0y}v;xoZN}fJXB;6I?TPbyu@4zsDp#DupcP3_Ocp=^_ns1y5WWcdc}8ODW2i7&+3l%di}Ac=E2d_~C+A<_Cvn zY7?im(Dq!YVoA6jLi6{x2pBp4fq{#gUrxxT6j5K=p8bYCigHdp7W%-DBtvaTdO|Q! zOo?W9DWOv?j3<{)wGb5XTs=MzFA9_#5Fw@DnHK)#*&N+y!Y-BLQ>~Nr z(?VtHw?JlRd&Mh#Es37aAiZe=m1x}`1yq{vK&@nL3Bb_kx%Wn#vi= zmFDoTWlW`2`9y(VL<%$@XvI;$B?wrUsp`UNvfaIle&jqyLy){M zPEG6Kp}JUQlrh#Fxi1#XR;01fBGZasRS;}L=Z8cIV zI*MAh??yjgL%FxCO=fkdk$LIr6r4|DyaK5BdrljqX6@C!2>=yUsmbzujksiQlhbC@ zB$r<&G+{jz1L3!&)h5orwlITNR&F~i`>d}_jXIED4{y8FlwCZ1|6)w$c&p(^$+;Kj zfBPME_qnC>=nrAu_QTh|O_yMov?-$>2MB%xZPmnqJ7H+vF~fQ)%)OzAo1$>pe*XUi zdSl;{1U~m~KQLZgvRDfLz(DM-_-}uHK1?1HH}XYH)Pu2O^C!nQ)p2XnzX`*eg16hb z6V62&lO+0(Ijao5+(ZLgX=5@qfm0!xLe+ZB2u2ii>!%Ppd=ReA^C zO@8}#J@&N+JDQw}$^~vneD(J0E&R3l@>qOCb_Y%GJ6}!hd0BDsg}dAO?TZ-n9q|XZ zM|J`6i(54Nqu`&O>M8z5JaL>;iJ?Tf1R)WL)K{@0KI+-m@V{UuhBYO44q&fe|f+ezx_EY0&svweKg7YB%0ZreuGO8q)4;!$)&@H+>oTyEm*%1mZ&CYHkMW0m41{44XHnmEAX zM9ilQvDj98Os#se`sYVPcpdg7`Y?pSR|KR{6u{9%agWldH4-Ug2v*?o-tNF~(*gT! za^Gup*+D;16CT2RdD5<;zY&V&fGD)mjFvC|Ji+X@F&%e0tqHe-kWroNF(wfq1Er9` zKt({fQ(XYJaKZo}n<~7axltdg?|T?p2=g&C&W2&^?(&ZMSnqykR5|4!Knl_5{eFqD zr~Za%#^txuNWwsOjAo43!tKMrF&=@A!)I8hAmX7vU%z7s{Q*an@A1297C29CE>CF%fFUV}Al(3^D!cH2& z3`ClvjFUr6HaS0}UQYf6(=5gu8I_at)|~v(oK!agFFH!~#g?cA7UrB1>lh&2DJ8w% z7eV<$ft^Nie)Zu}gM?wBGl33y-8EAaQg(3}kkt}b5e_%+{%?gNjXBhfvmPh(PhNor zh4l!gty)J_1sCHGL3Ap-3Qf3X3|{UVtci+zrV`(}l`JI`a%@d?G(VKp8nuv0fwn*n z(WD%1WjWEH;$NVa(4-lkJiuwf>$p5@XHo8IP0oo?4y#A!vKE%CA#*E5r`aWe8v#By znHeAAhA;tw_Gsr4IKr>7@D}h0H5Hh9l;|}ek0Cn@8;RX03C4mw*k(-d6$~eBI%hp? zr!g10nJ44n5SN4&cj#UdoxQ3e7nv#-59JX@D+TAfHqH+gTo;r$OC@}T3!{o=Ws;QW z9;HSJ;DSE zQ}at{H0eel(j{X&Kg-h5Sie&E!k@&bZkO%SebMU!l!0o8%Zcq6!=0CMp=P0 zAS_E&3Ii2(Q5}{NCybIrQvH62?Rf8%e-9|x`ByQRZoKnu;F@*9L-_=U9w-lAX~&Ay zB7Zl|vct`~0Hgj%QW?37HHUg_q!M>ca+x)Ot$j(I7?<^cn+u8qK+1t1Z2=Tlj=JTt z2vjzQl`Q98>ztMf5M0+|Ze?JYUl$g;QdZ*owFGTyvN5b=A+_4w8-;StOfo|%)|!e+ zN8KdjV}thhsu9v>+HO;YcU^yQqs!=%hMH3_E`?!eq{{|5sQ}|KZr1ep!!kCMo7V{I z^@%b?x7P~It3A!TJ(E|M7q?4xtne5jOXfNbX0|zY`|8+s91c?FpbJzT1X$-s7?=f0 zyr*I7l0j0u7!3#y??I(J)`5=C#G{V|%mT++4w?mODI1-c1(OezbXL8w8lD zX~=ury&qt=LDqN|*JhI&uN%gv{#dS#0%+hw!oTr8P2qi?D*fQAe7>9rO)SI&P{IAE zpPz`4*4Od({$*O_i~I}4zdO#)w=*kj&gZaPVtj=jG&zq_!m+PL6{IK4Tx0NI)qhb^ zI@AT1_9VY!85bU(tXamWYt#t6lT%rj&q3bZYE(ChCeVA;&ohe;JU|`7CAY%&UcWiK z^G*SYE(n88-KZKcm5aUb@lnQC!q)A(aQv)FMNYMwF0I7|lz@^zWYSDxZq1fguj3Mw zbDrXIUVhosLB6tnYtbM0nR4zuCFMLA;vLg{HQvj|ZpnfJ?xPXCj;*3>oTA`O4g+-H z;|ujYl69Rl%e`uLy)@`D=t+e zBk8It{0!mlo%u8pCfDNX(+tO*eLdV*VOB@AwQ~VmO2l`V2K>$hGY_pcj?epvpY#i0 z0Ek+dX*WtDkF6C3VG?{*(r=a=D55{0<@y{o#@k9UA$*F+GzUuC*1XB zcKfgzT<}ra`%xZt(Tq7nFdVkwQh7IO=AXM2Hf3#IrTkeY^Il-{rXObDUd;l&exfQs z3=qC9@TM;`u+0BX4Fn;@MAU$8RQrdlbj}tXa#6W#YNA>VinU-0{pH{7WZ8XMDx=JR zCOHLNN<}Zeqmtx+GMzYnU@0=0brJI4#Hq=W&PC;rXXBMOWU=_AJtH~lZ|G7(@m!w& zkXv>Xrn*-84#u+RteYm_F+WtYB-}3MFyJ zIop6<_7JR3BvR4e508`{}6qr;AJ_6 z&@X5n7tcF3JEB)o@FZQ*KEoKCM_p^OW!P#<$aoQoxk;%&9-jCoFFyh2Q=1Xn#ALyo zeeO~%QKCy-{eIz|ebFfc-JVg=@nq4qR{bI(fBYPn5mi) z3TeBnb!MhlBw$L{iK~jJOVrK5`gpIIs(ti?|u|Czfqxi9)mu8@$uIl?} zz*Gr@u{HF0NTFb$rj*!4z_yX3&BoBB_w%A$eLF$Wq@H7`F_Up+kD-zIC|J7G?jM;e zQ~eWug;XOUc5?7hg}VwuaSnsBRY?zo)&vn`@PgTMQ}T1<3JPYk8>G@$lgP;K;WO_qS! z^8T&2NC8z1Qv??1a+SlP=Qy0y!Jp!{f4EnVn5?^3e6Qa6v9;9IfJ&T#!V9L@KQrI| z{X9se-1sYgmDH2!GhKTN*=fZ_;*MV%ml>L}K$DY0Wz72W>Pd7HT7 zK(1vQMl^c_@xbA@a$k~|y0e&CnO?sC`{(_-OGrjs6Wh?c?ao%w|D)V#rxpw)*qbV1 z>e2tYq23c5TtTs^y(XWG{%WU9g7DteStH92$rBE%cX&D^ac!laGeYI~B4kDPSo53A zZ+N-YKhqZ&L+c1XTop$ye}qs!%K{#D$cxNt!0V3D>0Ox|2Um)-UEy!^4=J&_qTPvrXr6IMD8X&9eG zoZlgAek#8MzX{TdQPZo;UR(SDz1NeyM~t1tYSc|QZCPTYShqldKpgP+E!Y*G*-(gFZ%)U!CZd1teHtIt2dgdEWz=~6;wP7 z0rTzI$EI7XRx9L{&c!-i1kh?ypF5KeL|=p1q6|sT(rBd`4EqA$nK}TVQ^yvi%K`&G zU(nrbT_`e@dZW>#yOma{i(RUgsdkFnagB0sEQLBgh`GBGMr8bAD^|GkV(W9@lkQh} ze{QQOZNhv6!W|%M)v0-8%tKc4`*NgCX9!C#pYwNgoqcWb=K2hU)&H|3e{s6yIT^w>TOS5Ue%tBwPgx0V3-Wn!OXGdjAhrd*jEQG$y93#oDES9oE zyUd)SsLL##b!<&Lf-_9sGLioxoAlM^&(Gui1iG7=g}BJUdukV1vRW%Cg%u=Ahr!B@ z{WMgp_0$Y4&Du&;2^7M#Oe>yl+IYSsd%AS%JO#}xJ;_{s*y)13pScU6-KiE%A;)yF znsh!U`N7)^2R?7i<7!{~h3>qZxSomQSfD}Rpx8yiEs52WS8$`05Z9rs+9V9+xTq{j zvDSMPGvHLNKsK|cDoq6CEV?y`;6$wPDMN2c7>I(rtY@z$lrOzp;4+Y$s)$GMN$MRC?0Y8p=sz21sXtlbTDN{wy5 z1+(m0obz;?jB5R=)k?$pS#^&Ld5&Ac#AA|4enO%pUQO*u~IGcoRr`~bQ=+B@$88uHxBZIlq#EuRxyV#Br z9Cd!+m54LlMU=^s3`40w!12ewXvFU7)ZdWcc|@))Xac=Vrd9TX{>&q)1=wv|$Nj3^ z=tP-pD-liJ%9#t$8}n6m3k>8lPFqpd0npXc6P)#l-LQJLo6Vqr|K(rlHHJHp+Bna) zncE)qD3_0G)Sf85L#$lRcSoH=%jY{kvq){`^R(mxf9?F6rJj=ii{5s$*Kdj|c_%%@ zuXucFkq%f~|BcwM*f(W+Ju+?Gepl0nivIX}II5t>AvDd@?zUys*`fIohCxKTr%6or z$>r%|-}Ci1r~X}LcnWdk;pg;CVxB>wCeH^!kM( z**q&+*Pl1EM1C8*b43Pk{E|c(I!XB*;ecui-%ASx4TxjR3?Qm}5SUF+Na*6ZL0F2eKt0MJ8Kb|MPJXJ+lR4C=9+v(T zD;hyD-~}pyew)^NXy|I#%54aD|7(ud=_leJoEjjmyjPqxArd^<64)B}9(R4MNCL~l zN57yLPvjV{@KXZ-`|1`7sCocO{7ngclKc3Cu|mEwkR*ydWu>OOrX;P*sTH*$-DD9~%d%#JsT}I+@&bw;heWd2CS?L9 zMFrD~pR5YaKJ#K7oND!eibCekvTuSlnN@#nt-mnVXia8yp!&<>oTefpvmbQ4PW*Do ztm6YIclMlnvZz9pCT7XrLaLN;D1`vLADt~KkoR`FazcdxTsX6UukY+ee$UG>1%V`-lx@u|T5J;n9tfwoXOE^Y6UzOL zR?>Ir_uJV*c%LX7Zt(5c1Gp(rKMY9qS?s!rq=1kF)Q3H;cw$kcumBhmYC=>@rC=n8 z87wJZxAY&D{1&IYxv84L6>a_D6asVP57;VUU*+?EkQ^mY>>%O`p-LP#7@^bZ(xNm= z3;Tt`Q%MUh<{u_jqwbjmQAnX>uEkgW8?t5#7ob7sN92h5gU!u%FrO-#of@fu_{!}x zlw-dlA3vgO!}UE+T!WpbPG^=x^i}&a$E2dr+8hdd@d&_a7Y^6)59D{f=U|Pxx}Y2| z*Z_guj4t;A5Nt(EEYLt~4e;`?ENKVGe8A;O_~&_rH5J;~!LYC8#B!BQP}`AB8kdPk zoJJRE0|fexNr+TYRZ>jT>MRN}fbbP$l_H_Xdjoc8vL4Mbkl2Mt zsJoSlXa4q!+}=Vt&^r=+H>q!VvHSN)&ka3n0eynO#RlgTXQ7XP0SNJ0c6mC_LIp6u zyo7_f=jUT%-XSEhla6O1yi5Gf_3QX2eV*}nPe`(^QS z_mC%_q+U~x&uicyu8oMIo|@g0&cC{ek;j-$)-1(~gB+B*fFU%jyYAJ#ZQ4D;qMZewdalSx}_J=pGPO zCi?Iem|`w}5uM}eXh{m5q4=hQ3L9pf2j^{w=@)*45vd2{@^Rp%JCeHlU5fkIj6=#h zeS`0ORkcXkXrU9?L39y3O1{Dm77T58@~B)c>+{^NIVM;MdN4=>fitj)G@l$5!2kzb=zE!LeV7I0gX9yBMJb{9bhl9PlRBYaD}kz zhV$iwA6YQm?4XL3z#Kzxc+D9Mhj~n4dC9N1HMn?mEKNYoFarGkd}bJt;*MW-BGl<4 zwe(`D+a}89Koo)=uC!QUY@X*rHJaIr{K<@)ks^9#R_b z?=Ioi?zB10!_vp&e0SoS>EmUxd5ji$Uf*j$*ljWHZ~S^Pqq6@%rk9BH2rvw~B3Iy} zHKlm+Cos9~!nI+e6y~GV2qLv&5)(@j9R?D=!(%1i@OSWw?PQ0$dWykR5+DNb03Dh- z0MF{iVS;aV7A1_W9vZ`Cfl!0`hIah*4&)EPFi+(_;uR21!LV}U@b8KSF0qwB00KKG zbO+;{0?s9h0mPnq)N1Kv$MB5;z#0(#70q!35lGh($cFWbZR1a0#WS$=VLwWp@JdT6 zPgCY){3orFP!oW(9}pW82-1_Qq2^1R5MkHI4E9Jt?oL57fXIhJln8<#ClCsI;vKoP zNu&>SHpmw{rb7@bASOFtGW&Ig+LLw_RkjKhcY>q?$#F>?JWhc@L~oCHh3Xs|LKX#( zvcsPMU~l_uR?HMZf*dRMoJjv1Vvsy5u>sJ@CCU_y=R1&tgpapBMKFyXqVxdWwt#=oEokI8 zF1uBjFCu8fQg~iNfy^Fo8M7=QEY2Itj+f8c;4Y1*;sj(wQMEZ=v{jHt#ZRu8|Kh5{ zae&qgu(R+0CxN)v_zr#)U)U3Y)bkS$l@%;*eQ*m0;w6PQf<`%CUin!zA}1nf_YzK4 z)~X>jhsqay3W_e4?ZFU$O@xRM8j2CZr^*E?ypa}=5Uh|9O#Dn$f-n*i303yCD{kpl z?$#@A^8@Y)lSdbW8C#0ss1P_;vsD?Yta@N>1F|@ z7E8Vz4Cd2{?g1i>ay! z_}Cp?|Js&JI#`#1;xvfTfCREJ6!b*EYylCo%|29zaRF{A;TsQXid^dUZ8gqUDc?#8 z^~>Ye-4MhmVDpaovjvN0VDUr=kx~8I(=375{RpHKr_&?6nkfuPH*tYLbfNEUVvcGp zh5)8gz5O*N%e5p2w-mUg!Y2{;@qe^i`1c6H0gwNUp z^Ew=r65j4}NWEuFFHwktGrd&At-1+YytGL~P22=`d{4vo2b*IAU`!rC_@vMkvk3dL z{-=KtA4RaX9odm2>=hiwg*xiIOtEG@(GTMOJc6he!>ZGxPo1TJy1E)6rflP-zt9HK zxfy7j-O+Zp-xTkQ7GWuNl`5wemw~^!F=1d#CId;His#e2z%yDTIr4%)yrI>y*VB5B z>3Xd5yM&&z1gYKPtrT#=_c&+J08E2h)>&|?4M22>`b^(%2 z>O-R(=H474s<->p`!TUTD?l*bG_W_58jeI_0AUmJjtR8AKJXiLu-kWZB4e~&UtT|> z^((4^#v2p3xnEv~Z;D6|sk)CTKp0S0K#0H-45-ajEFyhKU4j%Qg#*m&?u{v6_)Azd zU%W1%@T_a$FmQb%vL}rJw$3IV-X-b_1P2XMAs95F=7yI$g~SVnCO_Lbf7X(-8hjVY zjc+`SwV{rQB2T+8_}Ow0?M87~P-|5Yt+CdQb|!Z7J05QB1pL5+u7l-knzCb~S&@+7 z?4bQ@{B5(?dn|;BS9R_nu)vawjB+dQ-f&zu0=>5&Fih_3^03VypN;n2f5#zzS!Qan; zp(TjJ5S;W|)L#G+R2|WDC*^}NY?d2_Fe-0ydjEv@B5&htmW2aU9a+GE_@&qH=n^B# z6K{YIywSIFK~f!#FXnZTq0J|e7Cf3sy&2D* z5_{g9V$R{7HMhVfVkYu$Q9@*?ZX&rI8{kes7e_;C-s#RRT+eR|IU9$)hoU-^;8&a3 zXHl)xel}-^&J)eflZiBW;{nMm^Dydb1Ac4j5Il`Ia33A=QVC(1P!A;~zz11SP+6FV z4=Fd<$aAbOcJjO9M>S%Rf{lWlQ^4a5EO($F^ zq|mnnPr0?Bzm;b&-*v^EabMf!S5TzbP@x~Q-#R`wl|}@hYDA%Z4hB32&=lxUXw}ib z$@d>JAskMoxsP+aN-K)QR$)SMWzGjF*JtH>sg1MqurikKdcI z<&Z4-DK6mD{%HH!f;>@%A^Jt|2 z_XX-%Cj9N zw$ZvFR-J^MOx0m&Ru6-wayq4&oCU9YnS(#@s?Z#d$%n%n>oOr-_2P~Pfui@!1(Sd3 z>U1aX9Mt&n(e8KkZX@O|d4IzNLmkh57aP->ABSbmtIYm{^mWY)9#qMEluBs@UohyA zGtZwNe(j%fDa%ydq%!w;TuetFycF&}o^>Jj>F+wObF(nTZV6(2)FNk;yJTFw>iJ4k zCUnJ;dpW^9`hAoVrnT!4Hup7@99ix{%c*{?h~h9wd5-m$PZmYKf#>ujg+#L4wHA(? zJGLU`APZ>j+#CnC#U=H@g2>@_1AN#3SSC~kTLj~Ro=rzej9b-}OyPsQDF&Iq2xg%< zzMuI<`~{W-BANXwp_3~;q4CYMqcPK{-mB>+152zsM{**oAN095@|gN0K}UV#kjHLDC&x_gPL^fi?KfzKjpaM_I?@hziQ=hNXKcfo9ek$Ni2=M=Sy34ny!gk@q6AUp7-QC?G4Gu7LcS=ilgQ!DycXxM) zq|)7>Qc5?{AR@}<+0VP*e_*W->%%&Z`@XL82cTnw14BS1OOuSjn=%ntR8nEf7aO0W zh`7v#vb1*OLeYs_dqnVd$D%+jHUx^=d&(JH3^Cqh*H6fFuPa7ULw^gXfd6fU7L-?$ zVJaLDNB!d19Z4G0>+Xuk5!~0U(Mr^2VkNTCt$Rh|`N96yQN9@vL(k;&f!;6#K~ciR zRBR3iV|izLwQ!p~geTg{kS9@IJ7Ng9b<4e+|Va4c4i{vGRE*S{HDvM4VZlm3ad1D+cb zsRD&HMC{%NoYgN4a_?%4widp{#4A$W7@gs&&AJ#q`rm?f^l0n}-CE>B?~|&lZO#cj zqp)Z22HAr3@1cYl8QE;~Zt1PeLIYpVDXEgh*oPc_sFuRyjn*>pQAI zfy4k@I1-2MW~R85IV3@>Gz1E-ZV!upT|6iL_!X)0RS7X4 zx$9tZgNph%3tfqJCvEkTRtZM8Nedl}ti)pw`_DrXX%f1Kd>$UYgaUsYsn;n$X8m{k zR1vu{ZlM8`7x3xL*yedTkAQM&IbS(Sv;vJ&wC03BJ_R5akC60|`7B`|T5Ys}5l6nM zO1v*6`X5jsq?CMF9?$jyZv^VSK0d?>x!ZJTRb^(K2vJ*Dv7-t4nj8`S97_mc@pC5Y zM^*;OjTZXktXTEZH4fjc*0rq*b+a`8H+SM*sS@}<7QBKk3rRbNmkNw7*3f!E%f1w@!ypj= zs>*gW54L0Acvg9RCB7!rtRR$jPaKBa%w;?l-P??KWRMT{O3D6I)V@L7iIh@n=SX~0 zVE?J)0OBSWnB=+9oAN`TEX(aPa8?JPZ;_}faw2rcilWZ$*EuzOPWR?yZ3Co`)K7Hg z9&JK7OkOPh!Wl%JaA{_+|1GoO^@Ovd4$qw$AhlXYv9%GwwoWOo2IO6sS}VOe?h@=~erv~}75MFF z?gQ1AURNJWhgbe1a*R*=L#`rLc_eZ@IvD`O6dNijoFV9AB{?;gCINcb%Vjzgp`#FX z2Iq0K8v+3JJ&d7(EG<7UnCumAJ$)S82;VN(-Eo^2Zom$Zm6kXicBzT_1- zA8SVRg(e02*0(rsBzaXa-fut*rX34@1JXm`Z5N>?ad+V!w2h zM3YMjGDd&Ru2TrGdtQ1BWXjC}t?@9?(vC+7=(amqcg*}A-&s#0?*jBebt@KVpm5aA zO{KO&jMntzTapiaSh^awI6-` z8STfbtlb5=4Rg(VUW_iYh(s9)72GOX)1NjvCOK%iMy+Dfn1G2ON4)eOJJ6Hr9N z6b#G>f(2YqUtCB4~M4wKsR^3_hT7OHT<^^XSvpSVmHzHg6!j(h_e?eerNG zb9-`x>>Vw*V`~Ty*Dnvm#f7}go)-Kag+l0EXHA@^2>@Tr*CH*4S6#VdNxu_1nNVo0 zJ68MD+}bNC)uhLTD1S5srOLgJ6=ToTDRbD_c2^n3q057H@({VHUc>jX7+{rVmSr#T zXi*D4{I1udH36y?6^g!)2U4u#6y|hEfvq;5JLaWw`y>Z4sunXo?NLFKsvEGsdz5Tu zPad%f85MpHo^&s<`K2Nr$q8$-hHrxSUOyy&1v znO4#(V30Qh8EN|uB^<<1>wg8c%jdgj735^1iXFCk%GGqk-TA04~&6-!@9D zOi~+FFY}2Y#8KAjvs@9T4bB~WYbzH>UlkpFqfTFqulNP-;cq!Zg{x`+Nx*>ICnvOX z{t&|+diB#`(mx^EKREy#fzXN+Ey}R7D83(>9nq{iARuY^NoRz0dSZ`@E00k;<7I~E zB)Ycu?AoBo5dS84RxWLU%K4bMC+(zH?pE!M75NQSj0A!l~i;{ zb9*#6AnciW9B7H<=!^WXGI>N6^?x8_7@9{{N3M8yj<^TK$G(Z~r5e_nRQ~SCmIOy( zA6fp5lx`=Zo;7V6Ol04G$;;elrWp)>R}EC@KqGoXP}kR!e9uI##a0NE3PB>h?jwJ* zqf_^xnQDR!4a=mwVCjSKi$D4Q-sC=og3Rg3Y%FkOfx`_#^U8<#z>@!<& zu{-jpstKvO^RRg_gq?;G+;=D`MXSke&}qq|4pYb~Rb#49(khFT8%Zb9lSE3Lry}}f z2X&(*yp^56X_9Oc8IFqLy3ylp=u-&QwI~jfYfRuFkEGJH&`H@63gKrF)rOmiX8Nd6 zo5V4Mm?gRVTUvV0LHx=czG@OqqZ43!VPH9ceVf~yt%G3N;M^#5U8d)?^i3?cgoFn`R zJ#?OD7@h~d?*Fc<&G==8QZ0VgIe~@?oi1LT^`{1>&jMGu3iqw{lk>uf&GUJKHW$+( zKh`4Gi$#IgS`191c&`^ldPi5tKN6)cf?h3(GtEh;Ep)VT(0^GxMCwq&mSkRN4*j7Q zf3d`(wkYSLE%jm+<7htpkQGuyUW*q|6jYX~h_T=xjpd;;K(Ta)GFPMc{7jWdN1VKx zB^94Y)xT|_icjeMzadpuXt*)F3e!;uS$gmDW>5_yMi=#vxii^S(XGdfeYkPSo3Xlk z^2c-4LCaK?*K%i~fjLg60PrYrf zOIu>e-6?EBrsSzG@;5OG0WovWXK?Vy^8ToIzcT}SB>jhDC&yqj+c33s+?v(sf})Hb z*0@2%xVSNyS@N&d$R)+t_?4>oh^nM7Yf+a?>d`TDt{4Czy22Go448*H1L&K_-n`b| zZsIQ^O8Hz|;s)N|XZ7}2KU)~hMx}urM$=s+-*XuSeUDlji~oKYFVTq}+e#^jgq#In zsRpBs^F9HDRw8eb`F7yA5KCON@lSDCh2?!D@FcJ!EiP?&^PjOqcx+qTcS9?=E*uOz z0;^I%(G`!0mrKVZuC?MUnC;9~>SahH9J%DbffE4)Z29#ob`S$?EUk{mHJ_i@A8$A= z{aa5I3D8m&)aj8UnycmY*dJ7qcS{>M;6=k)y@~|5E=9~RLo`?1$k05k$}0jm-si=9 z8gNpuP!e+cFTme|I>drNI5@Q&D%H)UtMEJ7)o1>&E=^@?tAk5WmirZ^a;WC(R1sqa~8Az@VLOEFybbj0sT8Dd&rsTIG!P=z4smI5xdL{`PCf z)RQ#lcFQ@FDLs`%fUHIDpAmz!Ozdmv2~2W~q>V;?q7Z*jSlmIrZj zS5!ejIYlUaENPyVVkBrg*msODhA%ydj5ZMl~06lz_cI&bc@`kh|JHrt}4e%qo;&-|QS%y_{9*g|f1e?{Ysu%RXXFP7r zycttDImc);f!;{T^k=^_I&YkgdPlmzU$bEMFEUtM6x~7KaVx)*7Zd$~X2X7B+64Rt z7ec**Etf&7oW&3SfSvo3m{MZ%lg=h5{Ws=G4MM_o6roMC6X|30-D$C=R8g9(t*6ul zqMU#^iKMD34b_q1lVT*9v`c@~Tt&!$~=xH)YEkQT*ZEcban{APShe^B_IZ7Y3D z2B1|KHCgbJuj@cE(&rvkNRv9iU*>+376(+!AcZzdo+>F-uxmseZb&;t7J(gsu8c}+ z{DF2zEAL{h=sVxRZ@cVgj1oJ>s460njpW&;_k;4>uaYNl|G6>#Kh3w3br!^OdX#=qt zw>qG6uMfnxtWG%S$uS6-<)cgKY5o1tf3sNB;j;Lm=&g#t!r#rfPOSG(`sGh2$D7P< zAeQ$p1f7#YugfDR z3wY0PvhmW_W_J4DwePN~pOO8(1jpO3IU%U1BiY{mHFW9hHG_2tW zxZzx>Sfl|G;FlEUZxIY{k{Ca6gYfa(Xg4}gN52F+(fSmgOmO>Gm3`JfeOuiy^Ntt# z?IQ&b?gY5$HHtmM=f=l}d=#(aNzW1k4y2)g$7K9)qotq%=9A)Lj4PBH`->Si+2>}; zogQivZlTG`>U}e6o(6tdyoMG*Rq+qYUJggBA5^XJfVPR6FFrD#&$GVN`z*UM8Gh#G z#XwRw;-a+ob^cOu%WVO^YDXJyav;GvcdPpi7iP`fW$3f!xrp!YXq8wKu#D$nlfv?w{ivhxV+ZMv`Rk)1@P#C9ix7ve z&SIOc$qRDpLM6YZ7-4S=hC_*x%MeU;vsw#d9sq_N&1kLA_X>&k1l4ol*kP$k=}t|S z3W@o-m1)X%2eLv1U^JFShnZ=9Ft)&uwd9}`qw^}xW#m{hQE#;vn z*58vH6DHC<_oO5a)IVzMtJJ!kISVTwrdbi`6DMb$15W5oIM)b@Kd+9nbM8t)sf;|NM=_1zeIb#vL~P*$9^hqf`GrBV>K9fA;@pKc936d9K$FBAt=U#l55- ziF*3?`qbY8PWYw~1;xTXsjvBs4R*WLuYsLm0Pf5YJ1boEGYcxn0;v$U6)ew=IacOS z^qf=@#e$9vYAB8XxlssJy9jOd%EiEfMW|=?KuCQG-950qSffa0++w<;nQOhn9j(to zXV0KV%-PJ4)2O9diVg(mgIM^NS`Ok72nd-H((uF6H`ye_Hld$vkvA|MVURtR%CDKn z`?_U!11o$|g}mR18>vx1&PT^z6|zj;qKQ9{aZK0(-j`vx+{>GW;&7yUFE4G8aLY!2 zBnS7LNb~wBb*gn9Y9#JxO03O~-B|m~o%Po{mPMJ>|c(9$MZz|D0tE zk_Yu6<%mX`z!1V|xiTcvvn;8|3Lthjvd#6mGxBxw`DiH(Th&pe3UuF@p~5HLC3hyp zq6KsQvtS5Ua>-88po6H+Wx`)T6^nw=g+>V^#+HI37?;+)6yn?+SigBmgS64o?BXm4 zaPButP&x1NQpyzMzUcO;b(0mr8SbX&$)x%eqj1Hw4S84e(87d_9hf2RvXaB3A@WTB zSW&*^e*&^l>H={!b3J|hn>B&f83DFT4mqUXQYejck_{;wVrJP;DfgDuf<4f5tR6mm zG_#hQ24PCvqF;wtp~5U6!vB_@7N;nffSZ69IU`^v>!)E7V!GRVdY~bb17K3B!M521 zfHu{SCAA-=EhFleM}&k8wynkyiYuwqe^_>$-0;h^6+Z6zTP();_FHeR>)UJ3NOP0( z{)4li%Zd}8ci*xD*?UH`N{v;me(TK18=KkmwbWac7S*+_#yBaFd6v2QTA%e#4Qs0^ z*ENsHdlN`)AX;=x{jkI4p?8}2`W*l49})-QuDgliV~W!0Bdb_*V^YFT3^*-7QujXU z^*(ELW&-z>NhGM&iiq8$yY@i%T()KY8y7)XN`Yx4BLLM%$>=FlSdAL=?N3h1dMqo)#hB3Yjly1E9v!B)l+jAL3NXGY zGmW!vRLkLwXmj49@Ti`AWfqp6$5_e};4p3h^-4Hw#h6r9oU$Ue$es$awG2U@b^sA% z{46cQ&R3e|aP-Rkak|gle>Cl2wV3{ql0}SfTb4w=_1VuT7ujH&@^4Rhdt1XK&PAjY z5O|RMdzVG*>DzCOUmXNRgKZVkKxGYWeaE<%wMvlcxPYbRWmp6roVevV0JVxoCwDz6 zVB?S)=bHBNUt0q2FQvgZHEnNxc~^Hwpld~Ug_f|y%1H8C(kK1{m(lkw$yBld@{Zdg z(em0@Cz~Oq%S7 zeXB^ptI>XuZAx#<;kN{mby1pl`LC=ghO@mnu~$(;sN`b|`*<}qSs&r1Z!Om{R*kxo z0^{NFQ!+RImnuIP64ho4$6wV)IwJ~=I3*TB&#TN0lC%>9PIAjqF_7u7*UHVaXNs?s z$}8Vs0(Wz!670W~QEZ>E+#b*M7ob)wAPiJ6GZ2*8-@3?$6peB)g=C{MON+gK!h$(W zx2=e|Z9H)aFWeJezS88paE}IRw&0+WFn;C(r96LXjF*b|r@z^lMfXWR~n()CRluOsq8?%%OXq zyU@HZ+}gMb87z(a&NiIl z^(XTz*AdP=zv|vdoxET%TlqU^gg@(dMQwPcNaEb7j9j(=x=6DIr5rDO_ zv z!*yBKD&Qeop@M(G?zk#~7DWghsMt10oHR6*PA!pFFj0@UBDsE+m(SD@>fEa=TA%Oz zK|xC*6rk9rCb-f-n(d{V7p4lQMNhyj8p@;u5b6S7D1t*e`WCg+rX(}!1P7i?$9PuM z#woo32?ak$X&cMOaa7bI@BmD$n5)o~NeO@`u7pkN>5}0>jJoFwde#dvzCuN^DXQv~O2_~?@m8C`8NHaUugjh z%_q?TSb3r1brWdqS%5GD9+VIXMkMFlfJZN41a9SZ8D>ofM^lv+t5VX}GDltj&_Xcs zlly_VGCVh7+|Fy?r^1ArkX|Cg1ZfDef-U2;Fp$~sF>Gs-luqjcicS^2&;}!QW%!IY zjOG1JYn@F0GK>s_PTqik*33hfU4}T%EC*X`^ToVU_EE`1LUq zI9v>lIN1eOa;j0`0+&^hP3bc~E#!1yh%;6)-=ZM{MpTkO5>zG%kF|oYKM&4RlSzVVo^= z%2j2~xHfd8j56$HUY8}?-t?I5Fn6p_QO(eoHnJV}BnFzH+!sixF}Nth7)54X z*7a4PLKGwKSF+GYXjT!WB`VTV+g8A6PkArl)*-u65w6KgL98X zI+QsT9Co$G29(KTYHPO{f}Bm4RG>)ME@<6ZO~H&%*Av5ooJE56KykZV>83mkvC_^c z7sI%JGH%%oDEIqHrv-go^QFk&*UsXpIQh+&H4W{=yIndGRyMZeu!`az}Z7qJS$g0q))U5gwhepI0VK-8PFM%e`{sv8LcQDHYsjPOk|v= z*0Djg+uumW!0)T{;uxV*M(0Cs8^BfJ$S;Qh8+^GAWq4)oMa>c!tdt9C`$fAH*2rY1Ls-k>8TRjW0CU8du~?bMbZHa#r-p!;6Mytp#p z*o-j%=M$i$7x&n*ukv)-B;(0d^X*rMoGm*kM0J`BFkS!k`@n6}U1{}uISt&1q$W)1DFlryr7d$nDuB6`|PK?A5dG08NeL0QDBSyqzu-$z ztDK_d!l7o*yC8yPE7jEUGxZM-b+2OA zyV4W<&E-g4`$4qiZJFRxs zuxLBT=aiv~o6VXKGJpbMK0|3-W&+RxFvn_Jq-vUO&|L0A?If5gN#z|!BJ`ZYCvPk4 zCRE)(eS2q!eeLf&aPDouxW<%eJ{L{D%Vf7cgvj+^*s5-Pq>}4x-J6Qlo*<*5tF4q6 zXa5J6msrPV?FW5_-12ptKUHgveM_AQ&py$gnR=E~$`9?xyM_l;N$1({^o0*;g#fDh zxDn;>dsCCAcIP6k^11|8z$Lw6RM^jDJLS5ed@bXqcNoS$hpK9ZHS09T-qyFs59`{< zQ4S0pBrxU0K#a2FRCjrfTf!I3@LnxL%nl*ugaE9vP+I_q6WwNc-hy_2Mim}mqZu)- z8D;ApVTb%*D>qMJ#}h54iQQ!x)%9>hA0FwAJ8?y+;K`}rB@tPqs<1r53rvpAE{f(R z&kTj5BcFBKb$Qn|`-=(gH~*5lSLnuVn{Ts-&axLXw{`=!>E03YWKuOIL&lJVW5JB* zdN0O85sK1TP2pu1&rAi%hMd_cgdhL%_l2^!?k08KpnKnN+!8t|Dm($HME(n%0vw(6 zgd3eqt3+joNJXHgEd{4(MyFd~#OmcVIaXGZ@|7tI3B3Mf??L;akR90jHPeB=fwx06!#I#@;kQPqluOg``%iN)!BE*gz9$C{AQwvZj zol>qJt7@p4mVcb^>1pz3g*Q`9wsWeqq7Sw@4|g2KcRH(l9Lwq0RqMQ%4ha(&VuLqQ zVavng1U04(l3H68o7KtB&HFQn|JV@Gc#{waj#W7SJc|8^0qcT#BWQWFSXJvmC%+M@ zk{4btOkhH@&i4Gtyl%>sNQg*g+@We;i*vmAW(XkwDxJd9?O8Oit~yhuukmy{HG5&_ z3!8RUPha4TUwn=d{M}>OaNBxja!C=(acV1h(*ndup{G#W_UW~u>Gji-zhzz$g|Qoe znHktj$ojSRGw=?~`FkUW4PEG5o%1uq-Y;5uE)5&-popuz^e8?gzk7AB2`tVqk@E65*fbSM^l=yIigOT$=-%1WBedo)h zX(22G{F2~2H1P$5fWN$pJfYK~ap%%z=rt+E772bsCM|t0Y(y}2b`+W`LeMW9 zYaPQ@yii}I9ml5!^@&srzK=C0h&~s2+36q5kr4YwWE%fBjEW#D?%O%+HxplH^0j8t z%YYC&|7b6Qbd}CX%K$#nPDYQ;j2(im^83t2|G-Jt(8S*<=AtQ$XV3;t9nw-(HpJo?Fd3sTp#g=w=4AUg>dE^J%V#uFd|SvLUI&` zm+ec?RCmCliSl5&t@K5Vi~by(%^|=nthPT#oWy97;xYrN{^ixHuP*r{6DnZmP(49?;7d8Hwz>Kbk|)e5K~-wnoFk9fGX3ycaqL-2;^7!DjJEV z!oiTYJlGA*v1=#RYD=#vwCvRW^McNPmmy0E# z&~*B>AM?_gk8}Ll8nqmZ#KS`s0Ss#Q$X{-2p6C@JL-c>iR7VTI@=ySTJg5+3k1Dww zg=A*Et~9o}3XMp5EU^!)U#jJ6&AvQ%ap+d-_PXvtGb)x_NK$>N9?of2OI;IJ+k{or z%HRGim?OjmtE5{?Cf3*-;a8|)nBkFFL5Ap(Mcpd{=CY002L|E#R;HB?jQIZ19}VLzRGo;S~xmoeaiR z)Byxsl8cSRQMeyRVt_6qspy`EL^H9dikP#Lg@(>6>xM#9q=s;9;_ATt{Iwj#MN2V? zbxEczY%HTC3w1T0Qm#sdQ*5qE0IGeJBnPPWj2$45qJ41z3a7;gx!aUhCPQin&g_s> z(?J@*e@+2?h`J{d782MGpnk=CANQ1Fm5>}6F0$f%O(J6CRZoHaUPe_m?3-STfg3PHHEI6-3K&l)Vd@nL~tlU$P`TQ$|i+E87Pwl(_({{%aaq|kzu zXQQsl6y3+&7V8oi?ALbsJpVGk5RGZ-2VthD*3D1?vyN>C4t-@IX*H@Pj!>*{+B_CQ z$?I0HH0j9vH|bD-9nd7y?un-T;(1DT9r@1Do-T%2FfkjGc+j@Y6J_)p`1A$s=q=}4 zf5zXdcdBMN$9jA}CZN^ckg&H{fz?e|A3HwjpVcZNC-%z~SG*Lsak&}5ynbU94il`$ zW8C=2NOTs{!%rnw<@+;4^n!+R^Gfe8GZ+0vR1`~4SS_>OA3N-09cX@n+9ng6iwJK; ze)d;Mh#bwV%g9FirhGK0`fqo#c@)akwrcf`J)LulrP2Qj_0ztJ7xt9J8i9huWn2N< zeT+_G!OsK<6zw!Eg~HDMLYi9N532pLq=tPV)E)EKY=r8%+m5iuU4_q;NR6OCwnDS# z*0pUPnChQ9g_A2T9r)>HTpY4UbsjWYQ2N?Elt3?=STL?7NLb`SJ2}Y;m+bRJ2@H z{8F>uV_`G)0G#)IgH#_jr)jzPOE9vkaR1>CM1aKRLPqT41MGJguxOE^={yW!pzUwc-Pp%7h@5 zt<78Nm`OVPf>kcT!4%@e{2b*r-lg&cxh6*snSF?~BGhuSO?-T0zYl8JIi90+a+bPt z_$}%76KS;bSAG5fWo;|tW;^Z4R2=@gSn{csKD9Gi+FZs`z)K{_l=eq4z6yJ}S~;ZC zd`oL=$!h>NE?jOif+P*!E%1#gn@X!eZz31J&GgSI&!d2KiHSDlh_EACmxp@!h1QBi z2;D%~AbZ(TN~U0Im3gS`S9^>iu%Saut&#JH z3isXN949jm!dFsY{a$C-n+;6!-wS>r!T`5t!ZvSHYD<*tH|@0l^I%}dpt#^sJs^z0 zynz4pAXUXkq|3?bC3_6%u0vQcZTBE$EEekj9}FzgN*qMvKYk9G{zmEip1<%ELFjD* z*9B2aUaE$}EaV-t_yH*Qa^e7Bl$bxAoe{qm;rUP_U&Gj>1+hRjOV}2<;WqUoWj_(7 zduSlxAg+B?7+N;vqTK#+(%6>;g=WT{J-SB4NL|KTvkZGgVVk1*2#M2acQUpvi0YI8 z0Mj1C{-u5m@M^fmIm`PodVC@3vYK6_8AJ&ATN+Zi_1_X(Tk8ASPFyKRN*>KWa!ZE3ENIWOg zNN^#OGh|retn>gz_rWTmz$)eWp1H5lTjqc{kMAjZI%k@B-%moOgJaoXf5r|J>_1F#9~)@72DD z>zlL9n-H)+Y`gZ-i~KK)3y)C)ge;qY$FT#$$q5ZQG@F|G$b;UpS%UHL^9ftQ;2^*~3(T5hI_Wijd50V}Y z@)LNNzG*esk}2WD%KLN0v4gC$qMueZHCKl!p1_R3g0D3uJzDDqHfzJ~>wZegL6h=@ zT;Q8#+H6%{HSg2I0{Fe}%V z{;cKv==LRE&rAMG`QHn8j3qyAU zQ+zYyYfpL&eg@32JAM2X&v}}4X;R&DLJ~ak_m)nNbbT|8%<0;Zx=k$aQ-o1yp~rLt z&en8s_-xjmY-(2+5L(QZVCOdcGJAeL>^|tsmbbl(7C^nN$K%iw|6fl7_}D^DT}kLF znEM7!NPhv}^~~`s{pUSKjuGjhJr=AA|5xxHdVg~N2i`7v6d zu+%5x7S7p)`{muExnjSwqW%IIE^xzTNK5cKIJ;#FzU3)g>pH` zjD^9lj4iX0hCG*epGIR|vvr-4Di2Z;l**A_i(t-oqcp0a1NxSl`ADzF(`;CiwfLL_ zj1752Gq2NJYkN%V#g0Z86c&!W38?*B0py#ctHrat!Grb!PGQB^a~1>=Q9{?d%*iDZ z9W#=Sw!@#U?Et!w{3TS&NDpKgC$_t*SuNk^uvQtZ?vCrg2^oNlqD(`Hj9{3!XqvYv zyQ=(>Y$?YfdG#dVG{%BoJUSr|pMVrcP>LECk(^3CiYaL=fUn>wO_3%HA+#VLdg;d2 zkGehbqvjmH%}e=25xPVT1_1Y~h~soQa|J#AgXRLFSRK5%cRFz$kGRvY`-{PXyHtsP7mpK*&m9yENXhB556fYMqW??BIFtQzI44 zZwRi1$Bf8tAx5HTLWpS4zdR>rq&#;OmYW~jy&kz!9bvrHZ>)B$wrELn2c-Gh?}TrqElmLRdtqOhvG%c0CpnwGAfx@Dj^HT6BN`zAc6C z`(#Pcu4T?`O-2l*yknWzkyx;n+|*%UzhjUADH?i9DyH*M)E~+a9jOyZ5D;1|DqHP@ z^E`s|jlhzL_JEe6|0nA@v*CRsh%y{REN^Zls6sU%{Z`gOj$os;K{KyG;p1)Y5j*iX zYtkfH(X2tym~b)I5{qUqUtha;0!TvLN`iMv;;_WVOHXp#-R#Q|{9%_c53}OOLPeRC zy2Oln(P;sSkbY3u>+`W);~}|VOsJp^`T8Wp(-xt;i?CO5qb4C64VNtkdt$e_c|5|$pdeN!xB zdxo^-R%E+k9`=-zIYG6`B8ttA4sx$!KHYPpN4TS-wYcg8W_^5WZ8&xVe&mX|KELYo zjia~NVmDK-@_UD7M)@m_0%I~x#@w*7SV*{3EKU337C|SRmsdr?hz!GA@i}bqDWqd> z7x1-S3a^c|wO&?O15YL`R=)cxmOP*i#HLwDQp(J9n9hO`a{hWJrv*Jk;@by@W%1D- zdN4-SZ&rLQ5i~Q53Vk35LnwkBY!h|H6d@K_uN2*o`KFiQawWH(U6f6UCNmnv>fT9eXoUKZKFexPtqEjH5@D za`OuQgWkP7^#ydZr)eOsahd*}U4&*LSW+Y@)-Op1(ze=}+nd@y9@j~h z*vaZ+PBG;%s~FJ(!cjgLTQSChtzj4|3!y)BdZ!8c-kOwz;%CKKf3Pb!e7F-isAO)#V21@QXwgLU2Bfr35e+q z<{0>Nabk9~)A^an$q@#a0FN>Tv_Fmrh<#~>C>bs~8V+I_Aw}V-_MSv9{HCQ*cQbup979{30R`|Gl;X-`# zGw{z!$fc&me;v~yipL<<3f-kY%tucRU;acBb@gflEGHB%+jbQW^K(AcEPjCbaJ41=c=hM^0j%D!c%NeM zcjUSq#BK3&{bIP^j~`P%T7o7gO(U8`jsJ1gqclvqN*9_*RJgAlwj_`npB1i^p=4Ro zxW0f6RjP4o>fZI91%tVRWNJR1SYOT@WO7W{zARIVyCQYZi_Qo#wkV#D| zv83+p?od5FZ1ac~o5D7y9MyRGw_fcjRgHpOOg$^ z0wyJ+-S;XK?7_RD&GoI#3gRc~3-xp2pk7Se3(eu9BK6~{hHKKz9k)?VF$Fn;aK;KmHcMV6x&K!sSsR`^L$DJwqq<0iMMz^{ z7A1R1W1qH+N|Bq4xhp;L{GW`jGIr>=xq4GAqT%E_o4uRV*e9*)zlyqZ6gU_E2tR38 z@f}YKEhN$(m}n>zo>vAY8dfJCT^mb@1vY+7uw`#jo47nr`hCciWF&fVk*j{6dBvuq;73{3IU!9qb>ssAW^^&C^|20QPDs+j6y63y?N{Ndpr)~o+v(sp=fgPz(;icvaw`rAb>WS zzkDK{Q^(WUp{0B{liz8zPU*U0CSO8w{}e-aYqkgxdmQH=SiMk=&o&^THSAWfJ2!K)cCJ-mW?)qJL z5SwvkMoVd+*75776x_6?&4f5ASu?iIa?7C@7LMt<>;IqtsNBy~Y3@tE5Axoh(8Z3B z1249wHnsKVHNQ1fQsr=N1F_{ubPD@xo!B%w_|apD+I9+F2U8V)juR zUzM#BQLUe?ZIX7AKua|m6M#PuLHmgKLx0IXcV}do!j11tZCtp(bHXzWC~~9mSOb$AL{PvtF88d9{dRq2p-(s-QC^Y ztw^CrDaDJE;NIX)vEmf>QrwGcvEtHF3N2E6c)!1ywPwwKFxR=t&6Aw-?ETp>d68*+ z*C+~*ds=er?I6%$1sR6CLa0-* zB4^C-K1sAD^qR;mzv_C^R+pl56f?xMT0bz&y=vfzwj7Q{_eA6lW75`Yhh{&)=H=+W zk&jjDG%PXpHcpnU>jF>ATV5C=iQcKxRFA?J&J&jxjk+TQiFp)hXP@N}fXSZ0Xg`=~ znZF6_=VUj_Mdfgg z^HMF=^Ls03Zkd{WfC6vBj|BI*yg=>T!vYq(Kpj?>K|ZWe%HMn%RB3ApE+G5Xzr#e2 zHU!~J81nAgQeW;1k;J1J3}GJ*`JNwJF1Pff8Sw+w)b~ZLu!&qU= z8(S|&0E;Fb!Lv^l^w{~5>$~VX^Xe+&(LD*GxB=;i%}gAa*d%ti7Z|-4<0KjV%k#*` zb7^0WmPKsbmWLktb^Sox1n9C+fFQ@nOSIC$B36$4T`HDe?3CkM*P;NS92rf1tN?l5 z096xg2m^VmJ?meThx)n!@O7Ri45g3aBS zL!&sl3dN{=sQ5zsgOIqgY`f^V5yT!?MGq=b@W&g8JiB`YKz16uu*-yYX;uiJX35gt z_uQ)?iI7^(e!(Z8ivs0hHLv2x|2Klrbxuh*u+^oJzAhPEmI{(p-4tc4(< zr?4@=>CbCoJVqag^C+>=dEAFitn6Y_RX#huxP}2+aII;d-EdMkwWcixKam7h;cnuL zb42x(G7&Y>l&K`=4DVMt>`;3KYt@>ix1z=E!;@p&*Q7f4+&)axdf_QAJ`Z^AB$F=a zHPX_k8ueW*)~Rg3p3f@)Wv-}-@Ugfcpo`(dt?6eM+l%7RG;}8vM0DQJl%9_M-Z$kO zw48=29K{MoT~q{G-LYpXF^DaX7MjE|7%fgrm%=|YTbY$@n0VedA#)}ta&MaA%cu2~ zTa0W@BB9wByU)>DoOxK|mqR+C53^#83zV<7k``l&IxuZmQ1O%O$F00L(Rilvr!ZL$ z6yz)^JF? zF>(}BrXrVSC0pquZY7JpWFHXi91(vbSVHjgC?UhVFNw{W&#-n&_XEmYq7k^272U$7 zPIf+Sv9JKXCssi?ROexI14QEcA zL?l1t?0vYKBZN*CBC1V?&DoqMTyhkN><#!?UzN9dtNFh9^PCJpDVu~F2F1({I-W1q zp)1D$s0a=pkV4$$|H}8_Kk@b&9xRijU+@mYiD5n28>jL!r0A>_Po_hhM-$-;3GdO- zAn%!7xRhgGzFcl)6!_kPA`^jVUL8K|V0~zC7AhY2yZ8uf3+!h zX>6MUB6=GY;OjFPzGj`q=r1Bg=nfiZSB^lSQwHdt;op%@qf(4KODl8Cwiqk|I|g0F z7j|@yWHVk^3t^~}oIRsWaydg#1)S~Xa{o#Sa+B5fzB@jN4;8CcKg~zfCshI2T5I9Z zu~w^7O`E@GFW*0kFh-u7DBkyJMX~}IC>E-6UCCJ5<-fb1aI-&v{(G}t-&8u;$_Ze) zv-vRII)AIZn)#IfE1J>*Hs(v%s1)4I;*&t-+oz@Ax)FCOz4slT)CcSg;G#4fNcU*H zJXyl%Y2|0?4N!mqzqi_2khE5MJDPVd0#ZQj&y$MBD;Jihd4OiXz+Hsv6f>sXg2%kF ze(KK0EHW(@Xc8^NMlR5J(^G?zf4KsjoM@5jyt`-mesI&n_obCUE?4mAuTQk9C2uYZ zAce>rQDJk_v?v)ACnS%&AF8b)OA9j&B~dHB|6JJ^cP&$=vr~4$ zoLckKgUZ3e=%MO=E&2o(I(8F@uiYgVS<`tnwW?3U@l`Jc?M7#EJ?7f=X}?CX-_uk3 z*bHEfI~4e;y5SxItokW!HZBi~Z$&Cp_^{wn>Za)Y4a%s*JH1%mfZ>Px&mE~=Avn~a zV*InLnJ~_6TG@yle&lu}=^PM53TxM$^vA>RaG85Dk#1dbC9yFU)XOWAjgP~vy*#qZ z&vS4uUn0Tamn%hfzP^Bv4f?ga?I$?dJSsi}#74U>m8(8 z=r*EpiyfhlBQgL4O#4c3l$R+*7W>*AP1^t{?1Q<@8A6Y&uA)P4+x(&&gGS4P+KqvO zS!_E)xdXJIei8ZGvhb12pov44YcvS#=|4@45w*~vi8q)}_$_0D6QdmGwXfmXyy~+i z_H75Jofh17?fovy*{Q<$I}_UW4(6P)G+88XJYo5lwECi+z*s)eJh^9mv&USrts zKkDK%BV;8SBI!YF{{1A=PjXPn=J)y}q4PW5F%hbJ8BkJrs3;?p90hb#h)J{$Mf9s8 zC%JW+L{pV`NmWu z(egQ^Op=;H)sm~_UzhFpaI3zhqe~_7NQDatft^)M@lAhxR7du=SM^8m86eOQC|3ed zJTm4Vhp*+th~O12Bw{Jpe6EZQ>9#jy80{+EVHvN;@GnORASf9$9zZApi_n>5WsuO# zna~i8!*DyDemG;aDFklj6Hv+GqLwxBml&fEZKOBM?j86FhUr=;M(&3(;Y1jvMi|6K z___lh+=v;So<;t|mr?SKE(e_}#yLj>p2L+4v>_5CDhb{-;XbiDk`2<##RSztzj1 z>&W}=Pq;Sr%n}tWurZ7IvQ}jmFyIyZ{+6+;MyzSiY8PAZr-R}k_QOf#2R3=h`{!r2 zn-9ANh2e4^UfO=RW^+aBR6x3Y9m_!SIEEjjSmZyb^6<=Y_Z7TrBJW4Yrk|5yJkw@H zB)$H5I4*@s4P>!J#ohiy#d74&zcS_}hH4kdB)7$}fAGXRiKNF1E5V^R{soGwh52Ts zI3R-?Kq}yg7GrvwT2jcS*_HzJFrSJ(@yMO$9k04s=f{w1=s6$FCExq{b88bavSnFwkWZrsCv=+$eH*{ zl$G z>=@;E=VFfdqU!TT3SJ(Un8{TP<<#{3;H8$YNa*Ch zQDc*s&wKxeMK-nyJ%`XD#rM?(IzzqrKpFzdn`a}bBqQt&j-b@~L~vxGx>UWK&l$1gk&SVljdHio`__%l6^%F9ji^6s-qQoN4506R zM$`sSl^ESeegHtmMN;5Z$*2>ur7l!*Q(Mz4a}bPd6})PxrP}_4*5Oa0Cq&-Fh(8gp zMq+6@PlBGy%L2x;oDg1WM1M;l;+3jSog?DbS**S-vU{Om3bvCRL?&FQe(t;rqssRn z^S`JRuh|tx`D=yeEgxpUTqGd=QK1|+R{WS2OTG|PzDFLaW?`Yy2sd}ei(_TEZWMjG z<^8j)675MpK;GH!!pdBp3_Axc30tc*$vhaa=O{_EhD&s&zI#PZ%b$wtiinYvcWBsE z>gC`bGyU`oDi$ist}x+?9~xm2N<|yW+y&VhbuK%E?YbP8B=lt17hiLQtv$YwtQTGja-YS)K{zRyu6< z10-$v*NVgv-&U314mxwEMyjmg9~t2O)Wve8MLU!YkvtiY(78fVK`WkJvSCC!pb^VD3qbuqTonDPgi_npI)J5Tf6!owa*Cp33>=$9|H$z z7Nn_UqVEf_PY$sUUBb)Z&NjxcQN-k~xiztV_=PNRI)W_=@(Wh}`zDMbUE>Q~JfW5m zxOBkwCp}H}jsyzFv^Lf~DEcTgkK%)xEvc49236w zqQV^mmNaas97BnnM!E-6E!((P|DNT;hZI`~A!u0gS!JM9Qr81vq5aL*u&6}?q#}N z<)zNqx-#8H-`chs3h8cmRx^8tqHayr;Q6`RdB(uJu>@(_x7#RJ^zFCzsP1XR78$bc zJvJXP;qDmarC6Kpplf$Lk>*-HeLV{VDO%eIFERwEFa_Q7h$?*X_|HmBv#cnU` zIZj>{=R}nyAriC4g=rMq&^MW~uM;<{EBz)8$VPKEqo3GyzPd>Ylz{yhWU2dz*23Zy0+I5z}VU;~>k~OvWF$Q1?yVeGhb8vqvc#|Axn9 zk6Xw4y2#1T%#nd7(_iG&4-WQEVfmV#>FqiR6`t}-QsFGPMlO73QzBwq#zMi12&i5T zs8i|T2QW(*z`vRsIdO=z6(f#B=p-Y==Tw51OaQgf@K%$h$BUp~xHv((t9%G!PcM$X z4QQeKh+w><+q@!je5~u;rtwsx`cyV_dxI(H!%R}iN&fz6{@ZxEupfA^<;>tU5t~i4 zkR6qfIH|eK=rC_sWW4RE5A3vMLE{`A=2RHQ`Bd=<_73?BhNWwY=Hrg)aElQBhkDZ% z%7^w-<0xE~HDZ1*P$?@Ua)d#BC0yX-KeHZPE;8{<(&Xqg!;R3&?=Aa~^V~UhG7LKU zMf7!hGA=<epX`OXix}bBhfOx?Wku7dj_P7^tB!ri2$r#Tq`4f zGR-|cK6UX$eR<+>dBXfx(fZDD_YUW$J?!m$os_uhEFUhmsJPJ>xx1KBrrglwuFU66 zX&V}%(kq3vtKZx-{_uox)g3b1x7SzgxNM0FesO#%f1hpn?H_!bkfc=7Xs;CwcxV!8 za?(#ywbiSn^P}H&Lxk)dDZdv%zNqVmPg=jQS5pm80^Zk%@PX2)Z=mRv@6YZTTb4*Z zKQOA`606CSb`PIuga$^76|$^%=uh9#_3dk0|1fybr1fRSGiy>L=aeyP{uKZ@^gd@aUvL_Zr3R@6`7In9 zR0s!ScxN@2ELNbCyxL!V-eRhwcp^Fy^Zkuu0x~(-wliSC;S4NCiI9S1xEXdmgKI07 z%==co?;2iMk*}O>C)-rVQRWHp*o}(Ns3iGgW~XIZ63uM4PFr`sN~YH-t4Z-zK@QcZ z`|>U8^7RUt4hPqXkFV=G(p!cQ^rmVMdMKFmEYa`XY0OA6&+>83&ELiGu!$EY`+ZqBno%T?a+nXN6phYG zQ>PbH))b;*1^6Q?krTDY`5%WXEd?FU2 z2phfe0VsGO%lMp0agrLD5DHGu5L27RuAgIp{7B?>p>u(e+lk%^TVf3pU5;~Ni^8Dq z@_eqR%=mf_(~<6<-t1BH>nf>s_^;WP5ZR&0!y=JTpf;OU9AU;fcmIca-S#o}Y8n@2 zLKf9#0|?Ie&gb3!bPSBYkZ80a@V+-I&*rkvzou~)S1olkw$1<%druL9wS8pNMO^Mm z*U0i^(DC>`B6EJjpyY_=zI6&s$>4M-K-r?B;n$ylyvlZPEj`HP=>J33^7A;d@DmZe zxQh9qE_IKhGEt1UMI@y5{#VGf|CnO~ zw4cOoY=@-Y?mrW$F)vB$b7lVXPC-IAE}d__M0l;DGbLHBCWpCHK9qb=*r#rDBv!g^ z5Zonwp3fP9e2_)r{qiTDCs>p~?K6&kN~-Ii|4b_NWsPH-QRNopm~Ltjl4viI@U%@h zNAEMS`JRRMjQ*R~@-F+qr(`4fkYz6u-KBGE;X)m12H05nRe6+FuY$%Poz<`=i}ast z9_k~5@4M}XQfHMjv}h{>oa_7vudo%FSD^hs@k|mIq%b=1pDi@Hq9h*x{I8l~RvVoZ zqaLbB?B|Al*$?ysHf&_>7%&$sUbyVPa4PwK83oiVjC`mzNHJYBie*cqe<;!1o>cjJ z0rGR1EI^johGU8bS!`7PbP$eu1C;m`;?gziVRo?){Yl0u z^0H`U2pk(#yg+Jn7-oF5xXVciRY=ixP1p`LF{v!zPrIPO3&XLqA5FmuRKo+i4@Q9W z5fPHZx_?v?rM}c;H|4;nrf(9k$R?;Gos2k~=;d8qylk-*N?5Z~B;$i7C|Ji<(8mC{ zyChsw^@pRfy(cau6B{s}mfiD1HsS#6@E&20MIl!8VOMkh)#Tm56FEN2lGw4>zv2kQ z&8|*dH5gHW)yrmJmh8-rRfMs>B#v3g?ob$Ri7I!@BkC;6|7$?AXZI<_Cl0-Xk*W~Y z#Ys{6#9pijT3)KaZb_Fz0wXfKc=>UFQK|M&KVjz&2~_Gp`O9L%TYgPi4A$?Nowtki zFV2z_^;C`SZ%umGw^H7`elAcV(2Qq2kYEm+Mx>Z4u^Bd`U;tY{M|`sO<`Vhe%+O1z zJF}T60mk~CHuK#E>{$IqIZy?HLuabun;=!n!QuMshp}cOcePafTbQ#ax zvOHc|X9C6^OB&q^0Gtjw>(8zy8ljMQX&-uvC;K%(K*W!(i+U#GWM=;)ijrAS>vt zx{9RGO&)I0O^E%C5!8^kOz~Wyl@r@l;d*ntfzlh{zsYW3XJ@#gbUUO>#*{@~WZ3gi z;%cl95JJQe@-&_9aWBfNOh3Y{&lE5Qvx!oXRi65hf;6c5OL5Z^{iQS>bv|1h{P_D1 z)3|}(qAf)^ro;kt9OIgUg@ov}a8yF}gK&5Y;eFb+L3-0ot}`+gTS@ZkJWg@yhs8R| z?=K6J$)I){ZvI9^v&xO1#z*ALNLfGM1Y>3SiE&_|u7i{*ZO5xjd zA#=+%GKmXpqH>(6k7A*OG)ndv%mLF^KAG=OyB%z|t%+bt^%nnxut=6N9-lk-7UCbd z*8w)Pz1(K^V9RRw<_-6L*(VC2ZZkG^u@|ty`*2+pwY$}|q?->{8uKQ-BTH1c{=TZz zM=yKQ87pjw7k-v)@Y*O4h2Xsxuipj}6jn>c>7o7XEO8?|?>N>^-7^D<@kvpWHCO1s zn9uR!r-{4G(3$Ilq2N=Wo~{w%BrMKBIN4E*3Olka%(@vF3abbwv3CHDG(OzE{ry*& zGuEYtEBrlv#NT0Ln?1tUHX+&x)orLCUy=+C#=Ny)Do4^>gezw=#WF=066M1q^iYHfeSI zTO^!tKmJ5?obX*)b*$%$c*T@ro~fVD^z|UeMU1{gjMC3f5w?Syy^3}@tWyl6^7riN z_zbdygRE-UGPm)15iv@f5UmsLyxA(VV@8YSl&`FVYKDp#bX8swFvgX_t)o&M%{nA z`%&3doH!G`T~&e;7y}1KLKr^>ttU^PW6eOZv&dCOA*vC9r6{(l>NhH$>mx)ds#Xy> z+oFoh-g3F_qjn{#>84m!po%-a(GrL%LQ^z`5@i#gw1fLd0bT275x?&q=T z9o7`amb8VKR82&F8gCxu_)?16GQWCp4MwS^dYP+wdC+)IO2!8)^@wK3`#)ppD3t|_ zSQRJgGv?!qNE4-m8gt6qEt?N}JC zcb`C4n|Nww)L5X`>@`m&_Q%8Zia}-tM9`Dw_%(-rz{ImY5811aH*5A;HiUMLO))k| z-KYuC*MBf%y2g*;wXH}jov>}xNOGlSfu|g2;ZyV_Cy0u{w^Gj3C;8Y2SQS%ocA8{z z35G6WJ`gm(S-HY0#`Xod#u7B2Nzvz-S^4=WQ!>Db%w;7# z%7$_T&W@MQ%LmA^N`ldyAm56psJ&wr=yFRzu=Q{Gn>YC=6aa@49={^GbLYHaYPM9O z-kv5GmC^)xq#lJ;?J>YvB&kMr`7B~!TKR|{{wms${pvM{iP~a!_9N5tuf;%QtDYg144uOnMRWy^MZ*Q z{(uKgA#7OO|Io?!m!RRAVh)##RC!t^yJD%0V(!~wUiAge3N*_KWHnJVZ6s4xsA*Uv zQuxOO_2Amr-UZ0t1-z#5k^b2kyKj^&i&|7#;T3uh+aJ`=KFs66aOn%BglMCTXnAX6 z(m9O~l8Y&mi)j3@c!)G~{br1+g0u=fi+Nfcb&UK-NfRrKOpRDA4Z6B{NN`I`&Mz7| zX9#;^@ozm-0N{`dZ2VnX?z&NMdQ(vIP}8Jks_qVnxuoaCFR@`_czWb3S%9epT`r$; za*2$ut%4wJp}C6vjsNrnsh*wa|sD1zQpmeM{Rn zOifhRaNvrg9q(w4i}u4>$}3$^ZS^%NNquln^5s~gs5JgSKc(D(*vX)9b`^}n22hm+5TpRJ|U#`YVt zZbLPFpY3c1PLjZ|)y6b(RH5(f+wz;!VbC$^g1xR2`*?tRyT3JtmvfLG7#deQ@Z{zY zW3$fv^rQ2W)!k}b{ch`d)~6ya2=^K(roG=N4{C`06EZ8)P-2ZOqV82a=M2)`UEG1( zrV(*E`qPibC{>=P^xY?HE@XxJo}K04OYO7IT*6)gqT%xtUmB`-VPXVf;$Hlasc6;q z_OSc||D-)!VJ_1bamie^w9?zUMz*E-v&P(uam4!$r@VZ3EUaalrCndOyN^(ReZ9qU zFdJ5){>w)@P>|4F=u#*kL6Ju);0VY%61~>-5$2L55Y+N_9NySP|7jCF zBkUGfjjPf54pqdXI`ZS9Wwu)BC>Ljo^3f8x?USC+x9LH>o~xf3L-yL-t|>3JmmNxq zTAVB*Ip0u-x)*O+s%!IWFqynM`Fb#Wo3Ni674sC>Z^RH|95{d!BcvE!5W)np5CAOa zgBlBzk{(mQ3mFOUNnfkdOiia8cJlEs()hq z?Ea4VWm{w32bGIESw^-uatu>KQLX3lwM!sJIvNPefqOqe? ze{Tf5_*>uZ55A2WUd(bh(uz8I*tAWn-5V%48e!hF+}BfDo&aP&i|9%YbEGX(6t0Aa zjius=^n8xTaqmuWSChF!w}#3G#XA3y41;vfQpC)?>>^yZuM+K8eBF)m^I{bF@|!}` zYFD=e%($LFqH)6WeV?}$Pv2hyuPcJEr>fo*Hz$|LbcxQUuFhaiWEGjq_^X!mzc(d+ zQ3hms7kg}S#@NuFzvM4NOg)wa!=IIJ4Owad1RN73(Mp0=tW-f_p`Pd-?ZL2Ka(zI~ zB}Tm%k39(a^o2#xyJYs#cXEy!8rs`CzkV<0%oYo+DzmsNKkYqGPO9^q;bQgSdDqb? z%2DF}BbM~OtK7>JJf`}1M#oh3wsD`VrjLS?ICNHy`l31g%`ai>{sFZcdckA{L!o!N z@*KoF27&UYx9KS)a`%OAqWnq|TP>)u^YAYA?Z$B3 zjRsc&@uTZ)(3uL-%`(x8DphSO%TltX!LRNy#+*uUcSYKy`{6<>V_(iL%5@dS;IZ>W znVe1CGRWr;l2|`7lN!E+3)$qXhiONfjYZyoeAd@rxO%Jyi77&Q+wNL~?!DvI`|8Gg zo~nPm4=g)TK1CgA3%w^~a8+l*Q2iZuKK*MY(##bLb2J(^RgnuqZ$mWy=(Yb?_W6;z zb*7_k?43Pko09|#`uw2M7lw*UuUX+vHxPwG!^{bI&=197VcLAH@L(88BE<~AV)NX4 zMpF15@7{Ut_os6!lm)Q~l#V@R3%}htAr&~BjKjE~?0Pp+tn~kW6^fr2!28iK!m!#- z$WQ3C5!k!^*I$!5GsaJ^ri-Is`uTw=*8DGMNeRSa2~uh0E8*Xh0%f0xGI<;aO0 z9Hg{2VogM{nJ6+c!asN2Bh3ayJRdZoD zu6&FEoZu7qsW5=hE~_Xib}WL{8Uytz;|;d5X>lw|R9jJ;qFL5v98bTKegbu)w{F;{ zZ)nB7*F`HO?{8|;=@rQ*{fy&}h_V?YJJ~w&Uue!{WG1<(4cfagK4yK)Xc79xB&U*d z_%UnpSlA+kYKOHnQAj*{H(k<=tUS*V%I5ahw2i6Xp3ajts5F+O_WS~~7@{Z7$F#c}kPsvLk#hyf?|HP(3c|7R8 zdB@&PK95B=iuJ)VeMIE%XZL0%%&Mx-V$(Hm`k7w-{4?0P8Ne5=X42(3X&|%mH*nw+ zGL}1V;@YzOS2@zXYgX%LPLF!Y4Zlxd!$vD2LtLw6{VrJQ1%RT*|!BD%YzoY$OA+EsA>vqNE7=r8JT?yc8c zCBZx2#$U=j{GAf(k?NYIAf+qyCdu!&C{6_V4b|cvgS9v7T zlUpHI`R6n2#*4*u(7et@AV;bCYG1R45czE8S{_E~Pk}WTfc$=@J^;CLw9)xR7C{R~6_Ul~8=|_{QpUbrT(F0N>-(jV zA9kl@Pd?X^MnBM@!KIRC;5d@M)@>0;fxO7L(g*hcpZxe-4v}!@vjUv;@o3M9mEWE; zhHl48-L(IhK`~-MvScOB)fGucYEm_sJmrjaj4=R<%P$$6Tev$dKIw{A;7*7C4q8C> zShAn2#{F$i$4!4>_q`mB*c~_diZ}b;D^vmj=Eba5?M6e8r%1*y0U#?UK}f_=&z=g9AR~b3%e7z?1d#b zsUX+2Uv1k_<%^$~*k;D1iYod}%AViOf@?~NX<=9}`vf$}Ct}9>wyih|+I~7UR<4#M zJ51-Gt3l?n%s967M)LF%FLOCOogmF28eK7j%wM()foJ1WvwoC+#Q5)It(%|TbI~VK zPMZI@Gu&agt&scIov*S7c z=6aOxnWtHOV;uz&CnV;TWw=Jb3(>2|cqQhu-@5UZ=^Dx<3jXSZzWAL-A{(&liw2W$ z>J;g3jsokUffm78?(g3j?^0#g9UX;vxz*4sZU%w#@}(A|hEk1TkuWI`%JJu&;J5&l zOoV$_>LF8D55BdWH0-^J4Qj}rk`E88_#LrMr_{-?GSL9@1S_Ql6!ak@VNXP2*1#yb4bpb;m%F?tQ7a;}KlgS?v zfb={@RkIim`3xSI6^nLiP)u0PIuxdR9%uTsn7D0ph&$js-h42VJ7MKHsmqmSZv8H z4RG3Hh#Yv&f=CW3T(HGwQp6Hq=S$nU{m5t}ru^dePeO0dK4JXI(BWB0M6}vhCM&i{ zw}8L7)`Yt}J_GuW3_tKwZn9XUHhiWzJqbQohQq00C<#&Y1QKe7S<(eC4JT&rBCL%=BAOps?;3Tm z&c6m@qzh`aQ@B(&B-n09zC)}+it#1gDw7_%C!nI!~?5juQlzGx>^HxBn8 za_u$zu|k)z7lR7|%uPfCi_*u)yHG9VrraI*?<50wCu%lvri5$p-(yixU^U!RqO5h?YyJ?u$Ar zjo^bJk#%~h=t0M{;6RzfA7ZmkGfDLWMUnm!g3d`8TP2Qn9C>Hn^Wtfz6}AH{>mCB zB$t$8;G4_`a}G0N5fCZP=eZ42NY)ZIjrS=(@Z8vfeb)cTvk zT=moS>UIF5ZeENAlE`u3Ebue!0KzT0hjj?p%8~^_%Y6yq>!La`*5X_SOaeN!rhi zy)-UrM0LAXeyCUC%a3@PfW7N4|Hg2QVo@9J6$NS1*`y!;>aqNoRhoV`XC1N`rP9qI zU>8tDOMOw#B7W!x-+&u?sAj&EjBkC}w>+w<^fWR|^Zl|Q z^x>F8=Dwah^tSWu=Zoii@{`@o8zWH2(;qRU`|UQ*`#q5!kz-o!%q;24@Q5_CoqT51$>I}-RW8YW^IF0c}C z%I7NmFI<*1LjGU)qCkYQUxaE_gnD~~=1PS2zX(M?sIF+Fp=qSCU!ZMQ zJyM<(YO@k)Ga6xS8s(G~r8i3Gk`*C48>QhFX^;5)F%q z3MGwsW}6gDVH8ebxg=pYAH(>bDq=|J!iYv=Vn;*T4ns0m!t8|L*N5<&(Qq-+xR#M{ zbkkS_1W(Z@tmH_S+AogC7WTjbyB>iLIfiFB#WS#4RTrEf@y+qc85s_IjI7!q*7s z(bq(k%la{#k$4e)et_p-ANC1E(I`hzYfDk7hfH7~JmCQt*f3o3VyC(LV(Mvs>(wKa z6MoUpFrrIe-a(EwoBed=WOR(*8kH(-7idxb`Z4Y%oA6e4fzKA$jxB$|Ie#UVguk)oBJ}N+0ihTbPKhD9enddyt&%2W287mJbXy z7Z7y5#uFJY_yRJkSD`K=1W4U+zI5PAip%qO1Dr70_()-bLX#Wb+%UL2(wUfHIN5y@ z6H$@8<&Td|Y#)+#DQC<+S~CHrRUdsB0jmIcn{njRUhEy&!uMolb9`kPx@DhiP5w2O z)b`>UKdF~5rIUIS$Z%ocGvoxh3ClUQ6;A{CMjkJaX4n>B(gbpv#6`JMN{|UAY6#j# zupuCI`690que1s;y^|0G1MrP7RdOh&UNQko*oFpXv<)92nM}@bGW=VS7$N7(dDX6L zrp$)wwadbhaf={Gdd)+)Y zdAu?jiBVpjQCS~asn7O7EQDu|t&pF!#8ZUnRsfkh_@0Fo>u9#$JPItC8eDXNlSJiM_>e0{LDSyp8-3t}bG%LDK_JrlF^g3lzQL zunV*0DIw>Y*XLSJ;WAe)QGY3LArvAt&!WsOh_4{HV{6!zZL*HU4<@LV@Tlh1MgL{P zjI)42m0B|8pnV=IklZCe77ub`l3>3?vA@HUGRZ@YY8NbNUrXnlnB)AaWcl}xF|3*w zYnOLG_qiO!Io{7HWDd;<$Cl>>^k#4@&Wr$I0UqQAge_@{7Z5RnndohV_I&=Q`$Jpz z#TGhiF7#=_QknE+L4>_XESbLhYZ<5H0E;06a`uG~+T_6W#Yx;u?yu`%Ab9O1`Ux-6 z;cA1ihFtBIFwVG9pK#IR8Z^v>bpa-9HY6POS2C+XB0e_=4JtWcAURS({C%G?O@nsg zrFa7eA$}w7Tv#_ITs2sT^ogQjK^JRiu8F7IK69w58wOCxa@btq3v!a~PC&acq^LQC zub729kBLK&MZ*Ndc74R~&xLFS#9WMcqDt*+ZPe}liZ=*Iw3Sl6!US!fp>&ou6BqFg zF;nB;vIU>(+XkSy73o>fQ%djR&M5SGS!QOqYh8PS)xbsApb@nvTP{`EHT%uc8V4d~-5R!T~tc}N%Ap+9(G zJ?#!a37d)KCf^%LASINwR%6pz?$DBKvSbiph8|fMOFI&WfZ1qCc)-c zjMJHPl-IqerZBK0Ey`(v+NG=J`FgLstS$>7hAwpGg}Y}~#Po>wj7G#Xv!TSJ*C)r) zX`pu+r;16Xv?N+$+JLcwDpIL|P^ETPbN51%o@k!`VaobRQ4`xoktBUCXH~b-9$Kw9 zPw&HnuS>&JtR!qNPhYFl>5qKI1{z5-Am_jW)uOGRb%?xqZ|S|T(>Y^mZybKF$?v1g zk5E3VSB7BAM5n2uFabHwe!8!LX@s(ieW{~h9RO=d7-;6aRK49p1V@+}opk^K&t@$O`z(rKtFt92 z{z1{dLRsLOl<)LdEF`QXfB~#v1N9B2)o&)EPf7+TL!GGJJbLOQ_l8g2p0Al_o)(< zj3jnx9n+29E0|=Re8osU#Md>Nl0!aw+QN0#$MijyzwUY)?=baQow`kNK|Ky%(uJAN ziwf8=?kp*X{8_cJEZZN;N|`_2oh-W(ZY54W)+z?_a7-$3ek8j}#$yMu+sD3^B&7} zsjllmoEWhINAfy_0yBGN2b?az!JgN<%YmIY(ET?}Otz<(>8DH!bTc?MA_G>}`d`qa zEysu4pNYBWw? z7rT01!8}7hv!PBZDD;tCBz^K`IXJd=Ei6z(_@29>v-SMpvUa$-DfK;wChUs_~JJ9KK{aRV4ij0AJe7(z( z#QmU#?{Mn)rqh*y+WYO87i%horV#1;OlY*)+4u0vziTk}x{H_#YY9eII-;kqwmJmHs84NwnMkH=>P7PmTjm?Pm4@jK~T=EgOBs^e2D_v9kj4RhW<=m$(U=eRsWVK2u^GaKA<^0$&4JPo5RDY@`ioS`o;s z=m$u4g9g1#ER!EZ6f!EfeEZr-YIHd6N<95c(Si4$YIC&wkF|FsMBE!Xb6js;64Apo z_Fk~J(D)iZ3-sak1_Yt#*dhi?N=D2PXE3&(#Gi3kJux zIPYz9tVRs%G}}~b1v>U>7C!A2Up;z_wm52=e5U(MH6UvDO^B5LeV4``Uk_Xj#n=A2 zMx_ph99kRKANmhYzWc8)72kVGxNeMG2*;SBslQha@seC&{QF2~VqUbur}Vu90gQB; z7M*FlF+luSVLge#!2{INW$7_H%<8Tssml?u-LA{^giuNkmLww@Yds%KF--7JZ}%;j z_ENia4qMYdKk{KN+^SW-Nv0uDMB&4c|&m$&e}DjNov(KffT6iGB*?-mYF0Bl>DGi&rpFW zc@&=lx3D;Jpsd?P88T?tm?p?t+j-Y^Tkjkwo2k|@4}G$BenKQ?>zc&(($@W{ww#@3 zf#*v*?`H|O6M6NuFYWKW7`CMZdP9MSCD?y!nuN*_B??TW7%?i5Z+F#Oiu|bk; z0(1lef4nQ7kVye?AtOSEBJm9e2hSRy1Fz6yI*WO30tO&;z`jTPoki3-M#7pWHN`jB3ES5p0fW{ zqQHQJ-X5GBhwZlRa>qmq;mlQL)P@wKiClp?1=)oi6Q9Zdj-^vpB>Rl){Ol zm7=a1Z>p~@e|&D`eSGkTX1fjd=7X(G%cx_jBe(uQ-1b3L1cOF zsw^n7qHRB@e_)RRpirowc|pL;O^qeUWQG9`zTTBxDbpyY-EqDT0iL`SoCH9RgIczi z*`BO;WDFw^cYd3VKI8dh7g1KV0#O)|HY!j9OKAn!GK2ISbycOmRnz{C)X*)K>)82b zB0PV(8Y3g6989!+LrhQ0V!M8tQuRepcs|F$q0J@_V|fz)^A|Tnm?Z1KS3IPL6#ZdM zpq1EPlV$>!B+-nfiddwA{ck$!AeKVoM40Dk$qJR3HBv~<1Ath%O!CjEuU^%rIE#G! z+0oD^dsDd9r(FWOCI$6lez0ML8 zBzK0uz*c{C3kMyg}Z?~z6kitR~@uQ7kw zfvMN>%;WYU4NpV+)`3Cl!ZluZy=3TdI}>CdM?VKjTc+fOUZX09$ch*e zLQgP5H>Dez>`2O>P(l#B3k`YQE%CXp0r2Bf2!BGK78C+pZ!^;ek-d^;8tr*5D=BXR zb!mc)AqBtTJHif39k%9U_ZXY+l1qE{>v~N&7hjEV5TfxaUScAo{Yf%I$peS_IjQ2g zJe=(;+DWLLfPj^3wfXj*v0HiMYXDH<6H1IE<)*&s8KnI7J06#Am}@SAK#CTaiYA)h zO?TM?68scn#e$5T2-c+oi$2h0+)J3lfxnfb^Px_ig(pzr$}?PgxE_q3I+}FV_Hvfo zAh__iu%J926is#8ikQ!w`wxC)4m5KM%XxacT*4Fqt=4*a_FDP^dt?=3KiarISz{+<^m$VzRdjpUv#l|1;u#vA1V*{6yk%ZeE6q`FK#F>%%lKlki49*C9t8z) z&xRA!=DmL5v6Cif@@$i@pR6)o`Hl#RqkeI0^F{j?3U}8R5_iVrem`(y-@lxfc}qR7 zNmH6(hK_R|v6>>S=!BXk+nhJtv;C*jUVietHO%#5rJNWInDO|aWF1?_l`a~cG1-c* zPfeM!nJ{~o9Qh5i_|>3^my7}BoQM0x3@7aX0hB=Y>t`LmDx;bp<4MYsn|`BDC;7Fv z+Ghh6IjQwOR#k^F$=ShC^HE@{$K#)1*}DF%wBCj92R$0Gqopk%9GcSVQde=5MP0_1TA7pnujpV>3;fBgtLg&WjU-~+S>%!EEm_gP{fa}> z{`*H4FaU+*J-H2gkzmGug=IfEl@^J9S=B)~sdJZ46aSabnsm9!2}ihcv=&VSJPs+{ zbKEno$cwRSTMJZB zp|9u%<2kyk{L%92LhZV;-SjUZwM=7@ldZ(NYIs5gMYx2E^H1p;+aXWx9_zr?sMSMH z?|U9CL2_Mr2OAE!&l8l>3(;C~C9=r^AxaxFwYtP*>yZW&h|%aZGYp`6 zu=?W(NzBuVTyy1OU0!Q5xvtAVids}^XhKVPv-;F zYO2rvgeMl(v(K{qcwY3)8rJgU^A_*dw6R+^hDhbxaNn@#G2xr;??@*e?rmgx|DQFj z3wG~s;?wtbptxUanj(qfDi24j)Uq3rCMRsvgeOTS&$mFuznO?)JRr|5iL)SAlg=@9 z76$(fia%bZ%!> z33Dh=gsFIkl1?r~zWZqLHdOu2_iEhgU=_I*R@i`BMg+KFj45Z5QDt07XS!yP4^kGBh<;)ib7}Y@ctt_TWGQ~b7nYzby+>D( zlgw$*rL~NR4Us5Sz$bKQU}p`*qa%s*9eYx3-;s)F+WI!vG4o2wa4|m6Ry||Ln$>>O zDM?0?4HN=w6Qu!v`u2*@$de>66buZ!V1CF8NYDzZGl%+U_WKfM_YZ;RhZ0$-XE(82 zIpr@-)2tB?c3NuU6)dPH?qNkj6*FI>@Jk#2_qKhxc4t`oZSkxD$m44UyddB*^d<e-n-Ct}2m$b8m>T-5Z)33{Xq|l$DJX45R;;65 z+Kerptw|iyP`cG9q+?H3Qq@`uQ-8WWvS-Mm_NO?DH1+x~8i^53M-hj*@Rb>=O385V zq(0*>)wl20E%DH-;Weo4!=i)@o?VZn^clW8dksPpkd0NkSjL9n6QwUfEDDKrp(&rG zTGN;7bhOZUa9G;exGvd;b@cO{*`Z7!^tax!NeUn$PH=w?;(|)u0DJVdS!c%n!`e+mZ6`)}> z37-gMeNS8y8IW;JjxucfF;ObuA$UY6_(KGE($4!+u@Cr=WCT@gaaVZzV6vcQ@>Wc+ zEHbsVJ(;{{x_rfG>&v`l$$r1)O~08oyMf6$B<)X@Y6^gNgG3My10m8ZRv@HpXzN0{GOTXnq3o9!L)*S-gZ9bO z27SW2+TvYr5qhYcYKDHvIhZV}mk!N_PWt&Aql7?9yD)Q~a>pQvMX&^3$fU@uBG$I} zXq1ue&k1KAl7>ct8}Y*DtLqv~jfDAH%~rh491o^ZKs*XnjLBqG@YG+f0GX8%4V|(w zcaxDW*3Bi44UL<<@_5I2hrtCSt>{jm^jA{8WZv~x1%fDEuw_m-0V}XGFW5pL+|6K? zHzz3ji69{UkuBtr{mid6^1d1JcPHe)B7e3^{aA0>1T*9&-U4@uGkp3df^4{FIBzIpe`sArL0S#L7e>yRwzj1;SE;}gPc zV+FCTt+W;`{E?FvUiNt^>&@r(X*xlpg-FioD9*Y}>TI4lf=lS!!)L3u>^a{u$U4&t zLlzT^u}e_&&2Do#I-yz|^MPo7Jye4@|GHF zmzuhlo)6o5efiwHv(!q-7$lnQ%-!enYpFvPTHuTJR3LR$1`-MrS1C}QGzC-*n69|= z$-}+{spU?KJ`f?rs|1GB~|;J%`Uv zcv?E6^=Z-J!_MNXc*il0vhhb%)1+myf*c++=sc}NlY@bM*4~kGSpW$HH`yvQ=L;}& z%6*a5AJwLNUxo!v)ByiAPO}9t zR>&_ZCGu~Qw}pD*ekB)K6-!*Oydf#0tDeC=>Anj_%fE*5$U?S33)JKU*%j1~(bBRU$^epYq9H`G zSd8m_UCzf!H3}`3huO|PL%L~NbVr-wa*mv{*hhukswVjYt1srG8bb^OM1+gKa!heE zZoaeXQ={^DcP20?n^%t$(b!LDn;~+G`S9z@tNoa`QebqNc9JAt59LScxlQ5C&g{qC zGNHdfB7$~x^v~f05J-{$#E?6@h+&TC6Sh?CLrQw6UMQnGc#I%P1;A=S z5WOV+pIQmiRLRWoTSAu85<^Tl{1N;`DRNrKjFMC$`y0boHlUGxSNP`rLkVr`^rUo{eNC+uQ4ix%#r&ZkEymSEJ@qud|)YE$?lkTgp zO$kY8(@7+Ed$8PAAwD{K7nC#6#(U@Id;2`3$ncfE1MqmIOr9!C3^`7W`1g;|$Bmy! zR`Huv^V4Q!36wwFKegX2@N0X2D;(!FecIyZ((AV`5LY-EkSR;oRPLKpGwy|%=e`=4t_kf=DyCd{wp7UuuV|GRqX4n_) zZrfN(oX?i@fH=kOi3UYQN_1YpMSyu3%g7- zb2HUKmZ4%fqwy_%tN>FXB8*02Xk?AJHg&reMgEB5Y+Kw&ha;O4iT^=;v9d+p?1jjkv)S;_tb z8n)>aI-I*}I)Q>qq(l;H=;>u_u*IgjTWtm{0{#D6h5d8MjvUFUmXIM7#Ry6Q!v55* zjKZOtVq%8EMH}MEKsl#yfDWLNqh_pcyZut^$v}uw#xBZnF@CUCO?s;sJ2@Ckv+Y6( zUC*X2uX>JKHx zMPb>+!xur%`~zNbMfqdPCUfq%o~qIO4rf|}iP5wrK&to{B3}LGmOK3g3|_d~r=6`t zlU$;iE@K5QV5x36g$8%QwkmCz~p&MmK66DDoY5V;veZ>mdP@xWs&3flflTsq_ms*23pX!R0 z{@*oX(b05*lQAxsr|QI}m>@q1y-d9iSHrFExRl@Q#WpDX5dxEkLUdjDM^E>4o(2g- zDhZF=k0J2gd}y2G=0c#TKmsRqs)x+q;1d#b(k|hvF>yR^4rpqo3z%Bj^y9YF^2j)x$aM)WWN8(@$~17JZGJ>Ai66~I6|8IzR%{t0XdOA7-xFeBB4qi88C zOZQKC@tHij*&@9Xz|)uner{;BDMT0G_nvF^{l%{diaO3BMMDYtoM@rM+{mLM(<%~? zQ;Z!FUHI5E$h^hxTxg-${*{JS(T^#006KM^t-$?s9`K8$-8xus*9MrR19Pt~#GGCc zupa&0`}{)9P4gG67`r(r_lAaqoDdqMT{{g3pOo1!Ej{5d;d1D}WmZrL>!bMP!ijc#st9Nr%(`>TBU7-a8R zVxPWqY90a>VxF_TIgw`2AV$n!?{os@q^h_HCI{6@fOZ@O()v8b#$g$kVVNr0!;>ny zK!|p~G!Sg8CHuVC!1>9` ztf|g^)ZVeXabKvVd+DKYYwy8p;TLcJ{1I;JCsP(_A7+gf=@=7wBhopk^jD;7)<9Xb z`;&dN=*usDZ$w|MKKv`%vyq}K*1J=z%$kdOR~V>ERU0kVcbX4JGJb)8gwa3U=07`c zUPm!lmc2d1DW?6C_S9f>97tC?m+2fi1Cix7K{pwh+E#&cQsEoY*aK@XM0a`Et8D^wrGw}FZJA~M8f~fB$}4>~05SVAf1<%l;|eqr zso43}{$Y6F$2TdaUllIMHx{VaSYo>#{Vud&VG10=l`8C;8FybcLU0wjqK)q-{)M#r zhTgHhv2>Ws)V?h={qYE`WDFP8=IZJ#c0V&qj#g0zhexNIC}A=`x7VRbN}V<-1F&U|z5mi9pRP`VU*(PMCu>ipGuRNg1gU!`Qyoh$=tn()CQ+Tp zBIO57(Tc;qnhm%OinnaJn*CiLr(f6PCJP21b+{^Bv{T14YqGwvpyy!T&9HAkVWcW6 zeIz!;8$F41o_E@h3q5GR`N9`>hh^#Zox#L;a+|0^T~4L?3)yf4Y)IOrUolDQ(o(c3 z+>-8)Zvq;$8EtB!@u`mXdcFL!8A{*Tis$UjVE@ZbEBZfjdYL6DP+&5$CCdY@ZLl}h zuG^f-ZhQ)fb9j};?7SOIJ@8{!JV>jO!vV*kfsi4W^#^lKN7BP#ip7gPTS@nM*sZs* zeg6s8sQs&s=Sy$U3)>jOnpXfswkJxdcVlDoT}C0ChysFZkntpT2qI;L3#kh!`{A}d zqfm%=Q2rw)rv`o@qR+%MHLVsFn|m)Nt}Pxd1@Pl^#r-;&ei`9X9`w&j!%;LVa7_zH z(WH7%E=vX>nm6m(QCAc^2Oay#-Sz9U=?sh+_^$0jc!XE`W>cubfT6T4Bv8S@)cz4t zWK^VbD6}t-h0p9hGu-&BcAaIme1aAb6x8Bo`N+)T2sGxd`;m%Y8@)5kFzW;&(tDBVVeD9(VsUlYnizc_F6 zw>SJnts|T@jRrZC8|>Az?Iv|nM3031PHhTP=5@e3lEqeCESmquc1p++oX*ChsH@#v z6|F^Z3{ajg;1y$j)%HoCDJX55A^4T?uNL0(NFDU1l}~-y#%7bieBb!J7t|aLnk-5J zE8KjsNj3X#=11ruqSk;Eewh0G_Tm!1xUAVD1JcA(>ZG?D<`opKpfxt$L7ROrvk)Pm6VkghNOeodQFqYdNn(jGldid&V9V3q=sn{7oD!`y6pVwz`d zG8|>z#fB;v3wvDDaxWa_c=tH_!yBA$1OMT6US8KWUngtv!;(3>bC?zp5&nOE5RCi8 zZ@GDHVoOxh2JBlb3yb~46PD_@5TxC>Wd<~ZA{mWX-(o0R9phkQr_V}3ji4vV-)NEN zH}8vQ{8#O+!N28|Z-+|M)r3T-qNueS7HhJ)9*9w*d>AGRUoTo68H%UNDBnkos(6(? zjbJ}eIwE?GrlENFi2vkZYre-s^%p-4d!H*?!wc^^IdmxY!le3hN z2OEX#Gyp8YTx*3j{NqKq9Mbm#X!O5%#_d?xTtSyusm&cuGWxH{~{7%pq#69MowD< z(bl1(mTH5NcvTR*V(2%M?^414-(DaBh`k}f=&%TupRx*%ulqWYh^v@sjQ61uL+$o3 zDa0TvX5!+yEK)OHBB3Y!eQM>TK%DC*u7q1`kA9?$KM>|eYlv6vVwDZ~n(VUGi>Lpu z{nfAH3GuOlSD~Qy;Z%uVFiZEhm$zygteGdw3@JCNm_7eZoa-8-$h>h>B_@~e*Eb<4 zB#@6oq|oMWQPJluN*ke5*wO6txV9pUD1!Li2KB#hTsKEW05?d!jX@bmo{1v8ef;_b zI~S%C=g1@yN|aikktEX)p?6Y^R8pEz#hn2uhwub@$CTy$5V6k6cqax^p8}3uo9r zZ_HFI!TS}P=`kR#`ZI3IRTkfQVm3iYJ!K{PRApmmwwpiE9Xy*^3vRZAYYrHAp_;D;*|COE#AS?L*xr8^%> zj=^E>wMDab+k;ZyVi8(5bGMgMonA{21@d-@i-Db}tld>F6v@GkGCrwR1H%;_lM96> zOasR62yvPQlz@mCl+p}Jwyohr1jyhdyD&Shaq2YO&l&G~(9Uk^n2@u+o!IRIAbdL-J~;73T2`FKozek1 zdk3?npytLyD-be-&w#GLOYP-g5zX4!;&>cl2}eCCdx zFWGC)bE*I3PHV`x!PcpcDmm=f_b-lzxE9d$_~N?XBdD4v;Q@$$&-1bijk^q{Y7|urH8h}q$QqlF01Tnk%)i9ohfV6zq6g|@ z=Jx2qw1b;t?_lGC+mK@jI%!3V0RL$=Jf++a5E++rHya)*W~iwY&*AixLyXX)o!&BG zI4K-qOo(HcA5@~xV=vWQ0@BRRG`R7aU_4k9Z4C^~>w>oR?tTHf5TZWB8IZ)`nj1nE z>^unBuV#P=?g31wP!c=l@?UmX#)q;3I>4_JHp0}^!WzSHg(N3YCsm=u6&DP5q2$OBBlrA^wdeNK}tSNAI@vq z;^KX-d@=uJS!EFR_kjs}Fz_J)azYIYl>~G@CT5s05J8}XB56s9ZT#` z6~ALTiQ{+{*y{9~^&*GMlZos^y!68l1PLwV8!#p{!-aWYa?>5{!36nd8g(dRIJ+(e zOd|D<+3dS;<8ckc&*o_j5P8tP>G**&=XcYIqSl{Hxicdr1AJqu-Y7ed#%y9-lkF*5uAsH0z2atbGq<>(Fp&@~R*h}l zTTBFEaHZ|*6%UTJdPrg_v^SC9M3dQfvH>-7q3yJ>;)q?!_2TwlV4k@e?>k3~Ej;&MPD+Tnf|lcbr;Zl-m^DYL&j9(BF_V1&h;>S*-W*Cxsv*gf9rv< z*`-{|5DQ6<)cYSxydtB0D%FOz4YaEi^-Gz_);|cv5w*Df;|X!KmzHBo9ru!!kLZ+t zBCU|rsqj=_*VNVidj*&)lcy&>Y*S)maRE4sJ+bd}Y5u0u-Z zXJeKVd>IM2jG;SjmhBf?YKin(^pl31RO+m7z4l~kr~?!nYWAEmYb7zcA?yOkgSTH z87AbqF~LLjg15UH<)3n(I_Rz~baQ>PeFq=gY(HXihbRf1U=yxmn^9YHo-x{P>hS*D zgBnUZ;Amy*{gvd)7i9@Ii+uVd=)F|L6AXJuuV z$lAF%e8`tpyJ=~ec4vmFKOYJD?u_SmcR|O--TyT9{7)J9c013f5K8u6I1NV@n^n3V z->X_|scJ{a>ogy0RQO%yNaXWy{%Bo08L)C2T3aO|0KN!;;>3LfA|47vrU)cgbKiTa z4U!>X<0iBkBYLDZeD{aB*5}f>(6p=OE4{96 z8JB)@HT6+Y^x`RF=&7re1VB#l;^N|}$z{kt=3Y<6z25S}C1fA;dl|A@?q0gKUR3mc zMO{xcRrd79hrSj$&YKqda+)G?I`0`T@Zq({#Q1Svzm`OSioqz+xUO;Li1L=oF$OekOLN4a?2hpSPFD{H^|g3|1-InZCKT1bA;v!jgY<>k>AFt0}n zgcTT6&7QaS#Y5?v+|>@y{iE3W5##cZAy0DLik!x((%Xlg@0Mhbn`<6vi@XZxdAIx_ zp@-`@;*8|^>f3r<+C$94b>X31OLdkhlDFjl0^?b8D~=!BPmX>-@m}nX{Ab41nNEFl zPhNtzVOGiOhS_hq2PgZjdb1|wpO24r1KoU|1Zt0lUKk z<8bkC6HzE|Gtld#NaWaGZwR0X@{d0?4tj~wwC;yaQb<(LsKH#15}K-$9NyZ{k`?wq zTm}e>Rm2z-O2Pw{v3GAyqj_=^pQ4-;Ym!i*@k)4s5fEqtDIL~CAj#E-B2 zNx!LF017#)$HNYP2PC3c+OA!5s=Cl1|dP)H0+iroOu>j`~}HIp*DJ`ql!=dR&& zesDvJeIBY2OH>Yy_sysS3|zdpBK(szI%@oX)(<@SuISk~MKOaLec0wJCMf*7QMXX! zR_t;sV=jFl%#s*eU+z^SQNhCi1JiK1fl&xR=95QGHR$U5$7wZCI=)Werhku~fC7r7 zhxpQxfO&*E7gLmijL+}x2A!_%}xWsEsQJl{J}=L&05sAmd|U^r;|*$0JSEouTMZ!w(GH^H)4zH z7#b7XjRcm!#f>CbhV5puVC&*$s^paIR=VQx;{VqQ{GVkY$IQfTC(kbM%T9r7#??X= zA)bc~_Ih>9sLcC9Z?7NW5GX|K%^rh0^wdQL~n?CXC0-YVBLmoc*N-i@+)_Lc9O zckVkA`|sIQZJX={zW&;CWW%RVYdU&k>&x^q7wlmq4N?64Tdn3kXzl36(C;a1jg(|6 zQy|^AmijtY_;XVW*?Vu)4<5ol7!SmpOuqPpWPGx&?qFoN**_2}g3Sb0MyqioEV4q$ z=62(tpmlb)P=gAFu?wwrl23}Sm@%QD>c(l&c!b@rr`!dl!OgWd;s3547t}ZXSsxBW z7l$wQ2-bIf8WXhaSC4Bw0wgZK5$#7EQ`~<`%{|1y^kR}RI$16At?Ce-`~4R2%SwpX zx+b$VGD%sAhK<}G%yEt+hPe%^K1oQowl8ra62+^M+MmSz#(V+VB)}!uR-m(A-vI0a z)-0-}Sw+om2A+5Rj&0z4ip6?OC25UlAR{U@*zCwq9?%Ne=|8h zA$t1v$KV+A?TW2%L|1X-Q(iemE(357k%Ia?Z3lew_ z*Dji{?DrTAFvLh31CoSvEg0WIZ3DM!$wDFX zTvaC&3Wn}{l(AyR3LEbh)CsN>x%)-yMlBm5$ruNB9n)o4f)N3Q+y>M~-~Q6iK>oXH zSpH7t;Juf-o)!@@dcEQsA)&qztcO0zDQ}(b(QEpNNrqIagf$yXqUCOKux4D`0OaBf z6cftJVvt~=BjuyK;=9gtyjaq=2ER>4^n-oZh>Cv%AD-&C!?E#R9-aKN65BV zz0#Q%k~8lR`}o}LF;rxgL7In961&{+(R%fqvXwN7t19LJG@~Z8wuQ0~bh40vYH+3A zs}LRgCur17i~|!b8k3NrZ(p;an1gFyO@VJSKCGWTb`(t?E=b3MXSg{gQB)!)vD_IH z0uLHCK&nBN#J2d1>^m)Y*Gi>tfcBY2)h5^UdlfDmKX(u9tTmE82EmAOKy)qOBN44; zOF%q!%x>lU*v~L^i6Sweo1F7YMY#t;3synq+cYX81w-FSC)MqE@R4)VE5itRukZLx znaShDlvMv&eTJr{WR?lo<1C|AwNC!7mptx6CKxOsN8>b)G8C(VWEhmV2$qL&!zx-8pYSiAYI}Xu$4VWBR89AP-iRG$YL}-K-s3?P7=&9>F~FJ zU%pKjHc*o1pj$GJe>rbb9HIEejciCnrl#QSf8u@gn-g#DeznxFzq16wscKGL^gN3@ z4*i?_`JI@4E66JFh=#Y}FXN)!8BK0276#M%AaA^e@e9FjMlby(QBcanl58C(MX!4_ zMKnVto6|KC<6u$EIDI%M-=dz=EP0oO)}~-_{i|v>0cn<5rY-vx>u-|L76dmGgW&q_ z(0dXT&e+cB#e2d(rSNCB~1KrLg9q|nr%q)};*O%gYt_UVhXZpFdH zS}ezvYAv)ATlHaG|7Y{e(|^pv7JGI2rSB~W(IljwAN2#7s#l@w)cZZyhrRA|FTxPi zLaIm(?96r%a<8QBC+ct~yGn!J3k=m86;}C`8a*Sb{_1^4*VVu4W2}X?4C!yZp6S21 zAD5Xg?l}r=6pC+D7~kw_XHD#Cw85aquG;IyZJSm1dZ-lwwE+)qCWUYP&6}%r8VO=2cYCJAn)!ej9=54<5)YS*198CC)SI4mE-6>ao}_l%x}GQUI;N=%5k7{#=^S1+1{mpu8y(liu90QLNoDt8VdRiLBuh}i%)l1QrU|BHsCo4INco`wFm6Ke>XhPum;G?~ z=Nhl-?jVyaA8^vZ;iXRP0*b1uA)eVJtFBveBq85Kv&>W$hHollyDN5S;ZFMBp1Ckn z@dyT1aHjM_XDVo~)q~f*zfm=!{uV6MaLCm9K|b`DH?xiV3Adk4%ew7kTsEKJkl;qg zDST&`m}S_^iF9pWl;{(jegDUM`puQlZD1G8W^PPxP{A&zC3fOryyRg)j3X;fB%0Qy zQW)c!=w}4(!T*x~#$^fExf!}t8osOHy92&2q$M~^{S~*hrbGyJr4bDaz8k5{bwf&M zr8GqQ%2UGXhee`?O_$D8tAET~t*sZIVBAhthtbN=H061=^3ueOqXZlx&2hUs_R8P8 zfzVpa!bz@E#_X4=kCd!kr|jKdx20S;&k#A^PPu?za>3H_VIlHSo$`-<$@5XpUqcj< zJ6%~_SWH0O2MzvHBgL)y!aIq9Lj(^9Pd{6CDzxYDoh0Whc#t=B3a3%8i;aaKlj5-> zVJ@Sb*`zA}run9%ls7Ek|3+c~b*hHg2)!z)fnQ1(FYIgGPyiPL<$3h4`i_H!%9gac z;Q-)KLFuRsrV7>ppepW}&}sw#1&Gfo7@IQ6LRHYq`7Snz&T%Nd;|$&X)&rVzdR!c}3np`J+U)|n5_Ic?lIXAQ$r zB0rwtBGJum3^_lf`C=%!bb_>OQHJmGzV`9l=Tfre?9C3US}CLPE>-t`r8$7{Py6T) zfr`N-_&IxMY!y$qC1OEQHIG3}yOcs(lDG|!%KvvZ)rA-5%@BxciVJPq^boKf28Lba zn{I(%+gctfN-_gjcqy?p_YA3o$gKqiPGr-@VxMVo^3?2(wY(=m^`FsuXLOTPFMX@2 zX{@|GOGa;;Ql2S!`dMWXz0zJ%m?78z5n>1=3k|%U#G2oXSWjk`Ouc>>uRjQP{Q~iZf1>H zW4JVz=5NObIc-483{s=_;gT-I_2bVD9B0NZ-JRbS>hf-RRZ+r>0Zj7a=1d_P?F^;& z`xcvM#oNQf;)&Nmq2(j#`LCc=e4ZeAtyf^B(B}-1_k>ha*~NueJPicJ$f90?nfcPz z;?7w=Y-*p-H%K&SbVtaKRUVsBcE|&LaBG1hG4`$s-9@7%~z@Qw0N*A%AEZAxpn%NV#PI{)OP z$X0#X!>c9*C+|#AC1;_}hWQ>UTGB$vDyaH^$cn}EdS>Pz8YHS&!;-?RO>i_k&Ba+m z^b4&KPrXn~E4xp>nrb@Yupa@cKI!}Uc<_OU;ZNz|NV$8b`g#cX%&Rzh?p$3vUF?uv zrj~x%(fdtWVbvYLnnh%|wvk7UPHQN}4ehIjQPq=wXOcRa2 z=9NB-w_tR8h#FQTL`uL0B=5F;+Lg+W?zCH&HBm~VRNSEpNw9CLvz7C-&)k(%*PdK# zyBq3h5xFZ#%}qMhU-OdJnkVXWGebF_k_VKYpWct3YMnZ}(pI%Pfd5Z*R!ddyWZVgu zX_1HO;*frdqQ*|?qgcUoSFW#^hcQoOZNO6PUaz2=p85!hEbE`TSfz%9hYiWE8`A$Y zSZUM{!S(N2GIvGwV@G^A|0t_!nqT*uZe21pvp)YXzOihiQMan;W}_*r+cUR#Wex9@ z`0M$^fWKc9ByPnG**9%?^dbug-OHmg$w2@D;y0Up;Yf{&~M|;2;!5 z5{dd7V!3QDqkxo9I>bhSz78XK$JKffRn)m^hv`oS-Pf5*Tt7YSVIbC&&DC^|D=Dh# z`?72jUy@(Wd;j2#@=S@^FE)s zg?DO46I3)1K`jnK9p*dPy-7P%2{$CxW(FsowYjWf83s?N%wC>tSsq0at&{MfnH4t& zH(Yn(c81@`j8vWtnQmxlDLks5-$PT4hNppmh?5j990P zu|3+^ot05#-VbB*MzixDigFiR6xT!J2Z>_%mX41$1M}(iDH4qmoIv*AitkfmM-?td zF9%NAZu3nm$&2;Ffj|fSO@bQ(2{^`cL9%)wHp!}>jFxfW^Q_4cqZ>XaYmsJp(OYY2 z!{qpN-!Up|Vwwh39e4nz_>#A3#ROi_57SZQwXSxtzIR?F*KP5aRdy3A`?FPQPMtX( zNnk5zVai};A)D9DvH1SHIQy+t(H%5sg7;s^%(HEn&`$a(HIaD~O)2(xk|dmsjq5f)}6Lz0x?|`1Jkv+TGOq!e>@q zHt&)?$hs^G^`5`%5z-8v2nwKcKB>2YP5n5gdHUXoh&$%l;`ma%kOz-u6ohT#bQH3C-=k^=1*yK zpB+DOijev14BB!WTVSjGr?w4V7=8oqX#*BsNUZ!|P^#9ngs`r-Y95%nu%Xleo zdgVml0xbWJsR+$ zY}&>A&8LicQF#2rArTiJJ|uw5$p6NRAa%S*u|lJf57~@T^yxoTJ|*K)iMJra>9zEB zm~QY1d()dJA@CVSSSyEbk3pLE09f-7q~!L8Y=K|WFLkI}wuaKUtRH&W>kEln>|n^O z0B-=&xK*X=N&{?t4#eG>}Stn%v@F%dD-*rSD(BBI;#p5IbT zKZsr_){%it9!OgT1$m^( zZ;kauo?~Y(;1cazJVJsg1IaWPvmvZRl#EaEK`cCC)Ho*>j#PG5e+NF>%RJS{w#Ujv zl_&7KIe&}MP?fBRh`p{_SI73!w9CELjI|H%?l4`f|hx715#zE+rtQMdf%mj^f-B(Z7*fD_M zUO$06#-P#-_1|)ns%%LK9d1_iCaM(1*4?JSENJT zt8?Ce;@fAsC<6vHuq>#Mk3&X`A^N_r%pQ#caTgu|O*|Y(Y(=@)_2Kb9gpx|B86?+R zL{<1F-A>*XB%4ZtU+*q?!mV>MQeo}o+;&vs>a#mVB9$5Yma{;r!bzv`1hmR{_p?9y zewMd6oyh*FV$8u1M=XYD32PRauqmx+~SO!VVVr4?c%99%kV9&+h*)@IA69FN+ zB5uJGR^lk5)zhaAZ-1)?tR6dwA=Lymqy%y{_XE=$*CH+n@!ppvqeD`mZ!Fu~B9Pb?G3P1vs%uT$%C5J(0&FQzZXwq5U zqP7%&uJw~A?(>4gcD%UFl##CiAz2jhgp$gGM!*=)DqXpFuW4^zB_95i^_LAZz-1Nb zha1YEP`OS4y3<)taEf+(gjX$-faauuUMW(x@ZW>eX(_8lcVx0mB%Gm|YT zvv>d_`0Z#_u9r)zO>*y|LCm9}3b;pLKlb4p4BvVM4RU5ske{YArc*HNkT}IB_A~sx zQAhP#7D34GP2`@;?8VcM`@eO!imYHoMITT^scQx3<;D=%Sa*J)Mi+SDBpG`%3vhKk2k>}MtHsw^tT_;dyyE5 zRSvf^CzI;seXgbZ0+ zOnIfW74E8VI2GYa()DxZyvTEwS(}N_Dh1m<>*ZD^sc3!{sB7$;yszV~^?m~Q+%e0B zF#0uaQln&A52@u94E??|trRQD%ByuXVA2n=h@ktom+AiuRdAh&#}srosSh{{5(HLi z;FTHX1{bI20`&IqmHRQfieaSB`s=cM`h34S_tk^eh2E2_<1q~1nu~_wy~qG0@_Per ztx{%aC-gkHII{W1%v=>IgQUmaBJy2yj1LMj3Opc5$%nf19)&#*-91F#*9Ca{8UONlttE1$jiMQEW5;lgZ6rvg-=r@xc9i3`$k%^#)b zKH9!gNI&o(`?@k&{`TDFf%Z7I%S->r-|q^hehjB~fAfj_<)j~|ht@#0U%U}3Rt@V5 zy|=iz@?x+PBz9*^Dg}{s>lJXHIwz%q&9m5!yXHn_<9e!O+hQWOC`YgyCtq9mTe4A3&NKXGp(~0zWIdA59|h)jlk|7_ z6?5eGHe`h;^=gRk<>`z6<)q4t2_J_X-+VJQ*BWu}EBG-SxhpkD!(XU4Q4puItB@LV zpNIZjF$5SoTT)@_j)ukhy+^A0f94KeUiKWz6_R@4JC_=+clpR2K2Gg#yLowC{p7_P z%jwYYgYK;W_cv-oVTj%5GJjT%`z~{yKPR_h;#s7keg8i7-^Hu&zlYD?-+UvwyP639 zck%lD-{aJ~+k^1C+vE3lcSOjW1z^Gp&)Qr8q;co(7VDDn#${K+3pY>;7lr&&gCygY z$CGsXz#*+*7-5|qak7b|w4f1I*ZOeD9mE+SI*Po=2xUiwdwxL%w?yVTNBWaS-rp<{ z=SG%Ln9&DD$qv%JIFFKajUvH~RFkw2dK-nG%b;K^A<`Ls3XYMNj6q07t7=43)kZUo z1<_qSHn-rj-=k*W4!6m5d6*mJm>c>C6o?*MP%@%1p!KHC+@!?ad=?lh~GG&`O>0mGZHT8=@>ZC0p>hX13 zD_@c|V*aFa?5K!{lf~rpz0?(`_P@c@4wjT^S1-0sU3c;LHSTo&z(m%%v~P=P{EG_A zXM_j2EJXLi@7{)J{1|H`o*(}hTB8N>4Ygj0`k(d0q-4vUF?gINLB`Cc^Wyzx8@ zSAVs-SSbsEOIGpo7WTOP%-y%yJCcbRH1X7#Il)qe`CVE5L3uZ0IcYT6J!2WZl6=KM z*>A=zoR@N|Gz$-ETzqMAuCIz-Xy$ZW=T1o#9OPv!cg3A?=RdVj#5$2qI4jtR$PM04 zpNY?2%`4s*f9`mlS6P=2%D>BR(GiE4sn-k=I^N1El$`|0FA zV)t_ks?DukOpRk4a<4SiEXE5Lt}34WNsxmTm}u5O+{)>#YGAwtsTwuJ(lrxHRlHh^ zI&MWRmesxLDVBJ(48hTjK{fxD@(eYrGkL1N($wVyBT~(PwCZYVL%QqzM6_!mgIjHy zRXr)Js#dz_g;srr)Lla3a+c4JA~~LNmZeBiiQ0R=aD06&<#k!oAK|RL|GaDFowadV zwK}N0XQJh8*_)m?}6M29UM*T^o>Pi6u(X0kmJCUUAUum#dC5oyo&MuHPCG$6_|V1Il= z^aMZ5lKQQ$_Or>FH^w3Nx6|-?B{^eeW}a3^kTzpe8c|y*PB1gxV>7VzHdWX}sNL9` zzoVTg_+4H?fFqKqcfBja8j^+YS1E+JoAJ|`#jAVQttV=GG6NsqppKB~?24nnGp5HC z;{R1CRm#^5V_`oywbOem3byYAWp~0zI#-zAwe!hDT(pBqL9OdD(KlVc?ga|WxbrjI z2@|wvc3C!Kk;R2Dx!kV5Tz&JSDhem+CWd`OT-v%ML>+Mul~UOY_xD!?YD7^4ZU!(h z_V-MNcfAXV?-VwGT{N@MEZ(;QV*iW2FW5u_2Dq-xFwrylrFXrn2N;cw_W(aeEwW4V zE7cJOM`Ke~cm{_QGr(joRIz2CR>29r6$T-JOC$XC1M0n3HsVQx(uI8iWP`x@GeBgp z<}2QhW;ZJ}TCGAZuNGq6C%U`q@6=TYIgp$dlW{Mp46Zl;ypsc@ z>jNs^DMy)ysS(2l5khQ-A@U8lQUrcrB!sP50op&{OsPA=3&gU5+?_emev;5KAcUFu zXBKR?((r33^qQ5x3<>{pK~eq(S7i0#2R8VO^l^ct!NNmR@t1;$%3c7U~%|3jt6hsX3okve0s{AxcU%+wm> zC0T3>dmLP~xpf_ASDj#AC;9&wAw%W}I~}_6+eX70hF==;{+hv`bcfB@u#?gY8Md$m zoR3D3>VklexwFvCP~7dpiNrmkWNP!*RBt-GXv@JBJ=%nK=nt=KCL{NVqFqtop0Q*P zcxoZ>i0p@|&=00AGZ)BoiLj}D4*gi*nC2tK6~=y3r-Q>L>vB-CD(kP}ILV5Z$??nm`v z($OM1%y{Z5X;v~hnA|kQed2633ct}#pMl6w?z6l@(pYU$;VPx6?k9^d`scm#;e*pg zRXA;afD^tV>$)w;cS4P6VySmNcT6(4_18b112w<_|prXr4r-R6ncrf(=5 z@)P|f0<>q30AaIttUioz{C4#K`_JmP`R4Tj7xr5Q;NOD{^0g(apJX zM?}8#Q}Jc^KWvnb+@{~M1$M)5ZOQ0<_ftbo>9za6^SQ98I*@WlkbR8kdq^sjm`tL_ zT5pk-*@a7Qr%YeTiqoj{p6}U)YxQm{7WGcSoh)Oq++Hg+xNPq@gQj4Xro@}9<0DNm z3;A>Ke>CCO1Ht|ugJBH>dj`Xka~n)7>;#cS)sq%49tvrl9`wtz*NtQfYKa;z zoelz6T>ENAVenu?j4zj}7;jqE2|OW=;38 zlE*}foc$TGBf6VSSSzTNYijc>)QD2S2R8`KES|E7%YNK-KqawGv;r376zCsV4+_Q* z9w8^Vu}%LP9MksmiiMvW6`xyze%_wmiBl-ElO1#8GgT;qIHH4I-2OXZEIGk}v*WTz z_&q$nf6H=N7h-rt+OIZ30)$;RkLS@O(S0P(sRY(Z`P~Ku;pa>8euC15mzLmDSAkR0 zZ@)ZS3RpzMJ#Pt`42O}^;!y%;;L!(`4rjbhB0MD`FP|T$v>Z)D3LeRm9N9rM6!v6e zWo1$^FNJJsfDxtRr5yQT(u?0~^S?8ZO!d=$IM@H+4qdq@>_V6&tV&du&#ro(vd4u# z%oeyh5B-%eJyOWEq~J;9_wHtO_VE&GETc?u9Wx{GaxKPwFQ-EKcdT*mxlDhCjDm>_ znXk-N$<+dhkkxDEwW!^|d)gG~UHcqYC8i&oyl5$@Hi_xS0=Z(&ai?t?Nr=UsZ7t4j zs-sy{Q`jx%wlp(&bj3^6bd*K`*vp6vVuTZbHJaWVO}&oOXN-kKU}||^(B!-RDZ7F) z*&igj>gEtx_v875g;$z{SvLM}=ieRa=k>8H_R(!6b#sv5&Sd^GAxy}yXpMBSnlgOM zQNY*+WmsdT8%%M}QQY-oAZM=rMmBJbw?xp4#r<_CF;)8IcQXXzOB^{f1`C5Nr0nGw z6pbdcnU1Fra3NUt^HG_o8Tmm$v+i!u04`q);b?zwj0S*azdCvZXj{@h!T%*@&gl(* zznpVdV9ea~{g&SgaW_S`fCaTc+~yPXr?zw`CdRrlgaAiGBn4r4f=o1Eg0Uo_kIk*? zRN?dE&~lIsF;I3O?Ry}jR_s{cdl{hoOc^e7aiUDj;`s1&fphtOC(36T_6qnQbIkHf zX?_p5Vx;9}oOLB=M$!?c>viN>IqX7`;W}RZ1uw}GE6<8y1~I^sZxTI4g&JU8oiwmd~so4q0y4GX+Fb?n7Oqv}(PGjN2O-sPfe_ zxAQ5r@3%%3Abb0Ygh$`&qLQgNPhgDBK%LVk5j6H}7fDf+o)mHJLp_wN=pe9TW4dQ}Yt-lO}DiI;)Z$|f+<7v6kAq& zY5d8JGK-#mq0>(1C6Ri;^V6aZKh2`LV4W)Vh$ch+&3d{ubL3ah#cfCVMm ziqA+;!}>@`aDGq}Hwe96?G?UA(%3UFd{B2jt;`fw_t&MXhtUC*DY7EQ;*^RG4z(06 z2XEQOvif=`PB%v1vQ+bY^He51n{H6A6Q!E_izu=Hl#7#p|>qtFW zGp+(u@1=(SI$;9X9FgF|2)YwNbx!^&5(q*+*n(!|`@;&B-2PY;A}5LQ)s!4f2pCc%?e~5u5dld13H27=lCUOZva$W5Rwmpyj?I(; zn9Tj;bzF=xcpRMRIL5Q<;!h?0*x9&mwyTyk>|<~hIo!=)AE@QM*v=0UsJ|_Yrx6TG zmfLKxr5e+T_-LdvL{x#CmkRX$d1rb#P2eevlS{9uppAPR=y1D8q$%Vt+6NmQ;{n~M&3MQ6XzXWqH zU|3k8oM!)9s(}2+MO(&d4;ukl3RD6N4!9QjD;UzCHhL9p%XeS;%-R`eH1Qn|Yw@=;al9rYWsXYD z`5&TKJ=HM})e(HQKZ4EV0AeI?_DMj(hrMl21t7RENX%{Weji47{9cgm(bQay2s@1+ z=T~iuE8aM%6NskXDl1rVvXz79YRuvgM))ivsF z%I;41n49q6oaGEAF#z25L<`^|FpCL#R0<{?^BXs#sA2JlH-DC}5aSZT@61X^GafI$ z4|9(g``H?l!5*u~vCI1SF*MR3qwk^p1abV|f}GH;m4w|%zw zE}=2B-vyJbYNX$p{d^ek!rH>aIA}uZ?}slR-ldMR(-q(%BRIa7tw|bGPzlui_W73d z7(}F^Xf@*EfPIn7KCdjHoOKC3!P{=2e?j?8+`9Nu5I+VE?wYlXcqAPF4k5>qo_O}V zZ4+{W&3e0puYhWfXMi~2Z!?D(4|1+=REjCTUA-%C9+&qjnuil|EP8n#`P7!-gG%+V zf{2O4!bndi;6sJxzcqr)hUzB+ROs+--z4$B%k!1 zUR#pty;bwt6~Ta${HCwmrp$xvz}V$Zthe~_)7<&8UeI@gGDTJcoQLm@&ib>TGVT!r zG-ELbr)5W|6go5k*y7z*FdSsjPnlVykkG#i9TbYD8bP;xMZ?xnO2V~Lmx=VB_z?J_ zOxv{yvYoW>%Jet6z02-Nwq=}Wccrlo%E;6D#BDkXkSn>IeJmD$!^STCRJ-qKlzgr7 zJHt?E#(D0C-R#O{kULkk6!E=^DV7oP( zS(zDzlE%LmJbLBvb zw+8H(=dG{$m2(94F{(XXpVE@PYQy78p@|rjqO<%QGj!IqnY*Ij7+Y21>uYw|0h6s- z0FgZFJ4_y}dj77T!LRVeyH}J}h2bZ~rZ8B4Dc&ojRLb($@afpkkTJgtC6rC_m(q@f zHh2I!{s}NdK?aS;RNTIE)BNIwvh6*xs(H;hJ~>75;o)HU-T_4;4-M1Xc;mefO&O!{g+#3$(k~VJ zVC)SQd&p?b+yhB43o(xeZ-)FlqKp*iU76^+o%rdNMe;r4?N$a9lquXG&)A8p<`pLv z4R1O`;oOkjLNoE7LN2*8izPE`@q zWxM8O!;%z*Y1mkK=ip|RSf@-c!ne60A$QsdlDy^3Dj*hBtDgI**p-oz5_)_CO4TPWwBxL-aW z+f`B`O}Z9*hZ1_^X{?y_MD&XO$Z&SFivO5pV#whoWt>wKqCOyPs4d1qu{H_LC7;mq z(H8S}7d;S$8lAE-pGmM4X}<#JDn(b<^5Yq%(;G|6f2galDQDMKV$VhDYtRmh<2B4N z9?%(9P<70bv=ZTYMJSfZX;~#Q@A!K2E1ma5wIT$gL{O+DH=$klFx;o+BUn62_6wPu zk&NdT?IJUrHiSWyS^C~vS<`rDNbL(!ZUr%I(`5P7{91JD8~Vmp_bS!4L9-WO3*m-< zoMdeIX^s!1E;iWAv%svRp2weKI4PJAz~d)s2l1Ir9K%S>I%EL+QLPs^Mz%iLtkydukR5{t~- zIT2hWU z#`EYw`W{l6I@MEmxvABvfg6n2e~ObD3+2) zAAT2pxWx)zm;=?TTf@lFDKm>sXyGc@2qxsH+U-$A2OGw)c zb#%d}p}(x4QZSsJ9WgI{ZH-Wb_E(Ix4~`Wlx1`cJn2cTXfL1RXI}6)}UueAkck zU&rxgo_{V3(71wOuHT3()Qg*&pDvLSwvBDiCIuxdlJg4zY_+7=XoNL6v>8`iuxrsW z(eP=}ffQ@gI^0cAMD(0R>{T*HCK5LD`R7-tAeqSStY~1ZHI_HapcJI|#GW|TuBqI< zqr+Yrzj31D{zuS05zRW*X!#*%)d}5>Zias{XvWgeMWf>#HR5yx0Y+EcX5x=JZr>(^ zkvCX9By%G2#s+4Z1Xc#j;n27nx~x*Uj>?H7=8JA&nKsc15v?{+%vihXjlG_7qdr|L ztBi2Lp5w(-<;x1IIIX0;YY+tjmnUe9zZTb~7OW{5N7fSWBl9*;;_L4^j(|fQ@%X)2*UrCd8U?4K;FqAy83YowX1SO~G3kna+m;@gIlz`iPyC#J9r6 zADQ`zVXryhI8!jLZ!!OivAlvfQUgk8oJX&ygIiw>EtUe!5>SjpSb=lTa;pCoj<|+I z5b<>MiFihaC_Uch$Mr%LH3|O^Sc0#(>t?(g-*)nZPAcCUCuQ1#SOucLh8U>?6 zfjH)*U^0H9oLW37wkXpeRP!f>)~FOPGLp9x=cxuY6)N%PTz4F56eTG879%^7yCOTV zhnjIUDXy1wa*d1Kv#K^RcTp0@a&5VK#9_9a9U|p#H2zY$^&$6=!( zR`!_SKMh#xTb*oCU9V&UJKwo!6Fj#EDVwnJfqGRT=~#dhgiW@Y>|J!Mtea%__$Nj2 zR@otI2eUjIx((UoE7=@?Y`%R>HC`d~*&Ok;%Qh+j?QJ($06;b3%mXW?$NG-kD`1#` zkRK0kUdgkpp#DaoD&srRu7~L2`ZDgrAH7^uW+Vt5DkssNzK`i;AKPdR8ae$4L$YktHD=h z1YWlgplRrBBy{oaPZP?c! z|5WAsNka1WaQqFP%P;|wh=-fE!{&GIvNH1&#Uqhei09YhL$gt5{=VJ=?|dvP zUwd58^1fsfNga8bq~g0pz53<{+jD1KVa=7N2i@@J6SepwD;&I8+J+`}H1i2ZhT|w3 z!Q#+y?-kcEm&}U;O)G6*vEAmWkB9r6us17JVFL|;vR{F4Nw3h)bm9oUa%*jlxNTLBc~#LD&JVcX_?LuMEbgf$&xl*B6G;Yz$4Y)d#xQi zm_@7-IHfnq1&SmrJ)%0Zxu#(=kP6_wvouUIP|p7rW0TqTAe+mJDdju5Yma!6Suun1 z#U&QWa|x*_NlmU?iSkYOg_$YKRYpz z+Ma~ck;L=Fgzis66l)*l_i5~X$>Zj_NrGux3y$2P((0OjRl`|yB zIH}3_v%F-%TQQGrj+KF;Yu6EWM~gvWj2r-?v2}XU?YXKw7!7r)iv|8UQ8AxZ_>j6l z`ddw=D5l9YCb(PC!Fwho)WDv(KN5%Neg^JU27-j-UcXw*? zdR?tgh8Z7e>FKpa8-DGdmGP%eu8AkYL}=4H2$-l`a_^JSgJ6 zL97sVb>Fq1gMDeyUOB8y}Ko3`FkjPX;)| z>p`W6neaQtyClMH`y=2j7ntZ_sO0JQkyJJ&JHK|9oP5P&#<8XIClTWr)A0Bk4kTQF zRojmG@As91p;3t(_-eoHv0{(@~y+XIg9GQ`g^FfmSB9tV~m9&8ti&dvnEtR<&fuQ2bsWP-F1MI8O6m@z*&5 zw1;Onu{70Rs`8$c=T+ysx7JnLuwcP5u>8E*^i`%*=5|m#jJS_oHuh<1OQT4wYRjJa z?6JDX-*JkrB3e6M)K+E~S=CkLIOf+?7x*mK)s#fi*4I{~Th-Uql;_viziO?oPZqmA zCn&*zp;g6|RF>o z!Fp|%tn~EFKm1}X2Uu~4k4271O^yet@R#o?ug$YsZ;-6m0M7m%tAX0ReZJ*GQdU7m z2_KOJm&EFq?}E12^qcF7lpc|Ka%05bP1*&?JhuRgB;auLV_50-Gg%Gu_IVsoBHOU> z-FrU-+waNp5zdpb1nZ$QqgA{GHV~e)1$~ozXP-1{KytFR$`hqK=HqK6@7XiOS^<%upIRah^6=9X0P%a!^5fy%dCKLetBx;tul;U)zaGn1IKfIPr z-LI|`(H<+@u=ml0t!ougyF0+(D8zCTR1iuTi9F0>fAr=+l`>2<%1;zbeBWf0w-e%f z!?De@m63w=MjRhug2jZn((gJW!9zrsvw{R2|F_gw5&YO@%MAwri<@jvoz{Zs>`rK7 zld2fX3%9XDl4Teju@ zWkXbBg%eqx4(odOypy0D5_?maAmhanWB>DqSW6m^6ZwLUKylCh&LRS?xOgt(taKhZ z^E5udE=OnnYNT*O^z)N1`yXFuK_gEJx#SL>PKSIKDfzR)rEs5}gky=8Vli+l;=9d6 zv5J<(DgmA3KW5^T=4ENwVx=W6IY&h6G`!~=(X2nHs~7RikN7gwos3>tlc*MFPb>&? z_{3=!yOvXI@2NVa8z%N8X^IhAs%ztAlyjr2;T%>6YM`H`Q=>YjgTMBMpS_4qBYa^Y@7uK(6~Wp5Qy!Z!h(wFx zK^YMXca8@DZC1ePfdnu}iop#hQtr4)^G;IU_U!&eO}e_Yagjh@=ZGlEFM4SY$@{7b zb2Q1>^>d8~A)fL# z;(|X~?CtdwxTRtN6R;r}W~C15RFeCWCM{LS7H@uI0LBppd_G~-UrPtDtdpuZ-p3rY zpJISc8z^k6KlVaxy!UnFT`7WG4J!EwV!MVb@y!D@YnbdFBux8EGjYp1O$4)5Ol-Qq zydsF76IfwB-~QihUE$^U_!wfv&P$(4aC_e(!J8nc^u-s>M~5HIZJCp`n@BPXkQwJ< zra|ufGzBy$Li}~F&a2o$I*vbPsd`kwcU9|OMd(e)-YO-0qt)WLo9T4o0J)vnb2wJx z2*KZ}dv?&Xi^)#ZT-pK;zp=2D@FS^<7j1nZ55L^=roc-%Mi`4 zt!}(1ki+|EWBvehM+ZD<{ewy-zeChzWL}PXG1&hp7Pi1*6s#&{a8*OmPP$0ljQuq@ z95cuqc(ASFTcLKK8b(Suk#hC^gsKAH@seT;9^#@H&Vud877qJ2!WFOkACfm71$(Bl z>}g8x+drBZXct9;9(BOpiO2q3NHpGWr}IGD!=``lLG;~;( zc-P4x4b5qXC9Le}W&3D?tw<}KnB%E}Lu$k)dMf*iZ+BwKK>CUkIY98CQ~^0y;bHNY z0`qr2`YyC+%rCVko*_!tKCZH`u1v+q!^Y<+fnc+dKxGanX?TwrK@z>XVXL+` zh_8X5#_PYMeq-niT?5%Z8kS6F?4%M*y6<#QoL!eW_l%SO%mT3(fYq2&?THwq^Rr=^ z6qEzl%t-263)NvgiuNdS010!A_mYcxQMU3s3&o~X&dxfsc{B=2(&w>C!XrnB7xoj4 zVb01vsqC-506sJ9lmRX#hDA|)1K-aySAaJqJe2Db*p4u` zBOXr*i(OhEyW>$BE*t5%4iw*kUhgIpkoSw4drB1jOQSHY7Sjt@hD+P`jCAj?)G`~huYW(?7(N$?>ZfO)hAS$V<#*!T;}?p8l2YZT~2 zzPvzlbgl#9utkugCGEQK+!ykqNP7lHrAjB?`HFNX0vFM5s}x~T-2WsV`y;m=F~s~v zC+i8uid6RtYM#Sx=dr>ehs6lY+AM8G4#JD43#=1MKV6g)jP&k}GygGa>;rwQl=#>P zeBN)wCs<|d2qF7rz$QDp`PXStbu(H6=J*-JK#pOY+VLJUp)(p}SDO@QkGiA%96`lw z>Cyd7!o^XucH;#x20>io9XkS=M{=wT@0;3g z8)=L|R=!ia2^Y)yol)HDQ_FvIKo~182#y2+wi>P4RuG%yNC~yGE1ERc0XbxmIgDTE zXw{%<-80-)#F2Eul6|(ZMKkoUUr7KqD4@Bhgs9WC$^M;e>*JYqM_XS3zgE+~RWTrd zI7xl+1hoG={rs|%CwmSqaBcK!5n{IoxyS0dm3~){9mMt+1&x7>TVkwT@tM|C?G9BR zv7_xp_Z`M;9VgR0Qfipfi#!bC&`A^|+li5asHjS_HR3V9F&0IBjVM1HHi^-m58=SiVk0Vzo4ezlLWc+p`D`b7U%lMuNAk-3Z#8 zW?OZ!?#=ZY{egj~neY6MgboHJ@$4rjg85fJ_YKV}CCvI9&3k2_T#wFgDbD;om-3I6 z$~~9s8^^yKEO#G$O-QUAQOW9x5@c@3>%mitC0yaezVDr>Zh1D)^9?jSUG|w)^;ujW z_|g-AU8eo%fRmH{aT#l2zPK7Q=zGYj3Fl8Vkpn_=fIA#VfmU80*q`g1~O z&0$CIZ;mk|FMs0d+g!vx0TCc6YE{j9hOZMe=GE2;=ym7FiDI2|ns`r_8C4s@#z3yL zH85iA11Ak&qE(E}1cJ0}x~B>c*tTNaLV-IRva%;*OLQ}NMH_i~=oXraQ@rCx3?)M3 zmEO+9Qwz~kbfc$58zn=`-m^{KLLDvAo>?r@!+^7*+`1BjhEhL0SGxW2@HnxjS6`c52mB{uudxAK_S~aUiw7|JYtYmW(iuSjL!k@WkT9 zNB{ibIli41>U(r+y8VP&Se6cAnDJR$0KX9h!g(S%$T6;Y>7ZNWdl^>pn4eYlt|D{G zN%y&)v>lWD@rADg_QM^{=L9R}yw~dsyhk>~qiNwA7zXlWF;_X?_o8c~P1g?ooNSNvD zWrrSFOxI+`ewC8gZRIV{sJmN*&4YV#A0$JHhubdn_Cb6S?xWzMOY z34+Z7Ar{Ekih9+`m&9gc2p-Mob1x}$_~tXN{WVY1ih?;6n-Z+%biO)1Tl+s1kGg6e z;$-P}`+WMXyk;b~l^*3}Q>ky`zDW8|PGr=we-dE+WJnJ3cKrDB^`Sb0kGeKO zUEEMTtQ=NBtYIfM?mw!2g?4M7aMxja=Yy&jrj^keb?O6$Vq`RXeV!%{ggn6y9pLNn zs(l!r|Kv~l`GEHA-H=2qPfgWkT86Fz<*;w)XvpnoROndZ?N~8sS{e5*wF~@YfL=-P8f-}XI z?Fg#XgGVbXnek1MD2i@#Fx`xy{3jrI7OFZRQ9b|Dt(lvUzSn={zfdd^jjM>MJ&%}p z4&jU?EyZ{&m&0c3cexEOKZVT5uz!I9U@3=CXB+yUIf#HCfB}JyWo`3An+#9 z=5 zN_5Ju%<7^pA3KR$xKKGyevc|$vta@A0u9T7ic$LdzE-H9<%m95+}7}I;nt*D-vf7NaNv@k@3?<@40}7 zIFi7iQIFc`cY_0t4F}~YmLNBs8Ld@l3aDx8of9zdmi?C=jRDGl8Nl5|)k)@fU~5NU zIoj9x5YT@tb{fwX3!(J1N(N!iNbWwP2>|Gf`Fb>r|I{cXwhbg^ zi*={7#mCN~-$SJ_El0+zh@>9%|4Yh!!jBo~8M?w-PfJaT9tgSlw+cPo*DGrCunLh#+*KqyLAr zw~UJ-ZsT`ngJtQZ8+Iw_?vn0q5RnEEX#_!W=_REFB$jTZ1Vq6lqy(g;rKLn#RD{Fx zJm-JTd4FEd%bCyI^ZU;Iy{@Xh01&oOPBbA_5I&ZZQbu<4l(T&-d7iHb@bb}XAV6w; zr_Mr{jq@ZkB-TmBGQ^Ly{tH-29rz0!?B)I_YRbdjdV;H{g6tuSHDW_b-O=(by#{iJ zCr6|aJ_U4S?WZkidrU6l4maPUnTX)_U4IH}(?=zThKXuG<*ViScO1L_A<-vUlo z;D;!X^I$Z6@c1!)510dLk2esOktj+^v}#fd$cJ(jk6iqYH8nWS5&oj^_v&;k!M>Ng zlhI9XX4K;Tb93Y?{xvsFAm&-|AZr|lySWu5L?6vp-M2FkdN>$K2kGbg^11RPWE=KE zOZ;#|+&q$c(Q`4;r0fz*_cD9QiUEKrWOw6d)0uN4UyFsMfNJ5?CF7MNXE}PR+B`|; zljE>q{z5G*U9de3K#8{XpAeWSrZ@gKsbS7Mo3$Pvn4Zas`qLrtRbEsu(A;Cbk5nDn zH=eu}7cp89|D=@r1_#{_j@IYxrE>4<_|>A4-t|b}nto@I3iGfDObOAnjU+~_R`8ab z9X8=xr};$m6TTDfB_ScSk0x_!3FyP=iUC&rtd7N|akmeqC$PunS z6jj-vV`mpDx47dOyVx@I;tG|7#KY1RnUTHMcHJ#bj-SvLPM=w&4TFoPxJmrDW;#nk zw4Wr`y+7n^yInQLVIlme$v`%Uw9N_u<6B|TXH{vplwJm95~GH6p4G9Q4-QNK)Jj?_ za5nS>^Vd^0M{2f8y2QmF<8QxRk1(cq=C|+M`*ZBQ!4_kVCWXhWpNmBy?2$xa$9F2< z=be&{S`2#L$PKvVH}P_RYR(F8w^X`~^8Xh#hNG6UD_K4XLm7C(x$_c9=&djivGFyW zy7{18M=!o8U`!AkwS@xH+bF7lFh>0DfF({-3@D0qfO0BIVOF7hbXjJjB%w3uqe;0L z3J{h?M^MUx|7D!2oIL4+AP@Vv(Dp~rYu@#x0yCudKP|Z zS$Rq3Ey|&B9|}O;Fhw#$UK3ONrfVT^2WVpb@CEHIaFD?wqif+<0lGUWkdbi4OW{~< z9i!wDqfrklB6Q3;__q99qSr41AQj@0h5#jLi`AIB8e4U$Tz;v8k7#Zf)NcAxo(^H2 zPrJPS14(%POq9sDPs>i0GiM)<^q!~8{1XaIOvq(~P@^dBwjx9loXt*2*@3E9thwggs_XB_rxpe>^IG3{)sZp$pnjLA&%+t$qJo2W#_=AgSs=XW2Mf9h4CI!1 z^m%&f3MFz2RPYo`jlRLfiWbr2N+8Nn;LJEjXXuP-xx6aqfJ}0bf!JBkRTYeX&3c zkI{~>F8MC^9^H>@B-gwum|#yPB0Uxg>pS*fs0I8*CQp@>oL zXa$wEhe@9r_yj`FAyFGt#VNIj%R_2j$e@aXk1@V>Uax;W@1dFs4Z6PpM8l$?fl|mP zGfL=4x%Z4hMLeTc^;^yf3 ze|eFhXUHn~0mVHgxYP2SVB`f+nWsdh3NxX~mwd~T`mFZ>x!SvQL9PA2VF5L4QJtr1 zA#TL!JR;l+rV29wpE)U-GE*IpbmMNIl`zD+noi86jD=f31RTEYA$Y z-qk^3ozo%c7__R)*-GqFAK)}p`oROUrY)S*Z@GekQHeKO0=F-*X2|3p9y@_ z+a>wO3Eo}5O!4F-7GCQbq%+O0$l>Xzuaw_w8ciao8ViIrg{{}!DC|pp`%xjb&p*db zSzYA)lbj8x5ysz5tDgxT2twa^a^U==617LO^@L>$4}%YE#)ci}AS;F9gFP;rURKJ# z{Hx=2pj97y((|2A>8aIWyFr;H(JsA8Bg+$09C*XV9}~1 zB|IkPMi6U~v38*-2sr@n$aIw-=_*5hK0zZb%+&?`ZHoO_PR3^Jq9hRGObeeud4mrO9U&2a+j2;4tT}UuqbN;KZTM@%qDWc_ zHg*%X=1-L=gbY6)vx%9oOEu}kn!2PZI8;qIG}AbACpio$I89ABEz>yfO>#b<;2N#! zZ$dKe6c>3m)IgDhd#Iase767KKi6uF_Ip~9Y@|w=_Ik>WO`NABf1mwCrfcCftr4vI z#-}wgXHmRr>3OkE{E|hOglMgK z-^xa)vBPn&rk8EP`S&M}*gl!Sb{EcsJs?epuPABqC1*#KP*_hQ91IFWFJANti7U}u zfmjMsg}ng5xf_5)D`MO1rSNuBEi@5FoOsN_28&+*2BdT5pAZpDvGT=q%C1X%++rGe zRC0wczf>gt;xq44)xCvq5}R%@ykh7n-{Hi089Bi8diF zsG|rtwAZBAV8s=nnNJesj@%Y}um9qtVmKzUAjUU79+hkIQ~nC791Wx{%()Ik&s@zVYmF2~q``du50_MdP)Yq?H?!4^ zxZKlqq|GP~riVLEpC{W<)9%(!R?OwqBc!v+M8Qq!*X`1Zxn^pn{c)=J!j(g3ox{YD z(*~^T62awJtV|G~A66VDsiO0ejVG&^r?l6vHlppijIV25C6oh@q+iS;4OS<%Cz9`rlvhfqOHq}{?v;^t<}d@7wZ!R3)meJ%N=}K#JuA70 zDVZ1Sv3gY^Q_!pDfOp*#nIl*%*TpWM(Dk?swxdm9E>jYRq_}Zn&30Ex z)mHt`Z9iDS`w@@1N1gA;ZNJ{zvX$Dp^DVF%Re0S)_D@)N@~tpwuaKA0hrIPWeahpT zq`onc_WNW&NPTL2G;x!&E}~X@Kt(H=Lpw`N?M<-(kHHLfQp7mg=IwXQ2(=s!f3`%Z zcKJi?f^+gZU7Z~j+d8OjOO)>AghsiF-XL^;mD-q^T9~^9HoY3OVp4{b!dt6qFs_|_RN zRw7ec#c*DEwd3Sn>&KLio)2xjC39>m2&D`bc-MV|Xi4wkZAQ2}=D#VnO6Ig4&s1F7 zwl2N}S?YT{Efw50XCqVt5A$V=m8;eJJgisqCU$&KKkk|HxZ|)GIEym8f|@Xkf6E&) zq8qg^i2OQxL9aclc;O-oQ~I@H!e>$L!oubnHR&^?>4fc(qWP*kl;O(wtB9k`OL#l< z{TSPohSO$)UQm>?(U`MQj8%NGi=Auese!mB%&opxQue!OpqgEwFPoQC{N-^G;*0%9 znxJoyCc_tcA84IDIUUCE=(;2TrZ4wbIroT>Lfc@_1%=wqVK|;jNRaB}k>L%j#~115 zGMMhI>ge)0c7|7#Ihw}DPt68Jt3UC}{AfE|pv~zT78X0(!EgimL5%M!Z~O-IeK%>J>U0zm<#)3hWDF8$pan< zTMZX`Wj2m$6-<1?6U>eu)PVnci|$DC$@{rbTDBMBcZ`%0hN3XBHCB#cbeQ`to(7<2 z!4_;wmL*Z}=hLzF3*VowyM>*c=^bi%6I#2|TC@`aXa*jO_Dk5m2#+=u*oqQAR+o9{ z!q+f;zxwCBRflBJOfMqQ^v zFm1Ys-5>#Q%}saq-h2W1j9tHZv{I^FMMrKu&ueKXSAp-txVW#k6yo+@FikeLuBozL zXnHGx-oEv$V9RK53zK{Jt;Cwj)R)@)T{glLiMSa`b|MgdcAU!gFpYPYdxw;uy~wnE zhLZDj)3H^z*!jaj(ctk>!S)j+pWo-=cnLOa>w1@EUjL(| zes87$f7^keyn)cAffso-P&C)$rcXoFL1Q7thU z!B4}LlFeeY=i&U4-e3FF`gDgs+Y0QNyl;QhvFU$?iRvBF8B0r7^<_s$K@4k6$r{q- z3Sg9&b0WkVd0+{57F##%2`mLjC1L;z~%iK>yrPLP6}xFOBW`*6edDQR{>)7M$=_#(`^(;cNoC2wPQ|fKxq_!f z22_S)K(*@Xu0gP-OTOnV8HskUHR9>k25mtQhW4dyqh0N}+{yPV$$oiH-Ka>Ekg><* z^GLy{X#1$nm_se^=h)S=g6p$hR-NiL_(SdI`4Qf;TgUQNRP*~P237rn!46r!1&hB$ zX8!%t{4uJ?GKiiG3BZ}O8USSgkC;?%u%W0o7QwC)z%Begvy+u{V~Hk6>VTS88u>** z6wHB;h9x@ypr@AvPwCJw`4>k^GYqN1IFe@-P$=CVqEzdpRyyzf;g+hY3ZoL8e4V$| zGc{Jt9?Qej>*yQ)3sG%28o|~La2mq6kxF_W@8C@qn+^Hd-}<2DI4{rjdXxbel*7Hu zyIduic&pr&px$%zwM-CA@KeqQs3wpFAmMXq?-pM8p6hL>$cDxQAi7x6LN3122D{x8 zgC+ZWWQ&sB`H)TAO*SUTY;-CaAqJ))F>j_B{qXMe`*?|Np+RTIdFg)}`x%}+5rxme z`oY+VMev)#zJmMjivgBjbni-_3^;%mJZu8}BK$980e8I3=%e5Okcl{F22BPPh-}io z`1=1f-h(V55nOOvHZC>ySgX-NH>Y%HpWCnCdh}2slr!~1E5&)*&~ySp%+F| zFI}4MF{+(&@K%+F*=#k9NbVmrk89LS14#!PMjD0TQW>y@1Jjqn*4UiA>bkCw*vR02 zrz21(3-b0!$#K&4g+Jd-sjlrHX7-ItxW3F7oM5M`h@^6UH5Vb<8f-*#~FS$Lo}Gps|zT}&0G2Q&c` zFQlm482|F)@M}0@>HF(Mo;624%GaPA#K-9Qc|vlojGkWz3W#OmU#03bhQ{?y%{sq& zd@=7{@ngwegSW=~>w`DuN^?%S)5s_fU7r7Uv)9n*DXrJ#8s^Sn6F7v)|I544AIrbK zg_8*?X=a7g2B#B_caJLeNKy`Mm%j4)vs-yD6DKgJmD=Q<|AOVuj+Q`PNFWzvpn0k7 z*WurvI95ffpQBp^>2+WoC|!B$<`(U%fw`Q&**oQm!nMEd!2~npvAlBw>~Ku8J~*raRw1 z!ekM_5FW!i@n5()IwjcS6g2EE@Y3#R*9F-~Y@OvM1+zGc;#RYbtyCtaEKlKO7@-T@ z{KfRw%HjE8_NzYNw$M!F$visOW3|vkX7H~BsMxUrgdgz;CL_QcAZ@~<}W9b-f8rkUk+48E&w#DO#hg@jb+MF->9~LQ>a%)<1 z7Uw$(M5DIMpiLC(QK>SDjU!N3g7AP3Y^cz8njBow5+#YHChwM99-VEdm@}MakML+a zfN_yMQR&urLBx=DlUZf?!Du+=dc4+L0tBd3p ztRC;OjDU1)`HSg?x{7S!17S@#N#F2rmTdB>B+jE(of+dwL^fHDlcz<9e7KlP93Voq zok{*r$Ev`c`8aRg>9RK09_~cv8z04vVBD3Lqr63lwy;n07L)%24ZV`(kXzgx6Dy$v z*4in60iMs#Pax>COHaJSfbma8c#hL|52wqGo>v0fbB4NS8^kK@wq|cK%49vObPXSq z+Mqc&*ytZ}OI1$g^A_E)10%IjHWc{>QLxtjR0niowOuOx>$UDuVVfimy*Cn7yTG<( zH^c1F(p$wBgEi8`gt$hX!0Pvd4$tv|Yp0q52RlP(Qny+v5weRWxv2?+FS#EAz zojN|XYHij+Q*VYwsp1gVRRusfe!ZcI7QeyG<`u@R$huQ16c`jGI-%ifB zv_Jz5zM%chvFz8f^-D*hZWBhz-Z18n1J~Nr`Lu$^7tKp^jSu(hnNP(Jzr|+OAO52| z*)YHRt6O!1a~ZXE$j(C!~&mJN+TBfPde^hkU?3;xu#m+jHcD7 zCp&Ag$QXFB5?hx0dK`Co<$64S>yBdrUMKfPqWG+PNdm`;mQy0%c4bK%-c=>)rAiN- zbE*~>4_m5^WL)V>ga6JWi-%j8>MC(tNj6@)Woh@rc($|esASwjlN@S3h^8#2Uv(&X z7qe(PWxVq`EU;XAH86aOJ};^*I=0Bjts|~5?@T5*zsTKWCI|a@s5~?Gxg@Q_vm~4B z#ps3RGqr&?F2pDF0zcmVlDN2mw&%JXE1yQ21F`2U_q{HG)0Up-GprN57)0@lv#YJlwB zQh<5sawA!ootQ(3>fD*FTZ!PR>C4?~c_%c8S7`ZcD)ab2Y+Q!b9#871g_7Vax3!P< z#JPAg-Yg#R{T8{mTIjccy!*}<+0hR-D9{|f)nt)E2Cg$@N#iR?8(^t7S|s~Ks#J2( zt2aq{Id$XTEoU4a6|Rs&hn1Om_Lt-gNZOftr-aB;Oi}wpIzTSh${{nsd66p68?M20U)q3ay}rqmar-_ zI~)yWa3F(O^so+TF>D-=$ID8mJiXOvtsa6fve_vl2Tp@fJ~)QR)d&e{2jlCzs|eAJ zBjIL92s2!nz+^mvZhDpa=1RG}!U4%#!Ht8-U3S|=`2bnt14Q)}x0*20M>4kd5LRh0 z5wM;>mG_C3T_pUQb<_((fJGIogm(Hco(R9}{sx;=kSzEa<4=GiSrQ?V#1>IUMGk^) zC1q5yeerMjl)yIKFPF$UlKrC`enc7Li+lF4t_p8x!mJ15vBqw<#~rAMPx5)bbLv%l zBmhRDAr072K3uFIR5%=Di(*|O0?1B`;helUir?+MGvI-D7$`EUxpqt7oh6!XJCfLT z-%i!2O2?vuBCDyiOu%D{kAM#&SW{_! zMyvnE1;pI{>HX0N&7K;rC@$OMvuz-dpV4Dj#aALi*iWRq`mn!BI z^b7PY7e*c3!b&!%^q23ms8!#UyaxMOiQ(A3i$qKio_ZLkYeM55F8w55?MzMg=G$59 ztX?-mfvtXOiT!zS85YoWz6H8ljV8ShUG*>G`~H0EFVVl^u?nzq=?+z*;r)dY#4ac1 z?&5I_%8?zGl@hy51q`m6JF>Rx@~bGWN_V=Pc!{7_L~L~taxtyXtt;^b_mFY^TCMde z#yrHl6Qn$)bRKnRtlIqwaMgk#5)AjFj!A4K3Zi<{L%AO=)1)P!8gnU1c zq?pu~P6PS+U4(DiDeO)^L(F^>epaK6*?uVg~n)eUWr7HIjDT? z6PMZ}gHq}r>OTTRmR@Q#wBtW?cY9IQ(QGFGB=B=+m2l$`8lmwhFCX5mI(7;HnPN*ZM-ghz;sbrY3$#->V=`yLum|T-xQT_!qOF>sc(tIoqUjGx;+m_G?lIcsSh9kt6sq zsxN9ghl$`XtKp9t5W2sK1;yBajuwN1{-uImz>qI4zlV)c5gOrM*rhzWJu&`tQ#{58 zPVYcRHDFkC3t-g)f_Wi?vpAHZVB1FT2Lj`vH?Yd*8VBus{!e12oq%>gpLCw*Z%Yc z`-}9x7q`emb6AwWUzEsk)PwVI&|HKvMox$u@(!)=nL0eAPZx&u$w0mU8-aU`fXAn> zi&#c5F2)O^eY4OWG=!~)lAl!q^X@!s7aY^o&I;D6uJpE#J;A3js>tN!1X^KKR2W%GpA0xco6o=3| z;g2^R!V%FFa|VD?0{ft@!cNq>MqGEFoQYbHiZJHS8D=g!X(2nzF`H5b9&<7fsW|98 zN*DDTL2#Cp%nu|_Hzmc1ICk|WD_R*+q5(&&>1we2nA$Y{UcOvggrcysm1#srm zz(Y6!&n+vQqZM;BPE@m#jEp5)zDXf2HhnQAMcznt?`Mn$ip!i58;*AbdOfS4JM)C# z*bG8$=5iL#8jHC5P{TkbW5_7O5@*M1L>7OPAZKl66`Ap+!RYDu-Hr+(uyJNgkmD__ z)(B_)gwu;s$t$`cHC4k=C*WCzB?1v>f8*|%asE^|03!BQN6wt4a>@$=dgaH1sGM>N zQ4JtMIWim(UD>;=P-feggeqAB)pQi8^Qdd39KXysrBm%3Zh#`?Spb#v0YYNR2~pgv z)fj}Rna@?#&=d#At^u-ubn#m8dy6!>-!y46KH2HHYazpREV$hLIDi=Xdyn4gEeDw1 zwKV%|sYlkWGxbzru}^R8M%;&NEzhhJnE0JPGo*iuS2A`YT~1MBxDZb;GaCqSRlft< zKJ(9cTHvRqc^-hEIU>4Vb&adY;;Gd6E~y@qqxPyl`?<`ka%*S#cJE9VY4PtQemO?> zk7L8w5xX1qU=b|d9~baAXcvx`HBNR-tCIOt5jO6Eh$^BE@nx1kK&?GkeT#WIiUm3l zA>yWNeO?c#q`T5nhheJ0{$zh1%4X+!rZ-O!j~2?k87gL^D*{6*p4x=>YO5JEs|DgJ!U)C1%binFh>ieK`_sz9 zTNYsa6XAeh*o5rOxR!raR$}ZckT8~i7Lv6*E(6$8VRd+#1dz6 z5KQ}!1)+l}kLzmt5~$iW+W){hhHKtYmJXuvd~w7(xcu9-oMq&rXlt@h_HcI}Wz5Cn z82Sdty$0OHgC9rgfvb4_&Hx{WMkbn!#f|o^xtlZl{dX}GFofK*X1o_0jgOqfTdujM^<&G5v{f-e1*rV5{GDFlhtDG zZXLqk3LtE&=YFeZ2;h$+Ib|p0G$QTkGmSVUc7dwmBk|`p$hI4-EiK|JUU$?ic7V~) zr3TbBjT3DjNl^3=yV$w?*LZRoH~pEC@SyUN56FM}xWiSWRxLJDvx_p%nB~e?y5%u`3e?0! zYNe#Ji_n$$2!ekE5xDB%$GxLO0V2e`f>#i+4?Xfry;c*hFCS9iAK?!P8yQpH;uJNn zTbdb~$UHU4wTAm{R{I8W`z)S)x>E#%_z<6jP%=gld7|CiLkPtWddmi1ST)@0D_$f# z(!)phdyKqr8}GNWy)_Gx6ZjD2>f%^YQu2$EsrCbbR1a3-$s_rDFwX|!Z$1ptOyIr{ z+0p2|Nt7STupP>JHk6$=l>1>QZ)vFDYRKY1;%+bbBzU;Ib`U^Hen&d35>e$fV>YPn zimb~u#J|hkFSeLQJ?8veB?o3dcIZF1c(sV?O8@-mdpr0fwgDikdL-p_Jn}JI1JX`@ z3%hm^p{O1iW>iJ=)}l&hhG(Bq74Z>$tQxgbR?D!Dp4?Wqr*d;L)2L%7@x;PH5pUS> z#I20*U!ciau`oBJ_K}iy76)dCPF>Gj-Lh{CjnMeXkNExJ%fG8H#HoqKMv_HXeD^)^ zeiOksP~>7FB?aY}Gb)@xY3v9$Oj-m)@K(Nvddc>fmaiXHw=-gQbF9Ax1?b9Y&NxE8 z3_KRE>U5T&d>11X1&MOKAmpJh2OWh(&>E{e2F|n$*hQx0jiyn{6m=yZ8jh^(MlLBUOvhyKxJR%iicLaMupe&2H$-QTn9{@ z;JXKEQ548v`gX(hlO#^Qenl5)Mw!m0fZwM=6#P0 z#XJQ^z>NA7T-?Buhh95R{1UXw2*@M1lk%#V1#3tEl;u}u1MUX>ulId}K4b)Wh*)k7 zKJNKTQr$u^`grcG7@`w@O;;de=|UDpDk*L^^XGn!L3xm=DOO^akqe%b^eed6|Mp1r zl(2iE#$=r*a|Jb~ZSJ{+V+-HaUspnz&{lrEYe%ufMPfA`WQb5v)S6RlkG2|*esJl4 zpTAVAe=j?A)v|Nda27PKN>U6RWpCW%34TQsALDpKQWWVMmEW^ z!@OwMn9vE&f|0H(>RasC`!n-wYNM9kXrxdepi=F!qWEQoif`T?Y!?nRWzObUBOaFwl-tI`!M7 zm>=7cq-4D$xvktFxKCDcMpowIAMnE;9H+V-+~JxBpE=gDWrMMW`FtcexdB4eN8- zW2Y*|sh&o79}#2`f55WU)CZrWbN`43U9Z!;#8{^23#ERE!+p7yr~L7!{#f>n?-XIN zPIY&6o3=tBGG<;a?V%8dk~RcPWd)X64@&~Rr|R8(>7NdAt+H0FPu@iw@OC`@+nNkz-5W?szM&K%|IH-& zJ6Z>56JE*)yTXTx^NDobOKqZni!%^!3f-i3xs=~kH`a9ZdZ?4zmCXNQYwn-$^reTf z&88T|l2`QGdsAuqQd9cw?@SKnI(6$GHOLk5ANqW+%*fAWW|>)+;ob4LTv zXN+)U+21n=w*B}>jIU-bn^L>|jHQ+bAaOp%FW9Y4Pf;Oi=Ckj-Sh-!NjF%4}Q~b@4 zo1lg;j6(20oZVHy^mow}v;@!CjFj;72>}q@S>+b4h(_;o(e*PTAFVYw$_+;7PtLosKATOAi4Ld2Ml!xws*3Jls}N5^JEeh0 zIrSvArf-p#DIl5vfSOb84z+t34Yj!a^r2G*3CbL#SUL6bV-0}A zQZB=UJ$|_1`@Cq21$*BBc!a;={!kI*BD*YEI;Js}f}ITAofgaxcZbwttd^J&1;Z5Q z3qavVXd5?UC(2-PIX;~SAZZh^jH|c!_TdDANHoRR!#f$$eh)PX!-?h5h)}yVDa|B5 zXPKlq}T!bS<3o!cf}mu+awFMTnNs#H;Q6DsxyOd!TSoqQ3&%_ z81IIPlo$$k^_x6$Xb+I@3Zlc3KbQbhJKPj#r(uC6uI>K%pQuO?r@v1l9$@JoO*Vt- zD`T@HLw{tlr7@4l_#~JpW-0dM;JtP$lrYIld#^`4FKg82m)*9f7@%GLw8Mb#Tj<^^K5S~(;N{SN>MJf1>I#~4 z0qtbZ^6}>(wFfHW^9B^Kxd7plK`sZCKMxk+Y&fy!0BeVjky}PMX`pQqTD2 zd;ZUxXR~6q7ZGV)=Z~W-_Qk$g>G`RMmX1gEM5uOv&%~(n*csg}!-WOaOk55&;wkCA;+{qLncrXAxc|@%lprnutZZgJ>bB z!?{{zKAnkU3?01^BkT7R>EQ;no97VFWdBmntWiLYUWsLn3m^zc)>NeG(E%$#g3U0d zmirC|gyh(TgMA6a zO}x>lJVeo4M&IQP7B)yDe6ir1_;HR#r21Hu5JZ84Dw#47SYfGuwL_dPXWP~gh{Wzx z77;^N-7IPYIb&(A`mRW$l;Z(GTPJSOSRSKf_$utk$B=o?2rZU~%#pechL6ID`TN4@ zcQBf4ARjb?)jEr`tzKo=#I4@&);Cz`sO&x?tYoJ06qlORc8y})DH6Ta3F7&Xp1diz z4lozT&heiC34yae#3+!tis0-Z8{F_ zehfuJy{u@&4iFKZR4LpqG9qbMZh_$KJ4EI=eEht58pVWh{P^H09`9~igsCnIs zIg>amc$LV=|7PfNz=P_2tu_D8tqzNF= zcyg3DF_hE9w^TJxEuFxpmUXsH?Dysw@`Uf8wrP#6e|Uc97JSo0f!4W;Hy(LPp5k@? z-4%_J*_Yr%pwEZ?OT2*r#Y3DVRX6c7crW3Ok0#fk)!2=Rh}1&HYe|3G{X-|*BHPC7 zH)g;|eS#YIV0mzW`ND$AuP~A(blgmuLvTUwakVLTb<5vAKq`W2Ue3ScU$3~cAB zxH*_A1WRy7NfVl+6;lx{S)7>F{pD1MQ05f9$OZxc!bc6U+_$N%t~rOUcl-YsJGMLX zgkqQ76+vFyGn1M+U$ZqTEtE~ZZ~~35`Jr8@Q6Y(>iQRSsQgcY5r+pa?q>OXQvZTt> z5@NuCAMJ!;^D!L!+K#k*^Fsz9QzbWDY^)9Di{IJ2TLWup!PC*>*_#614LCsY z8TiGxg)mR~ha*F{@Z=R}p`0MfeOrw#KDh*orH^y}sGMC%rt+4mkc9c+zLC`8Hf2`z zEyLSqqe)%hszVuZ5tP!F!2pjq6<%U|pN4w>=l#d4Uigb5h3m)!Xaw3P7!0FG3uBN6 zQrrF>=g+UbG-8m?d{mAB4-1?Pd*NPV_;0^WZuz3*`nQzbGkgIVJcu zcah}1 zv*kZkl*}WW_?+;MUB%<*V`940b8Ow4&=Rf;&gIY^l@EpTk@?kN;%`+EWn$s0j2{=# zXfRS19&)VoYZdEN7}*J3i9mj3&Z`i3mSOVgE7wrG5m2UI<(kaX=4zQN1U$N zXFwc^2(aP#O(c20GAD$%4oe5nA^=|pE(!TImySZ9z15?G>r9$4c#bQfc_`nW`TyXo z@skpWV@s>RIJ|{F5~dx4H=%u6o0PhPu_ZdZo>zlsa}~vy;i}ru#%Pg1}{+(0m$a+V)Y_Q{(NZkVc4q|R+x^0%Ub zzA8uZNH=nwZ za4{WjARa+-vX4f1A|iwzPsvepvm1wdViW~t8Wr}FzGcJB`lgOk5ta{=$eMie`)^SLidwFUE+2#*^V>7OF6#hgG~g?O_l zVsxJPUR-pMaa#P$tiuO4&eqV{iwo8}fB|qDFpj zkfp~w>C@NRza#|iOr+^44#M~zN3otMV6zP(7LmD_{DLvG)LiO3Gf|(DZ80R`jY}F? z_>Ng2C($<)Bz-W~;Wg$bWBBxH%o9Xvm(N1hCz0sPd;%pvq~UEOXL*f!e_Rq>JznwG zUF!yFqIdbV;YV3^bmXde!jJzXv_;P_Q3~zYWY7ul>rIwwG4$v(y?>oFYkoZN`>#zm z2@ynVF8pXVzCk&;C97XOyCT}A+qa`C66`7qLA5u+A$NRx#>zZ(0*jSz#?-S?s--Jh zEGNzhk7QuJ*kq*$#$kOp6j3TCOtGkJ8}WGAai)=Ai)?(NdNE13Xm0^v*X#WtRiaYO zNC5bVc9K>?0~#zg6zt~ct7Nf|twuPiI40gWQb8IYbVbx8%GYAT*E-yozB>QhR%E6c ze^%w?9)I1G3Fd2jT}XBvL3G{oN_>aGh+okU>UU_r2jCkY8OKR8%$ZOH;i6k8E%&P1 zCUy-|rj1@GG{FOV0e?FpNFyO+x*Ze?mxDWaeJgPc_I!;+W1Yidozr!l>&g0^ zn04-~b)NEd-qv-#{&oJ@b%E`5L9bNq&iFed;zAl?pzJBxGLoBcQJRqETB_G^^!%?g zDph`}*oQZub;mPK8>DrQ1mibzUK~9jUS;o|LK{l2IUXe|96ISpuj4@oG+Ed`aBjff zB@ZOM)v?IT9937$@4J@>S0Rz>ZdB$+y6__-UMCPd)wQTG0{AN<@8a<989{p3q&$=y zl+aLDx_Orl{Pzs@OlPqf^8EqsV#Pz^N-0pUN?yB*t+yf0TBIAOvKj3d0?TEDS0?;X z>t=g{S+GdG5S0_|arr}52ZdluY-bCVOt9Q z%A|lu3Nw%c;2lLU-YXBiUHn`!iDY;4VClTVqnwR&zd6V!QpuTtCX^XGb}vwp4NT8L zofFLFBpcBXn3H}DRns0(g)dIv*;>=-qSagi3;D)lb=qU^q@W)#7u4kQJ+~>(?q>~i zHdKN<^kw(>{+l|sKF)!MCUR2D@4O?*B0hhjP<_J$mSf>uIs1E+@@_c35;;})<-<(g zlp8us&S`A!VnkkbQr_Ra{P!e<2^rc|8NkEYbfOkxevces8t?Z6(+-T&{)Gj`4;{_a zYovE5w?O|FQFr0ipV_x(Ko!H#3cj_um{IbZMaTCksstNbZ@S6fcHgiG7M%$_vpv^B&n{!|q0+)UOU(4yJ>y?GWaEMVq6s>>$=&NsKY6qpnCENcxuK5rX z?|oy!mkSA+&dvpnm80SYM-sZ&#@?84i2Z^lV#671Xywoz_#q`4Na*P?YwKGq`aSR4 z>hHHi(^P&J_-&s5s!xHb?Rem+M@%9zaw%Gi4N9h7lqFG2@0=MYe^*-hArJxwbmb}g zU8qFk5m+nrk1gqLi-^1FCB)CYs^f98fEOF<{107ag-L6Bx{s7yu(uq=n0A(TI(gx7 zfxLj7SV1HV1*(m-hwaOLgsKdIRj+sm>OCjseWS&GCRbkwF`UG{_ThhlUzc17j!o}- zjXs;(m(DC1M{_V|(ySY}g6{9(dNlj8!mdaBz0S-DVOD* z3ElDWX{sGoR{y-!>kUwA_!5sAbU7w&vn*wFe$9X}HNe=IF4>1m{->cJ{@pKf;xV5Y z6}(PuNegw%5s*OfhPs%_6Fq+m|-Q~`Hm^m_LiZETdWBNZQ1&q zoipBcAO1$-e&b%Dg6wB-lxA`ee^sB1zIK%%gGZRu5Z6MLxvpU1Ofu?$xr47!RC(Mv zKF=3^jD6G%ZoYT|^{U889In#2{;{ngs4}=eJH^hXXh!wp6~SdiK-kJidRj0FD>l}o zQYA80m8C}~{iy~X>+e@DA(-kq*XW>BTYv4MZ2gvuYOzkW+$QirW+L3@ ziNeZUfU+)H&4k`q8*NhTh%bU7ZP~HYMLYasp7G{R&KDMA0^d(m7jbvx%4tGfaFhY` z;^Vrgb;s|V{0*g$) z(dC?FFo{Nx2DUDYLdpC_!-Qb#Y@?YVzFW7eYDIRxzr_eHF9@RupLcFqA}3oF#BFu+ zgAh=PMA80CpjI%zFiPNZ7?dl;8F1>9sNuF_Vb!Kk;ezlGy3@mJe8{XbP{!k|`rda> z#Alk!0r@Q3vqP;hw$kcV3^rEWjq`Qgr#ojA`ogcy*Cn6QR6&RqulRyb{u6KGWNi+< z^@RNkj^FWqsR;l{=S2$jHpCBt{;f=q`b_`WdQq;f^WQ(QBT<;>Kc__^%xBv@*bh8U zZzV7HXKD^j<~dXUDjpJ>NC(;pbRXV>HL zJbI@oULCRzKta%9J(S1pqDZ9PC;C|3{~~+VT41K03HyI7_FvWU*dkLN?M#a(c#V)4 z(*;vgV5MWRSH-~}GgdiGo8T?MSWO>>UD11gqGsyRBb(hPc_|rSSn+%?jeRcJ+wpQe zUUj3R&`UN(e8H3GV+VVVW$+Dq?ww6=rDGZ*O!P^LZGigyiz;?W1u3xnqzVGy>e(51 z5tk9NnM~VhMW9gC9UsGdQKKmGWNOU+^lvQsvP)KF_EE>GeDW}3`|6n+9LJin1Sy`n zs{CM{`nvkx7T~7ZKBk=e>jC4r*lcHs609;eOtlTa&2oJ7|4H$+4$y?~wTYoEglUqpX)wCW!IW;K(YP>Niw zIv|p!%KrWPk01twFVkY_9Dc)U^TNBUA@eWktx!LShK%q4g?Z@z{tXr$q7S(hu7f4D z2o19rgo=!EH+Z-~?q=Z`m6qpryD36lH2+(Z_Et81lE^kGs9*d2+D@oBRCLC=JooZ* zKyR$}hd}a7mS=kLIVSQPl+zbuo|3sM!1L_~i8R4+B6IiS&o3I~kXe*6#jFgZvTwp) zS5;31e^+e9=YGSwP7z{h{NLoWKj{TcibT@A;5`|hr-^iFj;J6&LWbJEkaLJ0&|3n_ zJ@;EsY`E9BoRRy)8@(QeKz*QwQ_-%Ri}@_dq$f-XwUUna$3p)Xxx(t{hYSzN3m~z8 z0f34sWR_t|=ol){-1_KnxnT6CxMPfpWrn|G%sx#3wbv6SBO34btZBRM@FOeZ6w(Dh zgNGc=cdcV#x4z(&R2}B)J-WZLil}vIo6hWaysspa+;Q`=&#-Jh8l@7cd{$%{jx5KQ z#y*jG$D<-8q6aXvS5RD}j=I~Cb=Ezda8wZ4$G@oC7_%zh<-;k6tSf0Aqs z1G$#|PB1-a+#q}u_&`` zLg8e`3xW_>hRQnv?Ie196z)Y2jtK_BslPbWjf|EaplH5+I zKG^}70hPkVU5{t5J0Y`8M%;AZ>S`VcKNk&g7s(y2r!5ErNWl_DR0=r&{(IE;!sH$` zW-c&aVwA8CZuGQ6>(ngns=@6H3YR$m+aoBocKTbn&*$zUgf+r@^DNJPsbZz!%%^{XHlVqYpoxM;VL$KVw*^HUK^d8qhnfQU3_Bj#y^Qh6bS$~DdFGJBcYKtnpU!s(ZU>Of#ICv;RZohTn zeSis{@vBLs7H={a=m5u{Ki3$Ep-+#4;)8pLzrv6>opFS5Zp7sznqKOxn;!(H(713ok zt^*M$%vMkprrWax)Y($D6Zr}ppUID3;p^6;JMW(Nw!{REY$RiOHbYwl+*%qeYe|hh z9dVCp;0Jx94;<}&p|E8_!W5G>%l1j0p$!gfr9ozqc*}J*nF7OGFQ{#5@LCVPH%5U% z9PEJPGpKO2e|}4m3P3u2DBn>HXl%2RDR$w$BQUbaS@M)*;qXqvAnfiREi7Sr0J+V; zAT8{>P8A`OJ~#vqQs@Wfk>xY8uUX_aSk@4YPR}XBr;c>Wm$s?4SH(JuIF9`3Zu+YI zllH>Lt6f`;#44f^E@pt@*sjr~yAR;AEvb3t{{ia_lD9M~AHW)*ZBal9?rBcf_j7f! zr;Ao%6g}J!?>UCGVH&sRUmrD<7QE=a17zZaDff!1qx*MW*_!8zyX4T!oxYkBPhiAQ`aV4jTV-Z%Q z!ge&Gn;JFUCp4@6NXkGN5K?284lwQNXq03u1C+Q>=#i8cGTW@uYA^13UUC*1`&#uV z>nU7mya}CKc_?TQ9_{v@*tdC}#YNwyP3H^RzH9S?A^Ry6!DXNIJL_)-o8G}1^8 z*B?)?bb^Qj<06%I{(Pgaoq76Lh)3b}d@9`hy6t=I`ZvMSaROn3W^usn-B`6g?`>Ma zQ>_8uYzbe?>(+`F_K_OBmkGY(I!+8=RmKUf%OMB0nBnomPRZfz2)IV}&;siPASQjB zoY5>b=py^5j8rZ4*6vN%mKDWcqvHwebovhrLHJSWnSPmYOuvgH>?=uWn<$s`mQLVM zhTa7$c3AqsunW`q1O3{6ZfKcD%p!Plzd!8Ae&4AR_X3|^*v?0EyH02waCT&VZ@&A> z+Yoho_Xxl#1&EkHl%*gBCNM`SSbzy4Rtk}0!cr;4(q_UoT8GRhV>^}NJhQ2W(fuHY z!ah#TBOq1}p_BUrQv`$#mVp1fb>gGU6>t1^Es6cVNcYL5&q8dAT^5p9W} zIR-tn$Z=ljGoFo5(o`O+jM5;)d4pDZ_^h(?Nx}LvCTCx(Dda&Hi2+!1a1Tc7DXi1o5$GHD1!C~ESc@va}}i7 zvd>EX0~{Ql3!DnQC-RF`PJ|)&#$ag=jo&#f51kiCZ4UJ9(rRvHvpyj3+eNcEj zGrh5>;$)i*(h0Oe(4ai*GZi=GYY>W#g_U_R_83IvCrhGlgW^*sRxca$O&j7)`lb{- z4%qa-T%baDwsi45bRdl4q1xEKkumjl$n~8g*)9sg;?g7F-R0bi@-WCwCDN7#$T+@V>+P}P4&bDYE~=He%z;-T2wZB zH^aY^p3tMdd|QFL-p32Wb=gc8IM+9;PbvyxH}SUDQ?j67P<`P);jVB0*v9mqa;!aR z9~K>IPq>_YKZ;xzz-~dMk}p9^*;byYS?{c3kwo7o$z?v1{lw_`2srx+IL7^?l1M@U z1QhIkSUN;8i0f@@5Yk5rTe+^^^S<&qBe zoI)H(kA8^y=ZGiXzHep!)vGV*YVxupu)wBRu!??_XTQP@@b;B3)i{uqr8UmD>P)7;t5DzCgFmqSKL zA5#S}aifa~j)ysdkULKP^UldxQH9!Xge@{vxE>4P2-`57BUmV5n`90}F=oB8_iUF< z&j+oECN>D91!#Ht)sHA406yUMX5M{Z-UHXR;G=8dA?y8nu8u&yn3zbZ=L|WFf7zSj z*qh>fyrNFdP5qm-oWH~wNPh0ZgAA`5&~%MRucl4F5gVsMRiaISC*^U6ex>N#vKXjJ zk$I$H`_ru_Pl_^8w0@v0)k2qq<&gun85G50#2cEaH(P154xjp2AM@3lR65HsJgy`? z`q!^k#gRwdv_}@STeo31)uSjL^Q5e&eyAUor9GJbaOplrquV22!gWX06^z%qneZp* zzz>FyN*!d2uXr`NeYrYL(Oy?z*TYbl#a>>i=THH7{4X#_!RHpbjUk1W;^xaU9jYs_ z1y^rY1-rjYS>)TH*6St8`|Osctvtwqo5|6CY1mV7J25ujFj(szp|4!4%x2<9nzJ(* zwagcQMa({HdSg;y(yqyZ`&ha+I-t=^b>;D&q||VbdPAv09T z=@*J(#RYV-^+1JQ&|t;#$eT9vBQ%A(hdt}!p1Q-=x6z9$?6@{h$3Ssf%xYiP@J=Su zdFVbye*&%O5g^G8^-B(TH^5`>=Xv}(sz91!UXGTm3Y%|Q?m#4GM>u63tmBkew&e_7 zin862h7xrB)On>ouaIz%!ggU*^^+Gp`YaelRfd74mMC%)Bs&HYl212!qVFk0KmHk} z(SdcZ+-Rxco`fHLchHu;wV3uk7%rUTtj?PPfv5eIwzbCMZ(#OqNV(FmfbHRTz>PM5n_FaG773oACY1d@l5)nQd6Qx)R! zuWFdEtGdh89Y*vV&M7~c05WW*u*7ul1Y0{?$6KwdCF=X5&x}m<+Q0j$h9&cJaV>?6 zg~PaNNy5~7YL}rU;itnTL53w-!UG7+^6Zh@n`tJ4SImz@*qW1Q-deL6x3OD`a5%Sd zc#3cawsF1?;flSNIYhW~+PF(Zcxptva84$=OC71}3Fd2gzAfOMYH~QocB_3JZt>~5 zxZs<|y|`JNsb$O~eIPjHW7EDto1GtkG=4R$Oj~a$tbw#GTjFSq!GL^WyZ`=PJ^k(=ZU#A z$_=8d3hj2aF@iXiij<@(o$SeyiN^(o3D8$RgdU6wfBK<9;7~_{4ycX#<-Mj{yF83^ z#8xkIyPRa}gs|VH6xz0BQ5%w2YeGy&C|yaYo~P-_5$X5F*Euc;Equ!&fLe5@3lF$)14iqX?d-5C2AD z5f(z8V!&eEJ~M@ek3nz^$1kDbu{ox9se06II#h3*A=b)M4=oMq2+Sj;*EeuHGZBS@ zY(K#r2MTf&cux!zh3O!1^IN&sF6^I%gmNJduNB46R#v{_>L8@8e10l84v;5H=q6HL z(E8i-z|~#JGH013kBo90By(w|fQ)Jjm}TuyLMlLK!59gf6kFWHPjC-N5n3ueYf3N_)Rnm3op|2chc3h&{snKV>GD-FjsB~7Fo|!4z0Eu( zBUqh{&hYSF;FWFuY8ozKD0ycVSXB(KYy@QmVJLQ}A4&Gbm!e(=DU)|7XBw@Ic$MZ2 zLDv<<+4^>NxqsxnTasE6JcD@0B4Qqi+`GpsOX@aRTw#h7KxsiB1$LpjI;)!KVhq#M zAL5yRE-#YAvR>yVYD^KIsWtequ9;<2W@Re8DlD^l4Z2)?QQ!H}x($S-ER9xRDOT)^ zc~}(Nq0^`Y67mF^ozk&@zP6x}QWiohBGF3ZScH{PLm)6;sZ*YkC+Q|c zpf=*|N@iO4=)*smJ=ntMECHkP5i{~Wg)$Q!>%EL5ogR5Jq0z#<8wG zxWDrYu_jL}QuCd_^}B(+p99vn)Y!avph|j~>9SPKK%_xTz^y$lnXS9Y#bxW0^^RaK zR2IXR`1FpF*D;mOEKv4}2Ll!A1I_RK|Ku^z_9x_0-<2;DNa4(Pt783 z8HGaUR)@c4ClB;s;rmrW;%I|T?dt1W`D~@i*B|B=b7rI5I`3p#j%8Is{#KZY&i?rO z2f?tlAVarm1&X_ikmnN1#Q_#4%D8m(#%>`JewbL)QedSnbJ$BQIn5!zu`ktP!W2JhRDn#4q+c-I zHaPjK`u)?qn5+(+F2s{hpLL*z_2CoHBB^`5$+0^r=X26{SLm-=(2WN9BIn1?4I)nI z6HWmf{PX}4(?Z^?*DWy{tj-0XY!zd%nN%_*((IHIshFi45G2S*qeB%Na>;ZD^$bqE zYQxTSM~xgoa~wo!4I_07q<^uZ67Hl7;F@tBS7uR+ZRH=f$dv8UMOhLZa%>(*1wPYpzC-6ShPTxjUD}&x0SqcM=%V@Z$BuZqAwa zgtGB%iBlqRG{d8BdC$ha4|0|zUA(UIX_Ut+U3?xP(nGVNEgOzbZ4slG9NA4`bdXT# zhykC~!;{CyI7zwoD>I@u0Jsf+xU|7xw22`*cy(;!r$4GlqAWT@-#7kai0KFLK$rRi z{C#*LQxTao$)Pp-MMwT2KlfKT6la`fZ!VW+B`v-64 z6ca%!9ov1NpS=3l6ZaplJygD@+%ICK%33N*9^k=|n^~rmCmhr^%({4$|MC-Je3$c- ziA{=&8gVpEC4JGv&y{f!C359C8B(a-)^h^@5LONqLFxfsXg)~kr7e=@FeW%b7%Ta) zXlAK>jQ2yzrR=3=1?2$WbybnLR4rB!OjT-quk^)zVwmOq*sH_x*`s5dcO*K6?5gKC z9O?C6v>xh^Z`5(p9d7pWlm}Va{6I-|^bFDIJ?7dY3WucH=8hJmu?PU2=gtG-FhOJr z{$JrCO4QVv_6dT5xOk^r6y;bFj2;1drnRu7{g98i+dB>XD)z?c`l$6C3`JB+nbDS9 zPg!b2h0pX2)kLmXU%PSbKm69(TlP~+Z$dpk3JUS^RHyp3nx&KC zj2_s}Uf@}%HGmO4$JDx!6z%KS!uuI79aE#|FV~^+2nCXqR5ZKj2CiPN0>!J;Xnwy9 zd|QMf^<-+y!}bkA?_5Rt)6`hm%MIcPgc386upM|i) ze!VT(na!Nn{mt0IXcnSQ7uEN7;WG z!V1dc?Ie&v2$M*R~@3&r)gY13YB`foOU z^4r3qar^DnvVXZXw)QLfx7C=igkcKg;LIwqpLKfvCLp4gSku{_I;kZ!zZPaRNU4n8 zoC(irWYnNUKUI|DgzeFUFL5_%ITZpGD_|GJ+5;aHLWIC^rsXLCx?NK>P=ao#efOWy56lTTYN3$WNbCA~*`0J8_mtp4V(fAu*c}%mpC6WY#D-zIocS>Hd;c zIgYQ!+H@nnAZ9B~SDU>9kNOp9p8pJTb=MRQ8zSS=$UWP(mDzco2^jvaE^lNKe-c$; z{*S8YpwuwIq2KW-i0;nD?jaV>9m_!!Up&w2eySIjb6VbW%N5X74)LH9LZ!>Z&LeU> zmLA+pMDZIqHbJHDS(sMT(GmR+X-0S8Fhqer(Uk5WPW3Ld`E}_)>LrhZyk%G7Q{74y z$^$_a6xmst>sL57Qw#yLIN=ee9VOihmmzonxi&NTAR|80@M~7guj2>TD-s!fDOTFrNuxhTgj=Y!M;xJw(96YNyabwLUNK-^e z4bb^rFw4tJjCxdylr~w6{!y;i`@!s2@(*2uz(#30DP-g`*#V7Ml%TLsWedI&CuHAE zYlfMwczWx4)*XWh`^3cqM9wA6Pe};@uiH9*7P3Yof}_F~WwDB~)VvDe%e z+wDeDANyW;Rx>`d)o#{W8Xuh3EPm3kj%Ei$QBZ~^$;b=8Kl1(64}~E>)=V&)MrNn{ zGrrv=z$6=?)_ITYw+K{zk<6w0ovh? zE&EbWsYQFfDUiPJlT9o+pDu3Dx}hhMjAmk(;caUc;b)(lcb`+MMW?pSpP{&r^xf;z z-R?z4n00km)J)Th*>^(ESIZ@NXnuZxPX!Gd6!(VP>HasJ_S?hT;oBRaTRmOv+Opij z9SGQX;B8*c$)R$5S{u!c{MDW#p7j`$6xPv4skcs|pD$j%SM?p}o?1Os;?JX-C<9jb zRuA-Ju%4x=b&}YI#}s}mTHaUIQ|0qq$Rp9Mi3NV z8_v?lc3Lxj3f7Us>XZ|lb3lXAG&Ffy!slxYZimz{NB;Yfkb9bPvh0mQ3;536A&R^O z+Y%n7%`Hz#xOop#B7~$A4zT^bpcw=i*O9vGWB;j?*M|q%@{U15xLLZ(b}de)Je4>O z$}G0HbuD-k!&`-Cp1X?S|LWWt&+vPM2nM_eMp_6a&ImpW5w2F_y0TSXsw4J^imq!J z8VO~}6_su`8h;ZJ|I~f7GEKj(%XT_#{@W{NQAn?`FD_N>XC!R1G47MX7M!>Ip05m1 zvgf!ctG+~%2R&uu`b_E$* z=*0;lotdqigteVy;u+T-T|MXEIU6h%XzRs4;rzCoMv{lk^O2;pT8(91n4xb6@o?By zg^!_yiK!I@qjRGfbnNj3Z z%L(G9Nk?|_IOInkTP)byjG|*_le@XLkg^5C6qc4m&Mo%Y%ueV zsNQR@bal!F9k_|7B7&?eLK7F}q;6y)ZWU686?p5!stIg%mI$Khh{SAe z7IK5ac{@S%N0*a$4stW&$$ddnCQ&f|=jG|5Ysu zNgr_1Yd_#kPFBl8-mj@j!n7Y>!K41N$$A(~JjgI9Us zTGFp{lGM*r?IUGs2eg$kc$E>cMer{43iTrwv9>5uSO68L|8US_^q=K=CL)FG3%BOq z38arVA(-@WJl{uuemp80-MdU^j$wYsz$Q;Mt9|FTC3v)Rf1KImp#JFQ%OenZWoANM zp_{0)dhK#VZBo7E8IKZgyO@a|6BGHXnPV!jdkfxCi-1$j_#rvB0$^uDF}MB0g_|BN z4-;KS^d_k69jZ`(<;#%r)Z}=<_`4`SC4SKyBmE?c3yCYR;(KL9Y)78uObJOtl}DKt z=^1JXSX>J6BqtA~7#}~90kfsd>;}}6K6~7Y$E5Z5vG653**^4r`k}@V&(jnK1?5bo zm!j&pV=bWqt;M3Zr*4lHx8=wj_{htp<~Bn&Rp`qhY?n0>7(3ncG2z@q9ybWDkFaMc zilQn)+X7Q&GRHTqz#sIcGyI|B3fo}4P-j*TnP$qva|TZ zv&9Sx$wqy|8!|ngcqo zPsC(WXKPYcYVtIl)xrnNylIv}A%3%EsEjSk-$OsIhG=IKF-rPG!yzZ6_yCVdM%C^$ z9+~j<%dYBPV@DBnvm+si8n^bjH%wg{tH;aY10zSn4FR=8T1v2^?@@xx|(lDX3o zATFTkkrx2Yukd*3_em`+`%Hsv(n$91utD~kuU{&oUq7a2mv>-B(Q2wSeOf*R!}Y#W zv5%wIO?cD8_Y1AJfdu#4)@~#9{UK`Mt05@|$?bX9r)as?TD!kW5sLu+F2Ep$Ufmqm zA`s<8G{#!j&|lz^8clm#XZ#GNpcH_6o~ zJb3{ZvnLZtS5Un;lUl`Qk7pYT5OCz#RuI|tSC3@9c|w5kxkS7R9U=&OL~6G1Rt(LS z#0C!0z!E|6DR(C=1dp@yj)#tnhkwtqo=OT@@ECQ_$|ky^+I?tt!>91uc-YM0B}V+k z##JcijuvkA6TT|u*>^f8qP%x3Ibq5#<*)sM|9D5>DS`!XJaL{d{CXLf_Upk%%8#1A zST6bODV7H7X<|LcebRgSo;7c4oZM9wP`Ni3lj;Jq`#cr;VOJd1C z0#iO+YyWfAL7q(4Mr*XS&Mup1fve1(A<}98{*fjxb#}TYSPlv`*3AJ9n6V5^0 z%uZj~KI*WQ?_=J)j){8B0a;2sLTG<-uJ<7go>5+y9_PVB>HayA7Qz-2jW(!_9_&Tm z7bVip2dru%5aaev4cA<_g zS^^C9>sXE#A&QbYVlfilnyb1KY<8rKcPB6{(p8rMqeJSa-}3HRsFiK(l8^y5_VN{( zic_QL*6Y0D9#FC5$?hRZs%yqyZ)V=yIdj{Q z>Y`ZO314Gxh0r!LKDXxrb9rg+ou#d-P#z80N1ly z5L+?ZAmdhD z?N+|^9qf5_M_zq)tf&d70SS>nq!^a;EjDo zH;-&*v-b21=8vIc?_~yB2YcT;bxd*Ns3zmgFuMaF%C}3(hwt}O1P)Nm(l|9-&-%R7 zSf1@xKbyX%0O@+E@|j!8X`SBoj6FM7d95aLJ4lre1g#7)!iVuoex(;> z>e{FVm{fAD1k2bYL(j_AMOgfeoRw2~{`|B3!?5kE;OsZqOvWiQ*C-O;6zdhbdaGFz z^(5B+&Z35^-1B$+_uqKPg#xPY2}N_RLvtUduB1rfdG~xq?QX-1{IWkRkLdrA`c*Rf z@^4}9-~8rZGZ3!ZGV?Q!kuvWquc5E!txMh?+|ub6r)1|6YJ6IldvF;j2^cn{GvJ3k zR7~ekf7%I832wZP3`E6YZGRW_@`4}jssT_?{rY?jGZ~(Xm^pK_UQssx%!ho3?1a6b zbj}>`+KNsMv%(MR^#PtP&u=|~(<7Eko>o9=DX_8{Y)AahtvPVm%=eppxSS$zpc=oc zI(s%`D@`Qb9SAv(4Kv&%-*FB{2zgkKC9kRe?B&c+fJYb#9oMXdcgfL#yh2g+NA9`* z?(|Q5`rcwKEzyrb2fq!nL1PQcJ%BAa+AwU!leHX}Dg*7K(NWI1r@Y*QSITR`*bT*? z3N-f3P|PC^F%Ly>{a3aJEn&e>hYQH#H#Gp}=k}M_$5yc>OyzMqoA>Ev$ipY+3wx(G z&GR=5*gZAXX-_}Ks{x30Xv&}Kmj&4M(%wmoH!qMkFHkpsHvzXZoEOXp!Ofct#@}_; zgnuf0jrVo!e+xE#!^wg{OQxjq*OD^xlsX(4FC#WqcmJxg{oAv?cz1_~PKAM3i1EuB2}YVP>OxYyMXUR z8p+^Si+uyt_ctHF!1XOIIcB^}DUs#_Vjak?@@Nqq@KFH|R2a&0SRRV<8rG>$OmDoM zvi{(dCSm1R|L}0O-s5Xm7{2(cl}^uZN@eM^uT5TDJ1&(8h#>0DKr}7|te^ZqsT_Pj; zp;Jd$vh*Ppt2$Zn&|17C&r+$XDuen$3YUU<`AaC?jafQ{7`JU&sjFl`mJO+656AxX zYwZW-YAsY)*wbxL@qcLFp(O0(8~a$h@T>LYHR{FuA}XBx8f849<)Tt?O0&-qyqh=Q zDme6U7s{frs%iAiEyjSRQ6}mn|?S|x0 zXrBt*?C=9{`2zQ-TV(7jv*N0n@L-SE19oO^ZNo8p&h;du8YjgJa=3Sg!ILTbJoOWL zH*O020b}3NE2%Ni(JHJmAIIawXs}}OV#&>Ug6+|FbcwTe%E6}?+!rS>#^^W)gD3HI2BET$UNfXSED!XuRVS&^~X!U?l9k-@LqI?C3u@cQ}g%1v^Or{ z)dz5<*O7@Q0{MAHPLlA=>^e8h#t>6e%h2^`YP{F$6aC_giyYt-_dr3UI&!UQ+ zuNdV2YpEV_Es#2jdFk+H)U4v)pM49@m4~iz-zTL3FaZ$7Fuo2M|Cr8u=Qr#6Zl!YN z-v_zYK8t@uU8n3J6LtN?<^=yHk2jNQck6wp-mXe?)w-R0U{ww2B_OK`yN&v@)RoWe zfjYvsuutK9#QGP@2G=E84y}ti(3=bv>}B{B;QZ)xso8PC*K!?ARStY4^y(j@-;b=3 zx{7}0`;XNUtfT+&hocT^yo?yuJoM>bRg2g0jo!FYP!}o9l)vHqQH#Yi89;|2)lFQF z;V_mRb3F06>f2cEcj_ZBN{u7@z48lB9FtX*>KLO~wA{@#D0DYTsKT$gbS&c1R+1MR zYkzA;r&WvmaP!iuYOI7pcJ2)|k+!IjV)2t_x-abzV8X03s014T;2M1o17^2s1tf$Y z8@0u*eqsDQPSwp6?DJyv3)|XZ&Lha~SqPG@ggGRtDIeF(6MXEz(`xeYdHh9m+iP|~ z*>rMAAqWHZecn)o=>sPNTY~@l%xl9Dd4oxP+b)Y#!7}a%H@6w5!#~^Ks@1ht{9AoL zX%;ilEB6}rl4kDAZ1A++jQ^dOD4HRs6vyQrew4Py6&&x-^U9zFjXZVF1!s2tLk~sT z`Ix|d(zeSu=`QfimJYu*QQV-=OEOdU+Nw-zWuxhfirl|T4d5MKUjAkeV#$hD*8Habf=6cunUF0| zaA?q+@MO6^#p!a~&7+ZKw)R(Tw%yNq(6obF;7BP4MEolBmTjIpUex88Vq^FJcjQC5#JZ}a6dBqB;=!(W&Z&5>JQ~YXK zO?&m{+j^wpfO6fJnrZ-Z-rpf7>4wEG)d6pci&E@~ZK8dLD@3pn81fj&Y<{&tF37N= zoKqRjeG(ji)PgAMk;%@}za-@Gnrsq7R<;GGm?3v?h+J@M_O6_G*B5rpMyAcw7jYHs zds@xG8s@-?4}{?aNu%b~V7~UOAN0BCF(joYh01H;{kj$mXMF=6nyW~D#(wI#L1HmD zob&P5iJCtJEkHQj%XqeUV%TL)>;Nbb%_0`PVo3oo9V>N@S)vte`r91b*>#@KBf)sZ zE|F;+>Y)I$vl%y~o>B&7$3cx+kZ1<7rC}5G3oGqJVu#u?QY;b?6_M@@q9bEgA_=H4 z*9?-3(_u(fP7NU9OOh(JB}+jHE&5 z(#&-~IS-x+O#uSYQ{gy%s@G#n5O^r_tG{GLkU3 z@k?O7Z9b_us=`&)&`bb=>4n)j9)aOz!UP~_jUYb|qZSBG{WFrB0U9~wvLWs>^y1*~ zO2zR|B$*+>5DmNu{czvQe*OKQx2Cjk;)atMXK2N!Iu!T#U+BTQTo zFD;6=a9gS7W#<1Pn)-a_NOWyTDXw);A7k;cb}R>Qz#;g)rmg={Zf1ce=AAMQ(klo- zm$xT}n-+K%l2#KX1#n=X{t2tep(~(S)hn@%cZDPt_$cVlePxBn)6}wp8%%Sln%0G0 zTw#sFN+EaPc76Cy6^F2+dAXsHJvOo@FRI$!)N1;3=6c2(tZa&kljYAEIwd>MG5i`7 zS8$v3idF0eD)>Xc=#ZkC-&4z3SC2xckKix7oUGHZM2@U|@7L=JoP8~-&G?u-af=?t z#kdG|85tDcEQHEGwO^8Op`99rDz5F=o>KlAI=k$yUGUZR; zws&X$%9x}_Jaiy1G)ykIpU}WZd~e*1AxAzV*T{OE1{Av-y^Y9A>i>M;>*78 z?xCJ|p}zP#^{S8z_!H}3{FUW{)1o2*OC#v^BlZHqyEl0;ZBzqJ#KROmh0)Zp;_B-1 zVdpksi|@=%RC(VnI7rI56yzI)^#+h0sHTt(VpbJ>e z0NA?gV2@3g&lCWX1R%3{4nny%48XgX01hCKG!=R-L~=Xe0`x&{kT@Q8FRqON!gi}P zVNk?6@i7w?4+rD(j@Yn$rM)u(FcU}{5*Q3({09~SD+=ZJSf5c!x|cn>HoEhOLCC*^ zIW-Bz--**cy^isghz((OQ;rJ7lXt_7h|?DiNHU4yk#{%+EP9!2_-%0~VYbsQW_Dg4 zUGwT{d7EUh)iAVBguP$Fl1nw+!r7gp|%bw%`w5`h)@d+;ea;I zu%JdZWRmHB{E0?UM030Do_W;HIK=zW#Kc#W?9bDq)p26;a$|R+XzjAHegs6rK z3DPN~>CBSx!UW(20zvk1+EKx{9E>A~z}L7gGC9yJ1CmMHqBEuUaq`Ds8JA(-x7wQ@0 z2Bt!-2b0%ose7pdKKn!d+4yDTr8qj}^|p`)V+c=>J|1O2ziVN27F1ZT49BZ1Y>1gG zGhry3I$?z4@uJeJgHjdllFOUtyVONbvtz1Y#lzR-!vSz9nnGtTY6t**OO;-hUfB4q zFd#0LBbU(m3?hOmcwm}gwkJv|pO6NRb^R@fgRvfq1^nj&oPNDjz#u@FDl5Edk$6|^ z(uz}cdD>Q)i61hbqu|!27ITBuv-dP72|wt11>FxDs?UGA zSCe!v=6a=5_8^J2o6qN9$2OoL-C(DH=9{kO6e-#goYIWPNxVi@RFch~eo=bXL`~#J zkuztlrV^CZN4cl9;5Wbv})xF<%{8dA+Z-%(gKb^P#`a@GkFh zufqodH^CZ)k|g3qqNYU-W^u7cC)J>X&wR zThOO<;+?BzH9vU#k^TG#j9P-CRiWdN*IOE1DmvP_RyQZ*A@k71cbvE#PrQNhkVMJ6 z&bETI_7HoCWn{W3kYV0Q=;S2oPSSxR$zc*MK-nM|loN`VfRG}0|N8bPjXY2F`zFkL zW6I8Kbpq=kkCI{0^8qCt$b-Ryxt2dWfPYH_ja*5OCo^@96F97YS$a} z696n&h+yZ+?$b083V_}FvW@}3LmS+y^(snO52^a@(! z$#<(I8{S15b2O94^iUAUt6TJP7WRhpj3{4^Tr5&Fty@8VM=-jU-nwF7$MoX(`0yA) za5nk9M2pAqpF}Hl9ZPoh$`1K{+!5PnQ=*&$P{R-&45UJPtPh@KlK27Bd=s;cQJo_A zV;02o`yYCK*We*x>&DbQqMH9~G(`%?lh=v+b&EGOCv*4vi&Y4*4(wYuiBEqvq?Lg# zR>l(|{MJ?oJefWyMF3BP2;gFbd0y1e&z~7BiJ4_*;z>e&yz%~50KaaW62c!pjn3S2 zdR<7uTeUw8*P_qP3qD0r;mBJg>yAqmW_p8(`7NuY$DdQ|5$_=JtE#BjF$8~Xy!3#( zRBW$FqO{4|q~<%irX#uu{N2fC&eL_V)BGE=x|SGT`L+fs$&_Q`MtPEXL#8p|ZN6OwxV1O9I zX0qNUbMYqs>82pjmaxFq1MRJc&$h%3cY|~&EhVC&9KL(+b3W%^cz;;$TK985*QLLB z!_j&Nc7izQD?9kyf0HRbY2H~aArv>I+N&KNH01|NDaM&}hqB2@ z{^$>1RT#BdTb;3(Jr*1@`Y(x_wU5MYkIJn`N`mtg_IMs|UeB=JWia?%M!fp7^!$O$ zOCUV(iBkeipHI@u$mKTq3^djHGUX6nMlNz&)I}*pAMAnOTlFx?RNawYJ+ zk!p|(agH%og*qvxGcr-};;iV^`){v?*4dwqytT@b(7y|&q1Py0P^$};pr1Ed|47(O z6p`LUpqnb8Y5Hba1#gDz+D$~>U;%M}`2>{ILcJ0~?@Xg03zj0G6Hc@c-BMJCzcN*Q zz`7TFo86m{I6}p)6JE>0ZZh)5q%r*WaQNR$%6#sK3nU5+b>`j&`?Gz?Y<2lkHCyH~ zGDPeV<>o>j`1TJ|v{s=6j6?bllg#fnjcmh1k^z;HJ$=E%4kJvf3DV+jI{+s-I_FNa zL0fzL3S=|{AwX%#SH}yP(-aaMnY*zW{uB$7<#<_<3JWvqeQ7}m>HF6x%_+vt*+uSM(~4Hr&fYe| zuU=lkgpiZt=NQ>z}Ro)B;`mf;*+j zH_j2!Dsj8yRN0p`(n`n{= zN4FU1K6NLDksgE%@Y*W(a501QEePqYFU)<407EghDRCpJssRE8nr6k)E5w*AfSy*b z2KkKgL@HZf6Ut+4#khsy;LI98BLFB8Bj7${INw}3fUo!=j)dlDNSk1VMy3ran%SH)^KI)LZ(R+6Ph@=2f{ssy?Q}iyXC8-o| z5gzY;kXg_O=^M}ei}UF~I*h^);FA3p(X@F5&4$cRpZ5J&3%T0pd?s)9f^>;co@krn z-mrYECV*!bdxsxAX$Mb(T1=U?SH`lINAIBI1pnPcjaGgV{? zwPaXnBO5;9zjCJ?sC6xZ6!G@5V0^VA(Ap}nbw>7A z%y{OZik@VBqA&H0WWF4)VyYDgJlDGw!1U-yP%LMH&G1PU=V=R&QTsZ?FC5IUo%vXF zEyL$qt63_dKIRyL33Fa1_?J4sla?uSKM9!7E@lM(e(|^|_Vd4vD=h}KMA2hiHrW>~ zw`$|G_aL*81Gtrpi8_tA>Bl4&vHsQa`dH!Vr#DeUqFYQSHaf4?H7r0m5&uWf#9S2I zE%rR+fcH_;QDJ*YU6Z2GLm#D1dJdB7M+q<4h5pk*C7J;xL`bHM=^&#zqVo{SfBbPI z-01MEUjvrUN@l7at#yW20M`0p#)IsNTzfAK0{_cpq`12PSPq@*P5*Dw8*38jXAYXa zzxHg&Q%M25UR(MfFlDlyVHm*+9M){=w6LHT9Pv^6noqgo9}AF}p1lJ!*;&Z9?^m+L z97jUDA*B?f&O=~2Yy9=zNO48IP#@$z8}F}SA=V@~3t5qoHmYQ3%@nC5`q(%piGoER z)-x9$6hQ0$`22Ts zu2Xirn1dNIKwZImB}ccUHycpRipjGj1C&9)d|s zd(dqYj9PCYyqFTA@}rzT{TZ8e9+gV5H7w_HsE${qn#>rw5wg?6Bzaq=m!N%E%2)y#RAW%?YBXB{NYgNj(Z1`~jSX7h;~>q| zY_GW?L122GhDA(9p@p6wQKlB$q&k$lS)K(g-?MC!jU>sdWcw|(HMH0B=5tvsJ0MfA zida1t*L1{F=j`Gano`T%9e7?9S-4_12k4!m*0PyLtc=@ASv*{{UYRdc7`N9tc(_^q zF<%)n?r1Id@bGx`^kJQhtDz87C%evwTM(oKJmUWpeO|4n-`;liDM7V64hVAYiMlh> zH6aAnT%Kvb&g2r2+KkJ;nBJ#MbT`se;7d=O`iQfYE|=IbQ6 z>_B`xw9~!_EyFHK{W~@Q!#ez|YcKjNWL&m)7GxaECBQTqkH#CQ+Y*!w+b}@l?j&zR z6YZaF)L@_We4zD$m~TLfZ-eXWC;X2orpd(pTQWUPDtoTSgf9zN3g+v;@Nh;kjz=no z&Hqq2-X1YkJ@&(tBL~rZYo9)m36&b}${`E5Q4xbj6CNyuvXQy8y5>0~JIYF~Jq+4J zhrDY|aC8Sbn4|S}fBG8YRtQYn662`A$zw=>M?JaNyv(b{vao5oop6t*u~+NPap9bJ0fJT!85PS zKRth~kj?MLAOFeiXQ4D{)h2(B%?icIjYLk=-A9*rLq?TY=U#?y+mn4_7y_V-cp4*N zubZZzQPIRiew6>)>gM<7FlpSQb_d=aa=h%n!pPlf$k1ptwWDen9yqaP6PfrwU8;G) zCf#Pk>+3r-HU_Hy%w6c9u5wRy!?1HK`iiSOTPD(@hveGA=Emd;bbt<=8G0*^0m6dA zlu6{(6)kMp4MV8rE^=^mD@vnJ&_lM*Of?rM4WPNX0R9*uMh#DFcbu|SV7SORROai^ok26 z84jRZ5?fFVkUvDg?4xH=2@HA^%nHZAdxnoOW2*IH!;bjZ*xGlnX8+cwIaAWiBd+rfp># zK|um(*&_>}Q3`?Kw0Kd5^CRsfG28ni5YPlVU!-pUI@AkOEeewiipI$JA?Jj|vKC*B z5Pz4VKaZLN2vT-ZlXv`;sQ183n~TB=rWakO;>N3Gq zBzBC%9K}RjYCTiiAL6W41V$oN@2K9}MLSax1(jiB%ww;b5;JvY%8QeT7ZVR<7g1^8 zD9Dj?ajS;a@t}mqEn5lk7kY30s5dG0Th^tctI<&GRetwwGODGOkwVWq#CRb#(N6=2 z@e|1EEAu3Wf-h1GnyBg?F|vmr?90g2SJmnlRHF6dg#(ji^ave+vj%_S*@HoP8hZt%3)KOb4 zey6i_8STxH>H90nQej-=WONW~IMj7$0X0wu)m*RXfxf?ZaO7;B0PJ9`V;&OW>N9T(AqVvC!+WM!TiQ#g+YIXI2>U@{cG{ax}~iG{f21Tyi1-S$XeV z(4H^UTlmEPeBh9UePJLCjl>Y@c$7{$0%+0{5jiC^7leiM427n)`t_jZw+OtUt^(rI zN3QQ961ND=ya~Tl`~J&FHLG& z9NUZaAMAFftmDtZfR5qXPIdt+qX#vcA;YnW zBgkhc;uf0PgCO?m%%0)`I!s2zx`4cOPco#4pQ==Fj9SSSt`b`2M@dXcfnmceIu9++ zd|+XDmd|I+GA*Hz#9zbjzLFGo5E1X7qb=Fl-oi*tiS_y}LN%$14kuCRri?V|Baa&@ z@;>rY6_#W_v-B>r{~{qeOO%moxd~P3f0SI^4tCRi@Wsm8s`sI$C0gbk?kRD(FIM$p z%nUe74E1B2eObQF@xbDAC>u})8_gkF)7&KSL-hG2wvC30iJ67m83F-wTl|M>74Yxqm>lR6(6P6r}C>- z5Xym+q zKGy&R_tNi=Gf8zour;&-QJ1!LcoQ>Olb{u6jkjrye{N0i&l-krLr7;s#A`z=V?$z0 z{p~mAp{;c(1Mi-?4Q0X3d}wy0q5=UO@_tShT{G%O$n5=d^_TXgmu%*XcjQ@N^kgqO*|F}MuMfR-}4M{Wie(Cj_Bk6 z8>g7x71q}8a>f)j?MgQI{P>|eFZ#qgYRm6p&o<0TUd>&OkwD-Rbv~B8c9wJ(cVz;BEyRx z@4V7tVCkKqhf#@1S<0`!V!<7y9INcWrT+)eZ8Gyts4-7L_L$j!KS;y^Y2&}1n-9p4 ze&zIu*-1@1orfj_YcIkdP=D)K9nY>y?fdN2zsY>u15KLLdFxa!ZD+(IwNa@#l0DiY zg(l9Eqeyos>xU6~*3^{4Ow!6%1v=uBwoC*3BkFl)Uu7uULj)g#h;6oUE>S6E21RTD zzhhY2Yz|ebgw}%6i#Y*3ou200{C`Flx(8wAP_zKGi=r5-0N3=A5Wf*a1QLDoz2h%I zqhr%FlvXjR?Mf(vv7ORVlJ4T^DqYZ$>%O2Ug>@L`U3fqhL^L1-`c9R=1#|yPm~WO* z&p9hv6*vd4NmG|wp4aTzN?Yp>%zhCl1iBVPvGzl4RUzkOV2CHy8T}=$BE_Ey{$u=? zz35Z-r=IHg$w|Qdq{iFd<;Un1i)YMlh}@R6pV|M$dfne?IX}2D#I8u=x%bs9U&iym z%JZwI=eJ++oR>xpO$%;cRHu^1S4R`|-y~-ktdDYjjC`H_R3iar+JsH2(5`o*L`&OZ&SA zXWF@sW5fu*)^3v*;UU92XtK)$p&{w{RYNVIR~9b=W@WEA3!Nrn;swX|;Wca`AzLup z_C}2Nx234yTYjo<6_w%wJDjaT8m+`2wcW00V~W;(;pW)*seaBBnxB%y)VV97WMr8l z<{BxivK40YVdl)-kY!$~Pge(DQ)8`ac)xpz52zc&W*P2z4X7a`nNYnPm;6U&g@PQc znZ5#8Nbaqx6m>6wOISDTyi9EbMJk)S(p~VUyXfJmL4z~WLl?C|g29Erd^v&^wk=)= zkto&>cRopI^%H-K?B;=D#oBTg&$70JdIGBU_A8<&W2p8s@fFMG1w$g1wJ!d-U9nYS zE6tmQs)!F&kygFe;+;RX9GJJPUzj*yA#q4yvQcJa>}z*d~TQEC*2 zN08e26oWBRaBLtk8%2v&-XGEAg;{cQ@6eB1WlrBcAFkSa(iQ3+A2PESeMB63{7y!M z2f0oCv56SAr|<~1mmyr9b70CajP%UfkuiwSF_S`uJoJR>4Dw3!$l)Uwo_<&w$QpzB zD69(DIuRwP_>V^2={vqVS&=*>reT!sGI_`!&v6Ui)A)Gc#z-6Tt4lJ`HSQ&{5Vn5u zQK#U=LGcfr?$97pOqYx>UoT^O7bMCi$h;}-qN=&j6P<=N37Zh9pNy31!cl|!2*2Ls zs{3RI6JS5+pPs}nrSTGt`LkMg4%|7!p>m{J<$sUM$A4o|uYg(_@(CcY8A$r~E}k1- zC)tW&1j2e!oru(Vkzw5`?+Lzwp$bNn3PhS1Gd#$5QBPgHUJ)OWPDbkg8~ZKKuh2li zAwrU5>FDS8yI+t1FENr=cOGXV)u)w)Fv19z9<7^ZAsPEf6PGZ|jOV_rs+-0_%cX2c zwN?4a66wvtgRcPJqcVz-S;0%Q0}mmPu4{rOe$ zGQNqk~nl-h(F)83H6pFJQFscQ8ynQw2^L3SI;NPO#?a<@9PLPr;|Bk3}^TTUP zIy~+G{+<2^0%q;HEN3Jn<4)SFO5kj^HIRMzJx+kYw_LTt{0}8MBeRV^&-WP}0f>|( z@s&i;?P^Xx_-ow$WZK{@Xdx2VQ#bVUV#6w4_Bu5!lY2| zjm=`F<;@ODQG(>vN@-#^$f-nr(C9WjDSPqTMj{H`dJ_#AB|sG}ahaw=dZr3OV%_GY zkOR%qr3hw=kDX;US{XO?X>6O&dEW$DHG2>zNzx>x?1;6V1_-Vcr_5Mi&J@erzhbEc zs`5(64|p(NfQ2oHL5ooo?LVzvU%M<-yy?m|>-DpjP~6~9_vh3rq(4Z-3KE_L5@j#C z4920N8zx9&Vtdn(LU{m&sBIiNCW%(Q$||9^2|Fph+8G|1| zM}r4<(qp-b*>7FO5JfQmxli@%`3GZ`v!dUg*AirQp|I9|R#2LQ@#%s&98s3ymfC$- z^M~Nw`BLUt$GHO>!(q(_jzl93xrTY2lHA}{5HQwqyUZ-12~ZLlNToG4^mCr585Jzo zs&l&>vnC8>m?w*2x#VWNTc(;pfX>Wk#$0MSXVe9u_xuM&T`uSd6Y9_(p&%vtd|}P) z2U`&&4w!qN!a*%2x76xq{FjPnpwj$~wOF}M{pEP;Tb^dyM7)c&ffqpdrmpGSG^ITB z!b54Dbv!|}X;j&yM2q81ClL63=$^rR?XKob^z^JDp?Wf;rPb@6@#+lH==Ktz$AnlJShX~#?JpEACGUtVv0 zdcZ^P1<$@xz~l@`XcInX#pI{|9bEKL%i;JfST5Q@xm2QrA`nH<})rt$-qn6^fs7XWASP>!s@gap^(10vB}Scc*N+;uu1x@dPL&WimcQ ztaF;Y6V#?!JV+G1N}@W(j{c0#fO&8?K+{3dXP!kW^k!Zj1eW%3HH&7vDW~Y#7EVwt^nU{ z44DbW7^1X2d=u{p*#ZF&_OE83fe6m1vpfnuZOQzE%UXWi)gZd21bT?Je#~5VNSx03 z96!A(0}gHZ+CCrpnaGW*;U}SdS0dzv-;FgB_0ykr6BpdNk6z)o*8q9MdH81emd@?M z`APAN^FD9|>KbN9k)YoXJrPJw_fZuN?O`9D$Ysi#l$W91IK4g|gN6Z^kS!90* zLf6$H^)p>4M#)MC+G1hIPmZZL(3gE0NoFrn?{ywDlK>HZEvb)F)3V=cU+nAVl za)y;-p}mAG)f$#Y22KYvjiDlSwzOPk<73(O0-kE-4##|X$1F~?i*?Jp(b8Uh5fX!a zVU;k1{(@4|8$b3Cjvjf-?>Q#CHbxCGmfUvKCo98Wl|eyb4?`{zN+$1ijT)nk4wx99 za-z?KQ2)75v0$3j<}S*>Gu7oGo3bV?K^nJ}c|^EKyM6hxE85xf!XE4yg3FQSr`AmC z;eweqxAEIK@C653kQDa(H#(*60Ya!xt=qJT*6~I^oG3!-oSCU&FhjU zAC4{gUVS;){MrBH!2UXu9f+b#tPD?B&3nS(?aw*RNAzt54F zd8uG(+&*ml=Wp32td>Yl>3=Z{C~6qlls;;h^xg70t^{yI4&_L&I@F?6G_%NFuJHd) zN~|~)?$nYn3fMxJ^t(~E;?3{Sd#kc2OGNU&>Kg6U?Kl*F(*gzFpsQeZjPmx}sj%Z| zXe4C)msRcrQ8AkK7>72szJ44_4yr;rilO9K|0{KhV~%)3g0NgNu5zrfNT~z7_DrpOx^_k;wxRWGW|qPGKJxFR`E0BFXe$Up2<~Bm#rrix9W@>`o5fY3T1w_5ec@|lt8aV_|YholG5im)&SG^GK()@%rW$i|EVgVx?= z14hkPD(Ur;`cf?IE*&JS@q$pAWMY)&V^ikoxb|uS->P^MUzgB=A&H>A@N?G zS!t#=JoN_89AL;FQUweRF`49w8l_Q?{qbFa0tW_|A{ydP`}&x@ip50uS3UEpji@Vx z;=EsYLm8d29~ILEW|f(F4EIEhMU1gmxCss8YJ1VJGz!*}Q&^v))%E3_2Rd^&1BMd) z7LSR}y`pZ@HtD|tdkfG*=k|t8R$G@B=uN?{xO`5=Pio>J_5VJNrKq8#_ z61rX7r0L7ZAaEQb5IlkYk;xygnE%S0TY`bU0Zq+2Q_UfHm1MIkY1{417{~j_-F!Py zW0OWdN)~s`#EBhzX_XcZv~R+S$9`H{r@Lx(h!^g8EIxK*R#EfZ)};7wmQyMKnj|Z% zlu(8yM>lp>6!~!Oha!=gGy!4|Bo^%bcC~~fa>0d9hEi)jM?8V)gBXCN{3IsQP4Ojl z3H_+aE{!QEP(t^vsyrD$62CLZXzNZ0Dc8v+L6cMsK{o_T@qfYXCb%C-oLp3dkgVNo zhc3LwtYO^0eQda!?HYmQjfbM%-b3suVvW?NO9OnhAawZEnl6eDj!Hp8dVO`YbS8chNK9iH_1t(*Ktdh9!z!wZ=e)V(xm21-0r)S4 z`P-sE3^Y$BmZ;;H#eK%QwsmIhDSn^Xk-wRJlFs~6W+`<2(FO(Ok=Zt*8Ov|}tOXh} ztE((6GtlNi`P7Gp_-|_7F=&fbWzV8?kI=%FwnBED?7ZXd30L#c$-}-r`+k{N+g?Ca zL-jH{wI)4PJlw#=lf4x0K$B?EX>FSNvva~DwIOsXZf>93BU|(8Fp0<|nRDejn&D*i zFp?W`rG}$hRr!$`47=H+_?-(V%1PVHKO5p`2OOM1S#@bxW~(EKt64+1EGhCdtoRst z|6JOoP@Te@aRsmv`vKx4XDy0s@^*;){)Qt`O~dqn@<%DfHUz22xh5=cB@d#Tp}nHu ztV~m03!JQP5Ds-eR$CSX0ilSWl~MeOP_*h@^e33+*p*g(-3&BD5GLFMiat zTO%Y;#mcAJX431|BtWfnO=75~6TfS_|5(}A?eybglOI?%D{;TAk(9Lft*ldzo2N(i zRozyxRYj4eUZ%gydRfJ&+maK(ry)L%jKxXC4%HJ2xU?ZtBGKaXVSy@Z%Z0T_%OzaTLt9uU)s?g8?&WTXXRF{h8}4&g!39 zN7p%xwy(n@P})6XlfRk=K~>Mz$$DM^oZ-UqQ5eP9Uxz{7a@x9yn(DG(9;Ftah zN#^u6Frf|)I7m#qc)6-zz#J(QHIiIlJDVy>A? zb|~7fSr4fpm$185q{dhkokpRQZh^JqF?!I}?B2y9NmfPk%*Q@tFe(r~Fl{Ro8_{wT zF_ILgWL@tzk}PukoVQ}IjJ-K4n-cGg6ur-guZOT6F2CJG{JO+k zul-8j!k}OWT&p+seG{hIsR~z#*GClFr>@4DJ|7W23~Ra2w4@z-jDzRGOM?rmWcXMN(PY>5aJ!yz5Qc09oq z7(Q(&gKrdJVc3N(p_J}{F6^rn(*$%!!Iqcx=ifG%*1>Dt>%>qkme^D+t_U1TTHJPb zW6E+!eIiET3|hP)ovE%?mP1=b6vj>{)!||daF)LTSh?tKn8v-YezuAL3ys`D|)n8y(7M&G_CM#N|6zQ7ve^&k0iaY4bWw zG2B+kyPfcjQCxcET-Ohk9|>Li)2ijVQLcxtn3wru;g9%+(BVUVu7EJffaIk)-igm) z1_9yEt0v6@BHZpGd;=n1-9?54M8)1kr3OSpILmVGOa-!#r0BWoD?8cl;ji5LWwM=$ z17ac<6NsI$FchNX z6oBqT#nVCj%1>gbK2G9zzPe5k_m6sQW2*}A8IVM;g5)|#VWoH+OQIXd8-mhYf|>?d zXzIMUq1fH4QX1~=pZ&fl4xt4)?k-^s>POXKi(MCNO$c5N)kLfBo|@jYbVFXUf(AWE*Sq zIcR1JeRF$ue+_|p+mw>Ysrev#hjtt#_W~7^*xNAZj51u=O8pUYoKeP`Wp#3F)$<24 zuxf;STCrjNPdh*_f}$gdql+G5ss>?Pv7pYW-X#&d{$cs-c2rm$kiKqI;lIiX4qLJj=V4o`Gb+xjRvA>asGTXOlpCrDEb~|#@7^)NpaSZ37SB$ItY>nTm z9YkGR4c=XiKnBr>e_><6h;>v$zyQFG6zoUJhr_0hY@M67h#??$b2Q{-v|=)|T83~S zk%M|VmsyA3FCs_HY$2B=!;vH#i0dGH+X9Q>F=QQuN8x%wwm3kbtTn$NBBzBarb_iR z&h}o+SCwG)g`gT_NF#_M7~PumWIhWQ)4n-V4Qv+SdbHI3irmo<#5vVW>_gV5p71RI zEH=YVPYJ<%;C5KABF+N=5p^)6T^pHNd zAd5?6o(94Y@@yr!KNP$@s`?RM`W~jZ?EIygtx(@q6{K;6g`T7v!)cA=x^TgGR5}pW z*TOm#5;)IuAesPWa&;K~Yh<9n$nPlO7PhYe!a7Lm?dHY=&S?s*VeWRCQHIwaqwPzt zrb-{2$xOGaRkFw_u($tzC`|}EaTG%sEJYP0e|*W(Bck!=P&ht_s~Guay_p3Y(|4U{ zPL<`%OYw`RLNp^pn7@_Iodnkn;Oe@pEO6X(R-fDVR6iMR?UAr1@Z9!RA>kekH8M6= zasDxPj^S)y_!dQKTyV%LO(qRU=;{gz3@fT+BI1vEkWo1vymf~GtsQ3JBe7%1C}2eu z$kSCK+wfa_gI(#RHHgPwF(rcd;x(P$W>T9*eWVr*hB2&rsr-Jj?Uwnf^PTUtW#&#V z8is(#rm24WP7KdSioH0I&8)oyhz1WIN}4WvKSfK1@*vG9g9E_x4}4JAE$n)l{WZtq zBjvZe7mjB;NiY9V9u|euuZY>pH2|v%~R(&6^{MTHb)W-5~bP3ZZwh$jZzTAiz@?ck0(e{@Y$maw|usT2l|J z&`-c2pKonXj3Rp{g?tzD8)ch~K#T=^(YD=JNXDsEG=OqOy!uJwmpSm$NBU!d?YBTxB0AeQyIpuNdUPLSjZAnW=;M6`EEq1aEU=fkMzw&`rNz21Q1&lrX>@ zhX7HeWvKSEq>Z)na)uQv)!h>&&~U1N{3y~TT^Z};LiV}MZWv+V?35f}Z(9HHg8i}* zr1T7)c6Jsbuq-R#%_)TbBnbnjCuKxQ)F<4v4@(KP@{r4A;VAPTDs8j=b(q;Je&N3dH7CEjL*pWh}EIwhmDdP!IX;;V;RJY0fG zyww0tGdAd9N+yOK=}lB$rv0fp6FBN|>D&ufBA6WroG8-MHjQ>_7zzwCdz5F&PWtF3JX|SF6Bh4m$lQJa!goab?^2fdHP-lFVr9`V9^Re3yN-ck8e6K>)5c0PJtZzG&5tUAM)k_uE-+KG60GRS}4=Me)3r?LdvxJV}qfp zY@DPH;s=FL{%I*KKXE1z$1WZj1%pt61cO9WGc0^P4A(Lc4vhacWK=X_{IrUv+Z&l) zqiLOnD7Mf^uuYU#v=7>)n6wWBmnvHuH??+e34{_SPgs+IcLMtLWL5g!9x!smRznDp z@`NSG88$c4yy&!%#fB?Bp-d3=4q9sVKAm;5Xn_7ZW~-IJg_>sD9Vl`O-rrs;RnJ>EYqoa_OwUX=zAkoDu_0G zQ|xOUTF+lVhFLYlROK0ucweO9jxfGbWt+ZRCf)2w*%}HMQq?*uFVX0xz6)dj(DR+| zv9|+0Oome@_ud>++e1B;1WwX%yko&mEL$tO|2Pp?5toVjeVX-7-7$cD5>5}OdB7Sz z^6c%Uv^W=Ps_v0zIzwLAy3vAtW*UXnky5vJr2xg?>ctH_wUg7xe6~P(6%dUp#vEoY zxXxl{udu<)cYOFBEgJyC4BdX%{?0BvzX6xai=(Tiaj{bQW=pp{vnv-DN+5h;#Gnf# zBGFp-rnnUj@2!F0wdL9eqFz9E1eY0|iYrP|MRe){LU}hI{wbORT!KtAxikJE9wThE zc9qeUrZT*tiV^A^ZTsH+2|>|EY$gAir|NR;5VXbgTEQ(8>Xkw_|VKKPOT+h z#V%D(r2!Qt4wt<9yY?_7niwu4Rd4C5xV*Ed$W3ZuY75patm%MV7LxTAGhfk)cEfWG zY3Jawp$b;fK~UISv_YQRy?FScaouIA*Lx}7#56zxKp#*j7I1=v0`RNs8SCmNj?>(0 zv(o7pWJtb}oymumYmL4u+Zfl5LOuB_AP%5no{d!|#g5 z--9^(R3p3gWp|ILtvf7V-0ueRk?Si(*uji+kG?f4Yq0(xT}(0l4U&3&2Y&+VY3LM? zpp|~%tS$=5)zjA@*fZ)o1? z=!vK;Aas1re0QqZU;G@m>3(GT-wfa1i3ko+2l^Q} z&Ncx{i>_(M#r*_q8MpuFZcqns5Gmm|u4uyM(bzp44Zm`py&9o^yf3q}Cn|?VXkVnN zmQ$8(D+M^na59bF*~gBBkTLK9FeN>T&w2%sRBilcB=Y!&L-Z4UWDL6t0Vu8Y{iv^~ z12h1u%f?g+hd4x)nDP6zyB6bBBUfFF{`vto(>Lx@C7{AH&YkDtR_Pfs4hQl*cM9f} z6>|t+oc7y_96I1eJ85KGlDB)qk+W3k+VbGy@C^!^!I;NdQ5CrxF7U7C;0w7 zB4TyR{myBX^FYkchKXpR+QBvv!WNk%+5RpR1Ed8VztC zj1Z5S;IBja`8SA26yax~E6(WibkFgy>3bel7@iM}1`~bhZ>jC5e03KqVqOcAALQH8 z=dVuowa0`x5BuZJz@coc-O6m-RZVm$ye0Ot=lv*M)$qDg3{GEu$<&c`%;5cp$Y9oH z()wrtW+G``q3{;MjTS}ebJcG>=zO?L`>61Uss2<%GeS{K*bunrocErmNz=5uu6^dO;VQmPnJ1 zR>|kgVtQ)nzsJ(=Lz4Zc&UMeQm*Jw(a~$BJi=|#V#l8zu#0)l~+|-rA0-HTJx^(2I z)LOlw1Xpus7#v)`d7 zGmz%0Wqd-OJJyOA=d-CLmC`2(1h@1@;U=M}*Yhh*8@j#5uFCR$;b z47TSfaf)eLFr5ze#zLo*aTE9k#rD|!@Y)#|Xss9vi%7JdExz@y?OgHWZQ+WxHo0t6f-hZYd7JGAI#c48G-3j8)RIx>c^%Cmfna$Cug=nv$y?j~%@03j{F=t=`PeS_Swvz#?u+vEH)Ac?*sJTiE4!k!-n-C^N1P)WcpW|j>}x>} zCpTYf;9fBj;qxJW&KRwxJ2X1Zae7d#dRn=~zcVZX1aCJaaM@iIbV%&IMzjbf@F-yF zMhkdOe~-xJjP1XlxnI@WBx0!v_~^6U-k3rRNGI4zJdedDo~3wNH}Iag_8BM1b1dn> z8#)~3{at_K@p9u)EyIs{LcQ8Dj_*e;D8gtt2eli)EjjoN>=B-|Q%`&SjR!lPbR`^q zJU{x1FLD;D&vDC(WK!k;4NyQtYKV6bczhu`cX7K<93NhU-8=Z08F*;CbQ;u_%3{)m zXniNyO1!!w0egeOWt-Z4AzA}S46EEAV zP7@BT%-}HAUsYxJInPZ3y#8(${oS0_P3p(|WP7QQO>yk_)#_4fSCQn4t_LT6qQ{Ur5N27*(Th&=g6rly{16avB#WiyE9ZdeGq#so ztFj#M@*^Aeo6Y-h^($AVH+Mk6V)9%~zA`PVv7JWTH*K+}p%! zOOkWPSM#PR^XJX-m$UP~tmbb~7VQ0czWdPPd3a^J(h@%`ZhMejm`=h@3- z-*xyYB`beosrR4kVuFP4`?^IcM8bP2;IH3GIV;RRmFF<`6ien<`q;7+iNGtb!$UJe z<9v@hj;1Q|ve4dM6CG!aMHvAw)?ZG4|wS6}J1u*^uB^-Qd4pFhCZvDPLGO-t~lBcHI%Q=j+1No!VciODLif z>4bCCQIHy4?k^3Z^a7a0Xy~we2l|HpQCNIl9P90E?Pt+XdbZvl&%&gu^dcARSMZ(w zr+1%3po%fg$Q!A`jU3aT;vk|6w(3|^ow!aqb_I*#zQN{*~Lgm2yh^tCEZcP1jsi`T^Ypol$J_3dN_s~k&{9-kU z`7>xDqLDZEga*UK5ZA?M*H@-*c#6q|q&+HSy}ZIQsAkdkiJA+s=BRWuaT$r4jLm2l z4(AG|XnYcaQn5Pu$0+EaZc3*c3YuUwl~F8F;sM%C9LX| zuJ?zcu6a^5>?IN^jCX40H;6xrjdq->9>@H!P1W$HJosGA5$mk@svZb@8rE$LFO3%- zyaw=Xp@m|3;Y4Rb<%`=7HJFva(!w*q3YTq{hKB14+)a-Qhu^D~s4>2^>85VVs7|d` zSi?Zu;N;!UTU|T1jtDx*H1ZsSU!TD4CoZ9aLwg>ANak3ZPe)Q?(Q1hFggUJ6hu@~kaBdx=!TJkbSVhxC<$qh zRw)q_6cG><<;VB=J?Hst?I;v*li3yO~?(81N%B&=T$*1F2l)^ zi4s_>%4MvGkG-6Ra71X&eb$1{Y>Xf(I16Mcmq_LD(fT_kbHcZk&fJw3)H?ed~P(!3=+PM2SL%7P4d!SqQK6TPmJ)&!E#HgEuIZE$lFW$|Wo2I+IxPV=xu@&N7wL z%W8{4|L;9o0@*o7j1J2Lo;t%>=HGRm(J0i9xxg*!4qwq^R1dNAzlHf!nhHN%K=!nR z3ZVE0yfL@_ce(vV{RN1yrW)MG3s9UZoWIYzLAU?4g+L^H&^pAWGo#k>V%!O2&HKmf zM*EK!7WvzgK`2cmPjtHarJ#a65PY1H zVylKFAK4y^2|Q^$9v2Y~W=%)BHsXBV=c+h@Xz#}Ue83niQqsiylI6z(wUIsxfMlSg z%7NzY#LQa|%k|0GE-CeAyr^f>>7rxs;pvjg6%C7Lf1$`c=rIp>r{0zf%h{Umi0H5N zz@@Z>ZVy-yOomC>ZHoKwH=zJGg)%?&u_>7?~y z?AVREJv;usQ6g})tD0JAX04-N@}W3dIo=or>3e*2R7hQOQoTP*4ZC(ZcuqIA*_fBK zi1f*2BZtk1u;@uvF*L5AzC&Lg8w_q7_P;v0%hGf4a}Ef zGEE*9zrC97OpsJ3XMYMiVV>kBkHP3PD;UZ_0Er}ym;-PEUQd)$$?BuD+I{V^WMesl zyqhv^d+#;$`1Z3+4_jvqA46R0dGleddt9kfx{q)L;)ba0RI;Yq^Pt#nEdz~{*(8u! zOY9>w_b;65Cq1vMvD@1GYOZWJO{#q!ZSgG+tSLuXCs^%;u{{nPhOfE7M;&M|slE}2 zgDd?zip_=PwW>Vb{h{E~iS%1`mPug687l*QfQ0CH}XQ)HFl9 zv(czO9a9eUVjhwz#SfKGPoK7b5o+w6^S;{w)c`8`m=HL<^2cngBO*aVlBuczbSMHy z!j8&}`^S(5S+S%m_Yh#-*`brZz?QPiceEV)Gqd{e&h(;_EiD@Hxs%$ErKj^cKfcp{ zXIj{9-sjhQh6suIE_RzMUNmV4E44)FMns7V-RXu!0?%h?pM*XLPr?_UHSPFwl4|8L zKL+*G*E9_Jm-T!Dd@GUPH17S+*h1br>C!LU8_dVl1T6jp%xKZG5|C#e{+59JvZelT z(>irBlV~8UUipm>!6c%_LESyMAZq9qg|cSj zla$$hiksNjErDE4r6IH|P#!5~#jEk_?MLi+Fl8Vmzup#g%1t8QxX_vCpp_In^e-%~ zPalHB`1Z%u(om0pT73;1O#YGLTf%XmXj}u!9j>M37@rm|zAezNBkNT6QHYI2(MNF= zuTJGtFo?B4Q|SsDrP(-&ibo=_2)2OizZLr7JJRgyb#0=M193KS3G_wXc_9#fFT5t3 z>nJvX`u7S2AUz38;Q#Q<^EPayUu5(Ll}H1sg3!VGMVopTFljb*$S z9CEoD`ixd7mUau5J-!{NHlp-e8^o?Xv;vjy5&3QmI5;nG0m^pmbD~+g1f%71J|HS^ z2f-^+;<#@Wf|Gki$@Oe#B_=0|d>NCJ5-}X>9ynS@*v~OT>+$aqYv^}+_1xq4mc&a#W?d!YO7X}{7lgA1O1mOfb{G58uV5!c2x$Uw zA{_>lXpm$0<$ospQK>@#1yLmkGztl zYwMnDx*z;@?L*l~8wW3iZRzR)HX4U_8`a~H7uRBUknsfLHt@=r+>_Ph2bcQ)b&p|y%$U%b5 znQ-+$D&5$m0DycxG$W{WFq*<4l>uvIJVS2LYwU7UXKYvF?hw`7OkdJl)%-+ult|!6 z*m)9I$?GL@nWO$v;Z0D5R6PALN14}uQsw3TkN zxAN*^BQ=<3r?-G1{m9(em!$L%Ukcq(K@Bk!_Ko)wRPfy&b0udofW4^qzgc5I9!nhX zg>WQ&Qp-ampb?Z@0XOiC=^zXeOa0Hr2Bf^CK8p97tNk~IG~o4>7cmE5PAu*?3VbYu zaR@~jFs&T0&qyX_Xn_(jXxOep@uNxN(r5n->p$>hKy3ykO^$!>$NV_8a6u_NbdgAb ztUQ{2K7bCFfuKSe-aHH}%>+6skgpTXxu}^&Shl19ZFh9^!Q%`1$klKY=lhkp`%{AeQ1RJ-W#!Goo&Px_=sbXBQ7B*%&b zmTu0*|291o>?gZg8I*W@V;&s5{atryPVTUwYSVQZclC)B53;LEO+`)xzT!Vtcy&3_Ie`GcVt zz`=5B!zZ3IPZ38zeu!`LJs{>F_S&S_MTs5z%e-9*pZ1hkOo%9|1-^cccsPg^@}ss( zjMEL!Pap79bp>uq@#$2(Yfg1^VAuJv^h8f5>GsWdL-nRI@X;!sgM@UDg0-H!kZHD z!7hC_Bz=#83gJs4tdPhBO5a*0-6=?S2gR#$0=M-ues^bF)@39VP@OFYUo2-p?Qukp zaPUGLvIj@Hf+N4cp%^o%6f$@l&Oxr1^a9!??vXb zA6UMegjWe!gdZ_B*Ka>F^uCt{R+K3VBk$rx|T zkkiUe>Z-!%l^wTbSywVy0oYv^ib|};=(GEV4sxe+Zbrp{Wa zFr%q9x|)|UgV64|sfB&v*DIqI&C%% zQE+Ks;p33`xzpx}Z*7Q{C5)gtFw5^dNAj$KLt?pW`kcuL+%L`iv@U$< z>DPI+k(t~Ea~)G!vxb$T?W(7$j19-`x~e(4key~5KT~21#CryQ0o*KF$qa;AJSdjl#8^3O?XZg0=6s3u9mqBnk~4iI(+IdUDsT~P@BQYQd7vgbI2i$q*7(3}sjS+hDLY*NtnQoWoXiwwlMtCghe)SdG@>Tdgrc zwENnckI<4btCS#Lm*2c?T#NSO2nQI4!;>miEH5f_E$@sbzdGspqHy;Dp+e|NnB_N4 z$L%Tofpz&W!5&4Uj>3l8FTHuV8$Cz^OWPR-^}D9uY3(+1D6BW+U@qX%_U;x02!?%O z)cc~Dm%Vw-xIpeEl+p%NOAH|*mAWf4UhIPBh0gW5t}}PX__yxuXrB!~dnIYkrmKf~ z*B8nN#1c^myfIEZ>)Z>x<;dHfq3zCH;Kl#vCACXq+{Vodo?7wVT7}-OuSPxnNiT~Z z4ISUby*VY>nz1}w6FL8Sn>yb78h17}!s{u!CjEYK!v|ybXPDGSkNb?^DGWpssfi(g zC_V-Cu>ro_fq0@p#mi3HHnRsC+0AXYN7g96-In=LXuJoKsprlSj%RSx z67%n9if%m7M1cq@E$@|2U+=H!pDfe|956ZzaD-7tDEsq%=6-rL651@U5U4m+VH+lp zKiv~dc_b1bFi9(sFZe?M77L?M8jYPH1{%zP?kF802%{53UZzy=~V>#eWKp+z}qP6mH@^3KXmi5CO>0mRG!R(j3|bFvbMMl9dM*saQO{oVzY<=EAq zv4RB=w-1+ni}C{F@Q*Jk!*9v_fG!>+Q+w@arxqkP)G;Tr*`o}qL~E!6b$LuBUQ@myYB(E4G-5P(XqFW|Hib}eSCJF zxmuU%hnfTXTK^N>1UqlieV~GxQeCB?$fnYsY^1UwGPVBew*csU{t(NGDNT zVi{44xK(b$K0`AW^X-G8Eu~l6oPM*d_AiL1Ji*Z!B4gXSkvsZjJBF`zj6dv{{@cN@ zeX@wmWHg{{F+o|s$|TyPb#dioRQu#&TB0kM#iQ6XR!p{UI3PUxhUi0}j@7EH zc0_%6<}=kDl9tor2(L7LZ)=_Z4*F$5wBsbRJ7bVQ-n1K?o&sQ}8xs)2QPQN$NDP)Z zEqfs(yMV?`=Aw-~(=;bbv8n0>wOaGmK}wnZ{qn4DF@3pML( zDij(QoVyU@^e(mDtXxm>nHH>i8GTr&T()FUc36F+T2pqAMDYz#etgHU=lHO`@TeoY zjA>e54#k{lq2iB!yAi*iL@CvU+?3PpSgtRSNi(d*IjD?etDulh`9;d= zJ@xb3_4e~;wqjJ`(~!q!)b(Gi8j|t*+Y~T#%XewrLFopPbX^$Q?vG{8lkgn5bvsB( z15~DQSV_DrwT{E%mws5o&}&_O&sRXFHtxz*=YZ}!IwJ)%gZ_#k_2D4?Eb;J{7$Du-y4v(IhQn^rN}xQ)qK>ZZjxn8}Q38#)7XS+F$^UEr>Kj(nv^f;?y5%!dd1| zXFy#ZRHOj>s12=|#cf1aAi?R1O`GPy_PMs;qQD4;BxZ9CfGBW?hlXKBpQArPCyh;~ z$ZFrB8gjfxO@$@4sdxSR?eqta6QY!~X_6@mFi|xj;z)RRRtstr5FVHd zFL>vr36lKG$AYkJo&rBKqxC|QRV0Cf>E2KuOAvy0y?)vl|1AK%=QCD1+=nBohocEyWnAld=y<)x>U z&nZKAg}r#E-9Kd2Ll_p`g}Z7&qUD3>{`}?mIG^?U1FzAJ>wnhqqk~9`@Bf5<`H zP0v2e8S|es#)v%|DnkHbPpLf8#2NiviP!=!H@$0GMuiayJzxN z1tGM*Qk(c9Oih9|A09$EY*w_aO5qj3b&rTNCQh<4Nwd94?@4hqk!%1)=NgBN@fPls zn!+tZQbwZBciM&eM>&$7q&BV!6jBluL>E6SL$|&aF|fdAMvi((0|&YuZNozEwDb+- zQlOLo4~fIH*{@@c=_`R~Lx$b*(4t3>mIVoFmjR^s#LS>3oNAUE&CawiS#vE;fT2U! zrzY|c%x1}d%5c29)QJ#9WbB?0Cq!;Q7Y?l?e5Ne|R3(RLPlddBUyD)Wu@$n=FN-XVxA8j-Ls58>wmP5EyT=BOe}@_k&6jRHcMAUaGHpRQ6iUE5hkA_H$1AKM z*xWYaaMhp|yviu`BzyON+^U3U;XpEHl3ZXZiCX>_LaSP=|x))84sI%VyPigp4X=;}J(7zmv)B zm%nyXWS6Z^p?%MKh6q2_p2ZT44wM=5z^%+mQMCq}SpsJreNQyL6#YyP zPxrY2jCbs7WP<9}Jn=VVnC{dRE{>^0SLWGc$?+SkNTc71T8Xz;g66gWI?q21H!_FC z7@?6~)H-fx6|{iFY3Bz0Drm((O|k6EUY_GL8Y>VzfoThE?|BKosi+of|6@YiB@&y1g09_ zT$!%;-2~)`%aYrYA{RQ!ObJy_SIG_q8Uvz$%U{X~J7fMZfigrUJ>EuvA~czao!qkS z`R>tIVN9lLFPNb2;lfEifhP92w1pV0Lu|O=3m%cPwm$I7DLx!7)vZ~;Y>}}59-FXfonHd;>i$yd-%PIx$0g7%f$YCpFJ6I>KA<(T zxQjOjj0Vf!*UcQQlDB-2RkusGeoN*zh8p}oV%*8eifYIjU;(7mhEyGM3w&)sd;3n^Q@nhfrM4s~3_F>|pnO(~t%4 zw;G-q`uXVFF*r`yiFQmy!SDQxF}wb3XKwF-^ANSny2E0WQWPsmL@{k$+)kkWo%`7e z4eINWw%y^%1oo`i^`c8K|M%esk*B>k|DFAc2KQ0r0wp=;Q~3fXJuQ!!iRr^OqRE01 zAtF$D6`1Yv0R0=^_)Q&NQC{k&dakW8oFbc+7`wqE3xKt|jpDJ25EXyCU+OItcP4RO zryEo&))swRbn@H7viFy6{b;|j2VNP~)Ai4~cXhEQAD1;Y8pNKNt8z=oc4gf5jelNO z-z~A=mA5yE0t%>4JS6j1COmZmirll^M>6dvAH)Zge3}?6dN0y%`#at7w`loE)s zag;8mJGzWvD^8JTRYI}E8u^DyO|h&cR_TX@nfTu6SOtp8CnNQ~g<4`q1ZC{w-~VG<5gI{;{0OIPs6_ zNBO^=`$8`Qem=NvVWWv5vnzn8FeKD;z+*c(c9mUP2g&mvju-^}OHlvzj)e`ra~P-4 z7bO&g2Ir3@%qA-P#3;DKZ+3*r`nP)iM3x$42It?Lmd zJ@#!E#d;nuRexnGiEGr;h6XWJ5RRgbSVuxDv9)OXy5;H!uHQ*MX`ogYJ&5MfdB@!P z7J`@%lvSM&Z(4m?qS0l+Be8b@FRtTtgrMXDdqqkzY&M8@@d(&?RJq;Y>Qi;@3W|We z`1N`lQ)-hr5}Eo^(z}hAj(~sNM}PX)h{b-qlVZW!gW+qfs-4{ z1d6XQR}3^bmiTIPMk7|F*3E5nM3^9-qY_9uH1bozg^EvHrWR3$T#SlxVXD2Z9J>_a zno_6?pfO<9!U}EFg%-pchv;hc6@rfvKAgkVsL>=UrD*2PAg_2)e2JDYlFpK{UV>7M zB;~pjv2X6#TtBDLvQRx~T26}A4)xpOYAuSN5(f&&4XGoU7^5l|qf0LFu<_@`#_(Jp z+()1{cO$=NETwQYWiPq;Cv(eNZ_2f7(odm@Y=V`;jap6!qt8-0pkmz)5gjp>mV1=+ zRW8Ph*ygE5#kY#;ZyS@@1luhtCtmPOzVnz|gi28aOfKh4uEe&PS5K}DO|EM{9qm|A7#08RQHnra!c}p` z%{s=)>M6LO(JDUUh&1a*tZDCM-*uIM$Y^{WCT-VJ-VU9h*8|Dz%hK8&vb!7iVaBW$ zXL@Rkd@`C~kAbM7U|$&kNjwKp6G)^E%wbUF_Z6!|P+DWa!b>svc4m?!2F#Eo>$|cZ zuCz8WVn8d_1f38$4)sXZ!kWv{$ZBvdWX^9ieF&G$O0M!9fXZ=Vmd`mtT+|`mi4l9# zPZ?&G3sO7A5Y~^%ZrmMYM`X>j^nmT?SWWb%@N>K8GvXxXlrNvtqwtcdNV2*N3>tD} zSC?Rk7WMIw`f~>w4jDV9Njvj0%kF(XdQ=FHO$S;L_ZX0*cErg6sAELnZd1ZNfMNc{}24-k6cMzL=U*`K5Wv*nBVofNm5x zz%BMV@M&oHr@4jepU+J~3$hXQP=BDIV9Ktys-H6v)EbTSYxr`WNMw&f6aZgaJ0EWh z8RsyEYc3)Mu`i<&M{dB+Aq|#xnXJ824$J98%S1Xy46d!$099W1M8rC0M0CDCujvW7Ou#!KZm(70Gc== zBOLLradJU#Pa6l6Y>NXw8XZcAQ@TDx)GdO~0pDTNY$6Czn(Gcq5*uEuc3Q3dq}|J$ z1uU1!wi26fu+r@OxU=vOpd*nCBd=f$B@6&w>-#yZi$~Q@#3KOc@SgQhh&{;_1 z`5We&H`-7G>tZ8ZtiKh*;MW8H%Q9&n^2Q(2VTm;g4DsG^CZoBIm4Bw38L$8X}@3Vm1CkJfc`%qU;E<*v8h{MCCnUEw+;O0f+r4&@DWx?Noqd z6iCnvQE0%Kx+L*r+ErQ@AmI85wh}mm9d6HGwiKW7m6m=6lfxX6m{S07M#6?v>uyOR zg?3V#doscBV(JMxzi{_rF2!IT_QG z>sVD@rv5A7WQ*$Gg=b#hMLEuHD48VwV<>jiW&ty%ioQy*3UYFQ6^J9U2S_B;!u}6d zkG(PL>U~XRZj@D_Ail5$HN|(Xr+D5xi(gH4RbHQ328iuGY%}ykHBqMJS5Ug|Z_(mX zSPfWudAG%+w^iLx#G8ivvAe_Civi2T3goe2N88Gg^mkr?A-j40QCZeO@VHhQl77^) zi%*4cmc_f2AQu|FD4PA_9y&!&LK-cvmqV+qT21>#Tk0la{)1u7pUgWzQXmB9;jkeM;hNd^^8r@s1o+$M5!FyG0aOfYH8!)`Ta1 z#7iBtT#$ajVDLlH#*fy{@5}HG?M)D!>m!oaKRs#h*ne1<69JW6vL+4mXAP1hm-MT0 zo6i+jRU308^CC&e!Gn!1Rv@s|*QQ&NYIHBf+SVAe>NgvN^AKPsxgBQNz3Bp7j}8L$k$Tbs9iO?HrM$DB|_PQ^(bD;}dzr5Y;-UR;0H2@FfLt3_>;49dl(>C-Ou zL??*=stiQ8J9?NCuabSh&5kdcl+Wx#|aGm5VOf^F#q^DJR{!?c$$#}Ke z)Q~1Hv{E3td*_gdEvl6Hyw;a${E3sAl_9@gMzQD@u3#>B$N;yO_j`*a<{CGlU|%7T z3s(eJ(ghniuPAo^Ak&7^8ulz&BP>TAFJ5uWf8u9?k#xzhRege&p!d`%csZy#MYdpo zV&p?zf>(TllyG8JU4nq%_^aU(hx$-2!K?TH7>T)A!xMFF@vs+`*9bd3|uc&Tuily_7xis5$MP@mRI^B2!aVurWB0;@k4XaE@(0y9q?&!gu-x zZsNr>xWC}DvGqQ7DD#~58@gn!_wC!JRZin62GNpV$q%PQUet-@ja+yjPAQC9CclVe z5X63sTixI3Trj>{L>#s}b0N5W!}oC-xJn#4KQ*F#w=`z5H6g6j5>Qnjy0@E!3TuTI zx8~9WMg;uoCJt9L!rr*f;TBv7uSn7bNM7R+tU*%vYfMaDTJIAT=RBqO-!~&yp<|yf zr+!^d6aSr||2xb7cW$JWNP>tfGL7i7>GwwQ6P7U6sOdW2V1)c%iH-=1(CMr5zVltJ z%$De0Vf(7{fP?|F$~#?*#>L0=v}9}q#@g^0iLL2!0y%JKs4d;iAc{Of4G~4m$nIj0 zw~`Ymh5dUm<;1^#X8c{_Uru_?ZeDfWPrIDxv@OW-vUXx={d+5A&FmNy4gg4$h(6}O zap`qBRAGi=D3OZaqS5OI*PB!(d2cIB!la%|(+R?L)Q>whU~ai?MeC5Q5CF*SUJ%!j zo63ok%Hi|GK9FRCo0mzfiK(Q+UqYdn86;aT9-4j#;jaKpiWStq@$4PB_5*@JrI*PY zBkx*4U=;pr0u3a?Y2_}zpxm&`XUK@jg5d9CglJ-FF`sjZt*fDA`nAKml2{`9e;Z@j zE*ll`H-BkXL|K2Q=?A%e;e_xcFujg*`HFOOwAqN#MSpL9rtJ4Ed$l?E=Qq`m!`1o+ z5h^cY8O=tA`hM*k$TDK}u8Cu)Kx@u-(_G&C1^HkIWGiC}Ou7Jak2xA4)Xfn?M!v`pMSr?L&fH}6aOI&k?Lbb5 zIjswp^q#&%rT++{c5w`);sUi~x`y3Njqd$CF5PR3E{3hEAjjNYW}JT}=;LAc4Zjga z7qr6D#L`C_?xuXysGM4q@QYy-5L3B5tu*Pwso{7J8R*mgR?cVxzkkp{q4rgOFxnV7 z)1RjPZNbf6#_CX^-j(_z+2eDwWIt$x1m`5Ji@@&>CzJ92VoCSs6r$4VpjplU`dIei^O zb9b2=NrRENtndOCVW)+u8)2O@+RUZm@2qb`$m-oYRw#d(C#&a+;r{7D!MhNdo0a?b z;$Z(3_eSwukm-ta3X{^j>^xh?0_BK=2c#!j)qSAmx(H37tB@)D*Z#eLYZO?Xmm(r5 z4F%DjouV_QTo_&V_L-|$>0dSK(qdl@K&B?whm%WEvv3Sbd=jnCprOGKqUT9rM^V@N zTqT>q>_i-Fn0u#Gi7JRuO_Jq~rO2>v-g^2N!;Mr9G{_A{wlv-iTA9hW`Q&-?#&oLL z%-qXHdtiF5C7yp1LhgZu(p^?g%|*bi}$bzhM2?8fPjO<)+3`3SCnir+@ z%Rd!iUN?|Qna;UIsrMR*1qGtCEG&dF?)}cv4&O)0wIi7QEVcw5hi{WF-^i-{x0&JG z=NonG5(Tgj(ww`;T&V()2BDQCY+q)!HP$fSWJ$c>0J$GFM;) zq#AHz_#7)9FjKy352`NfoLCf~j4AU^gxJZeE;X7m*)fb!H+NTuwSq|O6k<>%v}HGW zVn8CTXyJ1moG{O^ttrS*;U)+atk1WCJC5aa<*PU>#9q`1&!T*bI{}_bD^nf(4-Q8aEUwnKY}jD zw+j6P0X!uc%N&`;JL;cgH8DP4-j0Z57U{e<0i;HC+M8)7E;<*0+7uRjqiZ;0VxR2c z$qKr;$oet%YMW!(Z$DqG+K312k|E5KyLg*MD1kJt*<2e!Z-$`MrRSpP| z&_culVVmwJ+4Ok2_WoGT<9%a2@q=VSLgObu78h-)VwDdfMEOV|#Hd+msx^%PkQ;}A z$i2bqMWC!$Ap!LNm zRYaOWkpPP$3=PV|_E~Bf(yY$5H%5>tHtAZ1k)oq+Ma>?3qYk~@O*i-}^IwvQ%2Qu* zbQ_Jt%Lu6)WrGdB-~2g)vT#QzhAUJ@kR)oG&gA77hoGQMica{R6AgT$0O$eK_+kJa zz!)+Y%X%~PjT5UI07@LGzZ(`%^4W)-iQq1E{3V~Kg#&-#@{^|G#@2(83zOz7(P z1bf()WX_veIa31($5+*59Pc$OwkYRpVfbh#%#y2-5JT?aXNm|q9$u&Q8rczl#-bcL zeMZ%f{X{o#%xI(tk56Lb9jAN%X!gm3t_zZ5zp_e(g_*ySd)9Vlu#610Mwws9j<0U- z3M_Ba8cWvyu^8b10Zm?*R&Di-`Y8%3W*Iw4@B1MyaX(kb`}$rGbFYII<4FlHu>Ski z6SDlWb;F`2{WtdU9&8~fExvqz7mL|&jSW+!9&rI*w|`xqg*UY5iKh)s)ij|*^C4;$ zhI^P~3u0B@Dz=u5JVZML%VHW_D(DHJe8@AL@r;l6l%T^(1)|`H{!V{@i@v_I$e2R{ zL=wtG%E?5--H-Tbu<&7Pu*>U*eH9QGnz+(CBK^^vjiM9X7PJ^#Zx|sY2GzP_M71@%8{;g`V}6yA+c98?4sNQt zXki+MA>XvFZfUFDS4x2)b?afbeJO+!y#gKg_m&I*k>iM_zt!wY9exC zxD1xnRR*C4qo7d@5KWQdGFXJu)kJ5L#)cEY1(G+WR7Q_HA4*csfrxgKG1?T0m`}FU zt+_SofY#r+%0lk~Tz_Lzd0>Rb8RXFD5c^p|*uro^Ad+j26kr*%Mo$G%`g6ALE2VZTV3J!&LvduMTca#!Dv`olqthHj^t&2K zY*TL0#)Z|H+)A}oN-talo4MUO$w*$j0bOcHZCq8>!7@#H;1Vy~CCE9||8b*tjcGIVe6T=5V@IUqY1W)Hea zVXn|(%o3j=Vg8aMq+x}F$4XG#-vY?nbcZ|ghg z4}$uR^RqrsLFuh>9z5Nv@+!OH6WYXU-94ArWVZj}kJf+qri>=f2BltP$^lxn7mNrP7_POsSD>9SfY$OD#<9V{7i8@eoyOv7OFk{CM;F zWHUk4=!pr1t%+WcOzMske5S%#$#pnOG~ht5S)QUHnbc zAuAyB5#HFgk00ZW`g}Sb!K53sn4DE@r%bh;W0iyvSREXK<@XKe$Bq@`j1`8|7CDxS z$P(lPG%esUwD=fh4^0g_k~Rx`r!6(@E;b;#6M zoAz*-{F~QU_|eqh`IL0mow_c~ADF=(Jk!V6Nwmb+PnIuLvhhqN77z8&Y(p6MKFzDy z`ug9Ah5z`LdbHY4Za!vu!ax{`IR)qMMXQv08(M5g6hLIpwd58I%IS3djLm5aYj|fe ze>=w0M`bejWiGGpJx`5A)lo9{P_ocYu$Y*)$8URCKCCP<>#Z9L=b5JAt;T{zxgywO<*H^WTZq-5-=59Xty?eki z>rPbe!k4C}2WT;zCP18zf}FwVl;Fj;H{G22W85U^>J1D*=ta0b-L1dTw_I&r4bScx z@Qg+aYsw_)`O%MWH7@;&f6+cRdTT_-#elXmh6cbQN~V@fcVrY1ucHPPkit-z0;q~z z>?FDPn^D?U>i9bh3FdDT;+7L-HIqsiDl8acTMJSsW0_3QQ}+_PZKjHbb(Wrq?*7(U zPPZy{z8WIl(30mFTz0nD{l^U+Z7g=l?y&I09k12W?t6zby@X~dsNAiO(-X!st<*6! zm|zD(cJGOrw{LQfCO6W?d1DsVI&!@CZKJCjB36Ak z?ffR618LI7t1(o54nkbzl;0S*^}8wVyDv2$Q|uXf^YY#B<-2kz)%!bH2T+?07@IG# z{8fwPHSW%ZrX_`3nP~ChwnEcM4G;U>q*CUMe^7d^6;0?xQzhl0**#tD9aJ1RufGXf z5?Aw9YTu~*){>yomiEF<0t>g`m#=gUA_DD|D+(z*284dUBc8}g$#y@ss_i1Sb}soE zCh>M|btxXbb{;b+UfXuwn^Jt9?R*cU_=DT|A4>@&v8FGuN!oYfXoW75U`1sKvM8B|;tFmG~BMK~#OG%~?mAc%lD;e;#XmVZo%8;F`bm zuVekqS`obf{xMrQ6^&NSSU0KK>oAK(^~{Y_zQxlgUIH*Sqn|n+Z*B*^@kIU1IJl|_ z1GaB^B|Pw(SG~I~-6Ew@UM)Lv3^fl>dm&}aS$H-j>@W10D9ulyBOUQv)0=e6p5}=X ziSER`(WB02|3ji}FUiqND{DH2k-tB6ahaQIAh970y-n< zvLpF@&nR+%OXQ=p@W8sS_tFxdLwgq)3gs>FW#jn z{4`X>ncuCJC_nNy^NbBB*bS=Y)gwkDN(O(u(GbI5-^2p_qq;2mLPZMXA8D=tI~cG) zYBDP^fhI-Mu{g1o7_+|_-o&;SJ{aN=w)}=kF>APm=sJMj$j_D*vZ`v5GL** z8@jIzbnX|wsjo7~AdaJ!oUoOe;naU=JTYPH8W39~i$f>s*3|Qm2@Un!`oTdQt=_q5 zh0_6cX2KJ%XD3;gq}oW@*|JmQ^9kINNYxvSCDET94|P|4s`CVSDm*uauh(jj{labsqaKveh zM?@y^i!O74-c;S>{ArH5DCfQi5O!j?!~q8__&7ZH*RS=lYe~I)X?%gO;0Hf5#j?*(jjpYEi-o2MXSNBTt$@1{p4{ zcZTmh>EGHmMN%0}HEzXAQ}I<}TMA%v&9Tw7N)s))K?!O3csYhuyp6?SPqDn8o!|Mr zCAN4j2C*BLtHLCnN19MGNO~q>j7&rUE~PkC!LQg%HwrY`#i%_iXF1K#!A)=(5>x1p zLg_=vrgMqU>rFE#_n#xZ%t_YOdC#p$LZWUk$KIQClj8M^o5cScsNdeb9g)BD^8szN zfhKeRMGcR5OS175?dH#WlK4Eza@Q#|)84fArReOdFfC3Pv3P0k-M^wgy`yfS z2^6J~_q-TuN~EtmTOU%(^#8y`qY+G7;5F(~y`g8iyV^5aIm4823SMmh0SC~SNwf{2 z00ID^QvpqBC2}AFf@gwIOA8PR0lQ`t8z19v0<#vKzM~hzmo!efXFiU)rC;KC?B^Fd zGwrpCpNFH9if1|Klq-c%<<0UUfN+`Ope)4vJB^B$$%;ah&B*eRSP(YXxBP{J!NgZG z9Dgv$oJ~HuZ;xb4_*cK^^1nP->dtk4^*IcLK_;1JuQ?D)$oiru&(nG|6{eIUneSyg zk;`Yl+>`HZKT|9dOD0v|mQ$DhMx-k-M@bh#~_z} z6X3baf@U+$64hXrr&#x;-l^l=((czf)>oS$r#FQw;n;DyJbJP-csXxt|IzfUqr8|N z-(|a&5(zkC(5U?Rp%&o#TSPI|eOPZY)1779;?(!I;&)^95w1-t3uaguFB{JKggP@4 zsP_<`18c(ySv!8$^!~mYtbt=x2gX#Or&u0FN25bfip{%_3@!-vyznP4?}xEwR?O)+ z<^kMwY&eS1pKzt##-TwB$|tStVOGr5$@yniBFQG1JThGGN;D~(rpa@3E_GRWPBC`K+{LyyZ!O3$_b{-0Fn7z@F|g` zpt7tK`yyNxmwk?-Ad~5QLy&%p&wqHkjKfHC_yF{06#0?Fx5o=%eaBEjpFc4DK0!ue zL~O`dQ{qO576|bw?3R;V+%dYbDmMeaX|K4h9~8jr&dk51=dmSJV`_Y7A^Jvw9}KsQ zp)Dc+G@j<+6JWRLz{8^AguvaDesC9nc6Zdgqt0UJxaD)Vic#!aVF{{lrw$c89RyeB z>c=!*d<8IjRmzI=SlrdlUYzDfe|Zf|R;SM|t)SA8OK@zz@so{b%=N2)R&NH&>M*8Q zw%AeHz9MLw4oLGinA^h&C!-6@rAOA~-l}RB7jB?fG%?Xh?v^NSWX38@YWwPvav&zp zS9-2zRHzm>Wa4$U-`FU!sURqts(140Nn7KUWy5qEeM2JgzGaSLuC$0RbmIG=%`VF9 z9Y9VUQ-e3v#(oCfOZ*Ezm%vyV5~C-+A4g z#D)EoL3g?Zqg>1mqh4k3&`??c$;xkQXJwLVNcdt?ozW1}3^_m(8zq*f^6wHfZj0tq zQ&N@9blneV(aM_^G9c76j8IE#_0}PEo%Li!o zm6c+&J*6Q=1Qe{=qOr;ok|Iq?Fmx+6eKAxN6?IHDdKIyWZ=9K8QE<_sSvi_*=FERB zV{e`aNm)@QfOD2yE>2%zH~)g}SO3oFSerss;IRg@H7#P`p7|h<{e^v&y1?9WmKYju z<|F@q9Rm0tRFnd@%ISVl6iHGL=YRQQRDfEE>oXQ71#++{hgcKq1zMw)>M3{nz?e|v z1?ZzKl!eaXbuisjm~J;-N|O#~xF-m_cn2<&{ilrn&G8(qBI`h@0ZV*z@xp7kM~)7Y zSs6Od3>e5QDkCNIC$;J1^Ra#b(mt1^@17?2$cH&Pr*S zatTKV{b%W3MbeI{bO~tHK12t4GY(%!!H>kn;3YtIsjSUyi@-JEthE0oQI*7EsLTMf zTyXUWo{Nommyp#!+k$C|(w0&4;q1OfpoC*Fz{;M@t?})c*FCS3 zV+$W(X(BRDaKZ}3lwt51WU`@VSoIL%c%?&|2B6PAv)e+U_|CQYqLXUGvuo&$rP->X zfxIL}J8^@A5QjVGZ`6_=-;ZJ(yP8@OAk?_JxMz8$fS(NA_npM$30-L7i?M;}`m~mif^Es0( zj-mGCZT6v}wPYI?lGg%0Y5+R0ak1H6u0CEPABQU8V&b8AX&;v*~RMSb`=anD-z?8+X1@Qhv(Ca?L zbzx6@*Rt!U+sFFpXT&fMR$CZ>(N;!`b4H1~E{?v&wNLV9dvc(*F+2qvBn$SM9_KnB z7N8nU4czs_g4*~PCj)c0lJ}7t?7mYG7<_$RRW$rV+OBSK01G?=)By*GYm86Y5)QMF zXF;QmoL4WSHL(Dv@Lt(0UT8jO2??u%zw_{ZJs)rY=-R^4nIMPj?OUy3k z`+j_t=XxpYyhZ=Zc)&P4NufOzCMAE1L*48&!t{R^%9FkrazMx7p)Z=sBK&(#NH?wf z5uAB8oEK%opA1or>V3O=v^phA&@@&m=cb)%MFGakzQ7Q5SYocMN|ZIeaT4wSsO6Z6 zHm3JnxaBtykkd_bfGMDZ$K{!d!>GOT(r(gta!1QeFG?8+Cs9xhy~=u3gFGF{TvkH& zKnpQ71$f6^CDs20-)|~BNd#gmPSPF(vSwJrHa{9WxOu;+y7}KxmSBPoIJH88Rw;>Y zO3D8oy}-4v{@=m$^2qvW`;zDflmWgMV0rsS_&AE3b6m~WocDHG;Q_PK2hcZ`-^-W` zPs`~B#=rykWr*(VNV3~?h{0VL=qp8!B;*E@5kdhph%8E~fL#loC%p+YHYMv$iMn72@po64hKsMST<#&KCg84q4$)SqsgA#y4 zkwmqGW*#Fm4ME+Zo&xrGteqK}m*p-4pJjo6Z4P8{O|friFsi?2kt|~;nS$~%aEF}9 z)K4bbFr1jzh<6<^Esy`rN@4Cv`&(Z>)`IhI+6`1VFzmyCbt~89gU4^0#3^e9rL)4S zN~vcX;F{gR{K~Le5Lx`}3uD(1Bj(PuuodUB98PO30H8BH&i0H!Oa#lI?*@qopjZd7 zj0L-d-xV83(nbA^Y)(>rx}@&sqZ#(38E>YU zx}=%oqh0c(U2W!vj?zYjUp})TFIAEpE58Q@quM6vsp78gn(5b@c?|iW7`swCC{~yQ z(BeJ(?VaO4?@&(Q7hMdALCJrxnMSVqeQw|+=vskfUI?GW; z|I0ebn9k># z9Z>Qh@u-NproS1Mywd1Tx^@eB2hTba}^7SV7XNzwu7LIH?IWrBkh zhtv(%YCPS{zTAqgG}1>_*pe96#G6mkg@G3Qfgm@ zsSHVdG6Rc4@J?y)kb-$=Vd6O;3yER@PF?}1FAHCDJhpCl#@xYCvT#QNYusjze($JnK6+& z5>cOdFrP#lGV zhoNlax;O%f7W0xLSOr_ovxJ<*ovZ?b>;j@(-8xc-W}^@+DS>BMU`(!^Q}tH#PG0Bi z>QZw`2BoxH{-x+w?7}Rg8UlKxHlED}81pYy=4pc}eoea?zg+xky7b}}{L(=7r9UaB zTS>WT|BT#^K}4g+KLSEjcjtlOk>GSep}fhm%j@*j1y&-lQZmDW3T;#Tp^BHukcMVGyd}}U&|&_vZ7aO3MBW#r z+1YZxp=VmhogAg~i)+o7+5%7=`gx6TG>e~zA5U(;IYFl8gk_jzyP~>5jG8^ zYu?wunI*n$e81p()#rW&!-@uKL=9 zXV_l*a$|3SN@q%-f&PKGroR83K`0mQ;9ZsDRHI+1JT5LpxWX+X+rt3=sh6C)GcuA~ z1H>KS`Z1C)56z9O^TwjHfD@5`qbIu(QTH;MeE<+u$CSh!LXT)yJ`En_42k||N5>Vz zsBYHF4{;BO`lewZqL*Og8%Re!PLo)!?QDz#Mf|-FE5;SJ_e02Nyqad{BO=nOg_5)~ za*{I5>VoIS;B%%N+}8`4c`HeuBczT3!g|X+v>x0)2}cautxgBv2iKDV9w;DwVOU*i z`m{aesT@7`yc5iTZED^PH)K1Rd&pnSD{7XcGj-=(yyIRvxyIl~G6$)Mr~l5xz~nf5 zVQhIeW#ZJ{;V!XXl-I^D49U-97*)mu1{qq|z3fxPhZ2Zm=ceWpJ+Zn-m$Gf}*7mdq zE0K44gwdb4z{MvZzB)Xr&N0f1X^Y4$080$g8VHTcS9EC5B7KH1*1+xqFQdyA&}(M+ zC$gLX2x7uR`mD+zWBN7~uPtou z01!Fq`)YCb(+IWI3i(^Z_u-X4Q>tWHuJGw?3f{SP0onvLIPe3=sf*K~-tCmZBWQ6M8P|d-CC<`a@oNTs^|F@dTD(b*mN$NOoc8Hy2d3 z3sk+dCt)%g5~k(1BL4X|-hc%9XLqScS)l1XU7HrkFm-pJ2XxEiY0rZZIotAlmR{DQ zhbaxbw3|s7^Sj3#ee_pP7}F<|H$51pj0ZDHO)?jfG-OD)>5zaAfWsS_h{ECgi`^a# zRBO@s!;*@>pPj#rG>zQn%@12=YR(n~#-g23fifM1Q9(3@tW-(Js+I9McRd@Q>$5M} z8;M=0Hk_(@P~HI;jVz%GSe(5TJ3bvE5kd0ta%^FMNGXD?$rNZzBY4ii@WE=5^y|Dd zA4#_k$K>H?-R%598UZ)=)bkrI@a5F+d%0WF@z16N`?+1!5#7~kE4-+21+w6QKbSZS zbt$+$!8D|32v8`ZTm?C0-T)eo zpMRFIyb5lwoxHs0Z~BK!2ETsfT8T9qzTd+R<)c9ET2PGd+aYLIGT(k}_`AkgUcKq% z#Y&Dd4Y=ybt$)jSf>zeE&Dh=$QWeTjeLDd@(BgD`+h~5hdHnaq?^%u+TESlMG!89~ zx`3PCYt}p3?>|0m;r-hpl-?!{-KOl_rv0}Klip!AXPvd~WeK&3)L0;w`WhQ8@9e3H zWcXe(xXU9gBG@G?VhwfnY&g{MJq5q~ZVoJzM>PXJ}&*Ftx_WW_WIX^s8&@}xZF+%p^R(V{M z%Otw%n-mZV@m{gHpmbeVbuWL{zmr4r#*=$iWbU&cDmQ2L%q!--cJC+KQaAb1)PICW zXyWu~lHbsvS0k#o5sxurn!o?J^q$EK!s2_6sIAYldrv6;?p@RII?`Q#Hn-*Yj{j=O zmP&A7YzCIh(x)PJV=NbI=1bMj4E^SB zP5J(QEWYS}uJTaWS|Bn;JM&{PbVZ&1FQ^RB7mkWUB^k$CIuMOZEgpi&S2h$+!f9NA z3AI)XrvgDvJJK1)p5CV-7FRCz#-cg!ib#+({5Io}e3Xr+nAf)91rpXlZARV|GsU9z zRBw;2tJMH7df)6IEvxyvfcl^JOBJAcJ)Z^ICy1hJRD?)9T%_ao6RY6$B$Hcm~PA}e>exg$}<@I{i zoT^qRoh&Y7Gk_qRP_KX7`99ZR&w22pz(HqT)s=BF@v79By2H`o54whomWr@;J4cYJC7>tRGkMU!L^@<|`v#T6^LT_oazFt7A5qnyT-ZlGLPC z-X!T-Ihb0q9|$uWiyBkzJ0}yaSY>pit1!FzqCo%vL}CF%8{DF?8qlGAWym`S&#@~G z{fDLF@o+3ut&EsI*3}BC9o_Ua1}oA(J=`%lDEpK7m0PEN7$FLK!*Oy{sur*6RP(MV z!Kt?P!|i^8ZX>pHeap0}bHfL>l@p!bZ(p3>_x{6nX=<~=Vs0LwOLS@Z@@#^uE|UyL zuXSEi&9!~mJkj;Tn%e}@_2XtJj$6l0ike&JF2|EX_g@F&Bqr9MmYL`OB#94e@wmJb zIvvuQo99z+lUAeULBU6a(v#`&ST+@)b!~b5C`&Y-4o2eVlnBzGy%Z?v zB)Cv{RQfJF)mJ$Z4TSji|Hsneh(UO9eOS1t;5&;!mMua)cI{~8ww1`P0ngZ250B^{ zX%yS{@UfFBQ<4F#feiff~D6n zK&ERO_m6Fd40DvZuLnYhp$=6oc<6_uGBRcz z>~vy9aR=$LF2?RRJXLLsG(Dm-ES;gxYZ~UTajI)CfQt6%#J^IRb9Q-)^0@rQ|X6F8eqDOOh!laiDYP} z>LKP-K~1~!Mf)GpH%lv6HQ2cguBHQ~uS1+&qNMo!Myn^)GJ6TIYnP%ivYs#S_XXp&8Gyd8h0Ai3W0?>Kz|B}SlMEEN%>;9 zk+F4J02LbEaFea^@)8{fw-Dn!vtWfE-WGoThv$?nd`$*MTrwt?hS9=~$qtn<#;dhD zJ$*ty-3yB<_FToHE`8c?bD;vp!uVdyDTcJjlN^~rGC zQwA(B4|@MSFy%OaC8LYNY2!T72+z}A)Ax;X?o?2I_~u`U7Wh>vf$Z}!>M~$ePM$pM zZ2flI@T10>N9?ZPc4|}rBlokRL~F_2_LUY2m%ag-EtwsUmenbbcVB{PaKb$#VcnlB zT1<^OdUNd_^!-`nitZ=73XAq!{eI#mD;Z<9H6TXaO>B_CbuF8M|4v82p8Q$vgRC$d z)Cmc`4V*l%qslc!J(Uie@lgi-B1naCBy+)pRaK2@0!l7r42!?UMv&h4ehUBgg%cT0 z&_VkFGV>?;fcI@I7O6bY{qt51W}_)hoZ_U`TL`E=LC5l^cxX6?=M&>E?H2Md%3bSQ zwZ?5t=fwTIT2#*7amQG*u5){40MwOuMn`|wIsJR(=#2BeojqdA`tO<2{j~ImD!fw-rK zJ{8MbpW4SfdI?G2FjCt;gyW`MIuoM+!zOd1IPys9_;%I5ZIP9Vf`ok?jD_Bx{y@Oz zV5meG>6pip@4BOvFoBgnv>X@qDK^llsaDNHsKS(l6>MEi298i}G z_o>Sp7E#_6S|!n?dcdUnSsgv&vvC{2Rg62O)FoD9=l1P)j);$`>XbsEbW3 zTFTr&I4b=26Q4D6^~^olCq#@@$J$yD-3s|Sz?&*pNf*5zA%F%bEaQ!*1qej@L+{Ln zVmXME!wHU_=McRt_J5VS>~>tGODz&HyX@OT7?u-G8NnC2|1#KpIBetawc7yV#4dvT zfdb&wxVymqilOHY0!CUDpe(|T?Su<3*SqTwBbW<2x?zOvOL9e0%s%k^0`@opcn*2K z6-$ZQA7!p1y9l?ECwk=)WvFcDS28L{c7gM6RulD-1`H2d^mP22MUVv7B@qxXJ&Fd# zm`41g?sB54NC1O}P{S26jIHR8?N&GUaoA+>-g2+9`=uz~5#rwKezb}wiitlFu%L!T zIOUoR%?cBu!(Q>lnB)d2=*0RPB55u7VqC1B`(4GFv9YeA5L9;nH#6cQ$jgs(FRN&(DL3(ciiTtf)PBmzGj(?y*XUDFHej#T8tTLfd3i}-ULJ;#0mYezDwYc$ z@%kUg1IHaHXB4Ipd9bJz=GWU#>Qrndl$0Iilmkp%G+C5m-V_9Y(={s09GJl#XwyB4 z@_@i`0&q$eAe#N?1{XM&+88bu;0*;%E9Oi=$IK%8AYv<^@lFq+4d}}7pAX>cT7dqE zCSI_m-mI{+M?OLD zZUt&6&X2L-0WZ@A??dDRNna1Lpr=11%j^>D#=Hh2P&a0^e=|e;mbBY!H8GlUU;oM# zP+)4c$i1C4J^UJTS|t#L&|E5Kl-yy2Uxj9`VsZ((CjZLIwoM1I`>f^%s5~dD zc$PqE#}p12@ZyRJ;^jjD65=<5Mg+rwZw%(FrBMm^ZVD@xvGHsLBu64Ei7Y-a3C@qR zjw$J@+l*4r0pZNZ*Wwwdhg-&I zC{nO!;TvLI2m-$gaG$1p4nbq}CDL`5E#-`Ujd59u0V!(~DkP6DCFmkQU@G;vlC%(h z%M6p#Cox7#uPCvNMVTvg=Labz2*>r8_7GL3w~O4!*fAXv?tdVh-KEe+wQ}7pq4q=w zo>ESGU&C$54+PLr3c$m=G-z9nr4T&5p$tvKSCZc!9 zpfXNJTkW&@NBI6*OXFEVBb66GAonKAquj+)=wa5Lu=)L@%zNy@^sSbrWUIoVQucEv zDysB|3%)3Iu;1zh>eQovjDVoRE=-}{Xl)J{y-1^FM8_h22+Dy%FGQAIZyDOT;C`OV&-AobPs#fjo%}g3~WB{+cksKya z1!0Mj-Dg+%-3c4Lt;Z@=Dp*!>zk%uv7+Dz*d;%ykoCW?2bx>wVWN!teNf3e|D9}hB zlN+^uLG|G_L0utD(Qe|GzS_pNI$ws=rz->+5L%CdxEm(jO%e&#SG28{$j_d2^dT~R zAE@8k>-N>lba(z{?=2(~xYkQ;B}noSQ6?qW*wfe=V%XK8^nQRaDCn|8>vHT-!R&LHpIVA;4HX;b3^0 zV;HZDCrM?YXu=-DM}K(9@uj<1rR8Ik4)YgkC_XL;d(ZHZPP5^kuC)1Xcjpfdi}v3i zoD}!#9}SFh+q**&sptW5N!~CV9qYYp4}QUpMQz+sC;<~H#meZQgv8(kDD^*1TzFI6 zHcR50?DYr5gy^zU(~JQL}@ zQ%vBkcKd~iAPHG-rasROGNVTi3P;BnxU%`XPAs#W?|A*Pdpj0m1Y>oZg1hxxGhm*w zIdDz1hm4Z1HI=6`Hx$kQ8naTtv&cVv!=+s(uzoRqTJ!RcxZ9qA4>Q#BmbqU?v2{E! z?16CgVYEIYku8F8pcGa)wJup-9i25yG%Z!1#F{hyjm^+fB-jRn)i*ZS-{1BZ#5Y1I zK=6R1;oi@$Zq~n_x(=86gAU`d4okBHgViLf`=PbbyS3si-8;!d-3=gq&&n`a8* zSB3~3g)LM&23)gqcg&$_u#pZ_mOl)`UVlW*Tl{@GTi4Bw$=zq8-mGc1Y~Qo0J2(+0 z9_rfCHZ8H-qc%~qopU)Ut5^>F9F?Fk44)Av;#AN5+(#hZCc@M3HQ0=N@eUoF)iTZ4 zD{nF$_)WNvEPCh;+-?}-nUfe^9hUGwYG^1k3ri%!TTRd%$$mTVvW0DDie7K3EtP+B z3eUPFYo|rMC7HQ~hLK;*$R1i~z@jI*>}-t(TkLmM;oKGM z2$NxNZhhIWn(B-jiE0}Hb0T+7w%QVmjV=7J#R*=E-qWTR5z*u9iVIIa|3ilrolFk# zaZ2fR`mSNhp##*UCXFBWyQS=!NrsBP3(RX`^+f|U5YjEzJFG_gWNO<}Y#8(i7^Kz4 zI)e9LS!Q29ph)`8fr%=`{U|F{)6m5rvSOKqRN@w%Euf3^UN(Tq9E~G*XX5QPvkttC z11)+*LSUC*nNo~TDleM%bk()~*}RkNU$+wwC?7ry?dA2|>|jdRtm!SG5NEY&E)~RPwIiky>ndN2EE9Pwbq=D> zb!B%gV1L0+w!e8QgU?|?yGI^0f6%*n6#BD-jC-$~`9kA6XM)+l+cP-)mfg%YMRM zJ*yM1eN)>Ea^)b`<h!-Ya(+I>d;HSPa4mIyz1mg3fbAsT&pF;t z7#O@K89X2G`tMvLH9hv!yL>(;;>dHXW;)`)I2jhphS%_Vs{S(u~Ba?^~o;jp{ZpgpsdjSCEnV z9`&-uQ%~$E*U0_Yw&l47%Z>u%4(rZ(5`7YsLLGtX0st^N#in6aO~2mfE(y zpHadcTsudzj3V9sjR}H)-H>~nBqe<^QCOtUY*uEs<>CmLH7g9~b`+8*h1_~p5LA3v zxF|^^Du^|KNE!n#`M$Cz6qT-@GLCI4;gc*F%;Yfq6K&{iL)$k-Vqj3*ZHH-=iHMXij36{ooEoY zQ4ue$a#%?E80jfdg6=t@EK;Xf0&cOD`GCGFfOB%IvsH+}6O@YV^Hq+Trf(hsSrujR zZnw(g6wWTmDOP_cF2KHX7_oo05ETg?I{p3f4}GtmjqmjxUdW~Q(OjigRikeEsC~mL z`X(D18l!5v%y6YRq>+IAOhVl&b(g#RpqPzYEUae-yn!)Tp`>cL<3Oq(7$;uhyiWkT z=%qtTd`Ugo?*tYUn=*EQIE}Nf*6pej<#Y6gcx;YT$0h3<2_jttKH;|-+a~a4!VhLX zHwm`3IaP_X))jS=s(fxHhqTiDt>d$gQC4d9#jh`nl&HvX#hFH>A^8hm>#t*0IET28ctpusZ$!7CEY5nwGuU|Q@4>S>Yo zqVl3a9Iuq%oI?6vG-?=nT-jT0pROjtptILgdK_r_rzpXiScuqP)xkd~K}?Vo8Gz;? zj%#oXa~y#MzKo@XO$J>8Y_%ndRH|luw=nF>W9DWM)wVzQ5bPl)5rsOyUI*m4-5k4l zF9kU_cIU*|7l+5lIz%eZpG(wQyUyCC;j*1dzo))(DE8Z2=_m!z$I9vX@u}cRNQGAX z=?ZgjIxEP?A@G{DHB6>^&N*17B$9m|q%F$ z&I`w=0B4MFe1F8OT(x`S>-J^;l0~1Kqt4&Hp@!O{ES|Nkz>C&zH4)ry%{eh)-J7nK z^X%0G@Bo;gpmRhWV?mVW%0F9gajGrvmOZLcs=l4luJ><;21K> ztVF3t5jOm6O0Z4&VnuFVW{d%1>AXGm)__3)o;fl~C?th7>Zb$TlMvZ^7hQ;U>(0cf zOn+t}&$d*;V}@b)UFOC+Rk;b15xHyn9lHcE{7K$a6&E00xb5L^ynHR(T;yYFlaG?D zAR54rFYTk#%eJYgN(ai7f3%HXTKXBvlP>d2(3! zE&G^D4VP&+DYg~X5`#lfc@f>bDD-{6mJ)Y@PO|Q>Ekq7Z(ljg=w05mGYppYXWcX&m zB83sey=&%#h>1`uo6{NEyWR$XGP|V`GVQz zs)6O>*JPUx4O4%IYNhrd`D6ZScDtdkzGouKX5vGxl8)ta9BSxOAFw$D5wXvO^>Dar z?2>GEe@d0#XDCrF68(KrA)spaxu+{cPWa^Gb1o1~@Cx_f@^Q;?UEqY-U~x2l%9{T< zN-Kp9m(?~3ZzhVc+;GUFVq|uW*EnrQ_aDpMHfkVytB8j}Uc#L2vPV5OkFaKX$wQFR zltabj`&z2GlCjZ#1g6-(@!%tB9pxmNu&U3xVqI9w{hNhNU^VuG zt-=5XOhmJ~)AFaJYUCcaaEvD;0G{UaPxl9~dEwGa0eA2ET0ETo>LLx<^DhGuT9NOrNAdg z9Rf(w9h)L;+;IvX^B#9qsQ0N2fb&8X_5q6zB!g|yp5AHlG@f2+Ddnw4ftBMsq@fC# zce#}D?A^4U))CYhj$n+K=5!|bLgiGiAA~B?7%1^J4oQJ zKcB6B8mh;mxkT*?h&hbV9~`NhjJx@HmzbSl%YsF&m~7T}&F_OX{#4YNn3a{wk;B-L z^s-+*W({p|0{dafpceGdT5Sa>LC!+JTu=C6__N&07}ej?Jt7 z&pLs`rav9=JpJPN-{9;PF$9xn?52#&J`p^fje#Cl_6eL|sHnl_l6|r^pgcs{C`#2k=xo9Y?n4uXXT=0_b2Cxlt)O*N$_c8=37N_XPj<5!ReB{v z3EN;&zLAsYk&~R1lUl^Sx5obcqfZJ~UWP_qmP=kvQeIwNUcppe(M4VXFLs5nvWD^5EfQe;%jI;t&az>>w=xa04!|P{%zH2mJ!@hiV^MuWDKukdNWss6ZwQ?nFoZAi za$GQRl`+gHu(po`%C_T6*%Hc?vAMsDbD=W!!&TfpamPG*qIgrM9Ha|M2 zRE-43GfzhYP7^;vzLc6`rV&yu#pQpWBlveg01!fkXyp3fiMQ61om)gaAY!bELVmGK zK^f{u4`R`DV)1m~>{p#$4Q^zGKoDWpx^k1cC50-YTq!cM!!9$18{<2tC{Dv#U49F_dLxfx?xC5&&Rih9{n`7F8rb-{qGytI~5=(WA&hLsVwL zdBsFJ$>$lfr`rq)16Y~*lgPPQCa2=Z2u%zIT<+-U3EfE&G+h<>3Fi=4ytn8pPMXy-6nIkW62YkXsHy&K@mzLJlv`ifMu+E{!bOrw?ABXC3IsbF%SK$K zQEjEkmrAtEB~_a)fyx;PqU!e%HF>hMBFvoYlM`7ji_dkdvHm{$h+WeW!T3){osi>;(RLLgx4#vM-AVdqPDugK?SQ&NkFm= zw+JHqh>EpK!yCfRI|Cpn6Gx+nBKRs7bLSN3CNi$P4JVWral8e@sGAR?G-nEzg(rBi znui)`!_QB@-nL>_>MxMtXf?eymL1nD_Z_MidKo-5VUmoA>cApuRc20+t-#06R9@VB zD+82-`#8ja0aU{+x<{Y31c~|nYGL&SK}`WoEtGb8WgMq(#_BX5myEb@MB_v(gkIwC z8KQj1z1B5d5Hj~JT=f+*X_a64q&d+imNX}p*iFNO#^{jwK|izetEUV%IHWZy1D3y?#X{S+b#3qw!k2iMSgQEZtSud+yTxF*8Cfzx$}J+mUo@JaKMa zAbI1u`4p??ky-NgN7s9tZubcD8*X{=Z{w+dI(>A=3y#GXJTOetz;iBHQ);{u7m~lE zEazL2ut2di}X|c)QYBr;m~LH>1T-6#dhuDj+1D;LXk#?Iir1 z=UA>;oX>zOiyiQrHVlL0ZcD46{cX6QdbG!`A|IxjpjDhj7qO&?Z9wQ7}Nv8`R4#Ia#|F`RB9a-+(#%sR#@hF1_ zi+BdYw|Mb}V*v}8C5S_&QzSG~MBc=8b%I|cfEP2Uu86G7z6S%T+UU8` zhW^H%1E|J7FRe)!gCa!fEdvX&znx)G)=J`3c}9rqYq}nW{=`>lISff0GFVVHJfaus(HMRXxE626R#PfWX%27|C3es*yHtlh?~vYb-doF5|G9vjbNcoE}SyW>4Y zE6?gtOV3i_o9ahD0Slh{$C01%<0J*ZcDz1=9I$7O5TrGt*FuSr01VyMn64rJJ>=Glsi^u+s! zrBsI^Zdms`6ldzJLkQ%tsO;`^QI%KNSumKr&gG6LcAk_aW>$EW1&Ga031f0}W~y~o zp?e7+op*85ry$W|hq5Xb^S4>vYeGA2|0^k5;&`UlNa-`9fRZf>zQVM~?=bui5cZ?`Y= z^=z!2^KhZ)ohYW98M&YHXFqnXL4ieilJG&hw82m#B?e|)E>V<) zcc*lBrw&~rDFOmgDpFD^2+GCpob!JK*X>!0d$Wf1{_OqQO3yHqZ7go`u5XUa>@vRv zzI9Q49bOQ}CQ2L-H#!LOco^gpH~Z@7>=;{gqaLG8I)$~$IGvwb;A|ggW(deL2@5-8 zz7lMEKJ+_ya56?!FGccmA<0~QE=~&xbtPl2Vb$tIKF#}?NY8+*i7H8{p=27Ub_T;ru~)K zdr_ySDfUe)SmLw}ePVyU#eZW8{igOu`+Es~64~rnoJUTQO3E*1`t;d71b%xj{;F4U zi^X9~*ki7H^{vm#C(pQ7W%2trHP|U}qaB??y`1CTN4-569<5=XcZ!>R#yuIexHsr@ zsJJ)w^!{g_?kw*7_E)9h2MY}~yo`a9i`&w*%)s|6-v~LyR4-y@FPRP#o;dp*Xpk^_^{;ijm02eu{J-ivw{9upV!6Cb1c_Qk^a2_-)p}u- zBk`aUzr#{zyaC%h8VIc0vEj$P-tIVGuGJ90^QqhO^GGt+3*N2%fFFCb=2?duLkh`s zRlUn7J>uInR75O6e%4Uf)vDHl`WCn%<*$BHef83tI0b@}d?U6B8Ff7L#@1Yj<9`S$ zUX?Rpg>qDGa>N6f)<)+7#@kj1C9GgF;0i z{;fe6y^?HzXxs{gEDF@)(3P|l73yrkzYORtGc03GuEc?W?2q6`n`qTE6=}XPHsIy2 zV&)Y){P(}9A{QS++md4p!vC$-U(kzy@J)8Yqh6A(dasw|l_zkuuazhAslUiKOO>HO zT3h=2Dajm@jK(+$}4MGglV``6Iaq{3j51oGB$IC%QqHsAOJc~1ra&uYj3vfjuX(*jnop*u6F+UMf_4x- z&w=$oql-;QoBwe^!SGLj4s$nN-Hw|wCJcokDC1iVngoH7HZP<}<})yz&A{o3DIe4t_oi*vnyj<%W!u*p$!imfq+a}?KCw{KKzE~KDb_=fQg4QalFwo9*sY>6$ zr4V%LSg6R1MY(Ufbhn$kA1Zb3jj{syMEsB}ObJfeFSD(vo<+Xz{|EASp!K&Dd_VQvdhsE^ z-|LAz%z;rsOU9kM7PL@r|2_nhflv0N{isbr@L&X2`mne1@hO%{x7cM70<=#t7j8Zu zS0Dv?HvJ-*NV+-5cRpFiovp*L%+u-q-o#n zpeN0G^=|}$xUt`ViLEZbOM3ziQ2g8=9=UZ_9V)kNv!HNw)Ic$i+1ojzuRuR^z09N` zVrCrTZ|A#PjzbJUl^~95V?NKOFu>gO{W}LG)!l!Np;hvr^`eVN+)30Y!r8h@UYDbW z9_>(q%LM3qIoZ2i9d;~h0xuX0GjtHmTJ|{YfE}B5xN6#^h7rX#c2P3y@bJx7{v2m= z=VNn$+Jt+;Rk5kb1R*xa84dkUc4eqoZ#=>VgSTP#oL!M?g2P=;ps0+((4XW2H!)b< z0#01$O#aTs^Cf9yPUjmxW-MBlXXxBHF@_@hYqZeiAltxEqJ6t@ryk+C1Hja<3&1oHr5Ur zXl$0q@KW8CeYd@>7pBWUTO6JdQ?TTW>rQqPEz3?kXb_yiNBUTEPPrlpC**Og&X>3k@~FxVvkLYy>2aZ~ z(2-jE4B7UJ9l9j1$?X_hHO&Ht#C>iy5i7w~V`g-a?9BnU8w6>dVN)>NK?Bal1QJ^J zG4+xbL9W*EAuG=@a9ua~{#%wZM5818ZYh&s0~R(MVOesY5!e8M5j$vdY)}US^(yJF zB9$N(85eaG7Lw?DJCBs~IyJp|eN1L-Shh2*eB3X647_(lw_r>Ld4VMxd69a3o+V6d zsQhtN%KuP~{}rVz;*AsQ&}rjl-h85QGc1OG>gf&=HEqsd{hte*F_M}a3&-0UOVZGY zhFB1ylTimVxs{>I2DXv^(c?sfLF>rQ;D^N0CdBo%2Hkx|ksb^G==K8avDAtk_? zKm$LjSUVd@dFK_&Q{F1tLW98fxq6(FDjRLXKwym`C#NcR+I4N6;sm+&z&aJ?+oB3k zJ3WB$F``S*e$hMRk$^@d*W0|o&Jmjpc zIq+oFIQABgCxY~yH8wgfWYc>3MUF7x@gMYon-A_GI2*!0B$j;nc~J(bBU;7&^-Pnu z2OUXQ(ybz~+&L9(zro+^I>y+%@CAKp9;V6#(N}u8b&W6eRtvVd>?CI07s~_wl@~9V z^>Oeo=JrnvD(pmy>XKHplT3~j@26=^OR^?0(khBR{&$yFUQdzxv)xWbRKi0|TqU0s z;|pJ+K%iL)juZLmp^Ad!63n-)(uSFG=3HC}`$j>qKvPfB2+s+p$*>B@&OzZ?4p=Oo&W zWHf}vUr@!#H}N8|;dVl+-o3*ttAc>4qes5yM(G;wk!vPq7%N){i2rdR)Q{5|6zxi) zLBiQ-PP@jTa=Qk3<&gV4Xl7zNm&Tv{2_!xMxHjh<#ut)fhEc8hUF2cZT zk$8srXC0xYIUo}`&&Hus-6)-VN1E3<@6bX!db6i~nw4C9ZNU}<+dS=>I-uWqe1SBd zxbAd%zn3PL-V~j=GwLKPFGhl*Rm@LwfOM}Y@J(3(m&hOKrlY{b{fB20G+CD%F%rV` z;-(|LUL__NpU-bcB}?fYvNbMw=)sb&b-~XhPez~Yj7qAaq8$(WpT&Iiibs@l@8@#YW5*f!Kj@vAoQy-xy~} z<7ew@qxZ_J_%u^^HId)-6a;7@r4M&7SZ7H|5wvoX66$J9y72ms4t7NV8o_u*x9>(-e-S_E^|h`#)}yot$4A`wilw!~JZ4K-47#;Us{< zMx;$+Xb{nk)SBm@{yqr{rpS$W$MkG2|f))}RSiKvB)XP%vjLw{QGr<3uw_C!N8kwZIM zeC!UKeY;kB1gN-h6bUd)6SvB&+03mja0>~Mz{^iU0h%DO&e6u(xv8wAH(=!MJFTrX zW`F{3i2|5>N5l}UL~)ix5lE=9gDy>{;)M2o+VTUm;r9H9IrJd)foJ*%LcisCv#OQnq*Uc|vkLzms%8)Z_VfC)#l{>8r#RuzfhE zcC9rP=y-~&>leqm$F7aJimfE`9z#IYOjO@e{VQ`jSa{u{MiXCvB0=Gv;J8;?g=7J= zMKIWFc*dP7l%b8;R=r=RIeDPKY_Y75{2Jbk?-^FS7JaBB?~wQt#|uBxD+b@YJ=ypx z=rB~j5215gr1R%~dwNBkv{S(@59x2Hm19Ddp~-T);FQcc{qQqB0nVB|MG#5%)#XHo z@MmgxJ$?if*7&Xn^g$<*6NU~6NB>zl@0Aj^vG*CzC6T|HBR}(%EzN`8yT#rj!sMYu zUGT?6*wY}*+7ZPCLdYzR7LHYMM5>md-e8@~jLp)|Z?CUeS6$c=l(m4O^p{1JX04=$ ziYx%92KjKVY*c#bxxHB6G{F|AP-187(Ja14lf7A;Q%bH5BdjSYw?lA-btgM*rc><_ zP*2ZN|COgXRVqtiI?{yEeW|CrNT&y7^yBKQAXqchtI9?3(C**S>Z&$hN0bc`2RLUa zzRQeVTV_99ietwpk&edfeyocTg#<>%Fe24@msuQ^SclktNrNjcO@|6N3ME~a1DE~p zi50rptKbP$o;VfiIwBs(xDlLrxwljLdDw-LlB$?@)` zWeJ-^$vV0|d$*6_x;+KNdAf>EPKiD7YF`3bh$b3~5pYQ7sM5)>#0_a8EJvkm*k+y5 ziZRmaBKw&Pd%dEwYssiBm{i(5Y8LiRUnJWD7e%_GAOu9v;VPtom2AREY`aYQERKfS zKQpp?dn2d^jD4VfXJnbaY$m*-phVJ8eY#w0wAV!{4S{y=p!1R-ni-ni+7fE=rPNE3Mj}<~huvIf4`# z;Y&R5S&S(1tw$nMSUGWQ)!l(2p2j4C$0Rb@wfG zaDlr`o`=63gW23D3C(&!?S?V|aySA>xc0XS)1@iO#Up2q2Pa!gd4(KzggI)B zwpb5iUr|f%fCcjJDS)wtBsJMQYmU9;T~l0(GRmW|pzu)RdzGOS`;#}WEg>$QBJf_x z-|}fdcFTIfkHnSo+QGPzmk`hI6uX;TQJU+u2te{s9-VjHOol)wX}x`GGyi@=pqO;m zZ{3Jv1Gn%r-j$DkXuT}$$P@!V%f<_icI+rTAP!$yyb*D4tJ7)_Ol^5H$cge$R0`!!f`=v31`I%qFf|vs2dc zpXWb=Qqeouy#B?Q`&=su+tpW7?)9}PNYe20Q`=|E3n0lyl3Mrpr`BP=1wZ3JCx1F# zttt@BaozIwAgo;b<~IHM(pTN?(m)wIWP!CV13TN{c{ zoFZqJvbs!xYbie`F_T8wmOJLbCn(y6A;y+}V(pSvFUien;Ii=-`p1KKimVC!eI+HL z{X@ilR~%^Ho>`L1F78}ko^wnY3?PFsT|<fv`jDSGuc7ChYGmm~`wbu5o{@ zZM3AE$E5=Cih8pt*Hfv1Je@vQ&DmIj=%_=RND@C3eQ9KqZjJMF<>5O4|7&KO)k;0N z+Gp9%gGyWXxGkeQ*ypOnD*b0_^1yEH>lU+1K}26LC|LCSy*Ymbbb&>>X~esL&161N zPyA~p!sx)p2A_dTA=6~#lX$Ql=ruM|R z$r8^T@nBNS(|bo1Zmox%Vb;*O>X)B;UPvl7anq@e>=Q`5h_SMd5I{3cyb)QM+QD?LXongupO#LKUO<{Sq4QwlhfjkzYF1U zHA_mK6Ft>qN8r2QRypBzVskq@mwkl`#Q)`qchRX~_qz;9^zs2LC zMzmBx4b4;YR5`M1`SRi(%0awe1ak;odY9BCwei@pa#JjCW0Y*Nls#4Tk~E*qC@fvGbq>ZqieLP58Nm(+?*m?Tk{_Anw?+XlbK}HVxAu^^CV1v zv9$>>&bBXxvGw?r)vVJv6+E|X`FhcM+41V`^M(AJz>Mwljp^FEPY-|5o!~BlY(H3^ zp<@8y=pYjQK$s0E0)tr8?*?Y87*EV$+!;t{r<_bJ5paD&Xs?>iq?RKbMC72J&1G6b z0$xOh$D-pc*_-H=DHTAUbzk2SJL{Gy#FL2xlep+tY2=Ig{~>WTtTU)H?g}P#Gj1~P z3;6km)ZL`bZaPOKgv`UN%Wb{e|C5)^e1rFwH(hRqrAY4eD2y~!@^6;eXyq%j%yK6q zXm}4f#YED6C=$o>Bau%LFcgSubEhkj*~ZCu90Gbu)0DZZ(w}OIP0NnZe9K1s^c7wy z{1fq8G7;ZjNfcKu*efNJu(chE0dj2YxZ#f)ton1`4%FhTc98Zn%j}qIS_OfE`n(0cm-;Cju_G+|65)+2F4g45&I(VYCgYcPS&yWCHPTlhk9i1QD>iH7I-D59=LVY@nI=O_b(L8B z#jHrz>;z4P@)=rnme-x=Ls!#dFyG=To7gy+Qaz{+;^KgJ614D;JB7?g660UefZE@W ziPbo}ycal<0G7s{3qQVVR8e1)?*^m_X|a(WvAGbqCHa&c^T5o+Etz(pJoq%<;mu3? zfxlP`$z!|xq`p_}yZmt}jb`1rXne6@mm?XMb5Vs6Hmn>6 zDtC6m0o@bPo-QRGOH>U8rY$n8oiRqvS@9!Pav{1<>t1^@e3W=JZXN^d)f!=h>SdUx zlIT88-j0;*@Oz_27{|~(tgxKj0?0b>Nia}J-MbuSJ}F=x;gL3gdlN!T+!wdPV~U}?o+Bl%ZvgrCIo#y z7NB@J0k*dt{VvBqqti?0r@uE468cpW3PIxWIUvzj!ofnsslQ7)-?k1_ir!Vk(f{n> zLP6SJ#cRgliD61G!lz#O9jwz{sfyL$G7u1kT4Ox^Itf*KC%>ZB+Ie4w>&K3b05RCa zokz%rNE`tox(ZB}ix0GxMjEO60w@{+!_fj#G@r*K2d!R>B*vTofq!MC+~y6XIVrP< zSQ{iAAXOC5oM(XQZunrF&*noqQkpqXz_b@kXq%CMvft`gHye@&cb`5xs7#Y4Kh|;m z0R2XF%VmtLO5PKX>35=IE2>&GvfIP*RDe|}O+qp3?+k}k@B~c@YC671s2Iz{32WMj z_z@YS4;@S8e5E&HtbCRYS+BwnjhYF6Q<=Bwo{R)rb8?RI@19;%Ss;|0^6z-7xq2@VAg}ZZC&%Le&Nyx;5Lq&H z5DP1j5Yl)!HIR)PV`+7NF^kl8$-?-+m5aY2+hc0mG_n3&ab?C>j)$Lv!0!kH#t;J* zoG-E%G6SKG@?y`TBIk7xOf-;dB92W&PLb2pRkeqsW5}>gn^UIfmo( z@D(qGqQ-A#223SRE1b6QaaQewcg`P? zHJE&ui0~xvaC5-G^wxGTi2~LFitmOo+LG>|qY<|Wp*+Cf4e|2OimKBNS>LIV_k75c zt~d=3bRF$F!v=OdqLnnzf%^cS0LS__S%)*L zZ^-&w_dRKQv#DDL93A0I9#Bej=)9`fy>&_-O1*U?GsC-YKMIEaVc5G>iG4Ti?xavC zf5{V9@goE?^u`R}H?i>fbsuq7J~qK`tw0(^m@3)2i%GmtEt8=4xcW3oyN~8vt2eOT z0V*eQDlYu--&4UOPpoj#)1##5;b!;Adn8y$uoZ^wSjt34bpOFixW|a?UB- zx44iE1*v=g?gY#qn7412MHc_*fS>YJ-Y6O5>kg8(6ZQf>QgGMntHZK6ITEYr$56rZ z0f)bzgQ#bvsF34Nju?};Pt4(?Wp_CLIF4)1m&&pAfQQG6Jq~Ha55Q4H>K^S0Y*?w@ zN})Md7VAE>m8i<9=|P3I=e@uyLuDu`|2B}UK+ENkD-Db^1O3{?H&+D3Vy1--&}5}` z-%*^|TXZ}p;K%lyQYT?ypWMEQ!tjLMgcdx!Jl8p7j)c*KRz8h?5n;*|N;(FV4jU!S z=Gl1;e`Guxe+Us6&Ai{wenvDVdvJ8#Y#(}NmvYvEENA+6g4q&S&boA>|0&tKz5*p}8A8y*bouuOba?UYUf?K(JOjXSJrbw+UL zZ^TUDGeDq|lG15dIBDR-1#oI>%b^DIrTRnb!~P>2ih+ZA(GG?*EI?aeII{{6mAxMf z<%R#*p@5sXA31<4)1sY{|AhKz6PQO-&*_1xc5Vb zmzw}P9fq?ABOoLs)*~cOC!}5^q$ea|(j#gbIcHrY;v*!kfD5u#2=bx}RY!K3l%pS^ z_MfDv!(2!-1c;xelgil=bBqc;PLIqp$*fk$7*;B3Gn0J$fmL72f}5HEEhCLhrx1uB z`w%G;T2K0-QYDO8RWzCE=pg$(jXBC=N)!IyvQmO;y5|m6A|cHv;j_Ro6=p!S#F2uL zWx}%wIEc2YPN$MX6UA^xyyb!wu&+Knph6^wm_q`U{Y$5t19kcn}` zOrx=)Zpzv-swu&}ej=}(ZS)fVSp^W+PJt<(bdWO2>p>s|=V$z-UXmq=6A!;dKO<+T1uo1Q0k+j`@SI4pu$@@+vJ3h?j|bB4dgMIK!D(!_@8?zq!gNq^UT38RzOn$OlUJQ@{K4m9z<=}bT7>1o^Y z)42t~@SuWqj{m#g?JO_#(rWY$r4!-mz<{n?BA+%|KtjgzE+g1b^HY+l!*d_A#kba+ z&}R{7w=lMx6S%tWKXAm~&9B%)Y^;rT7{hicbe-}y&o$9M%D@>4eXU&lQO;L~5uYqPss|grR4sLuzDTWb`!K$ozxR zGg4zaBV(s*V>eRbD_g!l@<3w89C(yJCe8R+8!@50iCr6uew&sQnknhB@dvoZ*LP3r zJ2*X=#8%E2gDZq~*w2GU7Ts4gHx?z<4lBJB#Gpomsf%PUp_ZBHrXp|(wLQy15f!lf zTZRW)m9_}E0s{Fg4f*mpMjZm67uQTyaa5FBh{|4lj+8LJjb@%ufMS($QGlgUPe>`k zw#mrqbkDR$(I$UH19bo&!|T(UzN-CgJe7b_a9!aX2O#yElaW`RXfABIYs#GwFx~ z4#VTDP}C}$b4;}}Y?QSO#q`^l8B;z0SM2*&r=dzR&PNK5Q_iErn%NZF(@Mot^`XPl zYh8nQ!|{)e6`|>iGsTe#RvF0(rvXPa3+uPkMewqR z^g4=5gQJv%FrGr}%*(^snXlpqc~U_LQg(r$k72b!jI3AjtfhQG<@wS)!n+xaSU25R znc{UHIVis4)5MR1-FS1SLvqnFg*if{zGtqmtLk%^@Q!6!xK?g{WasVW8+rN)Ctbkk zs$JjLTt82lH-|MvRLx+LFG9V9pN%6nN&AO(?bqpM{hk0y6ZU`VW%f`r`iJrw>m=!1 z`EqvGu%U&_1+`-S+8-o)74qu;cA}!bMTwW1gvRShG$pc4h`Vn2i#qj+y&@KO0r$)t zH3|wQQ_2HAZatm95afAr*&}i5(0Iz3aa=d^XQJ#R4KRw?HVg?kRbxYIb-Sc18E2WL6c#qd?ee4wBqd$p@v% z?7bfPjN!hZVAO@#D7dv*ba9m-dRBtncPP>-x;zsvCnk=jOruZT9%t$ zE77R)YGI7rsX~K1D38WV5A0L@l0Yd4t3W%=V-*2=%^G zVPHkA5TuFjEOakd`I!Ow`p4;Bv+U5d+WPy`a)Q)~p7`heX=?TtR6j04so*(3=#QGK zAJ=wmm=eTVuAa17LN)0I|5D=XlQ zre@wy`rB<+2f=qlG+hT+!xuo&tlQCG4#WnDd7V#7X}HrBgNCliN#7%D3ZuIhzb1b<%RjMl&$4+ zy%ZlpB|~S5(LSBEHg@BHVWGiCJe%hABE#XBwyiHI1pX|gOdMA_cH{|*yKnl!x_KtopH7F_C% zyeJ75VBV!GVIWY&@!^)3SRJR&iCxqgdZ6-s-?90=a5JXh%N$FD+?X8ZSs8R@7uRQQ zwDeXp4V|tW|3l;uZJYZ1ZWPbJoiGF~B;7J=97)@bpab(zg_VUU3{^sZS?`xYk-BS? z#hKE z$^-u25reE?BvruI@cZygUG*l*&7b@Z2`?b#yu8DFC4=!Rs=noe+>bR%mcwqbZE#1ke)yZVZ$?W#Y zJl$!0+Ux2&aGN>j<{Ky;UyBynS#H+)#mm#;Ph71bZZ__ZxB0Wa)*q+Yr|AZ9=+Dl7 z&}m%%JDz`ckU7#i;P~|0(GQl_XFRVo3~$blAFMhlADXRlu3Ez0(LLjk{>(U}9ER0; zsre>C@AZJfD-KSA^8%-;~~#EQ(ec2RKo$Hzd`M6I$bsb{|YsF znzsf5ua4&2yjniLMWQcjvG=y_j>ZvlS-tCR+n-GP`72p-{rq4iPspt#B&g%t@M{I^ zZgw-TZ%efX4OVmgUB?48&xBHV21M;Qx_yu7ib$GQ+Kfg1k$DENntk@%=X~~lui@Yu=5KS=p$`oXI3jsD@cJ|D zn}-Jgi@j9inFm{@Kl;QA`ml+irzN4Tgevp~mrXA=%|9Cj+89$7V5UbxzJ6ph+4m-A zH2%#KXcfoZeYlq>;vGw8NIa6a5P>TSE_yII%Qvwx5Px!5@sa^^dOy~s$$39X7_PdT zrgiz0Axf6l&>X0`l7jgzt!%VdqYb^Wp@ySKHm6lMjlt3xvm z>&h$p;}2`As_T#H8@rE={Jn`Jzch4KtJya7eyu-l9?YR~t8)CMe$+HV=62FH#fo## z(%xOiT{`^%fhFrX(tl0rPrzb7x!$&~D!Br|>h;H1fSwfM~W3o1nn}fU@xFO$5GEIa4aC;6##n4L4u9TX_MUnG~?>u*-$ zPy|HQjdttRzXlz%*UPDdw<&Cj7dHLbNdA*gi7%G02t8kDMYz30JRY{w5L{z^Gr!yA zC&4c^N*~xzc()`(fOhe`v=h)+IK$oceX-Z#=+!5ZKDkEO6kYTcm_plb(*xe-sWDdT z$P>R?A#y1`=Rdc)oDo%y5B_7#&~Tabg>Zc7(@pO*v=DxDf+t_?1;gd=+$+FBH()zV z$us+rPSU-BNAH#|mTqTqYB_qIg9t!%wlTzpx!n^c|Ju$SRC*H5#dxZ~gZyR~By=Q>~LLp@Ti+&CjkMFE2u7N2tE0 zn5kOZqb)K>9);t|Kdy?f-m9!Zi2x9dE*gB+lqfe2MrxcE&Ci8|#XFBR+SH*NiO2A@ z@<;nE>|rx4Y+bn%)&1%v)D~hk0vNnf{J;ueDsknHxB*C+cjfrr6frXF;ZIyU_wk;d zV~g5aLxS$T0MmzBY~CY=c;6_k7k?tP0ZAZQWKDrY7m0=wXe%9JzvtlQW{x(mNAT<( zfqAHl{SOULQ`29{hz?0dGxJW>tz}GO=0*ax$Y_47D@L?55JOHpcHoqLM0$}u3!em2 zarC79LZS^Q@WqrOZ+p5dH-hN|B!UHpISw$_P;s`UmS5QCjZ04uRa}Pun;WOkrlyom zrbJXLUF8gKevw=IuFWS>N_{ticruvVvp$5Uo(!G$f*;jO?CAqqQnmoA*Bdkp6lf(7 z>uq2S4k)kGk7!Ck+5$`eGbI9$p2DUK%T+V+NcO0<1OLdlm{M+B0mxp)0LRez80u1SQX&EU^;TT~Hd3CnmN8kkztl672l)2}L{$6^M;J^-8TL4Pv|NjRRlc|}k%lVw%X|5u!Bi)? zT>sFACpCLe-EQa*#v)c1^~lj5SE{To+W$*D4n*r2{UD5|PhkNP$0_8_jZ&ZD+Iv)m zG<$xqYcNPAlltbt<72~R&IsOtR$bLz{QIq6vn6L|G71Z5D$rQf+Cl1La?1aD2vO6Q z%&k}uQKf^T7VaH60Qz2Rj39pVkAHFfpGVledSB0;SYn)K%UKQ9wXTcpfp+~J7=J>gf~q6l2Vd-9!uRXokd-vI`D_^V|4!Y#A7*9(~(uRUK3 z+0mqRP?Pd}WSKzg#3=eK;e_gP_PF=rn^K&3oiUEz$yceKE8M7^r0grpB3EW$kSWI9^6Mf!PUW1^``9`i9`y$!oT(mkWH{X#HtwiH zF4MruB=IV)t>sn!$0vo(ukXLE&xzQ-D`)kmTM0d8)YzGmN3Nd=PdG^vGtKz(zNmX$ z?CN#gv0wrRM1FZ6EPde~I@DUpW%A$%MV}eXA@g27l3e*frcX{RUY9@4|EcS*4$x=b zl@ogGO7kk2)`+w&bw1o8xyiZ@F*H2N}+}H z+wA2V*pHEBuojKuzTgY>mHcc#VZ9TOeMM;W{<9Q4^Q!RQvl&|LtIaB}Pxjy&#}-8m z3SlCsAce9Gld^HFtqF_2dWz!mwrTTIsxkP#f;by3Jd%M2<8d4rA&t6Sy!%IGnmesm zOG7OltXvf@-HXk%DHlJwEYO^p$)PK^@jD&#<^bI*9KeA8ZrbB;b zh*y%z^X zB0H&NF$HNa!f_FgA#)oc!7neuzW0RjwTu4L#f?E?Wg~S+m;ip5&IwGtGeF`N2K7%1 zciMS@9v60$tGp=oa>dx=TeQdCM**x-U|$&L;a@BP3dIMq2EFxC{g32gur((Rw-FB4 zMYu&DNKt~q9}!f3Ata_Q(uE{a=mv{c7Z5vCGDZXDf9ruA0%>xdYwa5 zjkO!&wTAngAy&&D@L_oJ&l;cmKyRQ@+V8>#OHL(VSenT$?jI}`D>K?5g7xLTm@C+? zqsk~ACHDn^V>0oS3c$J3B^XJ=gc}2yCgeFcenX>%JtpxrDB_~S_{OV*Hu1zR3U-<< z_J0?;Y~=yn?d%@Etx3~mu|_2y3VR8$&J_x4lWWJqd=JA$4)o&Sn$oL*_zn?md*sTJi( z_ks9lZwf`FB>`c&$5isqxHO#adT2XopKsC`T$pm1Gz|PL-jHQrp&RG$gwxgaSY0FHuYJ|%Mmx_+hFFCyyY{wNJ$c?ZS)Rv%s;GX8t?8^+><9oi&yUv&(I-VP}o|8I}w@|K?0LhDp_YH`T zmiR3hJIz}fP4^ZnKe;Z~=_A*3iTu$E(^?LW!akv;t6c7N&PY>uLB;dHX~sI!0Dg>u zvN}P^fPmb(94{s*GW~p@t^nPIB+u5$sRQ0bN$S4D^iApIP+tKShyW7->N}9Y(k~p9 zD9*Vp9GEs|Y8PvUFwKuf%eNOFtPAAyP9Qg=s!qMAvOXe6 z;5XdB1WW)teKTr1^=co<8b7ldE7uxZ*XqE8D)0W9umbXP0MDc}*}*7#1YP`FP*KhI z!ZWo}p$#4;aIyX+3z})!(t2$hk&OFg0ojOhSylc_eqnxJfRtMTOI)zoPK| zKKkb=i}-I5@fCzUQRcnsK{|V-5rf`@$-4y8UJ}tZy%|z{>=NWhx{<#QdXje|1P`mS z?)pk+%^wzwq`mAh0iT!`66|IY6khnggaiZE1UJ`$;02I315V(DPac?}?9;%TL{Twx z{Q&R&mQqk(DejEd;CU;-jWDR~j^N@PJ%?dnrxeI7#qB-Ef+E0y0_H*dy>F@C><#cL zF=4f~S@?|&g2Q#lS~06|hT0N!j6}%!RDic$jVR;KrJo1{^;{)Xom@8HJY9N^pTveONh0 zJ+$in^dsLkAEuxg6?EtB-vR!ZlaJwmHUR>>P6DiO9Xu3X%{k~C7$8Z~`DGrT#Sr`g zwx&6#YUVSjxlhPrLwJS)bRoO4hNsJaX?IyT*()cUwYhqbE0x@ z_?wsg17eU0g|px_dAKvGs);8Yg!u>d);{#@wFX3PsuLd*ajZ&vdATt@Q_n1KzCW`dsnEdsAw^;GD1lke^Q_LT z-V@Ap8?9&z&@y08rVZpT^zYog2Ny5!wMlcQVMjFdC3y=49rQsh7s-le+K=&Q7r==c zRD{L2WQbvsmy67ni@~#aw3dV^Z9RR1RV;s(Ag4=oTNFGz%lt2wm)w^rnyAFLmL=xM zecGs=$gB*|zyN^p76TIsU;^BH=muyY00aPF3;+iMeod z(#O*aF{i~;YuRWlj7gmvT)H=wNFn69In`D%naZG$K%>@PIi1OFP;W8a?l6|XZxfL8 zy}j&z5@xm29X0c>5s^?@_0GeY1nkD5Og2z0n&jqvUjxf90tAx&H%<(PMGk3V@uTik zx=-GQ>EI&7Rg5_WInXd9t=)|2p8~eidqQlkQ7BOI3BH8}_lZe|{UTLfq6xoolLby7 zCYLS}*W~PA?x)h2>5qT-;Yq$^ud~ zkpQ%Hy*Y%VFwh^%wk$s`cJRga?0*}1e7Q)|Vf^xw3}rTC z$TEz5F3q%n0kZbrN`0*2&vOA3UI?aBOnwAi1ZnG6i7{NmulX+TP1y)u;FBP8trOJN z&9;*mkRY^sgp<>2necV=*txNEck9bVv^m zGrr~Vnz`vPPPGm2_)ruvIe7%=3pSU0MdN4hBmx|tc0*jHzb`1cZTe|uo^4*uTeF-e zN;92cEM}Yz>d}e{nD`X6;??U-KVfZd{Jl+4^`M;Yg4uO{p&;5IB%d`z7S@{{D)yv# zvgo4I9;w9T#qGafrjG*u8NqnYsN8IX!oZ&5PpW)ax)Xjf#IP_-@*P-S0m9Fj6sMw0 z$IrTy--m3u9`Q0g)ZUXaG}|1{Hx?F>x8mCpwU;1hKYiQ(Ff~ojq>m{Yc>2 ze~|ZVP@rE^IGy?ay4|2`M~qjzjTe*uqY%*v2C}VNXJfl7lcS((FIuYqew6-mZzPbh z+*vbhM<1L%akaui@d3u_j6O!@3Y?34zDa!y8!ua+33Gt|*g4{uX7ED!WiS(LxX`8) z-r^d;^~Qh1q+ET%8h`pEmr5`Q07SYimA}AdS(jfv;D$2|Ed7k5V|AqU9-Mg>Pd0nT1nI`%~ zs79YXxXk*9RO#|Vj3`q&jWK2-0c@JWGPbq+@ zhg~f+(U8{=g5hFAp=1nncwYQCBO3QJCTV#|RS(2xSdiZ)d+pSxf5jtM~%A z44j44#d}CQK9W0HgDgl^z?hCla{l@P#JgAsoT+Dtn>tjtHa{d>&62}UE8op<2jMfC zE>i=|oMiVTmCv9OgHQ%;M@eMmK%e8lq*M$`{326o4Wg|(O%5iz2MjIhwegXXVRvK@#7k7XzZ^B^p#=wN!3XB9<4}=96E6O< zT4m-#zX$Koc+`J0u)T-5)X1b>r?Q5Ob4I2Jc7 zI-Qp9VP>CVb%Pz|O{Jo*tA&#CEL}8rxg*j~&RB z`|`{%9Ip*|aPQIcg_y3~gd}O#3^Dinx1QfY%Yv)snqLQwq_gpqRa&UR0J@&BNUSrc3;KB>MIkWr~(2)7$ZCsRlWy7)7kGsqiJCUz^`2G00MlT71qs z>BU*jJDFW!mxS32kY9ea(@sD0sUpKKcQ0B6m?s*wusO&6YEoor zd0EXWU%a;NmtPP(y}ie(aZ%5lrv(3emf)rTvxF_Tz%=khMs-;J73;>S+(wd(Ky}iX z#zO4R$@%H3?5+{GZUAcHXBf&4xc?moSv&;Wi7hc=K@iaIEzm=AV6zNXh~U8X z^%ygIHdSf-n1h3;%+6Ku2}prsTOHrhh^PY@bX4v2{aT`UPt=*5`2HRbqX3palZ!!7iDp{7y|G8qi4M{pwF#Vgaa>SP8*X_iR3NRE+ z;BpEP^2Se3pd}PHhJi`J0>E<@0gM6dZWiqxDuZSsqbyK{G64v2-^TmJP7UeGJ6=V^S^MWW}0FAZ$6!t3~e(*veBpsrdjlY$Zs*H@X ze<60MA<71jY$T9K$~X_j2o7+G8FQkP5q6R}bO(we0MUpb`E)G*kSH7dE8ibAajh04 zMx@aFy(pQ)bd@JQcs@pr7$PGB+a2O)5+tb6n`rJb>la0~BvoGYva4BsWMOSKJ4b*+ zhhrKW_h>nl9aQyrP%CAFaB-g*vH`~PM|g(#lxI`aQZtq<{f}1&$+NA5-+#tYI-Zm@ zXRJhQdW!K6m?Zekvfd>k&(JJ*VkHfx zB`vBP;w?p}nWBKxBHXf~se_`}ZQ1hP$6hm!@3JYNjHcr#s1F8zzlB`TM`oQ-CC(S} zzZoPHU}RBx21OBpq)MTaX#X}P@#i6}~r*?ALMb35j76_b*<+$eb55cfM%nn~{E%TA9eoE>&w z{uectQnMKlvTQMro)djEV4&o{hAQOlBJudD3_H0HW=U06GK2gxPa#(R6^La7V zu$_hf*&t$}#358HTPOVC3-qjA1LK_6etv!*Xv4jc#EwC&I&Pf`e$Ce1zUu32F`y&_^Zai>sXo z;CWzJh$iB}(sCr)daUkkoPP@NGgzcQv25I7$$`=F<4Ezt&n+i$053)nEFejr?Da&d zK6be+4bnm9_}IYT5-pZ^Cd?C)#UVpek#A1i!PNO%?V0)!inzXm5<+UN&GSZ!)Y%ui z_O-aulHH%r@b#I8etBL!n?czaHC4Q)Y{4DooL#6%{=ij2{c&XN9B$mt+$s{ls=Nzv zN}y>#RFl`K-A3eD;eNc3Teolg?5G=|8Ig6A>WUz_7`sQuDrsgWo(Oochhyhi-cHpZ4E{bf5i9XLccTYZ&jIZwf6c7o) z3yZ}`#SpTrv}k@)fe7|eIj3BjwVzl6s~)pqeR~&gpK-lAgGfMbxs|dL&m5B1(fCDe zJvqr|(JXJsp^Zr!5Z^nnp7cRTcC zviiwYi%Nr#*%ZD-!-#=4;1%e#p=^eLw+&-QLvKAXjhoNJ*ty;lMF>%{!Fpb{M=-$;-q;O&h>slPoh?r(fBKNW_kl+G@P!w-w<=Bk z=~DSLOw-Cfw?Q}!!kNM(7w*5$OMZo;({Ecdo%oC47gaMgG0$K8f^TFW%F9^CW(bLr za1P%i-e=s4%AmpCgaodF+Kc|09R3R8(>Na5d&udQBAyW$VzD72ToaDzEiYS-@{+9} zRBlptU!q}^4nszi+#M~ki0n%V)tPc)l`5x3{4#pE_Jk2jLEpVV@9IF^q@wt5vyC^M zxU)geDT6VJ=5)y5xhHk_ax zXS_OmY78uWwn+2LIq7G^quO^+Ao3qJifE!v0FkInf;~4AK+*G%W;}A}S0s}KPrNhY zITq9%NmPDn`SFeg@!Uv!UYFKmOY9#Y?mI-?4kzA}#be}*>TLbO9sB&G@%d%!k}^}w zFAOZtuFPlyp?w}VIG8*RC%wQ1BX zK@ADavQb5j{w<(Lh@5SV`2P1xH9lFzYP&iaH4Es$FER;@niyP4n@9?{FE>_uo02Wu zp;1AjCsNxHPIcToC9&-wA?=)3@JU%VNp<{}#b>9v?LX(+;f>xQ3tcMvYHGn> zZ|KRAtci{c@I4r@_mC2D)*MTgZ7trBW`wNFmH<~6I>R_BkJ(932?IapbsK5$c z)@RALTe5fjl*Sq?j-6v+G8~pSDtOmhkEyn&Rk!u{_Z1CQq|UyDr+g6Asgs^dgY~hyw<|Jvdox}q(mso5FM_>*GQRL6S0??M=FRas zPgF$B==}FAd;f_NRB6XX?|i`X+&kzqw--*Aa)$lMxn5Qm=MXz}c=iD;k9`K`Pitbr zUbN_^h|@3{gaM$`Ohx(TZ~b{YMAfpJQQ|NDuj^ZR4? zUjW32!40p*$NK++h(@LNz0r^xoQ%8-CS?eiq~lY3D@H97P$L}oOHToCu+kzOBr;$! z&rjFpX#@>1+2OHZ9adL?ErW8^R0h>h69sHe-7<^ApjRkVrD-F@&A7gn8dRQ@4)uE* z331!N*Qj(gOqfW8l67dsZHz6KQEd>@hLmPZX5jPPo>xCrv5w?9HY`tG;BS2y`YUtZ z6sh`FntZEYz4v+4^YMgd=`Sukax)lu9m{_0uo? z&;A5*H3@4akkm12gv4(ug!f0teZj2N65rrQ?!0| zaQ0fJqA56|#-9>Q6_rZQaC_9^@cz>?o~GV7T*iLzLbP6Ybc;3*>mL%jNfb$qPjw!c zb#u2Iuu_I4OXMkXFk}$c3}l8)-`K?*V=-^!1_Gc;!iTKm(*TsF)rCTVdjOjXM?-7> zK|~27J_?o=LX5C^l(#=h7j!%;F^($`DHMM(pu-I1o!}r-P!i;?V2qy{SECEqo*gUe zIzHFl0^igZi%ZpD75`)$7S@-&-fq{I4_L){;CNWdqV*zE2y+K=TftFHm7OL&o00!T zwgC%9C$^?ZO(Q%3s->E5xxt6Xtyml_rA|}~#Xa8DIu$OYy9H=$PzF}Elmfx$EVC+P zrgU{B_V|kTD_fX+^7$??vN>ghYEjJyt5anwU@@EGYg8{*u91Rf9U%oEygf06;Dsm7 zcr-+L(X{_{g=2hAB(!IrpY*4&g3toy%+HrBlbN6-ieoQ*U8#?yq43%<${)XR72@nR zYOATa0M;dB3|o{(6gQp^+$s@&2B1i4oiNglqrdXlh$5nBoXXT6#qZ0!u2s+DJ(=rr zdHEbBwJ$rr8ckcMLhT`6fuC2p9ko87iu*n0pXVJ)?W$M&=wv#S=O_$sQfIl#jPIjq zlTaLWCkgJ-7`=5l)j3DlnUgQ4WM0_>owb?(im#Q!e$h5~rz(g$qWzyaYxm5Tyu)8= zxT_zh*k9U|D}N0A(U2FhMkI}SArar6$iKJdn??wwY&?np|ESIwQkg_ee{q<(6l$#M z*I7!g>z~4jDCZO&i|2S7y!AXy6E&GFr)BdRJR@_t<@IyTA6);y^5(}NPrFx_x4Jva zay&^c^Ha~oh;Z;o*vC+l_MxU9SF%JKz>K7{#`S@yeZ=!h!u#R1I&&VM;i>1?Do8MS zj{;0=CUTV-=cShY>wm;h6xg30L~x@(sJC;6dxe409wM+U?%@-Y10=3#j}k@KOe{eW z^5w9YXjQmC3=8ij&f_Ho=u9N-pHuY_=2m59irEBp6?>BUOm1p!Z86zfJ4B(N3fph} zK!3xM?{z(@{DHH{k1wbR*x(F;qtnusSPnGvJ!)cIv#DM&4s<&b>QW1{X+gtVFDLWV z<*sJapJO>PrjjVGNn}L*`BivF!lj`mMq*%Cqs|_TbzXT4Gg|N!~dE+B;p5 zSF)G#^-)f;mcX-63du`5-FT1z24Ke-I32DVr20Ig6ui}1&8=WgT#{4t3>e(K zB^u9^#Ho0C5}TyZxa+jxwAbWF!2Zrv?@z*$F}@K9-q&F;aUHa*ZD&h_4F?5oF}NRV z9HMaBAhTjrV6p+gBvS~TzdBi5MuJZ`{z*)w3!u}CHB<~wW{Bf%z(C7d^vkN>I}CVF z#y!olqCqn#UboDtdZbCk=?3Rr-nFLv1s{(+b&}2KlUeDvs`Tx&70POHbzgB%*l(va z%(#^^AT6bWISA^=;0?m3aE_dInFOj(-y9rH3?3&I9`8%YRDxDkmHGMu%awsRvzQKU ztDQRYZgn|VnhhYv8=DO?!r1W5M|-{X(96n6@2|o!EPk0t(La*jBoeA^w>qwOVVD@E z;#dl8gmX}zOE3N+7ye$jc}K!>G{wx9S?4)&dY;8J4HAIiv;ud3sh;;qFH&vdb)Olmp^rnADMIAgNeL1w(3m=7TPTiSn=d=fJ;mjLb8N`$CX6zugaV+ zkoVQDc!#U537vG7%!Vd zS!*7cH428{iT2;AtF_piKlryFdm3Cy!f>I|i${XO=Z{S5(#(|CixbL-<+9vW6=;jY zKTDmL5&0O^&H4UGyGG;z3d{+ipJVj`T;F^W4KfUGizd(-+Clj7OR~T3J<2e|*Y*~i zQ;``Rq>d2)5!DT|eU#v}Y9L2}dV*@PLodYHbPtXu%vTAe{FeVK8X-|ahBO?CMlsl6SA%Nz*Iw> zodi-j6Ttr3rIsPE`P1fWwr{yWB<0f? zt)1q!+pz7s6vQ@p+?Oi0e=FT7$1yJ+)WkElHOfBCfLc16-Z+@bI7{lAKiN0y6uy-8 z{n8PpYp_wM@tEE>GxM0zYT|*_sqQ%|1CpQJQ?)Yc7|rycPiA64&y0VeyXltmb%gT! ztY_9de*TbFo29688vEKuRD1ggMacY#XKupg3v0=hAxlmUzKJL`0d6nh_qD{jkRo$| z#N~kI5xrqxhLQdQikKJI+uK5YjET`iWrLg;C$dqP_#~#oSRUsz*ZMwWX0@|l(6IY zpw2M+?$G1~A5V2NifB{^3i~b#lP<^+*cN9|ONoauV_1mKXhQ(hD=MxN*WxPIugs<$1Z_1J< zBTM!}gwx=pEwqVmsaORwv+P!1`xhz%IMkn<;ZL2V&~3xN8@7_$5GK{oA6uen{mZ7t z#aSH(*;z~M{02F*2DvH+xjP1Vh6j1)2KlxJ`7Z|V_sIpwh6GuMghYmf{aLU83K7Sl zJ28J{Ii}>yNdnF!dAkH^5Q_ETiv+8Ig71*Q*4G3`-+@#IxLmkUSJ;q>iHhzZr-ed% zQg8IvAyQMNoF%u|?<}3;NywkF}ft;g0vq&3_{|>4Uyi-xU`jd`WiB9vO&}L?b#_4@s+9(F&e*wNZc6X zG8_{mu)2uA)G3v(ijJvO6Y;o8?BfBmWIKMF^4^b2jfwpm{=)vj9-o5y_@dte#5MNzwlD&ZHG!~ z*aiL?FKRt2;p@dj9vpaO0SQCIzCuQ(%p}tpM(d)myFS;6_kf>c;;0Nh%xk0u9;6H2(qWc$xT%LiJ^FP&_s90ZW3C67k`Kq#)$jBRE!w24Gnl`-k^_ z(Yqf&y?TJ7SwaWgRYGx{1nmU~$ES4SqN2D&HgkOJIATqX=&x{){Gid_Wh&44oy3*jrBc}Uo%!CRGavKc4*mse) zCf6m;O#u0f&l;Y@Ht5g`Kk}dFUojpaNh}VBCG~($g@L9ExpVxOu%76^{!#9V+_#zu zoJZ1u^`DJvvY#5nC!rD^%fx#q5K{-^yk^9^Ln8AY?X%`5VO3+M*;a?yqVr@~lAg>n zE3Mu;KR_{IV~GYPr~7=~vDiN3#+scZUIY5f-+QRC6pJp*S(y3n7cRVr!QS;kk_0R0 z;F909ATEtIw?oUX0syBiG3Pw#P8-d0Mp!%xB+CFN$H4e~qO#ZoR+vK$sXf9(P&2Zy zciTqW`w2n&4v&c;khP_fm}eN0rKcAAQvG{gIu3P4&)ghn;-B)TYF*~~UbBX5V3>ey zq_Zd*fg(zYU%p6q};WU9H+OH*cpj{Wa1xa%&lpB;y&Km=LHr`5}Tzo;YbqXMqYmL z9FHb7IFOX(ufRykm(ze!S9in--vd}J9Qz;{ga%nK>T^k`5j%I&3DX2A(EOt_*^v<0 z{F@jUk{g_#`}WsTmo&CapE-{}RZ<89S7_o#utJ{*lO_}Oi(2fgj0a63RbbaR@r2bS zW{g8J)j>N|N(gm~otf=v-d)L!b$*#W56litsc=%16hC~9Q z!~tBEG`Xp-;6WcSOh@&mI4z8dFw1^rVnEkHGXTH)Ow;P$rlO~5Gyg)zqM|HS4A=Xz z?eNMn!aouUgpO2TqBWA*p6!=}Gd(6bJC^?{ZhtFVjqcbi?AY$^Ji6L>4BJIg?Ao#K z+KcTvsO>tM?K(BB!35&Wm&QClC@%@B$omWbCnuvab*2yu%y#O7SB+m(m?rMtKP%4n zaBDI{8y(!AEu(d)5sQ-4;I~ds*~Jv;hIcL5o3%!rMB<%w_PAP_{cEjlkDZK|$VGs} zvdfAqPM2~8^*M{NyFeSIKGDLoB=yzPW~G+By1~70hUJu%n)IxM=zGzH$M_OybSQ>Q zvNVpVbzJ$klT3DkHqVlTuWOKXeU{F2XT59kG*SJ=!b`Ix#mmGr!dIUT-&F$jKa3uh zy-7>w)PkTR#n7nwoVB{u9%LFLD)m5yhRBLBFR3?gl_lMb*l9sYuLEvUzVDL5j#Z+F z>rQ|%4kk4YXuRB~*c{fbBveV_UK7V_?C|R_EWkwxr`6{?NUlh(T5!rN)i1mliK(Fy z+t-zGPj9O=yYg-BOryB8d11COt+f88rFOF z*2M+yIMurM&SmJMV{%EV23)de?9;os1^jaoHHIH(xP@*xIZ37W6miS&s{CG z=Qgaqg8j<#R1U+$ggi}p zW+oxnYtFO`PkWE3(pP%R%_{mKiCDKkA{{fA+K+#xr*$(|m1eUfedPOQ zP(^sO;b^qy6q)}sYRc>HtK)SYtYFSkC0>;E1bHyR33T&y+xqSB1`-lSN}2ycD#Lw^ z2Nxcf!8V)X5NzvXBDAcM8Qe^5*W4uh*`#V&cI9XPlKUoQV6j#&S;V)jV92?obB48q z#GQ#5ON>UmL8-kR=EqA;kTWOH9Z4Gyjt8HjAx%Q(*M2K_qEa+V-TNpn?pK3ANlWtC zBcOqkE~0 zAwoe4FfJ6gwgubp2ClY5j$1$#hjOlX4TY9S8u~d*%b_uB_Tv|Cm*U5}`uHP;9k_P^ z&Lhy3J+KFKbBc9xFG+1Y9*hFZoPPLlnHqzJiFuQ`ZLk{naq1pamoX;$BaHg~mKxMV zhqYr^4M>&1K@k1ngWcQkT)(kL>5UL+jc10>+K~TM@Bn<;TJ9lQHn8oD-F9( zQUe8mxPY}`)9w8;rkPSgysI$g3(ilKTDd}=hZkIPHAdA8o(idXSb)_F7^A}XWraHX z2UebAud?4H;gWY4na_TkX!YIu)aZWA|K$xXD7+7I0v$c>aan@*hR|1td470027$R{TuOa;9aPBNcp1h1uQv}aP@CaE*DxK9U{&qK+a zh`Ovi=91*$(_4x2Y7myiGj_YEqYB_PgLcm4<^Ku1zxnvaLRwOgg*m71J2Hmay?*?Y z4KD*4LjO#gt;2yJ0^^vJ%{AeT0M-~sYs1C&pwyP3C?)QR3k&eOabYm%-PAdrAOyjj z%0>#?AdPGuP}7z6ve_gO6ZE$rw!WGwS7ZA_M*bjGbR~ET`_FCrmi#{y;Pg&D*E$;6XpVxIo3f&`9BXz(4Us0z23-^l$Xf4aP(*7lcegZsXG#Fn|su@Fh9D+;VqAuux6vURflUKSGni7Pd-Gx~21)$>JWejU=;xwaG zd49{xHg;dvq>NB2>7Wf_CIm21P|s9g-x=L%S_9d81CEr=93E0)yhV&>%vvxu`kT&S zy&2TPrko^}S0f&7Src4+)@_?<8N1wgK0j%o`1d41AM+za#|dO5%dQwTxcOINTRg{_ z3@I_7tn-M(Fa{*GFal+EL9tb5-Cm69Wft zJRcIn0ChQ;GmV31+3wxgmhL&w9a5Zz*>;SuZ~T~PDG2Oprg63&*1V`);_FN;!G z1og>)7rmm#VHCVy&RTpGN_DUu7A!S1PJM7eCTVI5w6>8Q*VTA!EwOrv3JfPc*i4O# zCi&7jpoVWu5Y%|MnGt~t^Dt@9Iunn`vd&{pCV>37+=0;QgT6`@0`GS4!Hs3<3NA+M zX~3kQIAT+c#!!(mlh`?9xo|W^o&F;iE6`i_Q4@hF&Copv#lDGjhiCT)owugr3o10N z5aWs-Z_>#xr|$*^KnICGkX+X&(=Q=3nN_gpUnl4QoGfDBms!XH?s3(_vm_2l1i(<3 zre&cdrlFNdpu(7<@{d^jju+;EM5vIGYtP+-ibFmTw^eP^H9TCt2;kv_IwwG!^q2sd z@d1coh>Lv5%j5$5-_D!HTO=4LRg@~hfm>{Bkt=}Nr5?JXa9jb3{nL19Z>HEcr`60r z0@_=m9R2)Q*@nd1AS1^Q62_T z2SJeQo?Kcs^zp0qN-L6AF!38UfU30kv<6#@&KQ6=#?$`0H+_F$l)7qhD!)T)Iv@;U z?cVs)P>3Q+FczxXNxux!jAVD(oSaNt>8 z{?yggMXnwBw0?Cx@X8E4t|T^dvC_&PBfgJ`mlSI4*xC-{rmunA2J@^RywcL(9v>zB zltuRS6JJv$eZ9TtX>wQ$n4qO*j3HH7rzWP7b?({2aQ(V$EOM-Z`bHqa=|EoYQKyko0-4v>Zmb zW`1Y(3tK`8oe*R{3g9jc1)}S18nK?1BTbA0yFM5H7#`{Qr%*=ByPy;JDEIz1$q}h;D0}U)<-7=9t`7WO{%`G!$Y8 z(0d%FSuOp1zmeUX5T40vLXuU&CK1oLg-#Bf@?#X(*I@ZZjO}LNC>WNfO8-p&KY_ae zVqg(1s{-Po*r3wXvd?_+WexYdPVti-w@{sNBcfoVdH`S0na2i;g<4ioH$Cm5lB+d4 zJ||8XB8tFE|68N$+?EN7>DvR+|mmyV#(i?nou|)b5T(TLEJ$U zpPN!zP{zi9ym_=a5b)Fa~jgi3r_L}kS3$4xFpO;W|R_W#yDR*qvg*Mjf0d^%NI zW9|OXNF1jbMChSW26?V9rZuTUIb<=m^L_$iKxBZ;jG%PjKRRvB9-B#fb{r8+w)v?w@#bU&9W8n>&mbO}ap3`^KwTM$U#rharzx3pU>*BOYh=@9qrY?U0-`di z8I!+#Y3%Y|nMtV2w-Upt-HN%begT^c|8`#D?TLcXiu_$a^>Sx>Fh{kmsdtdBqW?Bb zC7wlF)$)g~8|j4MU{4k~A6$;9Gcdd$;vB;j?*<~&Oo4R4@;N$&B@HzM|~H%IEwz41}%2*zj!I$JxBVO>9Li@@Aj>jVqSJX#{op(?;e2-fJ=e4^Ql)~t#KbjL1q*(SlXw-Y;i!S2 zhNG~k)|J+1wHwsosR$&W%GJ#9!TbZnTM8$*UV07P;Q*tkF6?aLu5{LpM7>2hMq1Pp`E?)bo|=x9_g3fA`QYoJU$8`P(7T2Wvp82BB`H?!%P+NcKEP~)*viB(M_8c%+rgklOGyS?YIM(cUo127y*XO4HtxR0V{m1w#30)tJGH975h|i^+6c46H;SJkZdy)bT+HWCE50qTMc-rw$$|ZVZX5fL)H6 zZD*+V`b{J%>6;87>2s7?bQn5sNMg2v|aK6_;IY>BLa3K z?kWej9Q)WuXfl*FpL!10l>h!jEZgvLZK6ry-L&`qIzJ&6vNAgZ^bN#1AQ`Op_Cwa_ z1;OL;Bu6=R&xPIVmICn32q*Grvyube9}pZj@bM<$*D$)TxIBiV zPGp^Y%&G&*&A@A5p`|kPJhaG1S$@-mb*{?xQFTbkp4<1*M=j)v7AY(J9HFDt;nN(? z7OJ0p;fUC+jyTy%y*2X=a8W-g_Q&C*U8#y&uX>Jaj$Wg7#ZkCFsk65@w2NSb9GR~S zIo#<{$dHOlb1Z%%nAEvi^ciz$2y}UCp9``IdZZlnPN54cbhwcr#sNStAxwP>BztQ zFf_$o@cVj?UUg4S^((DITi3gMFV6bnZ-m;fsBF5ZUfa6{pK8gW2RwGUYaH#PsN9L| zUMkPfHqSx&@={d3kJt9An-jDD!m3l58Dv;8k(ipv6+J4dg#rRkV4qSWit^sJQ3c;D zbrPy{CFN&jEQc0Z7BpHG_FEQ7*3X4#0$53)|5ZzE&_C)JPaf7VoHAFfQ|zqW@V~Vz zC0LPxt}+r778}+@Ke2fD)_p4SXx`1UC+*;MAm4IS<8sn>t;8owIrY71Pu@hi&5o|j zep(TT7%v-9F6Xntv0u&E*fqL1b_N<}NcbYBYp>_0zQYypk&5K#2Tf6oxFry0x>&o0 zA@P=h@(>LrUeC`_ci1lmT|cexm2=Tl)WWRcs{%S6T_yOHOx9d-^zD+g9Rw;-28Eqv zTKAFK?~6f~{itcl_k$V9RP!`?rO`0MQLI+gUM?LcFrDN6MA%dA3b=6QKMqD7_ic1GnX=BFt@DR?uzhL!x zzPXP+dRMY}(B|XsFSx^YHvQzl#NWki9c)rQm21ASfj2<+l{a7Vr z`BOJXxdmPPD^OAXWdLh^=Cb}Bd;EM^V*iDg!Q3gq-szbwZM1W$P-*lD^I`jygZj+~h|W$!D^{=HDgFe{eav2I?vO zJg@B^($({6o`0tr^Rav5i_HSv5@c3?s(D~LKqMCfs}tfGivAII;6AfTa1V!6n$r>s zWgn_Ka^9h+aCjTh#}6jj%w~L9_bBtcSEo0S{9hUN^INXl9{u>65K)=gRvgb;vDWyl z$=L){2D(4rj6~cJS{3lh`7v@46FxqS2RpMqsQA95*4o$QDI(o2#38Kd)wTfg6Ab$y zATCVa&Uxb|NJi`WXYy#;u7g$CqNxk%`m{ZD?JL&y*MIb}xSAI-rX8`n{z@~}ARXGG zuAdJDTA18N01Qa6bN4*_M3(d`@7F`QutSCIfvd~ZKZZ--!PY@6Ml9b=ogFRcqf*Jv z7z=6tiZa}90m?!mzVl=-l7IezIA_!pKA_4{#|2Yz*a!8CwugHn9$iPU4;KkqfgbjJ zCJuL9_PTzrjULA3H0l<%YgTuxo`?tyH5z+Zzi$-OxEC9TO(1@o0Id~Z)*0`M%g6QT zQiaQ+uDOSEWnqNprj$Z(hQvE$J)Iu5#m`bZeRbm8fZE%lr3P~%sla#aF%;8`l(-X= zahpXu>eNkGPnfT24aRh5hHJk-*}1=`Sfufh@T?K|^2}}0@7fI&GgnrYTZ^|l`guKn z+@(v@{;P#ABu=n5$@zJhn2B;akGby+n0xU@@UIe+T%Zvg@0v!&lFRtG|F6l zrxI^G53rVZ^SZbC*aJ2V)?G@x)8&zK%->y^6XLd@1tp+pl5=v2tw* z*+j{Q8Ds_$FNOaBA{4)KFk2r#Y$*+A9y&1+d4%NZ9|$))E=N}IkznBqJVg)Ug4wYn z2OvTUtgOWYb1J8jYrg3pvt$Y-3+}XHTB6A;6xc9BZA!moWhw%*wtw06k9p{uOu$F>w0v#f?npQG zp|S4!_(O93>SV*Z1sb<$bLM?0w*Ch@!q3O)$WWG(Sc;4w@fN4MPvJJxP6EX$Pj)q5 z8bcSXcP~43O;y=l;3)j4F&9D=*E;$aTZ zmBl=`(O#vd?7Mi<_3V|9kJEeEM-88;2ThHDL{)e%vi>Z#jmaw`6qGxvl_C+R&Yk=?AovTB{P=#6k|a#mHCuq0T1_t@Y^ zZlzPM|MpJ~pPDXB%Qwayo8f1#y#5VN5Yv@e8(cu-9sl&5k;;2A-5Kj}_(@ggerBoD zeRrL3XH&yNVJ?65Zt>Ks);7W=SZpZRs5qxh81KXL74t)!#gNeT=f4*z6aa(;3aJ>4 zP0ViMYQP9Y5#Z6Fk*HDt0-|u9>&b9XPk*2oM<$u+sQH4!@Rdn#rjvH=L%Y!|$rsML zh2lQDbGwK0Sl@_5YOJW zuFO7F+jfZsd0@@Y!KWWUA?F{AD%9sTG7BUNosa!cRN?(5g(~YITPPZfI)kvdu2Rpn z*CCLV#gVLxi}?H_ zF>p^6;(A}^e{>afwzt^*roBu#7WA~G8eMq*CqK^-I;e!5|^t?Tq3JvKCebUgU680_j=B$G55AyA8cOshOqW2i{~h z2Pm~~A(5pyC`dNq!f`={?Cgm+glv4h7e*7YUxOf#gm1~*u8lSdAAK+NVGTz|&`<~dQCKrduQ-vF#$%GBVv18e{1F!h#q@)T|z%5{)_#<7AI z@a87BR^KuRZ+?@xAX5tmiPTJFb+I&lX6~afwl}5@UITmpGLnEqkXjB8o$p+n7hnc< z-5RuTuq0}uW(umUA~1-uO5rUtRPMZyKY3K9f#R9W(gYaJnTGaLb(*lLm6qBUmQd~V zR1VK#ILDWJbgrtugmLig@3d)uaomi1khZkb$Qfu=3lx|UoEo{%FeZn3*D7cF!Ex_H z`bm*ULnp|+aaHt~7>dhj;d%>D*{})`x`iqpp=6zFS<>u|%PK2~UjLotA0jrtrLz>2 zlD(X__FD6u65V^_<1@jx@u@(bNVa5F`yuLTnDTCHeaGzNo&cVY9Buv2c*B-? zHD~Iw9M#2bNOUvjlNaUd(L`1>Tn9_+g zQbHGo7_7L1dZ#>_{I*t$f7!n(>t?LfdsU8eY{o8K`?nbvv~7${bS|^1`NP%MT{Ylb zq(`L;2a@7u&Tw)TQ`pD~YBY!smH^Y=)|Qd{5y(B6T8^d1yb`?IVB01icgw>f<}}PcHXuKTah3V@C70jZldXx z1Q5MofyhWG287uh2bH2}pLk3|Ik@i}^YFbp8#Fc0sXUH;+$5!v>+!)mgIN_9$f+3&%Ovvm3>4amZA-Gc!c2b{|?S^?1_^XJt5U z5t`322i4Ru3woxB3Dq z-|$7*wzTLJI|>cvzTpjIve=hbm5+xfQAg)|%mWg%qly5mPqUnWfVS`b{0#lZw+9}+ z20+NoLdBs%ObiuVLjt$5{f=&oDd+zY_114q|NsB?bAu71NB8Iy=@O*75s+qdN_UR# z?v(BZX?1i;i2@2riAZ-S%EjyR{vOBm5A4^+cJ6jRPqLvZ-d7~DapHN!V~v?(CUb20 zKR&(y^lQ~#IjR3RPYjYDa(f_Jo)Lz98oRoz!NjW9XNndir*w2Otv3P;PCwf65nIg4 zE1mINskLPY3BNFlGyW6+FTno5Mo|FhzNQd(ry19l{1x^B@@t8VYR7vNfkw6qq?UhE zs-l`ClBkR%h$H18aCqh*`v;RMgYTeT4i7Q6>ja>^{ZVB7giC3uzNDwmrFpF43z9c$ zxv8YHGugRWP0s*G-i$N_2V}AATOq?KPTJv9PAm9~0OgLX{vg#8C6u>@YtxJglGZK2 z_9da1PFMYSgOS!C*Y~UDq`sRcgS`KA9#ZWFES;fu(qY7m=I2Ah10Hv-LAZ>QVs$Lf zB!wJ7Js%}PG=2TI&vz8iPrm~MdBPWXCqa}n7Cx?VkyH{)8jA;P_(7SYzmE)pM1lx= zlo85zO{-q7F$gSC$^>gz-xC!gmg)u#bSSpR*^U|zw<*4L81TKjJQgbu@k*qwriTto z@GNv&TNiz@ReJNn^s$vEc^5abyDg_}wxb z@Mrx;eG^X0zaKg>x3Ff6kFssL>kZeMp`-m=!Ru7=oX=sD#&z&|0Tj_3Y(ok@W%}~w zExll_i!mms;1Np6Sl=(7Eueby&S%Lp#L_%f=YzBzHu4?IG=MArsMS#-o#pE|qPl)A zdF2J23)$D}9QI&9C|_EuN0$=i)auLQr0XUfnVnmSU8qn%-`lU86QykG6^p z&ceLlFE8dwSDz$4?o#U?nnhWj^l0F`>7j7Y=B?XHj%Jw$f@zt?{{*fKdeA4e$vw#% z>HF-=beX%1`%BgScSx$5+7H+MHoWmaYI?u$UOpO$xZNkz^ZgUhkky1=UeOS9F!U5? zjlnE&fXvx`qArsRs`47;Uo9{GT(6Z-WyMIA#w!seEv)VFaaEq+0KpNsC($F;`T=DxqWmP(OK$a?dBwG zGIWqW)ZwVMEbj|Xah^t7($U?L=5No#KcOg|K&-iUuVPAKbfD#HC6se{6 zT>=g5W0L0KGG562!)43uSSsdmIMEtIVo}ZS=9A1u_J=sP&KZKgR*HXDQgMqImsU!l zp$v5UNIY|Cqo}k;o{BBj$^syOW`O>G<&98>EnN9a`6$}sctlDWEdU~P-zr6v zVZ939!l!J7-F{cMLR)xo7-sP{weh<(RfpVhr%xG|B4{g7U``NS3Krg{ zQ_Pil{JME)+oOE4@^QIMIA012MgKq*i_v3Gb_tMeIT3v4#s7JV`_Ub*E(Hjc!3CA! z4{XTeN`sE=$$&DLax!r;CI%2kEBv#3@5pZm69#^&otMPJcU3^3bYq&Oib% zkUWf_Q&pu?;mMl*+nmIj2Yw`yt4)xXAq95EVC5cE0di0#J_7o-XfP6Eu?z|Vk-5~G zArM%Jr&yW1CmSG2e|cE#CfzaOSbmF9ueoO44t)VV<;y0Xcqwdt@LIc>@^4ykZ5j3D zhxRx=Vi6)G)^-xEc4=b|TuU7?N1`xSKJsF)_{u?zT^p&fXM<=96R_dYh@^%hrg?3y z&Iga7NX%2qzsGVIF(5j0btrpznqajui5q@TnT2X8O|b3_G)>DTgUj2Ktr*5xwYUv!pjd!;7jA{jndD6%*VFgC-Ku@;e31Of=QGw z9)CWk|I*HwhNKo$%-Y#SOofvn_oPaP=?$t&F(&pS@V@Qw|2oz^ifLz0J!iz<^m{Jf{MTP!|@b4DGCVAxNj3m12%JHxDzT-Ejh= zT{{X2;lXY9AY0P8ACb0AHp0phB3k0a{t;iBl9K^tE>Q;LHKo|}gdW71WFlj79&<_j zu8i|?3RjL&v=Gf1c`2DrseG27%p`IYg3kg3?Hu%^{|K;lDgLk$RL+i9qF<7uZ-uif z?I^k{Gc484TPwMhE0Z#&I!rRs9LfjmPepmlSUk=_ycN>N6^u9(ea=*dWdVu}O#BVZ zEpJVuQt>%-%^z8sHh5wgQT$fC~1X9HmQpKz*y@yB#u4@_5LI#-o4v<8O zlO|*wdu1}1%?sNgtA3$k34U6yk7^Y%75Stzr)OLz`y=#H-M0MEq%EgDZAO%3cK61j z%1YUO$UGU-;_n*--Zg?q*pk%OlCsN^_S%v`*owv1ilfWw$+Z>VHT&-hDJle|CP4G2~r4 z27sN5Kiel7IDQaj>LPQQ7Iv}#zxrrkCj@pGzIIwRV0}P!?RyV8TMoIJf!*9>-G>c0 zu|!@Gmpjf~JO1!>Tkm>BF6&CaW&2&&<3)rkL#`9Zj}v#9jV^cVaVQFuzWSypTc1L9 zjpP~%x8YoN{nh1aLgwr!;_c|`#gyw?W#CJBT8#u$FfvSj{DPYuYem{wq1H3e@uC#*E%UQSGemmjhGph5pp)AMiMUrSBhR`W ze%|}3L?I!%?N@T#Y z|B#Xor^ zyPFdFHb0LvH;3pp$W5$BK*aSikxnXB92O9xaTg=hQ?T9Z{yslLtDLo?nG`nV24QTy zTuF)y@T(I`3(3!V-JRVe7U`E?__y2tBEa^OQ9N6I9<6ZzQ$UG;aoK`l1_xD6KyL{V zRl*;NfE(Y`mRnA7@q8uOf1J(#04e}IFt5VMdp)l}tS_Nu)#l=^;)Xnr;Wr0`c;zZ( z&7E&D17(FpK+&97)f+MAD>3HwyE39LB{Gy*8o!gne^+iA)zk#Ot};r|FNZx%X9~Bg zcK#CW7MK&+m;3d1F&U3Jt5q{J^ro{FcoxEtBG@n8vLw#$KBu zZNCEYHVs>?S6eK>0w0N=e(LMOde-oQvZN}oQL3+sxUcLwi5Mv zQkEwX6f}^E_Q@6G_U3x|^mhv71a9XfDfPDgCGMw>7$=d^yo|eLlZ0f|qAiLhe?*72HVJ1Z{kD?1oO5#D~Nwa4_K24zULAIPlPv5cp0fm7z|>f;D@7E4q!p~NI^P# zF*PZ00YVW5<5%V~I=kLmwxHgym4)DKd>co@A_#zGV|BJREGyJZS z)8uef5!`+vr?G;*Knj_UrCxmyQ&`lp(jvUo3YFEyvXyEK8OIowM%1ni5WX!y*J0gS ztYTdDd%GM~EYcGaKJXU@Z}oG($!j5&)xwBnGlCmCMtfwWebHyTv~EzB43VM+MdM>! zf`ORv9)3Lb*jaypXJ-~?>w;i4Jq*XY{3*co!pCUYM{LMj2jd%e_~hppMv@py3Ujwo z$@K!;?_R2oe`(d?FwC@QU}65l%Ku;vu)N4eRKAF&^$7E*Fxm~ z58vO~;f0^i-!dPr<#DdDtD<~KnsUSv#IkdGdy{nlV&$5_;;csJMiuIIUcS#n1&k;p z+km5B#LBykk#xbT-!`BR_aJI36l`w|-o+letCW+W6p|Ag@-8*FwRYIy0#gs5-D3|~ z?hg6t!7#BLUW*lRJXi7WUE)654;Aon#f#%tg~trC(dC#H=3sFI7K2{cxpRz@I~4qm z0ej!F*K;{3>YEpJ`H>0sHJq>@2Ya}%)aiTnuxll?yU6N*QlE)+=CODxGHfW7y>C@>bSb`UG*F-ARyu1pALwI~BXtbx{+($aLHT3}v@ z_zX)Rc9NMw`r$UiGBOs2KrrD3yonbSZO-bz;wnE?CZ9+pnIKrVSfySl9s(uhM51Ze zYiD9W5^%6t)4^EM8XK5?POBI?nFQuZA~bQU$G=h0T|CQq z+A01>S~?(P;o<0b1y!FHQ7<=}l9Q+DObbY;%TN@b)B;Vg0VRRn`h0tA(3J=7~~ zlcx}UZRQVAR>8ca&C|6lRL|d(pEs|1&kfNaAW;W_qUf*K0k!WQ82ybfN+bZYN zUNI^F8|r5T`uBqwSsV?|`dMNn{&>2bd?|v?4 zFr*5kbfELDW=7)n&PS(6sq^n4fR~;ug?9aPq)31T_d-kZ!$4VyDi^{42%#?SefZqf z9oXa8vz4ND>;a?|)FvY&M;a*p+@n1mxD}<2QavPx1Pb@ILCpc;Dz=Hjkg zFSu+P`$D?$_zd6yn0D4WxJ-TJvq;==+(K@-aae=Pq{^ez7&nkNl7M$BT~wOxa04PFr2B%_GDrLY&wm3wljX8L zzA2GTmEs4nia|;wiEA+x9?M--Hkr14Pg2L;EF%(|;6T6$t-^PES9QggVws_4WY;!B z*_$#iBFSuyXfNpImFcUGLhcwy0ld>&wA5#Bk^s97rs6Q&b)->Nsj96#C&L%}fAI_u z=|S}@VwBdUj8tLkFnFB(lgeWEyX&{9fh3La4OzK*8iqr6QT|mtbY>uhM#HqeKk~aO zI}Mf(6J>@#*>_!-_|y2g2we~gXpDXPx>qrpTfVHGQ;}P0LB)sqE};a2WF&3X&W~45 zT^Zm1-6qFWs154-ig)Gn>s~GP5A9hh{6g^kRbJ?|zXFzzDChCR4`qJ@==-3sa+bl{ zspkQNM7k82xajwAv)-vMvD`8>z)Y0O&(;);75*}eDh&y;+i0mJhOFPcD1HdA0Bg!7 zP+Y1p&TvwoyHOt2PVjt@Fu8#{zBINWG0(6OfDJZ;SEC&+usyoo((NdVjdyF3Tkj^< zH$=0ZP^#-yWK97R4vHx*b?~B(0X@c|n*ii#j{{}-OlIqV3%i6U9f`s)VgulN@-EfXc{rnKhg|240p)?sudW_IDO@p zRo3-Lq{8>la*<7nOAW9L%IEH77>54%4f2lE|K}ZDdQ`tj053vowm5dK&)qc*m!p{em z28(Qs7JeU5Gr$r<(e#89c*T{Y|9IeKh_oXz?cY$S0wm(WSdZZ!B-f+m4bAM{65oWd zwJ-S;)0yO_=^p-0^Zk*V)$OXuk)uigij>FWN(kU`AEsXnL{o~1LUQ6(@O+$z0<2)0 z*vl0|$$pEx{z%rUx08IKo&BEjlV{+U%LO$#a z@HAjaq+kEe&*X#RB(i)c{n}U}AM42Qp-)*=^c9in*4QGm`BbD_MG2{#@y9PF1WKL) zLy8~`$#*QBszu5sKZKmslo|wH5y^fb|7{>>9q{ISqGM07=5jG@_oUFuJ`3%hfinK{ zy!SU*Zv8~HFH6S>Z?0Ak-4hE(^Fxi3$C6#EB}^<63%tc@%#JKfpRN17<>L+Tfdp+t z;Q7Qw8f!5))!wFhXD^Dp|9jMn{1~)}>((<|j7QJ6Y9e*_&F}p~(`oES_bK->G?DAU z4Lf-&e$YIMr&d7*;!m@)NYy)Lfq#)VEn&KoC2INX-&tCJ@Ge<$C0rrD)ZKm~PafWCoh0Y8D@narEKa#XcWd;P_{P944Uyi08&O==tRUIn` z@NJ-}aY65OKTG!1F@;`a)Fq`nB;F};DM41*<9DSh5&oSOa>Aa<@x~vK)~DXv77TBH z1(E;GY`pwgByxqf#)l(ZT1L78&83U%qs{qrdf5{jc=GxoYkrUC!tbWV$|Zt$_uyT? zgti>ZVK`xgSZUhO9kxnmaqGeN9mwa`zAy;LwE^SqNlOp*u=nn4d%aP z5}_L8lmO%SX`mdK@eF2cy8wJG#d2rDH9+DYr(rjj0YTE_t3p;~mY~8k{6CM;gI4@S z6qq#~;jLq{na=XB75_skgk;o1gjIr78F`Kg$i(4aA#tP9o+|PY|7TJ|SzqfvsSr}_ zgmG3!JZFW&PnPf??wDDdflfLEZ%@N1Ct^BTZHF=FP4}V^{tU%Kk*6DxaUe!48@-n9 z=t4qn9nolEVdG~jk&ME8xI|HMhEYm+QN>#x|2Ce7+C?9;iT=Sv%PtjrASb0DMl;lg zSXVsA2rS^cxkLUT@%RwfJ?)qs^KQdPO4~99T`%=Vmn(yw~=-LeC^mwfBFp3a8>eg_|Z4*c?iPJih32fMWut49_ z(63I#%=tn`=7lB!sUT&ZliO6JsO>jVoQ)p&7Ym8+DUuYuCG)Rong%HrYB81^l8Ik3 zzf(>goFE)#M<4Z1G6R`l_F|uEGul)MboxttmV468EviFI~n4V^JI`{Wtv z^GU5qUIz$5iTjK~BR`h}EpHk`Bu;3A}0?o=GUy^KEm}st`2(-%IiWNobD9sk+od-aaq7Hcb`cxw>WuVb?DGg&I0nCA zuab;Uq%;VTBg>l-3X*j4WZ_aI+pfWVHX8bZgJd6ZR_hBEI3pu- zJ6+c#Lr*}F?l0Qi)q*o-j#d@zM=;=_pc%|1P6>O8 zMlc9t5wI>ak05%=`m|$#oBboAC@VSglRV8zVZ^w3jx;Q`isal&MSC@6$&1e36JlRS zPkr$ebV2$1mQZAaVDq9VOn@mnBKM@11%9skkeT-OoC}XiU}}&_QYMFdk7^eDgtCu6 z?=8ge;j}PYVcr zU}AU}7EQ?{h09RCM-%bfu4vE=vAQdRLo1D~kt~5!1CfvOMbVj6CahBJ81a<)OtGc~ zu{#HnPj`d~wz-8WJSoOl#6TTZR7M_Uxsf%acr_SuT0L>W5;5{1c_U+*Jy_#GT;=yt zqDfr1he*h4U!vyJM~qvfz%6}Anfys927nknCQuc{5qAwC;L{c2H2-Qh43u}#Y&DB7|$l^1Ri~w zVz8k74SO5KQVdQdwTjGL^ak}smDim@jU=`$-kjf=opM@hh1jaTb2j_OHf>&VV8%6H zpw)6`Hi~})`9qcM;pmjPumKWDkW*}(6<~&@Vyh~va_}Ik_O;U>u1Ox&nT@VYzS!PU zPj-XCBHJ?&4st6SZ@;-|Kd|9H^42)b%KcE2&tZ>!t&Qtbin+Fd?+3JGvjMz7VtX#B zSXnjpCqdY$Of{)4Qej->G%ugV;^)UbPgR;tgUmB3< z9|XA(s!zVm<}@S3ysuE)T2Nh1YDN|w1X$&*^p9G${2rosBO5dY8Y)lZAT}NBZ+~yF z`yRO*F~aIKEn)cQZzFwQI|IjBqBPm8^)@(Y2>dv7Jj#e~n6AW&on?RC>|* z;oP4qo>yT!yp@a{8N(J}KvT2Gt>(l(s>r0kCBeI6d~=O3qoEPEvDX-Rn>yojfJ3@Q z=5|p%R>nPr{;?1o|E3t%?HjAxMoyuX@Iyb}@}Q=UJ6WtdATrgRG+o&M1iItiXvY@v zPh-Y!Js@g;J6&8MQDMBmSn?Qmw3d)6^G zEFF#KyD9Re=D4~^axF9RKSX9<$J zfhSW53>Kdu?t?dOvuvcHAE zF>pce6*LyW9J8F1f%15t^d=v|>U&yLiW!Fni}F0CUeY@HOcqHdOe^BN-go+BC5aT+ z%y5H`#uZeS97@2EyhGj8zGQ7r`c zjtR2PPTaP<=-K&D!3eVrsuG`WT4HubCR%AzSBEX?*~O&~bB}pc^6NXSz&M*A&&3LHJdH%U)D9ZSU z#QqTA`Ee}$L%Hk+cL!g zy_>FZ?;*Wm>As=#1Nwx>Pwrw>S)$KBr?`pY!)S=eSkC=AziqcQONepG_J;cW)Awvg zJN4&g4l(GX%?)xeE z2nB`PxtoXF)I`#(x!EoS!Cq|&(HV$@N&xpzYs4=tn=nO7n+&HnU7ZS0>BqQ+Lj$0! zl#^-sWhBC9$t?N1ahWU_@oBPOx2qmnpb_6hGC0TD?xt6g=0sH!7fyuviJL|!PARTC zPH{$ffhag$|AbK)2^I0CG>A79Lp$|`LeXggesGHCl9qB_s`G*`!|Ab=1-|VbG%qC} zOx}7JE&Hq{3xYHqN9z*XQ}jea0QE}4HtBH5j(yQiB}c1p^!KgUl!R65WFQcf#=*ud zr$FPhgp${NVOOI_%;$I~pBM>NJI)(yU^^TgFHy;6^>NpUc#J-sr>6rbRFw3;6>J7~ z_2tq3AE1Ibn~Nz>=k7xv5y0Jx zqpb`|O;Q~||7WFn-$ky`=bM|tYWC&Qaj8zf#jc4&dZo>FuG)uI`l4ev4(GNQSD*9K z=Rv=74fc~?ivZZ6$V&w0v+^5Bh{G|dvN_nOlY2CXVeOAb0vPH&!2Tee^aCv_&=OhW z3^qxGz>6-%z)t@$V(A?2vvS+)-H!^qeDaw%TunXa`;6~10ur905t=wZtz`92Z5gYF zB3oshR7*)c6j5C5lhE43_7j7kSE*JjC@Xw_R2|3YqU%HrAr2c7Ui^|-m4_f$lWzkl z9*5#;!4R%cVM$=`WKRt~MomkgE$^$2B?1(Uyz9Pwo{GPkd(I|EBZ?NftZ4>R0QM^N zW>mjJmY1gZ!J`P}FRL=Fne=kl7tZ6Jaqv8X!mIX-jhX{@L%jyb zSc=9Bv0<-CJBpGfd6Uq0ZWmRs(uo`4UV=CgNMyy8mVQvH3kGxY;cRjt`J;=jia>9o z1o(tMFfS^nh4!*#U`i!C{mcrw)is>v0Vni>(I>Li1(bYVF%~c*CV6<@KG8}F`KR;J zEco44qK4--7hJ_^D%rOQz;9)i8gVDknFJ5J9H=~!rG?SL2}BBs|>^ht31g&4p7 z0}Ff)+3x&gn)2*=WjkRnnXs<%-#rf7#iH5GYhS7B%pQXzFaI74B?<)8^-FJdotJqy zidJRIl7TQ(-lvx>fuuGuiBkV9Q)=L<*NKq~ggMPLj-b%+Iie-yLdnxjw=T-^UtLYU zh+R?I6A)R9J%aL0)>NyF?dPd2m+~cNRvy!~KSq6Eyeo_^{}(YkD>*b0i2cA4wSuFsYs1#qIHT_s%Lz0HKuF z;BsW@%SxyZ(KPkZEo=3&85ccjsIKaDho~^=6HDQ;m+}~*M30e8{a2RX?u9?g@?%MZ zUm6qd6`;#eE)ueF$dk5tR>91DxC9*eEgt|xZAP+(R=k>o@iD7_Y-O2>hVbSFhlD=| zi!L*eNM)qkd=*h(lR&kxL95A&NL8O7r5~9$*zXZZ2ibs<9UT`jPZyGHHaJ!LBWbJ- ze+o%5a>u=EFKEThlBzgLX4Jk*d!D2y9lzloQ_S@^R@)@-@2MbTRGlR_TjatEJp`my z)?>FAqDJ!@ocuI+jwJZdq#pp}!nk9Ft! z>ss7x%kLCNYNR1i+VOoODMLs+{aXczeN+rNcMKa&rQ$Q$@N};@Ar98l!suK6ZWeru z|0BmPK`{@GiV*r9Z8Yx1ab|F+e7So$wwb-<%K=qp=EF2u{Y^`F1*3jlZoLv8Zg`9; zAvf>fD9+2bP=mHFyX1CFP2>&&%Q-YR%_x7)qyIDngtq@_2(*ZV$p1s5_Cdp;zH-T7 zrcuwr8mbt>WFM1EEQ=}9I7=pY&Y&(>XJzP7J(Nd+ zL_l)YK=BlYVh(&7g%qWO@`D%@l!pi`ah~|aKQ^~7VgbRHQ0|We$(`Pbt8bfy9jWa*Zoc>L;y@+fePgcl)eWjHU30Ue68UEfYK=lC+@uEx>b#H- z$6NJtof9?2EMmqxGp)tNwo*>>Mz>$G8#{1E(3m%A@Y_jR##d`RG}#vhN86vIKhE&k zOgC}t{fB91`NEe~Hn8RTP79fy{1o~bFc1;**~$X=RJ~8bmC5~PS(zV&ixzxG}7V)$$omgxxl-l;QaH|WB0PuyJ9^O^59AK z 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