nushell on your web browser
nushell wasm terminal
at main 2.2 kB view raw
1use crate::{ 2 error::to_shell_err, 3 globals::{get_pwd, get_vfs, set_pwd}, 4}; 5use nu_engine::CallExt; 6use nu_protocol::{ 7 Category, IntoValue, PipelineData, ShellError, Signature, SyntaxShape, Type, 8 engine::{Command, EngineState, Stack}, 9}; 10use std::sync::Arc; 11use vfs::VfsFileType; 12 13#[derive(Clone)] 14pub struct Cd; 15 16impl Command for Cd { 17 fn name(&self) -> &str { 18 "cd" 19 } 20 21 fn signature(&self) -> Signature { 22 Signature::build("cd") 23 .optional("path", SyntaxShape::Filepath, "the path to change into") 24 .input_output_type(Type::Nothing, Type::Nothing) 25 .category(Category::FileSystem) 26 } 27 28 fn description(&self) -> &str { 29 "change the current directory in the virtual filesystem." 30 } 31 32 fn run( 33 &self, 34 engine_state: &EngineState, 35 stack: &mut Stack, 36 call: &nu_protocol::engine::Call, 37 _input: PipelineData, 38 ) -> Result<PipelineData, ShellError> { 39 let path_arg: Option<String> = call.opt(engine_state, stack, 0)?; 40 let path = path_arg.unwrap_or_else(|| "/".to_string()); 41 42 let base: Arc<vfs::VfsPath> = if path.starts_with('/') { 43 get_vfs() 44 } else { 45 get_pwd().clone() 46 }; 47 48 let target = base 49 .join(path.trim_end_matches('/')) 50 .map_err(to_shell_err(call.head))?; 51 52 // Ensure target exists and is a directory 53 let metadata = target.metadata().map_err(to_shell_err(call.head))?; 54 match metadata.file_type { 55 VfsFileType::Directory => { 56 stack.add_env_var( 57 "PWD".to_string(), 58 target.as_str().into_value(call.arguments_span()), 59 ); 60 set_pwd(Arc::new(target)); 61 Ok(PipelineData::Empty) 62 } 63 VfsFileType::File => Err(ShellError::GenericError { 64 error: "not a directory".to_string(), 65 msg: format!("'{}' is not a directory", path), 66 span: Some(call.head), 67 help: None, 68 inner: vec![], 69 }), 70 } 71 } 72}