summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--list.c6
-rw-r--r--list.h2
-rw-r--r--main.c54
-rwxr-xr-x[-rw-r--r--]tests.sh28
-rw-r--r--tests/depth_test/level0.c1
-rw-r--r--tests/depth_test/sub/level1.c1
-rw-r--r--tests/test.c5
7 files changed, 81 insertions, 16 deletions
diff --git a/list.c b/list.c
index e1d4ffd..71e70c8 100644
--- a/list.c
+++ b/list.c
@@ -22,7 +22,7 @@ void add_file_path(Node **head, char *file_path) {
*head = new;
}
-void list_files_recursively(char *base_path, Node **head) {
+void list_files_recursively(char *base_path, Node **head, int max_depth, int current_depth) {
struct stat statbuf;
if (stat(base_path, &statbuf) == -1) {
perror("stat");
@@ -52,7 +52,9 @@ void list_files_recursively(char *base_path, Node **head) {
if (stat(path, &statbuf) != -1) {
if (S_ISDIR(statbuf.st_mode)) {
- list_files_recursively(path, head);
+ if (max_depth == -1 || current_depth < max_depth) {
+ list_files_recursively(path, head, max_depth, current_depth + 1);
+ }
} else if (S_ISREG(statbuf.st_mode)) {
add_file_path(head, path);
}
diff --git a/list.h b/list.h
index c958836..e34d921 100644
--- a/list.h
+++ b/list.h
@@ -7,7 +7,7 @@ typedef struct node {
} Node;
void add_file_path(Node **head, char *file_path);
-void list_files_recursively(char *base_path, Node **head);
+void list_files_recursively(char *base_path, Node **head, int max_depth, int current_depth);
void free_file_list(Node *head);
int size_of_file_list(Node *head);
diff --git a/main.c b/main.c
index 35f8c49..49fe5a3 100644
--- a/main.c
+++ b/main.c
@@ -1,18 +1,15 @@
// TODO:
-// - Add language specific filter (by default all but it can also passed
-// with -tpy -tc -trb) which would only parse python, c and ruby files.
-// - By default its case insensitive but with passing -cs it tells that
-// all matching should be done in case sensitive way.
// - Add Levenshtein distance for matching and expose distance as arg with
// something like -d5 which would allow distance of 5 on a match.
-// - Allow DEBUG to be provided as environmental variable.
-// - Added depth flag (-r means recursive, -l2 means 2 levels deep).
// FIXME:
// - Truncate longer argument list.
+#define _GNU_SOURCE
#include <assert.h>
+#include <getopt.h>
#include <pthread.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -26,10 +23,10 @@
#include "queries/c.h"
#include "queries/cpp.h"
#include "queries/go.h"
+#include "queries/javascript.h"
#include "queries/php.h"
#include "queries/python.h"
#include "queries/rust.h"
-#include "queries/javascript.h"
int debug_enabled = 0;
@@ -93,6 +90,7 @@ struct ThreadArgs {
const char *query_string;
uint32_t query_len;
const char *cfname;
+ int case_sensitive;
};
// void parse_source_file(const char *file_path, const char *source_code,
@@ -104,6 +102,7 @@ void parse_source_file(void *arg) {
const char *source_code = args->source_code;
TSLanguage *language = args->language;
const char *cfname = args->cfname;
+ int case_sensitive = args->case_sensitive;
TSParser *parser = ts_parser_new();
ts_parser_set_language(parser, language);
@@ -172,7 +171,13 @@ void parse_source_file(void *arg) {
// Substring matching.
// FIXME: Add Levenshtein distance.
if (fn.fname != NULL) {
- char *result = strstr(fn.fname, cfname);
+ char *result;
+ if (case_sensitive) {
+ result = strstr(fn.fname, cfname);
+ } else {
+ result = strcasestr(fn.fname, cfname);
+ }
+
if (result != NULL) {
char *fparams_formatted = remove_newlines(fn.fparams);
printf("%s:%zu: %s %s %s\n", file_path, fn.lineno, fn.ftype ? fn.ftype : "", fn.fname, fparams_formatted ? fparams_formatted : "");
@@ -205,16 +210,38 @@ const char *get_file_extension(const char *file_path) {
}
int main(int argc, char *argv[]) {
- if (argc < 2) {
- printf("Usage: %s <search term> [directory|file]\n", argv[0]);
+ int case_sensitive = 0;
+ int max_depth = -1;
+ int opt;
+ struct option long_options[] = {
+ {"case-sensitive", no_argument, 0, 'c'},
+ {"depth", required_argument, 0, 'd'},
+ {0, 0, 0, 0}};
+
+ while ((opt = getopt_long(argc, argv, "cd:", long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'c':
+ case_sensitive = 1;
+ break;
+ case 'd':
+ max_depth = atoi(optarg);
+ break;
+ default:
+ fprintf(stderr, "Usage: %s [-c|--case-sensitive] [-d|--depth <level>] <search term> [directory|file]\n", argv[0]);
+ return 1;
+ }
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "Usage: %s [-c|--case-sensitive] [-d|--depth <level>] <search term> [directory|file]\n", argv[0]);
return 1;
}
- const char *cfname = argv[1];
- char *directory = (argc > 2) ? argv[2] : ".";
+ const char *cfname = argv[optind];
+ char *directory = (optind + 1 < argc) ? argv[optind + 1] : ".";
Node *head = NULL;
- list_files_recursively(directory, &head);
+ list_files_recursively(directory, &head, max_depth, 0);
int list_size = size_of_file_list(head);
const char *debug_env = getenv("DEBUG");
@@ -289,6 +316,7 @@ int main(int argc, char *argv[]) {
thread_args->query_string = query_string;
thread_args->query_len = query_len;
thread_args->cfname = cfname;
+ thread_args->case_sensitive = case_sensitive;
tp_add_job(pool, (thread_func_t)parse_source_file, thread_args);
} else {
diff --git a/tests.sh b/tests.sh
index 6f3d7f1..f191e87 100644..100755
--- a/tests.sh
+++ b/tests.sh
@@ -29,6 +29,26 @@ run_test() {
fi
}
+run_test_with_flags() {
+ local label=$1
+ local flags=$2
+ local search_term=$3
+ local file=$4
+ local expected_pattern=$5
+
+ printf "Testing %-50s " "$label ($flags $search_term)"
+ output=$($CREP $flags "$search_term" "$file")
+
+ if echo "$output" | grep -q "$expected_pattern"; then
+ echo "PASSED"
+ else
+ echo "FAILED"
+ echo " Expected pattern: $expected_pattern"
+ echo " Actual output: $output"
+ failed=$((failed + 1))
+ fi
+}
+
echo "Starting tests..."
echo "----------------"
@@ -77,6 +97,14 @@ run_test "C++ Class" "MyClass" "$TEST_DIR/test.cpp" "class MyClass"
run_test "C++ Struct" "MyStruct" "$TEST_DIR/test.cpp" "struct MyStruct"
run_test "C++ Method" "myMethod" "$TEST_DIR/test.cpp" "void myMethod ()"
+# Case Sensitivity Tests
+run_test "Default Case Insensitive" "foo" "tests/test.c" "void FooBar"
+run_test_with_flags "Case Sensitive -c" "-c" "foobar" "tests/test.c" "void foobar"
+
+# Depth Tests
+run_test_with_flags "Depth 0 (root)" "-d 0" "level" "tests/depth_test" "void level0"
+run_test_with_flags "Depth 1 (recursive)" "-d 1" "level" "tests/depth_test" "void level1"
+
echo "----------------"
if [ $failed -eq 0 ]; then
echo "All tests passed!"
diff --git a/tests/depth_test/level0.c b/tests/depth_test/level0.c
new file mode 100644
index 0000000..a872dab
--- /dev/null
+++ b/tests/depth_test/level0.c
@@ -0,0 +1 @@
+void level0() {}
diff --git a/tests/depth_test/sub/level1.c b/tests/depth_test/sub/level1.c
new file mode 100644
index 0000000..e4fd738
--- /dev/null
+++ b/tests/depth_test/sub/level1.c
@@ -0,0 +1 @@
+void level1() {}
diff --git a/tests/test.c b/tests/test.c
index 4326f11..1d5fd3f 100644
--- a/tests/test.c
+++ b/tests/test.c
@@ -30,3 +30,8 @@ int main() {
hello();
return 0;
}
+
+// Case sensitivity tests
+void FooBar() {}
+void foobar() {}
+void FOOBAR() {}