|
diff --git a/list.c b/list.c
|
| ... |
| 22 |
*head = new; |
22 |
*head = new; |
| 23 |
} |
23 |
} |
| 24 |
|
24 |
|
| 25 |
void list_files_recursively(char *base_path, Node **head) { |
25 |
void list_files_recursively(char *base_path, Node **head, int max_depth, int current_depth) { |
| 26 |
struct stat statbuf; |
26 |
struct stat statbuf; |
| 27 |
if (stat(base_path, &statbuf) == -1) { |
27 |
if (stat(base_path, &statbuf) == -1) { |
| 28 |
perror("stat"); |
28 |
perror("stat"); |
| ... |
| 52 |
|
52 |
|
| 53 |
if (stat(path, &statbuf) != -1) { |
53 |
if (stat(path, &statbuf) != -1) { |
| 54 |
if (S_ISDIR(statbuf.st_mode)) { |
54 |
if (S_ISDIR(statbuf.st_mode)) { |
| 55 |
list_files_recursively(path, head); |
55 |
if (max_depth == -1 || current_depth < max_depth) { |
|
|
56 |
list_files_recursively(path, head, max_depth, current_depth + 1); |
|
|
57 |
} |
| 56 |
} else if (S_ISREG(statbuf.st_mode)) { |
58 |
} else if (S_ISREG(statbuf.st_mode)) { |
| 57 |
add_file_path(head, path); |
59 |
add_file_path(head, path); |
| 58 |
} |
60 |
} |
| ... |
|
diff --git a/main.c b/main.c
|
| 1 |
// TODO: |
1 |
// TODO: |
| 2 |
// - Add language specific filter (by default all but it can also passed |
|
|
| 3 |
// with -tpy -tc -trb) which would only parse python, c and ruby files. |
|
|
| 4 |
// - By default its case insensitive but with passing -cs it tells that |
|
|
| 5 |
// all matching should be done in case sensitive way. |
|
|
| 6 |
// - Add Levenshtein distance for matching and expose distance as arg with |
2 |
// - Add Levenshtein distance for matching and expose distance as arg with |
| 7 |
// something like -d5 which would allow distance of 5 on a match. |
3 |
// something like -d5 which would allow distance of 5 on a match. |
| 8 |
// - Allow DEBUG to be provided as environmental variable. |
|
|
| 9 |
// - Added depth flag (-r means recursive, -l2 means 2 levels deep). |
|
|
| 10 |
|
4 |
|
| 11 |
// FIXME: |
5 |
// FIXME: |
| 12 |
// - Truncate longer argument list. |
6 |
// - Truncate longer argument list. |
| 13 |
|
7 |
|
|
|
8 |
#define _GNU_SOURCE |
| 14 |
#include <assert.h> |
9 |
#include <assert.h> |
|
|
10 |
#include <getopt.h> |
| 15 |
#include <pthread.h> |
11 |
#include <pthread.h> |
|
|
12 |
#include <stdarg.h> |
| 16 |
#include <stdio.h> |
13 |
#include <stdio.h> |
| 17 |
#include <stdlib.h> |
14 |
#include <stdlib.h> |
| 18 |
#include <string.h> |
15 |
#include <string.h> |
| ... |
| 26 |
#include "queries/c.h" |
23 |
#include "queries/c.h" |
| 27 |
#include "queries/cpp.h" |
24 |
#include "queries/cpp.h" |
| 28 |
#include "queries/go.h" |
25 |
#include "queries/go.h" |
|
|
26 |
#include "queries/javascript.h" |
| 29 |
#include "queries/php.h" |
27 |
#include "queries/php.h" |
| 30 |
#include "queries/python.h" |
28 |
#include "queries/python.h" |
| 31 |
#include "queries/rust.h" |
29 |
#include "queries/rust.h" |
| 32 |
#include "queries/javascript.h" |
|
|
| 33 |
|
30 |
|
| 34 |
int debug_enabled = 0; |
31 |
int debug_enabled = 0; |
| 35 |
|
32 |
|
| ... |
| 93 |
const char *query_string; |
90 |
const char *query_string; |
| 94 |
uint32_t query_len; |
91 |
uint32_t query_len; |
| 95 |
const char *cfname; |
92 |
const char *cfname; |
|
|
93 |
int case_sensitive; |
| 96 |
}; |
94 |
}; |
| 97 |
|
95 |
|
| 98 |
// void parse_source_file(const char *file_path, const char *source_code, |
96 |
// void parse_source_file(const char *file_path, const char *source_code, |
| ... |
| 104 |
const char *source_code = args->source_code; |
102 |
const char *source_code = args->source_code; |
| 105 |
TSLanguage *language = args->language; |
103 |
TSLanguage *language = args->language; |
| 106 |
const char *cfname = args->cfname; |
104 |
const char *cfname = args->cfname; |
|
|
105 |
int case_sensitive = args->case_sensitive; |
| 107 |
|
106 |
|
| 108 |
TSParser *parser = ts_parser_new(); |
107 |
TSParser *parser = ts_parser_new(); |
| 109 |
ts_parser_set_language(parser, language); |
108 |
ts_parser_set_language(parser, language); |
| ... |
| 172 |
// Substring matching. |
171 |
// Substring matching. |
| 173 |
// FIXME: Add Levenshtein distance. |
172 |
// FIXME: Add Levenshtein distance. |
| 174 |
if (fn.fname != NULL) { |
173 |
if (fn.fname != NULL) { |
| 175 |
char *result = strstr(fn.fname, cfname); |
174 |
char *result; |
|
|
175 |
if (case_sensitive) { |
|
|
176 |
result = strstr(fn.fname, cfname); |
|
|
177 |
} else { |
|
|
178 |
result = strcasestr(fn.fname, cfname); |
|
|
179 |
} |
|
|
180 |
|
| 176 |
if (result != NULL) { |
181 |
if (result != NULL) { |
| 177 |
char *fparams_formatted = remove_newlines(fn.fparams); |
182 |
char *fparams_formatted = remove_newlines(fn.fparams); |
| 178 |
printf("%s:%zu: %s %s %s\n", file_path, fn.lineno, fn.ftype ? fn.ftype : "", fn.fname, fparams_formatted ? fparams_formatted : ""); |
183 |
printf("%s:%zu: %s %s %s\n", file_path, fn.lineno, fn.ftype ? fn.ftype : "", fn.fname, fparams_formatted ? fparams_formatted : ""); |
| ... |
| 205 |
} |
210 |
} |
| 206 |
|
211 |
|
| 207 |
int main(int argc, char *argv[]) { |
212 |
int main(int argc, char *argv[]) { |
| 208 |
if (argc < 2) { |
213 |
int case_sensitive = 0; |
| 209 |
printf("Usage: %s <search term> [directory|file]\n", argv[0]); |
214 |
int max_depth = -1; |
|
|
215 |
int opt; |
|
|
216 |
struct option long_options[] = { |
|
|
217 |
{"case-sensitive", no_argument, 0, 'c'}, |
|
|
218 |
{"depth", required_argument, 0, 'd'}, |
|
|
219 |
{0, 0, 0, 0}}; |
|
|
220 |
|
|
|
221 |
while ((opt = getopt_long(argc, argv, "cd:", long_options, NULL)) != -1) { |
|
|
222 |
switch (opt) { |
|
|
223 |
case 'c': |
|
|
224 |
case_sensitive = 1; |
|
|
225 |
break; |
|
|
226 |
case 'd': |
|
|
227 |
max_depth = atoi(optarg); |
|
|
228 |
break; |
|
|
229 |
default: |
|
|
230 |
fprintf(stderr, "Usage: %s [-c|--case-sensitive] [-d|--depth <level>] <search term> [directory|file]\n", argv[0]); |
|
|
231 |
return 1; |
|
|
232 |
} |
|
|
233 |
} |
|
|
234 |
|
|
|
235 |
if (optind >= argc) { |
|
|
236 |
fprintf(stderr, "Usage: %s [-c|--case-sensitive] [-d|--depth <level>] <search term> [directory|file]\n", argv[0]); |
| 210 |
return 1; |
237 |
return 1; |
| 211 |
} |
238 |
} |
| 212 |
|
239 |
|
| 213 |
const char *cfname = argv[1]; |
240 |
const char *cfname = argv[optind]; |
| 214 |
char *directory = (argc > 2) ? argv[2] : "."; |
241 |
char *directory = (optind + 1 < argc) ? argv[optind + 1] : "."; |
| 215 |
|
242 |
|
| 216 |
Node *head = NULL; |
243 |
Node *head = NULL; |
| 217 |
list_files_recursively(directory, &head); |
244 |
list_files_recursively(directory, &head, max_depth, 0); |
| 218 |
int list_size = size_of_file_list(head); |
245 |
int list_size = size_of_file_list(head); |
| 219 |
|
246 |
|
| 220 |
const char *debug_env = getenv("DEBUG"); |
247 |
const char *debug_env = getenv("DEBUG"); |
| ... |
| 289 |
thread_args->query_string = query_string; |
316 |
thread_args->query_string = query_string; |
| 290 |
thread_args->query_len = query_len; |
317 |
thread_args->query_len = query_len; |
| 291 |
thread_args->cfname = cfname; |
318 |
thread_args->cfname = cfname; |
|
|
319 |
thread_args->case_sensitive = case_sensitive; |
| 292 |
|
320 |
|
| 293 |
tp_add_job(pool, (thread_func_t)parse_source_file, thread_args); |
321 |
tp_add_job(pool, (thread_func_t)parse_source_file, thread_args); |
| 294 |
} else { |
322 |
} else { |
| ... |
|
diff --git a/tests.sh b/tests.sh
|
| ... |
| 29 |
fi |
29 |
fi |
| 30 |
} |
30 |
} |
| 31 |
|
31 |
|
|
|
32 |
run_test_with_flags() { |
|
|
33 |
local label=$1 |
|
|
34 |
local flags=$2 |
|
|
35 |
local search_term=$3 |
|
|
36 |
local file=$4 |
|
|
37 |
local expected_pattern=$5 |
|
|
38 |
|
|
|
39 |
printf "Testing %-50s " "$label ($flags $search_term)" |
|
|
40 |
output=$($CREP $flags "$search_term" "$file") |
|
|
41 |
|
|
|
42 |
if echo "$output" | grep -q "$expected_pattern"; then |
|
|
43 |
echo "PASSED" |
|
|
44 |
else |
|
|
45 |
echo "FAILED" |
|
|
46 |
echo " Expected pattern: $expected_pattern" |
|
|
47 |
echo " Actual output: $output" |
|
|
48 |
failed=$((failed + 1)) |
|
|
49 |
fi |
|
|
50 |
} |
|
|
51 |
|
| 32 |
echo "Starting tests..." |
52 |
echo "Starting tests..." |
| 33 |
echo "----------------" |
53 |
echo "----------------" |
| 34 |
|
54 |
|
| ... |
| 76 |
run_test "C++ Class" "MyClass" "$TEST_DIR/test.cpp" "class MyClass" |
96 |
run_test "C++ Class" "MyClass" "$TEST_DIR/test.cpp" "class MyClass" |
| 77 |
run_test "C++ Struct" "MyStruct" "$TEST_DIR/test.cpp" "struct MyStruct" |
97 |
run_test "C++ Struct" "MyStruct" "$TEST_DIR/test.cpp" "struct MyStruct" |
| 78 |
run_test "C++ Method" "myMethod" "$TEST_DIR/test.cpp" "void myMethod ()" |
98 |
run_test "C++ Method" "myMethod" "$TEST_DIR/test.cpp" "void myMethod ()" |
|
|
99 |
|
|
|
100 |
# Case Sensitivity Tests |
|
|
101 |
run_test "Default Case Insensitive" "foo" "tests/test.c" "void FooBar" |
|
|
102 |
run_test_with_flags "Case Sensitive -c" "-c" "foobar" "tests/test.c" "void foobar" |
|
|
103 |
|
|
|
104 |
# Depth Tests |
|
|
105 |
run_test_with_flags "Depth 0 (root)" "-d 0" "level" "tests/depth_test" "void level0" |
|
|
106 |
run_test_with_flags "Depth 1 (recursive)" "-d 1" "level" "tests/depth_test" "void level1" |
| 79 |
|
107 |
|
| 80 |
echo "----------------" |
108 |
echo "----------------" |
| 81 |
if [ $failed -eq 0 ]; then |
109 |
if [ $failed -eq 0 ]; then |
| ... |