diff options
| author | Ben Winston | 2024-05-05 18:13:45 -0400 | 
|---|---|---|
| committer | Ben Winston | 2024-05-05 18:13:45 -0400 | 
| commit | 7a2e38d00390007348ebba3e75efb65b2e8d4fd8 (patch) | |
| tree | 7469045ffa4416a2d930fac4db0af46ff703d6fd /main.c | |
| parent | 1daff9912f02d0d7aa3bae606f0f793b620ed4d8 (diff) | |
main.c -> booki.c
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 312 | 
1 files changed, 0 insertions, 312 deletions
| @@ -1,312 +0,0 @@ -#include <getopt.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> - -#include "toml.h" - -#define BOOKI_FILE_REL ".local/share/booki/books.toml" - -#define MAX_SEARCH_OPTS 5 - -char* BOOKI_FILE; - -const char* get_last_word(const char* str) { -    const char* last_space = strrchr(str, ' '); -    if ((last_space - str) > 0) -        return last_space + 1; -    else -        return 0; -} - -bool regex_match(const char* pattern, const char* text) { - -    // empty pattern matches everything -    if (!*pattern) return true; - -    // get lengths -    int pattern_length = strlen(pattern); -    int text_length = strlen(text); - -    if (pattern_length > text_length) return false; - -    // we only need to compare while remaining text is -    // as long or longer than pattern (without special) -    for (int i = 0; i <= (text_length - pattern_length); i++) { -        if (strncasecmp(pattern, text + i, pattern_length) == 0) return true; -    } - -    return false; -} - -toml_table_t* get_toml_data(const char* filename) { -    FILE* fp; -    char errbuf[200]; - -    fp = fopen(filename, "r"); -    if (!fp) { -        printf("can't open file :("); -        return 0; -    } - -    toml_table_t* conf = toml_parse_file(fp, errbuf, sizeof(errbuf)); -    fclose(fp); - -    return conf; -} - -static struct option search_options[] = { -    {"show", no_argument, 0, 's'}, -    {0, 0, 0, 0}  // marks the end of the array -}; - -struct search_opt { -    int show; -    int count; -    char* opts[MAX_SEARCH_OPTS]; -    char* args[MAX_SEARCH_OPTS]; -}; - -struct search_opt parse_search_options(int argc, char* argv[]) { - -    // return struct -    struct search_opt opt_out; -    int count = 0; -    int show = false; - -    // opt options -    int opt; -    int opt_idx = 0; -    opterr = 0;  // turn off getopt error messages - -    // look at each option -    while ((opt = getopt_long_only(argc, argv, "", search_options, &opt_idx)) != -1) { -        switch(opt) { -            case 's': -                show = true; -                break; -            case '?': -                // optind points at the argument (one past the option) -                opt_out.opts[count] = argv[optind-1] + 2;  // '--example' -> 'example' -                opt_out.args[count] = argv[optind]; -                count++; -                break; -            default: -                printf("something went wrong with parsing!\n"); -                break; -        } -    } - -    // set the count/show values -    opt_out.count = count; -    opt_out.show = show; - -    return opt_out; -} - -char** search(int argc, char* argv[]) { -    toml_table_t* data = get_toml_data(BOOKI_FILE); - -    if (!data) { -        return NULL; -    } - -    struct search_opt search_opts = parse_search_options(argc, argv); -    bool print = false; - -    // get the books array -    toml_array_t* books = toml_array_in(data, "books"); -    if (!books) { -        printf("no such array: 'books'"); -        return NULL; -    } - -    // book loop -    for (int i = 0; ; i++) { -        toml_table_t* book = toml_table_at(books, i); -        if (!book) break; - -        if (search_opts.count == 0) { -            print = true; -        } else { -            toml_datum_t datapoint; -            char* field; -            bool inner_print = true; - -            // loop through all options -            int i; -            for (i = 0; i < search_opts.count; i++) { -                field = search_opts.opts[i]; - -                // if the key doesn't exist, we won't print -                if (!toml_key_exists(book, field)) { -                    break; -                } - -                // try and get a string -                datapoint = toml_string_in(book, field); -                if (datapoint.ok) { -                    if (!regex_match(search_opts.args[i], datapoint.u.s)) { -                        free(datapoint.u.s); -                        break; -                    } -                    free(datapoint.u.s); -                } else { -                    // try and get an integer -                    datapoint = toml_int_in(book, field); -                    int ret; -                    if (datapoint.ok) { -                        ret = atoi(search_opts.args[i]); -                        if (ret == 0) { -                            printf("not an int: %s\n", search_opts.args[i]); -                            break; -                        } else if (ret != datapoint.u.i) { -                            break; -                        } -                    } else { -                        break; -                    } -                } -            } - -            // if we made it all the way through the loop, -            // we should print -            print = i == search_opts.count; -        } - -        // get title and author for printing -        toml_datum_t book_title = toml_string_in(book, "title"); -        if (!book_title.ok) { -            continue; -        } - -        // author can be a string or a list -        toml_datum_t book_author = toml_string_in(book, "author"); -        char author_str[100]; -        char* tmp; -        if (!book_author.ok) { -            toml_array_t* book_author_array = toml_array_in(book, "author"); -            if (!book_author_array) { -                continue; -            } -            int len = toml_array_nelem(book_author_array); -            tmp = toml_string_at(book_author_array, 0).u.s; -            strcpy(author_str, tmp); -            free(tmp); -            for (int i = 1; i < len; i++) { -                book_author = toml_string_at(book_author_array, i); -                tmp = book_author.u.s; -                if (i == len-1) { -                    strcat(author_str, " and "); -                } else { -                    strcat(author_str, ", "); -                } -                strcat(author_str, book_author.u.s); -                free(tmp); -            } -        } else { -            strcpy(author_str, book_author.u.s); -            free(book_author.u.s); -        } - -        // print! -        if (print) { -            printf("%s by %s\n", book_title.u.s, author_str); -            if (search_opts.show) { -                //toml_datum_t d; -                for (int i = 0; ; i++) { -                    const char* key = toml_key_in(book, i); -                    if (!key) break; - -                    /* -                    if (strcmp("pages", key) == 0) { -                        d = toml_int_in(book, key); -                        if (d.ok) { -                            printf(" - %s: %d\n",  -                        } -                    } -                    */ - - -                    // currently we support strings and ints -                    toml_datum_t s = toml_string_in(book, key); -                    if (s.ok) { -                        printf(" - %s: %s\n", key, s.u.s); -                        free(s.u.s); -                    } -                    toml_datum_t i = toml_int_in(book, key); -                    if (i.ok) { -                        printf(" - %s: %d\n", key, i.u.i); -                    } - -                } -            } -        } - -        free(book_title.u.s); -        //free(book_author.u.s); -    } - -    toml_free(data); - -    return argv + optind; -} - -void open() { - -    char* home = getenv("HOME"); -    if (!home) { -        printf("no home?\n"); -        home = "/";  // no way -    } -    char* editor = getenv("EDITOR"); -    if (!editor) -        editor = "nano"; - -    pid_t pid; -    int status; -    switch ((pid = fork())) { -        case -1: -            printf("fork has failed!\n"); -            break; -        case 0: -            execlp(editor, editor, BOOKI_FILE, NULL); -            printf("child failed :(\n"); -            break; -        default: -            // wait for the child to finish -            pid = wait(&status); -            break; -    } -} - -void help(bool err) { -    printf("booki! it's a thing\n"); -    if (err) { -        printf("you did something wrong\n"); -    } -} - -int main(int argc, char* argv[]) { - -    char* home = getenv("HOME"); -    char booki_file[strlen(home) + strlen(BOOKI_FILE_REL) + 1]; -    sprintf(booki_file, "%s/%s", home, BOOKI_FILE_REL); -    BOOKI_FILE = booki_file; -    char** remaining = NULL; - -    if (argc == 1) { -        help(false); -        return 0; -    } else if (strcmp(argv[1], "open") == 0) { -        open(); -    } else if (strcmp(argv[1], "search") == 0) { -        remaining = search(argc - 1, argv + 1); -    } - -    return 0; -} | 
