diff --git a/src/main.rs b/src/main.rs index 87f2a98..68b87e8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ use syntax_tree::find_aliases; use tree_sitter::Parser; fn main() { - const TEST_FILE_PATH: &str = "./src/test/examples/bash_aliases"; + const TEST_FILE_PATH: &str = "./src/test/examples/special_chars_bash_alias"; let code = fs::read_to_string(TEST_FILE_PATH).expect("Error reading file"); let mut parser = Parser::new(); diff --git a/src/syntax_tree/alias.rs b/src/syntax_tree/alias.rs index 8594025..14847cd 100644 --- a/src/syntax_tree/alias.rs +++ b/src/syntax_tree/alias.rs @@ -1,10 +1,20 @@ -// Unquote a string (remove the quotes if it has) -// 'foo' -> foo -// "foo" -> foo -// foo -> foo -// "\'foo\'" -> 'foo' +use crate::syntax_tree::printer; + +use super::print_tree; + +/// Unquote a string (remove the quotes if it has) +// https://www.gnu.org/software/bash/manual/html_node/Quoting.html +/// Examples: +/// unquote_string("foo") -> foo +/// unquote_string("'foo'") -> foo +/// unquote_string("\"foo\"") -> foo +/// unquote_string("foo'") -> foo' // TODO: Add tests fn unquote_string(string: &str) -> String { + if string.len() < 2 { + return string.to_string(); + } + let has_single_quotes = string.starts_with('\'') && string.ends_with('\''); let has_double_quotes = string.starts_with('"') && string.ends_with('"'); @@ -15,6 +25,7 @@ fn unquote_string(string: &str) -> String { } } +/// Represents the possible errors that can occur when extracting an alias enum AliasError { MissingCommandName, MissingAliasName, @@ -23,44 +34,64 @@ enum AliasError { InvalidUtf8Text, } -// https://www.gnu.org/software/bash/manual/html_node/Quoting.html -// TODO: Handle each error of this function with a enum (AliasError) -// return: -> Result<(String, String), AliasError> { fn extract_alias( node: tree_sitter::Node, source: &[u8], ) -> Result<(String, String), AliasError> { let mut cursor = node.walk(); - // Find the command_name node if !cursor.goto_first_child() || cursor.node().kind() != "command_name" { return Err(AliasError::MissingCommandName); } - // Check if it's an alias command let command_name = cursor.node().utf8_text(source).unwrap(); if command_name != "alias" { return Err(AliasError::MissingAliasName); } - // Go to the argument node if !cursor.goto_next_sibling() { return Err(AliasError::MissingArguments); } let node = cursor.node(); - if node.child_count() != 2 { + if node.child_count() > 3 { return Err(AliasError::InvalidArgumentCount); } cursor.goto_first_child(); - let alias_name_node = cursor.node(); - let alias_name = alias_name_node - .utf8_text(source) - .unwrap() - .trim_end_matches('='); + let alias_name = match cursor.node().kind() { + "string" => { + if !cursor.goto_first_child() { + return Err(AliasError::MissingAliasName); + } + if !cursor.goto_next_sibling() { + return Err(AliasError::MissingAliasName); + } + + let string_node = cursor.node(); + + cursor.goto_parent(); + cursor.goto_next_sibling(); + + // Attempt to extract the text content from the string node + match string_node.utf8_text(source) { + Ok(alias_content) => Ok(alias_content.to_string()), + Err(_) => Err(AliasError::InvalidUtf8Text), + } + } + "word" => { + // Extract the alias name from the word node and trim '=' at the end + match cursor.node().utf8_text(source) { + Ok(alias_content) => { + Ok(alias_content.trim_end_matches('=').to_string()) + } + Err(_) => Err(AliasError::InvalidUtf8Text), + } + } + _ => Err(AliasError::MissingCommandName), + }?; cursor.goto_next_sibling(); @@ -71,7 +102,9 @@ fn extract_alias( let unquoted_alias_content = unquote_string(alias_content); - Ok((alias_name.to_string(), unquoted_alias_content)) + // println!("alias_content: {}", alias_content); + + Ok((alias_name, unquoted_alias_content)) } pub fn find_aliases( diff --git a/src/test/examples/bash_aliases b/src/test/examples/bash_aliases index 4945ac1..4faf767 100644 --- a/src/test/examples/bash_aliases +++ b/src/test/examples/bash_aliases @@ -5,10 +5,11 @@ shopt -s expand_aliases # Simple aliases alias ls='ls --color=auto' alias ll='ls -l' +alias "abc!"='echo String with special characters' alias la= 'ls -A' # This alias is invalid and should be ignored alias gitlog='git log --graph --oneline --decorate --all' -# Cases like this are handled by the parser but it's good to have a test for it +# Cases like this are not handled yet by the Parser my_function() { alias greet='echo Hello, World!' }