Skip to content

Commit 0780da6

Browse files
committed
refactored the command finding logic
1 parent 2455934 commit 0780da6

File tree

1 file changed

+44
-37
lines changed

1 file changed

+44
-37
lines changed

src/main.rs

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,50 @@
11
#[allow(unused_imports)]
22
use std::io::{self, Write};
3+
use std::path::PathBuf;
34

45
const BUILT_IN_COMMANDS: [&str;3] = ["echo","exit","type"];
56

7+
enum CommandLocation {
8+
Builtin,
9+
Executable(PathBuf),
10+
NotFound,
11+
}
12+
13+
impl CommandLocation{
14+
fn resolve(command_name:&str) -> Self{
15+
if BUILT_IN_COMMANDS.contains(&command_name){
16+
return Self::Builtin;
17+
}
18+
if let Some(path_var) = std::env::var_os("PATH"){
19+
for dir in std::env::split_paths(&path_var){
20+
let full_path = dir.join(command_name);
21+
if !full_path.exists() {continue};
22+
23+
#[cfg(unix)]
24+
{
25+
use std::os::unix::fs::PermissionsExt;
26+
if let Ok(metadata) = std::fs::metadata(&full_path) {
27+
if metadata.permissions().mode() & 0o111 == 0 {
28+
continue;
29+
}
30+
} else {
31+
continue;
32+
}
33+
}
34+
return Self::Executable(full_path);
35+
}
36+
}
37+
Self::NotFound
38+
}
39+
fn describe(&self,name:&str) -> String{
40+
match self {
41+
CommandLocation::Builtin => format!("{} is a shell builtin", name),
42+
CommandLocation::Executable(path) => format!("{} is {}", name, path.display()),
43+
CommandLocation::NotFound => format!("{}: not found", name),
44+
}
45+
}
46+
}
47+
648
enum Command{
749
ExitCommand,
850
EchoCommand {display_string:String},
@@ -49,43 +91,8 @@ fn main() {
4991
Command::ExitCommand => break,
5092
Command::EchoCommand {display_string} => println!("{}", display_string),
5193
Command::TypeCommand {command_name} => {
52-
if BUILT_IN_COMMANDS.contains(&command_name.as_str()){
53-
println!("{} is a shell builtin",command_name);
54-
continue;
55-
}
56-
let mut found = false;
57-
//finding the files using rust std library
58-
if let Some(path_var) = std::env::var_os("PATH"){
59-
for dir in std::env::split_paths(&path_var){
60-
let full_path = dir.join(&command_name);
61-
62-
// skip if file/comand does not exist
63-
if !full_path.exists(){
64-
continue;
65-
}
66-
67-
#[cfg(unix)]
68-
{
69-
use std::os::unix::fs::PermissionsExt;
70-
71-
if let Ok(metadata) = std::fs::metadata(&full_path) {
72-
let perms = metadata.permissions().mode();
73-
74-
// owner/group/other execute bits: 0o111
75-
if perms & 0o111 == 0 {
76-
continue; // skip non-executable
77-
}
78-
} else {
79-
continue; // could not read metadata
80-
}
81-
}
82-
83-
println!("{} is {}", command_name, full_path.display());
84-
found=true;
85-
break;
86-
}
87-
}
88-
if !found{println!("{}: not found", command_name)};
94+
let location = CommandLocation::resolve(&command_name);
95+
println!("{}", location.describe(&command_name));
8996
},
9097
Command::CommandNotFound => println!("{}: command not found", input.trim()),
9198
}

0 commit comments

Comments
 (0)