diff --git a/src/commands/mod.rs b/src/commands/mod.rs index a824cc4..f86e628 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -3,7 +3,7 @@ use structopt::StructOpt; #[derive(StructOpt)] pub struct CLI { - // Flag to search all classes with that value + /// Flag to search all classes with that value #[structopt( short = "g", long = "grep", @@ -11,11 +11,11 @@ pub struct CLI { )] pub grep: bool, - // Class name to be fetched + /// Class name to be fetched #[structopt(help = "Name of the Python class")] pub class_name: String, - // Search directory + /// Search path #[structopt(parse(from_os_str), default_value = ".", help = "Search directory")] - pub dir_path: PathBuf, + pub path: PathBuf, } diff --git a/src/joneslib/loader.rs b/src/joneslib/loader.rs index be6d1bb..e63e210 100644 --- a/src/joneslib/loader.rs +++ b/src/joneslib/loader.rs @@ -22,15 +22,23 @@ static INHERITANCE_PATTERN: &str = r"\s\[(.*?)\]"; static OUTPUT_PATTERN: &str = r" (\w+)"; /// Loads all objects from a Python project, given through the python project path. -pub fn load_python_project(project_path: &PathBuf) -> Option> { +pub fn load_python_project(path: &PathBuf) -> Option> { let class_name_pattern = Regex::new(CLASS_NAME_PATTERN).unwrap(); let file_name_pattern = Regex::new(FILE_NAME_PATTERN).unwrap(); - let script_output = match run_python_script(&project_path) { - Some(output) => String::from_utf8(output).unwrap(), - None => return None, + let script_output = if path.is_dir() { + match run_python_script(&path) { + Some(output) => String::from_utf8(output).unwrap(), + None => return None, + } + } else { + match run_python_single_file_script(&path) { + Some(output) => String::from_utf8(output).unwrap(), + None => return None, + } }; + let file_pattern_captures = file_name_pattern.captures_iter(&script_output); let found_classes = class_name_pattern .captures_iter(&script_output) @@ -129,6 +137,36 @@ for root, dirs, files in os.walk({:?}): } } +#[inline] +fn run_python_single_file_script(file_path: &PathBuf) -> Option> { + let python_script = format!( + r#"import ast +import os + +file_name = {:?} +with open(file_name, "r") as file: + tree = ast.parse(file.read()) + +for node in ast.walk(tree): + if not isinstance(node, ast.ClassDef): + continue + + class_name = node.name + print(" %s, %s" % (class_name, file_name)) +"#, + file_path.as_os_str(), + ); + + let output = Command::new("python").arg("-c").arg(python_script).output(); + + if let Ok(output) = output { + println!("{}", String::from_utf8(output.stderr).unwrap()); + Some(output.stdout) + } else { + None + } +} + #[inline] fn run_python_class_script(file_path: &PathBuf, class_name: &String) -> Option> { let python_script = format!( diff --git a/src/joneslib/mod.rs b/src/joneslib/mod.rs index 81f7729..015ffb7 100644 --- a/src/joneslib/mod.rs +++ b/src/joneslib/mod.rs @@ -85,8 +85,8 @@ pub fn project_traversal(dir_path: &PathBuf, class_name: &String) -> Option Option> { - let project_classes = match loader::load_python_project(dir_path) { +pub fn search(path: &PathBuf, class_name: &String) -> Option> { + let project_classes = match loader::load_python_project(path) { Some(classes) => classes, None => { println!("Error occurred while loading project classes"); diff --git a/src/main.rs b/src/main.rs index 6c80a59..356f398 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,13 +18,13 @@ fn main() { let comms = commands::CLI::from_args(); if comms.grep { // Search for a keyword in class name - match joneslib::search(&comms.dir_path, &comms.class_name) { + match joneslib::search(&comms.path, &comms.class_name) { Some(matches) => display::class_matches(matches), None => display::not_found_message(), } } else { // Generate python class - match joneslib::project_traversal(&comms.dir_path, &comms.class_name) { + match joneslib::project_traversal(&comms.path, &comms.class_name) { Some(class) => joneslib::display::output_class(&class), None => display::not_found_message(), }