diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6c1214b --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +CC=gcc +FLAGS=-Wall -pedantic -g + +all: tigger + +clean: + rm -f tigger + rm -f *.o + +tigger: tigger.o + ${CC} -o tigger ${FLAGS} tigger.o + +tigger.o: tigger.c + ${CC} -o tigger.o ${FLAGS} -c tigger.c diff --git a/plan b/plan new file mode 100644 index 0000000..e05f934 --- /dev/null +++ b/plan @@ -0,0 +1,67 @@ +What should be trivial: + * Finding tags for a given file. + * Finding files for a given tag. + * Adding a tag to a given file. + * Removing a tag from a given file. + +What should be possible but unimportant: + * Finding files for a combination of tags. + * Giving tags descriptions. + * Marking tags as related. + +Structure: + .tigger dir in any tagged folder. + 'tags' dir in there, with each file in it being named for one tag + - maybe also split into subdirs by first two chars of tag, so as to + avoid having many files all in a single dir + each tag file begins with a description, then a blank line, then one filename per line + 'index' file also in .tigger, alternates between filename lines and taglist lines + 'tags' used for quickly listing files by tag, 'index' used for quickly listing tags by file + 'index' automatically regenerated after any command that modifies a tags file + +Commands: + tigger reindex // force a reindex + tigger tag $file $tag [$tag ..] + tigger untag $file $tag [$tag ..] + tigger files $tag + tigger tags $file + tigger mv $file $newfile // does an mv, and preserves tags + tigger cp $file $newfile // does a cp, and duplicates tags + tigger rm $file // does an rm, and removes tags + +Pseudocode: + reindex: + if index is nonexistent, create it, and set new_index=true + for each tagfile in tags: + if last modified date is more recent than index's l.m.d, or new_index==true, add $tag to the hashmap for each filename it contains, creating a new entry for file if needed + iterate over the hashmap, dumping out in the index format specified above + + tag $file $tag [$tag ..]: + if $file is not in current directory, move to $file's directory + for each $tag: + check existence of tags file for $tag, create if nonexistent + append $file name to it + do reindex + + untag $file $tag [$tag ..]: + if $file is not in current directory, move to $file's directory + for each $tag: + check existence of tags file for $tag, skip $tag if nonexistent + remove $file name from it + do reindex + + files $tag: + start with a list + walk the tree from here, gathering a list of all subdirs plus . + iterating over the dir list, for each dir: + if $tag is in tags for dir, add files to the list, with path relative to starting dir + dump the list to STDOUT, one file per line + + tags $file: + if $file is not in current directory, move to $file's directory + do reindex + search index for $file, print out its taglist if found, otherwise "untagged" + + mv, cp, rm: + mimic OS behavior for these, modifying tags afterwards as needed + do reindex diff --git a/tigger.c b/tigger.c new file mode 100644 index 0000000..f6c13d7 --- /dev/null +++ b/tigger.c @@ -0,0 +1,123 @@ +#include +#include + +#define CMD_TAG 0x01 +#define CMD_UNTAG 0x02 +#define CMD_FILES 0x04 +#define CMD_TAGS 0x08 +#define CMD_MV 0x10 +#define CMD_CP 0x20 +#define CMD_RM 0x40 +#define CMD_ALL 0x7f + +void print_usage (char*, int); + + +int main (int argc, char* argv []) { + if (argc == 1) { + print_usage(argv[0], CMD_ALL); + return 0; + } + + if (!strcmp("tag", argv[1])) { + if (argc < 4) { + printf("tag: too few arguments\n\n"); + print_usage(argv[0], CMD_TAG); + return 1; + } + printf("tag()\n"); + } else if (!strcmp("untag", argv[1])) { + if (argc < 4) { + printf("untag: too few arguments\n\n"); + print_usage(argv[0], CMD_UNTAG); + return 1; + } + printf("untag()\n"); + } else if (!strcmp("files", argv[1])) { + if (argc != 3) { + printf("files: wrong number of arguments\n\n"); + print_usage(argv[0], CMD_FILES); + return 1; + } + printf("files()\n"); + } else if (!strcmp("tags", argv[1])) { + if (argc != 3) { + printf("tags: wrong number of arguments\n\n"); + print_usage(argv[0], CMD_TAGS); + return 1; + } + printf("tags()\n"); + } else if (!strcmp("mv", argv[1])) { + if (argc < 4) { + printf("mv: too few arguments\n\n"); + print_usage(argv[0], CMD_MV); + return 1; + } + printf("mv()\n"); + } else if (!strcmp("cp", argv[1])) { + if (argc < 4) { + printf("cp: too few arguments\n\n"); + print_usage(argv[0], CMD_CP); + return 1; + } + printf("cp()\n"); + } else if (!strcmp("rm", argv[1])) { + if (argc < 3) { + printf("rm: too few arguments\n\n"); + print_usage(argv[0], CMD_RM); + return 1; + } + printf("rm()\n"); + } else { + printf("%s: unrecognized command\n\n", argv[1]); + print_usage(argv[0], CMD_ALL); + return 1; + } + + return 0; +} + +void print_usage (char* cmd_name, int cmds_mask) { + if (cmds_mask == CMD_ALL) { + printf("Usage: %s [COMMAND [OPTIONS]]\n\n", cmd_name); + + printf("Commands:"); + } else { + printf("Usage:"); + } + + if (cmds_mask & CMD_TAG) { + printf("\n\ttag FILE TAG [TAG ..]\n"); + printf("\t\tAdds all TAGs to FILE's tag list.\n"); + } + + if (cmds_mask & CMD_UNTAG) { + printf("\n\tuntag FILE TAG [TAG ..]\n"); + printf("\t\tRemoves all TAGs from FILE's tag list.\n"); + } + + if (cmds_mask & CMD_FILES) { + printf("\n\tfiles TAG\n"); + printf("\t\tLists all files with tag TAG.\n"); + } + + if (cmds_mask & CMD_TAGS) { + printf("\n\ttags FILE\n"); + printf("\t\tLists all of FILE's tags.\n"); + } + + if (cmds_mask & CMD_MV) { + printf("\n\tmv FILE [FILE ..] TARGET\n"); + printf("\t\tMove one or more FILEs to TARGET, renaming if only one FILE is given and TARGET is not a directory. Update tag lists to reflect the change(s).\n"); + } + + if (cmds_mask & CMD_CP) { + printf("\n\tcp FILE [FILE ..] TARGET\n"); + printf("\t\tCopy one or more FILEs to TARGET, copying to a new filename if only one FILE is given and TARGET is not a directory. Update tag lists to reflect the change(s).\n"); + } + + if (cmds_mask & CMD_RM) { + printf("\n\trm FILE [FILE ..]\n"); + printf("\t\tRemove all FILEs. Update tag lists to reflect the change(s).\n"); + } +}