use rustyline_filehelper::setup_editor; use std::env; use std::path::{Path, PathBuf}; fn get_current_dir() -> String { let current_dir = env::current_dir().unwrap(); let home_dir = dirs::home_dir().unwrap_or_else(|| PathBuf::from("/")); // Replace home directory with '~' in the prompt let display_dir = if current_dir.starts_with(&home_dir) { format!( "~/{}", current_dir.strip_prefix(&home_dir).unwrap().display() ) } else { current_dir.display().to_string() }; display_dir } fn list_directory(current_dir: &PathBuf) { if let Ok(files) = std::fs::read_dir(current_dir) { files.filter_map(Result::ok).for_each(|file| { let is_dir = file.file_type().map(|f| f.is_dir()).unwrap_or(false); let file_name = file.file_name(); if let Some(file_str) = file_name.to_str() { if file_str.starts_with('.') { return; } if is_dir { println!("\x1b[0;34m{}\x1b[0m", file_str); // Blue for directories } else if file_str.ends_with(".csv") { println!("\x1b[0;32m{}\x1b[0m", file_str); // Green for CSV files } else { println!("{}", file_str); } } }); } else { eprintln!("Could not read the directory"); } } fn change_directory(line: &str) { let args: Vec<&str> = line.trim().split_whitespace().collect(); match args.len() { 1 => { // If no directory is provided, change to the home directory if let Some(home_dir) = dirs::home_dir() { if let Err(e) = env::set_current_dir(&home_dir) { eprintln!("Error changing to home directory: {}", e); } } else { println!("Unable to find the home directory."); } } 2 => { let dir = args[1]; let new_dir: PathBuf; // Handle "cd ~" and "cd ~/subdir" cases if dir == "~" { new_dir = dirs::home_dir().unwrap_or_else(|| PathBuf::from("/")); } else if dir.starts_with("~/") { if let Some(home_dir) = dirs::home_dir() { // Join the home directory with the rest of the path new_dir = home_dir.join(&dir[2..]); } else { println!("Unable to find the home directory."); return; } } else { new_dir = Path::new(dir).to_path_buf(); } // Attempt to change to the specified directory if new_dir.exists() && new_dir.is_dir() { if let Err(e) = env::set_current_dir(&new_dir) { eprintln!("Error changing directory: {}", e); } } else if new_dir.is_file() { println!("Cannot change directory: {} is a file", dir); } else { println!("Directory not found: {}", dir); } } _ => println!("Usage: cd "), } } fn main() { // Allowed file extensions: CSV and JPEG files let allowed_extensions = Some(vec!["csv".to_string()]); let commands: Vec = vec!["ls", "pwd", "cd", "clear", "exit"] .iter() .map(|s| s.to_string()) .collect(); let mut rl = setup_editor(allowed_extensions, commands).unwrap(); loop { let display_dir = get_current_dir(); let readline = rl.readline(&format!("{}$ ", display_dir)); match readline { Ok(line) => { match line.trim() { "exit" => break, "clear" => { rl.clear_screen().unwrap(); continue; } "ls" => { // Dynamically get the current directory here list_directory(&env::current_dir().unwrap()); continue; } "pwd" => { // Dynamically get the current directory here println!("{}", env::current_dir().unwrap().display()); continue; } _ if line.trim().starts_with("cd") => { change_directory(&line); continue; } _ => { // it's a validated input that matches the allowed extensions -- do some logic println!("You entered: {}", line); } } let _ = rl.add_history_entry(line.as_str()); continue; } Err(e) => { eprintln!("Error: {:?}", e); break; } } } }