]> git.mdlowis.com Git - proto/pick.git/commitdiff
fixed some inefficiencies in pick
authorMichael D. Lowis <mike.lowis@gentex.com>
Tue, 16 Apr 2019 21:35:22 +0000 (17:35 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Tue, 16 Apr 2019 21:35:22 +0000 (17:35 -0400)
.gitignore [new file with mode: 0644]
build.sh
c.h
pick.c

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..5df8edf
--- /dev/null
@@ -0,0 +1 @@
+pick
index 8a183dc3574d147384e625b7d626c97d64080380..7e679cb9d01dbc1afc128d4bc20d96a976e739c5 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -1,2 +1,2 @@
 #!/bin/sh
-gcc -D_XOPEN_SOURCE *.c -I . -o pick
+gcc -D_XOPEN_SOURCE=700 *.c -I . -o pick -g -fsanitize=address,undefined -lasan -lm
diff --git a/c.h b/c.h
index 086d347e39c8cf72b9b5ed000dbe708067727728..26b5396b1a10da7b134e1cd47ff0e886b285ac1b 100644 (file)
--- a/c.h
+++ b/c.h
@@ -1,6 +1,9 @@
 #include <stdint.h>
 #include <stddef.h>
 #include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
 #define nelem(x) (sizeof(x) / sizeof((x)[0]))
 
@@ -83,31 +86,12 @@ static inline char* _getopt_(int* p_argc, char*** p_argv) {
 
 #define OPTLONG case '-'
 
-/******************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#ifndef min
+    #define min(x,y) \
+        ((x) < (y) ? (x) : (y))
+#endif
 
-static char* rdline(FILE* input) {
-    size_t size  = 8;
-    size_t index = 0;
-    char*  str   = (char*)malloc(size);
-    memset(str, 0, 8);
-    if (feof(input)) {
-        free(str);
-        return NULL;
-    }
-    while (true) {
-        char ch = fgetc(input);
-        if (ch == EOF) break;
-        str[index++] = ch;
-        str[index]   = '\0';
-        if (index+1 >= size) {
-            size = size << 1;
-            str  = realloc(str, size);
-        }
-        if (ch == '\n') break;
-    }
-    return str;
-}
+#ifndef max
+    #define max(x,y) \
+        ((x) > (y) ? (x) : (y))
+#endif
diff --git a/pick.c b/pick.c
index 38abde83f0e5e3bd56f272a6ce5ef69338f5bc3f..6ad9f436ca17fa4bf34add3d5aac9a92f2cc6ed6 100644 (file)
--- a/pick.c
+++ b/pick.c
@@ -2,6 +2,10 @@
 #include <vec.h>
 #include <termbox.h>
 #include <ctype.h>
+#include <math.h>
+
+static void redraw(void);
+static void filter(void);
 
 typedef struct {
     float score;
@@ -13,12 +17,32 @@ typedef struct {
 
 char* ARGV0;
 int AltFlag = 1; // Disable alternate screen usage
-char Query[1024] = {0};
+char Query[8192] = {0};
 size_t QueryIdx = 0;
 vec_t Choices = {0};
-size_t ChoiceIdx = 2;
+size_t ChoiceIdx = 0;
+
+static char* rdline(FILE* fin, size_t* len) {
+    if (feof(fin) || ferror(fin))
+        return NULL;
+    size_t size  = 256;
+    size_t index = 0;
+    char*  str   = (char*)calloc(size,1);
+    while (!feof(stdin)) {
+        if (index+2 >= size) {
+            size = size << 1;
+            str  = realloc(str, size);
+        }
+        char ch = fgetc(fin);
+        if (ch == EOF || ch == '\r' || ch == '\n') break;
+        str[index++] = ch;
+        str[index]   = '\0';
+    }
+    if (len) *len = index;
+    return str;
+}
 
-int by_score(const void* a, const void* b) {
+static int by_score(const void* a, const void* b) {
     Choice* ca = ((Choice*)a);
     Choice* cb = ((Choice*)b);
     if (ca->score < cb->score)
@@ -29,37 +53,38 @@ int by_score(const void* a, const void* b) {
         return strcmp(ca->string, cb->string);
 }
 
-void load_choices(void) {
+static void load_choices(void) {
+    size_t choice_len;
     char* choice_text;
     Choice choice = {0};
     vec_init(&Choices, sizeof(Choice));
-    while ((choice_text = rdline(stdin)) != NULL) {
-        choice_text[strlen(choice_text)-1] = '\0';
-        if (strlen(choice_text) > 0) {
+    while ((choice_text = rdline(stdin, &choice_len)) != NULL) {
+        if (choice_len > 0) {
             choice.string = choice_text;
             choice.length = strlen(choice_text);
             choice.score  = 1.0;
             vec_push_back(&Choices, &choice);
+        } else {
+            free(choice_text);
         }
     }
-    vec_sort(&Choices, by_score);
 }
 
-char* find_match_start(char *str, int ch) {
+static char* find_match_start(char *str, int ch) {
     for (; *str; str++)
         if (tolower(*str) == tolower(ch))
             return str;
     return NULL;
 }
 
-bool match(char *string, size_t offset, size_t *start, size_t *end) {
+static bool match(char *string, size_t offset, size_t *start, size_t *end) {
     char* q = Query;
     char* s = find_match_start(&string[offset], *q);
     char* e = s;
     /* bail if no match for first char */
     if (s == NULL) return 0;
     /* find the end of the match */
-    for (; *q; q++)
+    for (q++, e++; *q; q++)
         if ((e = find_match_start(e, *q)) == NULL)
             return false;
     /* make note of the matching range */
@@ -73,8 +98,8 @@ bool match(char *string, size_t offset, size_t *start, size_t *end) {
     return true;
 }
 
-void score(void) {
-    for (int i = 0; i < vec_size(&Choices); i++) {
+static void score(void) {
+    for (unsigned int i = 0; i < vec_size(&Choices); i++) {
         Choice* choice = (Choice*)vec_at(&Choices, i);
         float qlen = (float)QueryIdx;
         if (match(choice->string, 0, &choice->match_start, &choice->match_end)) {
@@ -89,7 +114,26 @@ void score(void) {
     vec_sort(&Choices, by_score);
 }
 
-void redraw(void) {
+int main(int argc, char** argv) {
+    OPTBEGIN {
+        case 'a': AltFlag = 0; break;
+    } OPTEND;
+    if (argc >= 1) {
+        size_t sz = min(strlen(argv[0]), sizeof(Query)-1);
+        strncpy(Query, argv[0], sz);
+        QueryIdx = sz;
+    }
+    load_choices();
+    score();
+    if (vec_size(&Choices) > 1)
+        filter();
+    Choice* choice = (Choice*)vec_at(&Choices, ChoiceIdx);
+    if (vec_size(&Choices) && ChoiceIdx != SIZE_MAX)
+        printf("%s\n", choice->string);
+    return 0;
+}
+
+static void redraw(void) {
     tb_clear();
     /* Draw query and cursor */
     int max_x = (tb_width() < 1023 ? tb_width() : 1023);
@@ -100,25 +144,24 @@ void redraw(void) {
     for (int x = 0; x < tb_width(); x++)
         tb_change_cell(x, 1, 0x2500, TB_DEFAULT, TB_DEFAULT);
     /* Draw the scored and sorted results */
-    for (int i = 0, y = 2; (i < vec_size(&Choices)) && (y < tb_height()); i++) {
-        bool selected = (y == ChoiceIdx);
+    for (int i = 0, y = 2; (i < vec_size(&Choices)) && (y < tb_height()); i++, y++) {
+        bool selected = (i == ChoiceIdx);
         Choice* choice = (Choice*)vec_at(&Choices, i);
         if (choice->score >= 0.0) {
             for (int x = 0; choice->string[x] && x < tb_width(); x++) {
                 bool inmatch  = (choice->match_end && x >= choice->match_start && x <= choice->match_end);
-                tb_change_cell(x, i+2, choice->string[x],
+                tb_change_cell(x, y, choice->string[x],
                     (inmatch  ? TB_UNDERLINE|TB_BLUE : TB_DEFAULT),
                     (selected ? TB_WHITE : TB_DEFAULT));
             }
             for (int x = choice->length; selected && (x < tb_width()); x++)
                 tb_change_cell(x, y, ' ', TB_DEFAULT, TB_WHITE);
-            y++;
         }
     }
     tb_present();
 }
 
-void filter(void) {
+static void filter(void) {
     struct tb_event ev = {0};
     tb_init_with(AltFlag ? TB_INIT_EVERYTHING : 0);
     do {
@@ -132,10 +175,10 @@ void filter(void) {
                 if (QueryIdx > 0)
                     Query[--QueryIdx] = '\0';
             } else if (ev.key == TB_KEY_ARROW_DOWN) {
-                if (ChoiceIdx < tb_width() && ChoiceIdx <= vec_size(&Choices))
+                if (ChoiceIdx < tb_width() && ChoiceIdx < vec_size(&Choices)-1)
                     ChoiceIdx++;
             } else if (ev.key == TB_KEY_ARROW_UP) {
-                if (ChoiceIdx > 2)
+                if (ChoiceIdx > 0)
                     ChoiceIdx--;
             } else if (ev.ch) {
                 if (QueryIdx < sizeof(Query)-1)
@@ -147,16 +190,3 @@ void filter(void) {
     } while (tb_poll_event(&ev));
     tb_shutdown();
 }
-
-int main(int argc, char** argv) {
-    OPTBEGIN {
-        case 'a': AltFlag = 0; break;
-    } OPTEND;
-    load_choices();
-    if (vec_size(&Choices) > 1)
-        filter();
-    Choice* choice = (Choice*)vec_at(&Choices, ChoiceIdx-2);
-    if (vec_size(&Choices) && ChoiceIdx != SIZE_MAX)
-        printf("%s\n", choice->string);
-    return 0;
-}