about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorRory Bradford <roryrjb@gmail.com>2020-04-10 11:34:57 +0100
committerRory Bradford <roryrjb@gmail.com>2020-04-10 11:34:57 +0100
commit1cc76724bed0180355e53d705bb9ec30928a71ac (patch)
tree7ccf9e253c69a844995e3a0572120fc824fcc9dc
parent8af4130a8927f0f4aaab208769b93da1ef0c32f8 (diff)
downloadrf-1cc76724bed0180355e53d705bb9ec30928a71ac.tar.gz
Refactor
Implement `fnmatch` file name matching.

Define clang formatting, previously used defaults without a config
file; apply formatting.

Make `install` more cross-platform.

Signed-off-by: Rory Bradford <roryrjb@gmail.com>
-rw-r--r--.clang-format8
-rw-r--r--Makefile10
-rw-r--r--config.h9
-rw-r--r--rf.140
-rw-r--r--rf.c114
5 files changed, 45 insertions, 136 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..8af29b3
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,8 @@
+IndentWidth: 4
+TabWidth: 4
+UseTab: Always
+AllowShortIfStatementsOnASingleLine: false
+IndentCaseLabels: false
+AlignAfterOpenBracket: DontAlign
+AllowAllParametersOfDeclarationOnNextLine: true
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
diff --git a/Makefile b/Makefile
index 95202dd..75aed08 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 .SUFFIXES: .c .o
 
 BIN = rf
-VERSION = 0.0.2
+VERSION = 0.0.3
 OBJS = rf.o
 MANPAGE = rf.1
 CC = cc
@@ -45,9 +45,11 @@ static: $(OBJS)
 	$(CC) -c -o $@ $< $(CFLAGS)
 
 install: build
-	install $(BIN) $(DESTDIR)$(PREFIX)/bin/
-	install -TD $(MANPAGE) $(DESTDIR)$(PREFIX)/man/man1/$(MANPAGE)
-	gzip $(PREFIX)/man/man1/$(MANPAGE)
+	install -Dm755 $(BIN) $(DESTDIR)$(PREFIX)/bin/
+	install -Dm444 $(MANPAGE) $(DESTDIR)$(PREFIX)/man/man1/$(MANPAGE)
+
+readme:
+	MANWIDTH=80 man ./rf.1 > README
 
 clean:
 	rm -vf $(BIN) *.o
diff --git a/config.h b/config.h
index 009908c..3a37f96 100644
--- a/config.h
+++ b/config.h
@@ -1,11 +1,10 @@
-char *ignored_dirs[] = { "node_modules", ".mypy_cache", ".git",
-						 ".hg",			 "__pycache__", ".eggs" };
+char *ignored_dirs[] = {"*node_modules*", "*.mypy_cache*", "*.git*", "*.hg*",
+	"*__pycache__*", "*.eggs*"};
 
 size_t ignored_dirs_size = sizeof(ignored_dirs) / sizeof(ignored_dirs[0]);
 
-char *ignored_extensions[] = { ".pyc", ".jpg", ".jpeg", ".png", ".gif",
-							   ".zip", ".tar", ".xz",	".gz",	".gzip",
-							   ".jar", ".apk", ".deb",	".o" };
+char *ignored_extensions[] = {".pyc", ".jpg", ".jpeg", ".png", ".gif", ".zip",
+	".tar", ".xz", ".gz", ".gzip", ".jar", ".apk", ".deb", ".o"};
 
 size_t ignored_extensions_size =
 	sizeof(ignored_extensions) / sizeof(ignored_extensions[0]);
diff --git a/rf.1 b/rf.1
index 1d5001e..364b719 100644
--- a/rf.1
+++ b/rf.1
@@ -9,7 +9,7 @@ rf \- A tiny and simple file finder
 
 .SH DESCRIPTION
 .B rf
-will find files based on simple substring patterns.
+will find files based on glob patterns.
 
 .SH OPTIONS
 .TP
@@ -42,43 +42,5 @@ Invert matches.
 .br
 Limit to [n] matches. The default is 0 which will return all matches.
 
