kjv

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

kjv_main.c (4493B)


      1 /*
      2 kjv: Read the Word of God from your terminal
      3 
      4 License: Public domain
      5 */
      6 
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 #include <unistd.h>
     10 #include <stdbool.h>
     11 #include <signal.h>
     12 #include <readline/readline.h>
     13 #include <readline/history.h>
     14 #include <sys/ioctl.h>
     15 
     16 #include "kjv_config.h"
     17 #include "kjv_data.h"
     18 #include "kjv_ref.h"
     19 #include "kjv_render.h"
     20 #include "strutil.h"
     21 
     22 const char *
     23 usage = "usage: kjv [flags] [reference...]\n"
     24     "\n"
     25     "Flags:\n"
     26     "  -A num  show num verses of context after matching verses\n"
     27     "  -B num  show num verses of context before matching verses\n"
     28     "  -C      show matching verses in context of the chapter\n"
     29     "  -e      highlighting of chapters and verse numbers\n"
     30     "          (default when output is a TTY)\n"
     31     "  -p      output to less with chapter grouping, spacing, indentation,\n"
     32     "          and line wrapping\n"
     33     "          (default when output is a TTY)\n"
     34     "  -l      list books\n"
     35     "  -h      show help\n"
     36     "\n"
     37     "Reference:\n"
     38     "    <Book>\n"
     39     "        Individual book\n"
     40     "    <Book>:<Chapter>\n"
     41     "        Individual chapter of a book\n"
     42     "    <Book>:<Chapter>:<Verse>[,<Verse>]...\n"
     43     "        Individual verse(s) of a specific chapter of a book\n"
     44     "    <Book>:<Chapter>-<Chapter>\n"
     45     "        Range of chapters in a book\n"
     46     "    <Book>:<Chapter>:<Verse>-<Verse>\n"
     47     "        Range of verses in a book chapter\n"
     48     "    <Book>:<Chapter>:<Verse>-<Chapter>:<Verse>\n"
     49     "        Range of chapters and verses in a book\n"
     50     "\n"
     51     "    /<Search>\n"
     52     "        All verses that match a pattern\n"
     53     "    <Book>/<Search>\n"
     54     "        All verses in a book that match a pattern\n"
     55     "    <Book>:<Chapter>/<Search>\n"
     56     "        All verses in a chapter of a book that match a pattern\n";
     57 
     58 int
     59 main(int argc, char *argv[])
     60 {
     61     bool is_atty = isatty(STDOUT_FILENO) == 1;
     62     kjv_config config = {
     63         .highlighting = is_atty,
     64         .pretty = is_atty,
     65 
     66         .maximum_line_length = 80,
     67 
     68         .context_before = 0,
     69         .context_after = 0,
     70         .context_chapter = false,
     71     };
     72 
     73     bool list_books = false;
     74 
     75     opterr = 0;
     76     for (int opt; (opt = getopt(argc, argv, "A:B:CeplWh")) != -1; ) {
     77         char *endptr;
     78         switch (opt) {
     79         case 'A':
     80             config.context_after = strtol(optarg, &endptr, 10);
     81             if (endptr[0] != '\0') {
     82                 fprintf(stderr, "kjv: invalid flag value for -A\n\n%s", usage);
     83                 return 1;
     84             }
     85             break;
     86         case 'B':
     87             config.context_before = strtol(optarg, &endptr, 10);
     88             if (endptr[0] != '\0') {
     89                 fprintf(stderr, "kjv: invalid flag value for -B\n\n%s", usage);
     90                 return 1;
     91             }
     92             break;
     93         case 'C':
     94             config.context_chapter = true;
     95             break;
     96         case 'e':
     97             config.highlighting = true;
     98             break;
     99         case 'p':
    100             config.pretty = true;
    101             break;
    102         case 'l':
    103             list_books = true;
    104             break;
    105         case 'h':
    106             printf("%s", usage);
    107             return 0;
    108         case '?':
    109             fprintf(stderr, "kjv: invalid flag -%c\n\n%s", optopt, usage);
    110             return 1;
    111         }
    112     }
    113 
    114     if (list_books) {
    115         for (int i = 0; i < kjv_books_length; i++) {
    116             kjv_book *book = &kjv_books[i];
    117             printf("%s (%s)\n", book->name, book->abbr);
    118         }
    119         return 0;
    120     }
    121 
    122     struct winsize ttysize;
    123     if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ttysize) == 0 && ttysize.ws_col > 0) {
    124         config.maximum_line_length = ttysize.ws_col;
    125     }
    126 
    127     signal(SIGPIPE, SIG_IGN);
    128 
    129     if (argc == optind) {
    130         using_history();
    131         while (true) {
    132             char *input = readline("kjv> ");
    133             if (input == NULL) {
    134                 break;
    135             }
    136             add_history(input);
    137             kjv_ref *ref = kjv_newref();
    138             int success = kjv_parseref(ref, input);
    139             free(input);
    140             if (success == 0) {
    141                 kjv_render(ref, &config);
    142             }
    143             kjv_freeref(ref);
    144         }
    145     } else {
    146         char *ref_str = str_join(argc-optind, &argv[optind]);
    147         kjv_ref *ref = kjv_newref();
    148         int success = kjv_parseref(ref, ref_str);
    149         free(ref_str);
    150         if (success == 0) {
    151             kjv_render(ref, &config);
    152         }
    153         kjv_freeref(ref);
    154     }
    155 
    156     return 0;
    157 }