11const std = @import ("std" );
22const sqlite = @import ("sqlite" );
33const manage_main = @import ("main.zig" );
4+ const clap = @import ("clap" );
45const Context = manage_main .Context ;
56const ID = manage_main .ID ;
67const tunez = @import ("tunez" );
@@ -868,12 +869,35 @@ pub fn main() anyerror!void {
868869 defer _ = gpa .deinit ();
869870 var allocator = gpa .allocator ();
870871
871- var args_it = std .process .args ();
872- _ = args_it .skip ();
873-
874- const ArgState = enum { None , FetchTag , InferMoreTags , FetchPool , FetchSource };
872+ const params = comptime clap .parseParamsComptime (
873+ \\-h, --help display this help and exit.
874+ \\-V, --version print version and exit.
875+ \\-v, --verbose enable debug logs.
876+ \\-s, --source <str> set tag source
877+ \\-t, --tag <str>... add the tag to the given paths
878+ \\-p, --pool <str> add an existing pool to the given paths (recommended to do it with files only, never folders, as the list ordering is not stable)
879+ \\--filter-indexed-files-only only include files already indexed (useful if you're moving files around and they're not catched by rename watcher or you haven't used amv)
880+ \\--infer-tags <str> infer tags based on file data via a specific pre-processor (available: regex, audio, mime). they come with extra options
881+ // TODO (DO NOT MERGE) add infer tags regex stuff args
882+ // .regex => try RegexTagInferrer.consumeArguments(&args_it),
883+ // .audio => try AudioMetadataTagInferrer.consumeArguments(&args_it),
884+ // .mime => try MimeTagInferrer.consumeArguments(&args_it),
885+ \\--use-file-timestamp use file timestamp from fs for internal file id
886+ \\--strict validate tags, don't autocreate them (fails if given tag doesn't exist)
887+ \\--v1 use "v1" arguments, doesn't do anything atm (useful for scripts)
888+ \\--dry-run do not do any modifications to the index file (good for testing)
889+ \\<str>... file paths, or folder paths
890+ );
875891
876- var state : ArgState = .None ;
892+ var diag = clap.Diagnostic {};
893+ var res = clap .parse (clap .Help , & params , clap .parsers .default , .{
894+ .diagnostic = & diag ,
895+ .allocator = allocator ,
896+ }) catch | err | {
897+ diag .report (std .io .getStdErr ().writer (), err ) catch {};
898+ return err ;
899+ };
900+ defer res .deinit ();
877901
878902 var given_args = Args {
879903 .default_tags = StringList .init (allocator ),
@@ -882,87 +906,39 @@ pub fn main() anyerror!void {
882906 };
883907 defer given_args .deinit ();
884908
909+ given_args .help = res .args .help != 0 ;
910+ given_args .version = res .args .version != 0 ;
911+ if (res .args .verbose != 0 )
912+ current_log_level = .debug ;
913+
914+ given_args .cli_v1 = res .args .v1 != 0 ;
915+ given_args .dry_run = res .args .@"dry-run" != 0 ;
916+ given_args .filter_indexed_files_only = res .args .@"filter-indexed-files-only" != 0 ;
917+ given_args .use_file_timestamp = res .args .@"use-file-timestamp" != 0 ;
918+ given_args .strict = res .args .strict != 0 ;
919+
920+ for (res .args .tag ) | arg | {
921+ try given_args .default_tags .append (arg );
922+ }
923+
924+ if (res .args .pool ) | arg | {
925+ given_args .pool = ID .fromString (arg );
926+ }
927+
885928 var ctx = try manage_main .loadDatabase (allocator , .{});
886929 defer ctx .deinit ();
887930
888- var arg : []const u8 = undefined ;
889- while (args_it .next ()) | arg_from_loop | {
890- arg = arg_from_loop ;
891- logger .debug ("state: {} arg: {s}" , .{ state , arg });
892- switch (state ) {
893- .FetchTag = > {
894- try given_args .default_tags .append (arg );
895- state = .None ;
896- continue ;
897- },
898- .FetchPool = > {
899- given_args .pool = ID .fromString (arg );
900- state = .None ;
901- continue ;
902- },
903- .FetchSource = > {
904- const arg_as_int = try std .fmt .parseInt (i64 , arg , 10 );
905- given_args .tag_source = (try ctx .fetchTagSource (.external , arg_as_int )) orelse return error .TagSourceNotFound ;
906- state = .None ;
907- continue ;
908- },
909- .InferMoreTags = > {
910- const tag_inferrer = std .meta .stringToEnum (TagInferrer , arg ) orelse return error .InvalidTagInferrer ;
911- const inferrer_config = switch (tag_inferrer ) {
912- .regex = > try RegexTagInferrer .consumeArguments (& args_it ),
913- .audio = > try AudioMetadataTagInferrer .consumeArguments (& args_it ),
914- .mime = > try MimeTagInferrer .consumeArguments (& args_it ),
915- };
916-
917- try given_args .wanted_inferrers .append (inferrer_config );
918-
919- arg = inferrer_config .last_argument ;
920- state = .None ;
921- },
922- .None = > {},
923- }
924- logger .debug ("(possible transition) state: {} arg: {s}" , .{ state , arg });
925-
926- if (std .mem .eql (u8 , arg , "-h" )) {
927- given_args .help = true ;
928- } else if (std .mem .eql (u8 , arg , "-v" )) {
929- current_log_level = .debug ;
930- } else if (std .mem .eql (u8 , arg , "-V" )) {
931- given_args .version = true ;
932- } else if (std .mem .eql (u8 , arg , "--filter-indexed-files-only" )) {
933- given_args .filter_indexed_files_only = true ;
934- } else if (std .mem .eql (u8 , arg , "--dry-run" )) {
935- given_args .dry_run = true ;
936- } else if (std .mem .eql (u8 , arg , "--use-file-timestamp" )) {
937- given_args .use_file_timestamp = true ;
938- } else if (std .mem .eql (u8 , arg , "--v1" )) {
939- given_args .cli_v1 = true ; // doesn't do anything yet
940- } else if (std .mem .eql (u8 , arg , "--tag" ) or std .mem .eql (u8 , arg , "-t" )) {
941- state = .FetchTag ;
942- // tag inferrers require more than one arg, so we need to load
943- // those args beforehand and then pass the arg state forward
944- } else if (std .mem .eql (u8 , arg , "--infer-tags" )) {
945- state = .InferMoreTags ;
946- // TODO check if this is supposed to be an argument or an
947- // actual option by peeking over args_it. paths can have --
948- // after all.
949- } else if (std .mem .eql (u8 , arg , "-p" ) or std .mem .eql (u8 , arg , "--pool" )) {
950- state = .FetchPool ;
951- } else if (std .mem .eql (u8 , arg , "-s" ) or std .mem .eql (u8 , arg , "--source" )) {
952- state = .FetchSource ;
953- } else if (std .mem .eql (u8 , arg , "--strict" )) {
954- given_args .strict = true ;
955- } else if (std .mem .startsWith (u8 , arg , "--" )) {
956- logger .err ("unknown argument '{s}'" , .{arg });
957- return error .InvalidArgument ;
958- } else {
959- try given_args .include_paths .append (arg );
960- }
931+ if (res .args .source ) | arg | {
932+ const arg_as_int = try std .fmt .parseInt (i64 , arg , 10 );
933+ given_args .tag_source = (try ctx .fetchTagSource (.external , arg_as_int )) orelse return error .TagSourceNotFound ;
934+ }
935+
936+ for (res .positionals [0 ]) | arg | {
937+ try given_args .include_paths .append (arg );
961938 }
962939
963940 if (given_args .help ) {
964- std .debug .print (HELPTEXT , .{});
965- return ;
941+ return clap .help (std .io .getStdErr ().writer (), clap .Help , & params , .{});
966942 } else if (given_args .version ) {
967943 std .debug .print ("ainclude {s}\n " , .{VERSION });
968944 return ;
0 commit comments