-.SH PATTERNS
-Files and directories can be found using very simple patterns.
-
-.TP
-.B "Substrings"
-.br
-A simple string is basically a substring match. So if you supply a
-pattern of "js", rf will match any file that contains the string "js"
-anywhere in the filename. If the pattern is ".js" it will match any
-".js" or even ".json" files for example, as well as the filename
-"script.js.backup", in other words the character "." is just that, it
-doesn't have any special significance such as in regular expressions.
-It also doesn't have any kind of implicit positional information, it
-will just match at any point in the filename.
-
-.TP
-.B "Beginning and end"
-.br
-There are two characters which are treated as special. The caret
-character "^" signifies *at the beginning of* the filename. So for
-example if you specify the substring of "bar" it will match the
-files "bar", "barbar", "foobar" and "foobarbaz", as that substring
-appears at some point in the filename. If you specify the substring
-of "^bar" it will only match the files "bar" and "barbar" as that
-substring only appears at the beginning of those filenames.
-
-On the other side, if you use the dollar character "$" it will only
-match if at the end of the filename. So in the previous example if
-you specified "bar$" it would match both "foobar" and "barbar".
-
-You can use these characters in combination to only match the whole
-string. So with our imaginary directory above, specifying "^bar$" will
-only match the file "bar".
-
-.SH SEE ALSO
-.BR find (1),
-.BR rg (1)
-
 .SH COPYRIGHT
 Copyright \(co 2020 Rory Bradford <roryrjb@gmail.com>.
diff --git a/rf.c b/rf.c
index 11ba7ae..68d7e59 100644
--- a/rf.c
+++ b/rf.c
@@ -3,6 +3,7 @@
 
 #include <dirent.h>
 #include <errno.h>
+#include <fnmatch.h>
 #include <getopt.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -22,14 +23,12 @@ struct switches {
 	int count;
 };
 
