#define SHINEY_PROB 32 #include #include #include #include #include #include const char *argp_program_version = "pkmn 1.0"; const char *argp_program_bug_address = ""; /* Program documentation. */ static char doc[] = "Argp example #3 -- a program with options and arguments using argp"; /* A description of the arguments we accept. */ static char args_doc[] = "pokemon_name"; /* The options we understand. */ static struct argp_option options[] = { {"random", 'r', 0, 0, "Use a random pokemon"}, {"shiney", 's', 0, 0, "Use a shiney pokemon"}, {"verbose", 'v', 0, 0, "Produce verbose output" }, { 0 } }; /* Used by main to communicate with parse_opt. */ struct arguments { char *args[1]; /* arg*/ int silent, verbose; int random, shiney; /* random and shiney flags */ }; /* Parse a single option. */ static error_t parse_opt (int key, char *arg, struct argp_state *state) { /* Get the input argument from argp_parse, which we know is a pointer to our arguments structure. */ struct arguments *arguments = state->input; switch (key) { case 'v': arguments->verbose = 1; break; case 'r': arguments->random = 1; break; case 's': arguments->shiney = 1; break; case ARGP_KEY_ARG: if (state->arg_num >= 1) /* Too many arguments. */ argp_usage (state); arguments->args[state->arg_num] = arg; break; case ARGP_KEY_END: if (state->arg_num < 1 && !arguments->random) /* Not enough arguments. */ argp_usage (state); break; default: return ARGP_ERR_UNKNOWN; } return 0; } /* Our argp parser. */ static struct argp argp = { options, parse_opt, args_doc, doc }; int pkmn_name_from_file(char *pokemon_file, char *pokemon_name) { int BUFFER_SIZE = 512; // A file is of the form "[S_][0-9][0-9][0-9]_pokemon.cow" // We want to write the pokemon name in pokemon_name // Using regex: s/^[S_]*[0-9]*_//g // char *pokemon_file = "843_silicobra.cow"; char regex_pattern[] = "^S?_?[0-9]+_(([a-zA-Z-])+)\\.cow$"; // Regex pattern to match the Pokémon name regex_t regex; regmatch_t matches[100]; char match_buffer[BUFFER_SIZE]; int ret; // Compile the regular expression ret = regcomp(®ex, regex_pattern, REG_EXTENDED); if (ret != 0) { fprintf(stderr, "Failed to compile regex\n"); return 1; } // Execute the regular expression ret = regexec(®ex, pokemon_file, 100, matches, 0); if (ret == 0) { // Extract the matched substring int start = matches[1].rm_so; int end = matches[1].rm_eo; int match_length = end - start; if (match_length < BUFFER_SIZE - 1) { strncpy(match_buffer, pokemon_file + start, match_length); match_buffer[match_length] = '\0'; strcpy(pokemon_name, match_buffer); } else { fprintf(stderr, "Match too long for buffer\n"); } } else if (ret == REG_NOMATCH) { fprintf(stderr, "No match found\n"); } else { fprintf(stderr, "Regex match failed\n"); } // Free the regex memory regfree(®ex); return 0; } int get_pokemon_file(char *arg, char *pokemon_file) { // Finds a matching file in the pokemons directory from the argument // Returns 0 if the file was found, 1 otherwise // ls ~/pokemons/yes | fzf -f wp | head -1 char command[512]; sprintf(command, "ls ~/pokemons/yes | fzf -f %s | head -1 > /tmp/pkmn", arg); system(command); FILE *f = fopen("/tmp/pkmn", "r"); fscanf(f, "%s", pokemon_file); fclose(f); if (strlen(pokemon_file) == 0) { return 1; } return 0; } int main (int argc, char **argv) { struct arguments arguments; char pkmn_path[] = "~/pokemons/"; /* Default values. */ arguments.verbose = 0; arguments.random = 0; arguments.shiney = 0; // A pokemon has a 1/SHINEY_PROB chance of being shiney srand(time(NULL)); arguments.shiney = (rand() % SHINEY_PROB) == 0; /* Parse our arguments; every option seen by parse_opt will be reflected in arguments. */ argp_parse (&argp, argc, argv, 0, 0, &arguments); if (arguments.verbose) { printf("ARG1 = %s\n", arguments.args[0]); printf("VERBOSE = %s\n", arguments.verbose ? "yes" : "no"); printf("RANDOM = %s\n", arguments.random ? "yes" : "no"); printf("SHINEY = %s\n", arguments.shiney ? "yes" : "no"); } char pokemon_file[512]; if (arguments.random) { system("ls ~/pokemons/yes | shuf -n 1 > /tmp/pkmn"); FILE *f = fopen("/tmp/pkmn", "r"); fscanf(f, "%s", pokemon_file); fclose(f); if (arguments.verbose) { printf("Random pokemon: %s\n", pokemon_file); } } else { if (get_pokemon_file(arguments.args[0], pokemon_file) == 1) { fprintf(stderr, "No matching pokemon found\n"); exit(EXIT_FAILURE); } } if (arguments.shiney) { // Append "S_" at the beginning of the file char tmp[512]; sprintf(tmp, "S_%s", pokemon_file); sprintf(pokemon_file, "%s", tmp); if (arguments.verbose) { printf("Shiney pokemon: %s\n", pokemon_file); } } // Extract the pokemon name from the file char pokemon_name[512]; pkmn_name_from_file(pokemon_file, pokemon_name); pokemon_name[0] = toupper(pokemon_name[0]); if (arguments.verbose) { printf("Pokemon file: %s\n", pokemon_file); printf("Pokemon name: %s\n", pokemon_name); } // Execute the command echo "$pokemon_name!" | cowsay -f "$cow_file" -W 70 char command[1024]; if (arguments.shiney) { sprintf(command, "echo \"Shiny %s!\" | cowsay -f %s%s -W 70", pokemon_name, pkmn_path, pokemon_file); } else { sprintf(command, "echo \"%s!\" | cowsay -f %syes/%s -W 70", pokemon_name, pkmn_path, pokemon_file); } system(command); exit(EXIT_SUCCESS); }