kjv

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

kjv_render.c (3832B)


      1 #include <stdbool.h>
      2 #include <signal.h>
      3 #include <stdio.h>
      4 #include <string.h>
      5 #include <sys/wait.h>
      6 #include <unistd.h>
      7 
      8 #include "kjv_data.h"
      9 #include "kjv_match.h"
     10 #include "kjv_render.h"
     11 
     12 #define ESC_BOLD "\033[1m"
     13 #define ESC_UNDERLINE "\033[4m"
     14 #define ESC_RESET "\033[m"
     15 
     16 static void
     17 kjv_output_verse(const kjv_verse *verse, FILE *f, const kjv_config *config)
     18 {
     19     fprintf(
     20         f,
     21         config->highlighting ?
     22             ESC_BOLD "%d:%d" ESC_RESET "\t" :
     23             "%d:%d\t",
     24         verse->chapter, verse->verse
     25     );
     26 
     27     char verse_text[1024];
     28     strcpy(verse_text, verse->text);
     29     size_t characters_printed = 0;
     30     char *word = strtok(verse_text, " ");
     31     while (word != NULL) {
     32         size_t word_length = strlen(word);
     33         if (characters_printed + word_length + (characters_printed > 0 ? 1 : 0) > config->maximum_line_length - 8 - 2) {
     34             fprintf(f, "\n\t");
     35             characters_printed = 0;
     36         }
     37         if (characters_printed > 0) {
     38             fprintf(f, " ");
     39             characters_printed++;
     40         }
     41         fprintf(f, "%s", word);
     42         characters_printed += word_length;
     43         word = strtok(NULL, " ");
     44     }
     45     fprintf(f, "\n");
     46 }
     47 
     48 static bool
     49 kjv_output(const kjv_ref *ref, FILE *f, const kjv_config *config)
     50 {
     51     kjv_next_data next = {
     52         .current = 0,
     53         .next_match = -1,
     54         .matches = {
     55             {-1, -1},
     56             {-1, -1},
     57         },
     58     };
     59 
     60     kjv_verse *last_printed = NULL;
     61     for (int verse_id; (verse_id = kjv_next_verse(ref, config, &next)) != -1; ) {
     62         kjv_verse *verse = &kjv_verses[verse_id];
     63         kjv_book *book = &kjv_books[verse->book - 1];
     64 
     65         if (config->pretty) {
     66             if (last_printed == NULL || verse->book != last_printed->book) {
     67                 if (last_printed != NULL) {
     68                     fprintf(f, "\n");
     69                 }
     70                 fprintf(
     71                     f,
     72                     config->highlighting ?
     73                         ESC_UNDERLINE "%s" ESC_RESET "\n\n" :
     74                         "%s\n\n",
     75                     book->name
     76                 );
     77             }
     78             kjv_output_verse(verse, f, config);
     79         } else {
     80             fprintf(
     81                 f,
     82                 config->highlighting ?
     83                     ESC_UNDERLINE "%s" ESC_RESET " " ESC_BOLD "%d:%d" ESC_RESET "  %s\n" :
     84                     "%s %d:%d  %s\n",
     85                 book->name,
     86                 verse->chapter,
     87                 verse->verse,
     88                 verse->text
     89             );
     90         }
     91         last_printed = verse;
     92     }
     93     return last_printed != NULL;
     94 }
     95 
     96 static int
     97 kjv_render_pretty(const kjv_ref *ref, const kjv_config *config)
     98 {
     99     int fds[2];
    100     if (pipe(fds) == -1) {
    101         return 1;
    102     }
    103 
    104     pid_t pid = fork();
    105     if (pid == 0) {
    106         close(fds[1]);
    107         dup2(fds[0], STDIN_FILENO);
    108         char *args[9] = {NULL};
    109         int arg = 0;
    110         args[arg++] = "less";
    111         args[arg++] = "-J";
    112         args[arg++] = "-I";
    113         if (ref->search_str != NULL) {
    114             args[arg++] = "-p";
    115             args[arg++] = ref->search_str;
    116         }
    117         args[arg++] = "-R";
    118         args[arg++] = "-f";
    119         args[arg++] = "-";
    120         args[arg++] = NULL;
    121         execvp("less", args);
    122         printf("unable not exec less\n");
    123         _exit(0);
    124     } else if (pid == -1) {
    125         printf("unable to fork\n");
    126         return 2;
    127     }
    128     close(fds[0]);
    129     FILE *output = fdopen(fds[1], "w");
    130     bool printed = kjv_output(ref, output, config);
    131     if (!printed) {
    132         kill(pid, SIGTERM);
    133     }
    134     fclose(output);
    135     waitpid(pid, NULL, 0);
    136     return 0;
    137 }
    138 
    139 int
    140 kjv_render(const kjv_ref *ref, const kjv_config *config)
    141 {
    142     if (config->pretty) {
    143         return kjv_render_pretty(ref, config);
    144     }
    145     kjv_output(ref, stdout, config);
    146     return 0;
    147 }