-static int version(char *error)
-{
+static int version(char *error) {
 	fprintf(stderr, "%s version %s\n", NAME, VERSION);
 	return error == NULL ? 0 : 1;
 }
 
-static int usage(char *error)
-{
+static int usage(char *error) {
 	if (error != NULL) {
 		fprintf(stderr, "Error: %s\n\n", error);
 	}
@@ -39,9 +38,7 @@ static int usage(char *error)
 	fprintf(stderr, "  --basename, -b   only show basename in results\n");
 	fprintf(stderr, "  --dirname, -d    only show dirname in results\n");
 	fprintf(stderr, "  --invert, -v     invert matching\n");
-	fprintf(stderr,
-			"  --limit=n        limit to [n] results, all if 0 [default=0]\n");
-
+	fprintf(stderr, "  --limit=n        limit to [n] results, allif 0\n");
 	fprintf(stderr, "\n  --help, -h       show help\n");
 	fprintf(stderr, "  --version, -V    show version\n");
 	fprintf(stderr, "\n");
@@ -49,8 +46,7 @@ static int usage(char *error)
 	return version(error);
 }
 
-static int is_child(char *dirname)
-{
+static int is_child(char *dirname) {
 	if (strcmp("..", dirname) == 0 || strcmp(".", dirname) == 0) {
 		return 0;
 	}
@@ -58,12 +54,11 @@ static int is_child(char *dirname)
 	return 1;
 }
 
-static int not_in_array(char **arr, char *dirname, size_t size)
-{
+static int not_in_array(char **arr, char *dirname, size_t size) {
 	int i = 0;
 
 	for (; i < size; i++) {
-		if (strstr(dirname, arr[i])) {
+		if (fnmatch(arr[i], dirname, 0) == 0) {
 			return 0;
 		}
 	}
@@ -71,8 +66,7 @@ static int not_in_array(char **arr, char *dirname, size_t size)
 	return 1;
 }
 
-static int at_side(int beginning, char *filename, char *str)
-{
+static int at_side(int beginning, char *filename, char *str) {
 	int c = 0;
 	int matched = 1;
 
@@ -97,8 +91,7 @@ static int at_side(int beginning, char *filename, char *str)
 	return matched;
 }
 
-static int excluded_extension(char *filename)
-{
+static int excluded_extension(char *filename) {
 	int i = 0;
 
 	for (; i < ignored_extensions_size; i++) {
@@ -112,9 +105,8 @@ static int excluded_extension(char *filename)
 	return 0;
 }
 
-static void print_result(char *path, struct switches *switches,
-						 struct dirent *entry)
-{
+static void print_result(
+	char *path, struct switches *switches, struct dirent *entry) {
 	if (switches->basename) {
 		printf("%s\n", entry->d_name);
 	} else {
@@ -131,28 +123,12 @@ static void print_result(char *path, struct switches *switches,
 	}
 }
 
-static char *strslice(char *source, int start, int end)
-{
-	int i = 0;
-	int diff = start + end;
-	int len = strlen(source) - diff;
-	char *output = malloc(sizeof(char *) * len);
-	memset(output, '\0', len);
-
-	for (; i < len; i++) {
-		output[i] = source[i + start];
-	}
-
-	return output;
-}
-
 /* return 1 if breaking early (e.g. reaching limit) otherwise return 0 */
 static int recurse_find(char **patterns, int *pattern_count, char *dirname,
-						struct switches *switches)
-{
+	struct switches *switches) {
 	DIR *dir;
 
-	char path[MAXPATHLEN] = { '\0' };
+	char path[MAXPATHLEN] = {'\0'};
 	int break_early = 0;
 	strcat(path, dirname);
 	dir = opendir(path);
@@ -167,14 +143,14 @@ static int recurse_find(char **patterns, int *pattern_count, char *dirname,
 			switch (entry->d_type) {
 			case DT_DIR:
 				if (is_child(entry->d_name) &&
-					not_in_array(ignored_dirs, entry->d_name,
-								 ignored_dirs_size)) {
-					char child_path[MAXPATHLEN] = { '\0' };
+					not_in_array(
+						ignored_dirs, entry->d_name, ignored_dirs_size)) {
+					char child_path[MAXPATHLEN] = {'\0'};
 					strcat(child_path, path);
 					strcat(child_path, "/");
 					strcat(child_path, entry->d_name);
-					if (recurse_find(patterns, pattern_count, child_path,
-									 switches)) {
+					if (recurse_find(
+							patterns, pattern_count, child_path, switches)) {
 						break_early = 1;
 						break;
 					};
@@ -188,44 +164,10 @@ static int recurse_find(char **patterns, int *pattern_count, char *dirname,
 
 				for (; p < *pattern_count; p++) {
 					char *pattern = patterns[p];
-					char first = pattern[0];
-					char last = pattern[strlen(pattern) - 1];
 					char *parsed = NULL;
-					int arg_len = strlen(pattern);
-
-					if (last == '$' && first == '^') {
-						/* show everything */
-						if (strlen(pattern) == 2) {
-							matched = 1;
-						} else {
-							/* match whole string */
-							parsed = strslice(pattern, 1, 1);
-
-							if (strcmp(entry->d_name, parsed) == 0) {
-								matched = 1;
-							}
-						}
-					} else if (last == '$') {
-						/* match at end */
-						parsed = arg_len == 1 ? NULL : strslice(pattern, 0, 1);
-
-						if (at_side(0, entry->d_name,
-									arg_len == 1 ? pattern : parsed)) {
-							matched = 1;
-						}
-					} else if (first == '^') {
-						/* match at beginning */
-						parsed = arg_len == 1 ? NULL : strslice(pattern, 1, 0);
-
-						if (at_side(1, entry->d_name,
-									arg_len == 1 ? pattern : parsed)) {
-							matched = 1;
-						}
-					} else {
-						/* substring match */
-						if (strstr(entry->d_name, pattern) != NULL) {
-							matched = 1;
-						}
+
+					if (fnmatch(pattern, entry->d_name, 0) == 0) {
+						matched = 1;
 					}
 
 					if (parsed != NULL) {
@@ -261,15 +203,11 @@ static int recurse_find(char **patterns, int *pattern_count, char *dirname,
 	return 0;
 }
 
-int main(int argc, char **argv)
-{
-	static struct option options[] = { { "basename", no_argument, 0, 0 },
-									   { "dirname", no_argument, 0, 0 },
-									   { "invert", no_argument, 0, 0 },
-									   { "limit", required_argument, 0, 0 },
-									   { "version", no_argument, 0, 0 },
-									   { "help", no_argument, 0, 0 },
-									   { 0, 0, 0, 0 } };
+int main(int argc, char **argv) {
+	static struct option options[] = {{"basename", no_argument, 0, 0},
+		{"dirname", no_argument, 0, 0}, {"invert", no_argument, 0, 0},
+		{"limit", required_argument, 0, 0}, {"version", no_argument, 0, 0},
+		{"help", no_argument, 0, 0}, {0, 0, 0, 0}};
 
 	int basename = 0;
 	int dirname = 0;