nu_std/
lib.rs

1#![doc = include_str!("../README.md")]
2use log::trace;
3use nu_parser::parse;
4use nu_protocol::{
5    VirtualPathId,
6    engine::{FileStack, StateWorkingSet, VirtualPath},
7    report_parse_error,
8};
9use std::path::PathBuf;
10
11fn create_virt_file(working_set: &mut StateWorkingSet, name: &str, content: &str) -> VirtualPathId {
12    let sanitized_name = PathBuf::from(name).to_string_lossy().to_string();
13    let file_id = working_set.add_file(sanitized_name.clone(), content.as_bytes());
14
15    working_set.add_virtual_path(sanitized_name, VirtualPath::File(file_id))
16}
17
18pub fn load_standard_library(
19    engine_state: &mut nu_protocol::engine::EngineState,
20) -> Result<(), miette::ErrReport> {
21    trace!("load_standard_library");
22
23    let mut working_set = StateWorkingSet::new(engine_state);
24
25    // Contents of the std virtual directory
26    let mut std_virt_paths = vec![];
27
28    // std/mod.nu
29    let std_mod_virt_file_id = create_virt_file(
30        &mut working_set,
31        "std/mod.nu",
32        include_str!("../std/mod.nu"),
33    );
34    std_virt_paths.push(std_mod_virt_file_id);
35
36    // Submodules/subdirectories ... std/<module>/mod.nu
37    let mut std_submodules = vec![
38        // Loaded at startup - Not technically part of std
39        (
40            "mod.nu",
41            "std/prelude",
42            include_str!("../std/prelude/mod.nu"),
43        ),
44        // std submodules
45        ("mod.nu", "std/assert", include_str!("../std/assert/mod.nu")),
46        ("mod.nu", "std/bench", include_str!("../std/bench/mod.nu")),
47        ("mod.nu", "std/dirs", include_str!("../std/dirs/mod.nu")),
48        ("mod.nu", "std/dt", include_str!("../std/dt/mod.nu")),
49        (
50            "mod.nu",
51            "std/formats",
52            include_str!("../std/formats/mod.nu"),
53        ),
54        ("mod.nu", "std/help", include_str!("../std/help/mod.nu")),
55        ("mod.nu", "std/input", include_str!("../std/input/mod.nu")),
56        ("mod.nu", "std/iter", include_str!("../std/iter/mod.nu")),
57        ("mod.nu", "std/log", include_str!("../std/log/mod.nu")),
58        ("mod.nu", "std/math", include_str!("../std/math/mod.nu")),
59        ("mod.nu", "std/util", include_str!("../std/util/mod.nu")),
60        ("mod.nu", "std/xml", include_str!("../std/xml/mod.nu")),
61        ("mod.nu", "std/config", include_str!("../std/config/mod.nu")),
62        (
63            "mod.nu",
64            "std/testing",
65            include_str!("../std/testing/mod.nu"),
66        ),
67        ("mod.nu", "std/clip", include_str!("../std/clip/mod.nu")),
68        ("mod.nu", "std/random", include_str!("../std/random/mod.nu")),
69    ];
70
71    for (filename, std_subdir_name, content) in std_submodules.drain(..) {
72        let mod_dir = PathBuf::from(std_subdir_name);
73        let name = mod_dir.join(filename);
74        let virt_file_id = create_virt_file(&mut working_set, &name.to_string_lossy(), content);
75
76        // Place file in virtual subdir
77        let mod_dir_filelist = vec![virt_file_id];
78
79        let virt_dir_id = working_set.add_virtual_path(
80            mod_dir.to_string_lossy().to_string(),
81            VirtualPath::Dir(mod_dir_filelist),
82        );
83        // Add the subdir to the list of paths in std
84        std_virt_paths.push(virt_dir_id);
85    }
86
87    // Create std virtual dir with all subdirs and files
88    let std_dir = PathBuf::from("std").to_string_lossy().to_string();
89    let _ = working_set.add_virtual_path(std_dir, VirtualPath::Dir(std_virt_paths));
90
91    // Add std-rfc files
92    let mut std_rfc_virt_paths = vec![];
93
94    // std-rfc/mod.nu
95    let std_rfc_mod_virt_file_id = create_virt_file(
96        &mut working_set,
97        "std-rfc/mod.nu",
98        include_str!("../std-rfc/mod.nu"),
99    );
100    std_rfc_virt_paths.push(std_rfc_mod_virt_file_id);
101
102    // Submodules/subdirectories ... std-rfc/<module>/mod.nu
103    let mut std_rfc_submodules = vec![
104        (
105            "mod.nu",
106            "std-rfc/clip",
107            include_str!("../std-rfc/clip/mod.nu"),
108        ),
109        (
110            "mod.nu",
111            "std-rfc/conversions",
112            include_str!("../std-rfc/conversions/mod.nu"),
113        ),
114        #[cfg(feature = "sqlite")]
115        ("mod.nu", "std-rfc/kv", include_str!("../std-rfc/kv/mod.nu")),
116        (
117            "mod.nu",
118            "std-rfc/path",
119            include_str!("../std-rfc/path/mod.nu"),
120        ),
121        (
122            "mod.nu",
123            "std-rfc/str",
124            include_str!("../std-rfc/str/mod.nu"),
125        ),
126        (
127            "mod.nu",
128            "std-rfc/tables",
129            include_str!("../std-rfc/tables/mod.nu"),
130        ),
131        (
132            "mod.nu",
133            "std-rfc/iter",
134            include_str!("../std-rfc/iter/mod.nu"),
135        ),
136        (
137            "mod.nu",
138            "std-rfc/random",
139            include_str!("../std-rfc/random/mod.nu"),
140        ),
141    ];
142
143    for (filename, std_rfc_subdir_name, content) in std_rfc_submodules.drain(..) {
144        let mod_dir = PathBuf::from(std_rfc_subdir_name);
145        let name = mod_dir.join(filename);
146        let virt_file_id = create_virt_file(&mut working_set, &name.to_string_lossy(), content);
147
148        // Place file in virtual subdir
149        let mod_dir_filelist = vec![virt_file_id];
150
151        let virt_dir_id = working_set.add_virtual_path(
152            mod_dir.to_string_lossy().to_string(),
153            VirtualPath::Dir(mod_dir_filelist),
154        );
155        // Add the subdir to the list of paths in std
156        std_rfc_virt_paths.push(virt_dir_id);
157    }
158
159    // Create std virtual dir with all subdirs and files
160    let std_rfc_dir = PathBuf::from("std-rfc").to_string_lossy().to_string();
161    let _ = working_set.add_virtual_path(std_rfc_dir, VirtualPath::Dir(std_rfc_virt_paths));
162
163    // Load prelude
164    let (_, delta) = {
165        let source = r#"
166# Prelude
167use std/prelude *
168"#;
169
170        // Add a placeholder file to the stack of files being evaluated.
171        // The name of this file doesn't matter; it's only there to set the current working directory to NU_STDLIB_VIRTUAL_DIR.
172        let placeholder = PathBuf::from("load std/prelude");
173        working_set.files = FileStack::with_file(placeholder);
174
175        let block = parse(
176            &mut working_set,
177            Some("loading stdlib prelude"),
178            source.as_bytes(),
179            false,
180        );
181
182        // Remove the placeholder file from the stack of files being evaluated.
183        working_set.files.pop();
184
185        if let Some(err) = working_set.parse_errors.first() {
186            report_parse_error(&working_set, err);
187        }
188
189        (block, working_set.render())
190    };
191
192    engine_state.merge_delta(delta)?;
193
194    Ok(())
195}