]> git.mdlowis.com Git - projs/tide.git/commitdiff
more reorginization
authorMichael D. Lowis <mike.lowis@gentex.com>
Mon, 21 Mar 2022 18:56:52 +0000 (14:56 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Mon, 21 Mar 2022 18:56:52 +0000 (14:56 -0400)
13 files changed:
Rsconscript
src/edit.1.adoc [deleted file]
src/edit.c [deleted file]
src/fetch.1.adoc [deleted file]
src/fetch.c [deleted file]
src/fetchsel/fetchsel.1.adoc [moved from src/fetchsel.1.adoc with 100% similarity]
src/fetchsel/fetchsel.c [moved from src/fetchsel.c with 100% similarity]
src/pick.1.adoc [deleted file]
src/pick.c [deleted file]
src/registrar.1.adoc [deleted file]
src/registrar.c [deleted file]
src/tide/tide.1.adoc [moved from src/tide.1.adoc with 100% similarity]
src/tide/tide.c [moved from src/tide.c with 100% similarity]

index f5f966a201cfa6894ceebad148ab8650a3ca930c..521cf768ef4cb81353f6e5592d5db4b8c284ea3f 100644 (file)
@@ -22,6 +22,12 @@ build do
     env.Program("bin/#{bin}", [src, "libtide.a"])
   end
 
+  (glob("src/*/") - ["src/lib"]).each do |dir|
+    bin = File.basename(dir)
+    env.Program("bin/#{bin}", glob("#{dir}/**/*.c") + ["libtide.a"])
+  end
+
+
   # Generate the documentation
   env.Command("", "tools/docgen",
     "CMD" => ["${_SOURCES}"],
diff --git a/src/edit.1.adoc b/src/edit.1.adoc
deleted file mode 100644 (file)
index eedd942..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-= edit(1)
-:doctype: manpage
-
-== NAME
-
-registrar - registry service for tracking open tide(1) windows
-
-== SYNOPSIS
-
-*registrar*
-
-== DESCRIPTION
-
-
-== OPTIONS
-
-
-== ENVIRONMENT
-
-
-== SEE ALSO
-
-registrar(1), tide(1), pick(1), fetch(1), fetchsel(1)
diff --git a/src/edit.c b/src/edit.c
deleted file mode 100644 (file)
index c01ad25..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-#include <stdc.h>
-#include <x11.h>
-#include <io.h>
-
-#include "config.h"
-
-char* ARGV0;
-Atom XA_REGISTRAR, XA_OPEN, XA_DONE;
-
-int spawn(char* cmd)
-{
-    int pid = fork();
-    if (pid == 0)
-    {
-        exit(execvp(cmd, (char*[]){cmd, 0}));
-    }
-    return pid;
-}
-
-Window start_registrar(XConf* x)
-{
-    /* launch registrar if it isn't yet running */
-    if (None == XGetSelectionOwner(x->display, XA_REGISTRAR))
-    {
-        if (spawn("registrar") > 0)
-        {
-            sleep(1);
-        }
-    }
-    return XGetSelectionOwner(x->display, XA_REGISTRAR);
-}
-
-void prop_set(XConf* x, Window win, char* prop, char* value)
-{
-    Atom xa_prop = XInternAtom(x->display, prop, False);
-    XChangeProperty(
-        x->display, win, xa_prop, XA_STRING, 8, PropModeReplace,
-        (const unsigned char *)value, strlen(value)+1);
-}
-
-void edit_file(XConf* x, Window registrar, char* path, char* addr, int force)
-{
-    char host[8192];
-    path = abspath(path);
-    prop_set(x, x->self, "FILE", path);
-    prop_set(x, x->self, "ADDR", addr);
-    if (!gethostname(host, sizeof(host)))
-    {
-        prop_set(x, x->self, "HOST", host);
-    }
-    XChangeProperty(
-        x->display, registrar, XA_OPEN, XA_WINDOW, 32, PropModeAppend,
-        (const unsigned char *)&(x->self), 1);
-    EditCmd[2] = addr, EditCmd[3] = path;
-    if (force)
-    {
-        if (!fork())
-            exit(execvp(EditCmd[0], EditCmd));
-    }
-    else
-    {
-        /* wait for the "done" message */
-        for (XEvent e;;)
-        {
-            XNextEvent(x->display, &e);
-            if (e.type == ClientMessage)
-            {
-                if (e.xclient.message_type == XA_DONE)
-                {
-                    break;
-                }
-                else if (e.xclient.message_type == XA_OPEN)
-                {
-                    if (!fork())
-                    {
-                        exit(execvp(EditCmd[0], EditCmd));
-                    }
-                    break;
-                }
-            }
-        }
-    }
-    free(path);
-}
-
-int main(int argc, char** argv)
-{
-    int ret = 0;
-    int force = 0;
-    OPTBEGIN { case 'f': force = 1; break; } OPTEND;
-    if (argc == 0)
-    {
-        spawn("tide");
-    }
-    else
-    {
-        XConf x = {0};
-        x11_init(&x);
-        x11_mkwin(&x, 1, 1, 0);
-        XA_REGISTRAR = XInternAtom(x.display, "TIDE_REGISTRAR", PropertyChangeMask);
-        XA_OPEN = XInternAtom(x.display, "OPEN", 0);
-        XA_DONE = XInternAtom(x.display, "DONE", 0);
-        Window registrar = start_registrar(&x);
-        if (registrar != None)
-        {
-            /* Loop over files and send an OPEN message for each one. */
-            for (int i = 0; i < argc; i++)
-            {
-                char* addr = strrchr(argv[i], ':');
-                if (addr)
-                {
-                    *addr = '\0', addr++;
-                }
-                edit_file(&x, registrar, argv[i], (addr ? addr : "0"), force);
-            }
-            XSync(x.display, False);
-        }
-        else
-        {
-            fprintf(stderr, "Failed to contact registrar.\n");
-            ret = 1;
-        }
-    }
-    return ret;
-}
diff --git a/src/fetch.1.adoc b/src/fetch.1.adoc
deleted file mode 100644 (file)
index 527e549..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-= fetch(1)
-:doctype: manpage
-
-== NAME
-
-registrar - registry service for tracking open tide(1) windows
-
-== SYNOPSIS
-
-*registrar*
-
-== DESCRIPTION
-
-
-== OPTIONS
-
-
-== ENVIRONMENT
-
-
-== SEE ALSO
-
-registrar(1), tide(1), edit(1), pick(1), fetchsel(1)
\ No newline at end of file
diff --git a/src/fetch.c b/src/fetch.c
deleted file mode 100644 (file)
index 3f09d0a..0000000
+++ /dev/null
@@ -1,509 +0,0 @@
-#include <stdc.h>
-#include <io.h>
-#include <regex.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <pwd.h>
-
-typedef struct {
-    enum {
-        COMPLETE=0, MATCHES, IS, ISSET, ISDIR, ISFILE,
-        SET, UNSET, EXEC, LAUNCH
-    } type;
-    char* arg1;
-    char* arg2;
-} Rule;
-
-char* Matches[10];
-Rule*** Rulesets = NULL;
-size_t NumRulesets = 0;
-bool Launched = false;
-
-static Rule*** BuiltinRules = (Rule**[]){
-    (Rule*[]){ /* Match URLS and open them with the browser */
-        &(Rule){ ISSET, "BROWSER", NULL },
-        &(Rule){ MATCHES, "data", "^(https?|ftp)://.*" },
-        &(Rule){ LAUNCH, "$BROWSER \"$M0\"", NULL },
-        &(Rule){ COMPLETE, NULL, NULL }
-    },
-    (Rule*[]){ /* Open files with addresses in the editor */
-        &(Rule){ MATCHES, "data", "^([^:]+):([0-9]+)" },
-        &(Rule){ ISFILE, "$M1", NULL },
-        &(Rule){ LAUNCH, "edit \"$M0\"", NULL },
-        &(Rule){ COMPLETE, NULL, NULL }
-    },
-    (Rule*[]){ /* Open addresses in the current file */
-        &(Rule){ MATCHES, "data", "^:?([0-9]+)" },
-        &(Rule){ ISFILE, "$file", NULL },
-        &(Rule){ LAUNCH, "edit \"$file:$M1\"", NULL },
-        &(Rule){ COMPLETE, NULL, NULL }
-    },
-    (Rule*[]){ /* If it's an existing text file, open it with editor */
-        &(Rule){ ISFILE, "$data", NULL },
-        &(Rule){ EXEC, "file --mime \"$file\" | grep -q 'text/'", NULL },
-        &(Rule){ LAUNCH, "edit \"$file\"", NULL },
-        &(Rule){ COMPLETE, NULL, NULL }
-    },
-    (Rule*[]){ /* Look it up in ctags database */
-        &(Rule){ ISFILE, "tags", NULL },
-        &(Rule){ EXEC, "grep -q \"^$data\\s\\+\" tags", NULL },
-        &(Rule){ LAUNCH, "picktag fetch tags \"$data\"", NULL },
-        &(Rule){ COMPLETE, NULL, NULL }
-    },
-    (Rule*[]){ /* Open man pages in a tide window */
-        &(Rule){ ISSET, "BROWSER", NULL },
-        &(Rule){ MATCHES, "data", "(.+)\\(([0-9]+)\\)" },
-        &(Rule){ LAUNCH, "man $M2 \"$M1\" | col -b | tide -", NULL },
-        &(Rule){ COMPLETE, NULL, NULL }
-    },
-    (Rule*[]){ /* If it's an existing directory, open it tide */
-        &(Rule){ ISDIR, "$data", NULL },
-        &(Rule){ LAUNCH, "edit \"$data\"", NULL },
-        &(Rule){ COMPLETE, NULL, NULL }
-    },
-    (Rule*[]){ /* look for files in /usr/include */
-        &(Rule){ ISFILE, "/usr/include/$data", NULL },
-        &(Rule){ LAUNCH, "edit \"/usr/include/$data\"", NULL },
-        &(Rule){ COMPLETE, NULL, NULL }
-    },
-    (Rule*[]){ /* look for files in /usr/local/include */
-        &(Rule){ ISFILE, "/usr/local/include/$data", NULL },
-        &(Rule){ LAUNCH, "edit \"/usr/local/include/$data\"", NULL },
-        &(Rule){ COMPLETE, NULL, NULL }
-    },
-    (Rule*[]){ /* look for files in /usr/X11/include */
-        &(Rule){ ISFILE, "/usr/X11/include/$data", NULL },
-        &(Rule){ LAUNCH, "edit \"/usr/X11/include/$data\"", NULL },
-        &(Rule){ COMPLETE, NULL, NULL }
-    },
-    NULL
-};
-
-static char* homedir_path(char* rpath)
-{
-    static char path[8192] = {0};
-    if (!path[0])
-    {
-        snprintf(path, sizeof(path)-1,"%s/%s", getpwuid(getuid())->pw_dir, rpath);
-    }
-    return path;
-}
-
-
-/******************************************************************************/
-
-char* getvar(char* val)
-{
-    val = getenv(val);
-    return (val ? val : "");
-}
-
-char* eval(char* str)
-{
-    static bool inited = false;
-    static char* patt = "\\$([a-zA-Z0-9_]+)";
-    static regex_t regex;
-
-    if (!inited && (regcomp(&regex, patt, REG_EXTENDED) < 0))
-    {
-        perror("regcomp() :");
-        exit(1);
-    }
-
-    regmatch_t matches[2] = {{0},{0}};
-    int result = regexec(&regex, str, nelem(matches), matches, 0);
-    if (result >= 0 && matches[1].rm_so > 0)
-    {
-        char* var = strndup(str+matches[1].rm_so, matches[1].rm_eo-matches[1].rm_so);
-        char* val = getvar(var);
-        size_t sz = strlen(str) + strlen(val);
-        char* exp = calloc(1, sz);
-        strncat(exp, str, matches[0].rm_so);
-        strcat(exp, val);
-        strcat(exp, str + matches[0].rm_eo);
-        str = eval(exp);
-    }
-    return str;
-}
-
-/******************************************************************************/
-
-static bool matches(char* var, char* patt)
-{
-    bool ret = false;
-    regex_t regex = {0};
-    regmatch_t matches[10] = {{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}};
-    if (regcomp(&regex, patt, REG_EXTENDED) == 0)
-    {
-        var = getvar(var);
-        int err = regexec(&regex, var, nelem(matches), matches, 0);
-        for (int i = 0; i < 10 && matches[i].rm_so >= 0; i++)
-        {
-            char* matchval = strndup(var+matches[i].rm_so, matches[i].rm_eo-matches[i].rm_so);
-            setenv((char[]){ 'M', ('0' + i), 0 }, matchval, 1);
-            free(matchval);
-        }
-        ret = (err == 0);
-    }
-    return ret;
-}
-
-static bool var_is(char* var, char* val)
-{
-    return (strcmp(getvar(var), eval(val)) == 0);
-}
-
-static bool var_isset(char* var)
-{
-    return (getenv(var) != NULL);
-}
-
-static bool var_isdir(char* var)
-{
-    bool ret = false;
-    struct stat st = {0};
-    char* path = eval(var);
-    bool exists = (stat(eval(var), &st) >= 0);
-    if (exists && S_ISDIR(st.st_mode))
-    {
-        setenv("dir", path, 1);
-        ret = true;
-    }
-    return ret;
-}
-
-static bool var_isfile(char* var)
-{
-    bool ret = false;
-    struct stat st = {0};
-    char* path = eval(var);
-    bool exists = (stat(eval(var), &st) >= 0);
-    if (exists && !S_ISDIR(st.st_mode))
-    {
-        setenv("file", path, 1);
-        ret = true;
-    }
-    return ret;
-}
-
-static bool var_set(char* var, char* val)
-{
-    return (setenv(var, eval(val), 1) == 0);
-}
-
-static bool var_unset(char* var)
-{
-    return (unsetenv(var) == 0);
-}
-
-static void runcmd(char* cmd)
-{
-    char* shellcmd[] = { getvar("SHELL"), "-c", cmd, NULL };
-    if (!shellcmd[0]) shellcmd[0] = "/bin/sh";
-    _exit(execvp(shellcmd[0], shellcmd));
-}
-
-static bool exec(char* cmd)
-{
-    bool ret = false;
-    int pid, status;
-    if ((pid = fork()) >= 0)
-    {
-        if (pid == 0)
-        {
-            runcmd(cmd);
-        }
-        else
-        {
-            waitpid(pid, &status, 0);
-            ret = (status == 0);
-        }
-    }
-    return ret;
-}
-
-static bool launch(char* cmd)
-{
-    bool ret = false;
-    int pid = fork();
-    if (pid > 0)
-    {
-        Launched = true;
-        ret = true;
-    }
-    else if (pid == 0)
-    {
-        runcmd(cmd);
-    }
-    return ret;
-}
-
-static bool apply_rule(Rule* rule)
-{
-    bool ret = false;
-    switch (rule->type)
-    {
-        case COMPLETE: exit(0);                               break;
-        case MATCHES:  ret = matches(rule->arg1, rule->arg2); break;
-        case IS:       ret = var_is(rule->arg1, rule->arg2);  break;
-        case ISSET:    ret = var_isset(rule->arg1);           break;
-        case ISDIR:    ret = var_isdir(rule->arg1);           break;
-        case ISFILE:   ret = var_isfile(rule->arg1);          break;
-        case SET:      ret = var_set(rule->arg1, rule->arg2); break;
-        case UNSET:    ret = var_unset(rule->arg1);           break;
-        case EXEC:     ret = exec(rule->arg1);                break;
-        case LAUNCH:   ret = launch(rule->arg1);              break;
-    }
-    return ret;
-}
-
-/******************************************************************************/
-
-static void usage(char* pname)
-{
-    fprintf(stderr, "Usage: %s [ITEM]\n", pname);
-    exit(1);
-}
-
-static char* type2str(int type)
-{
-    char* ret = "UNKNOWN";
-    switch (type)
-    {
-        case COMPLETE: ret = "COMPLETE"; break;
-        case MATCHES:  ret = "MATCHES";  break;
-        case IS:       ret = "IS";       break;
-        case ISSET:    ret = "ISSET";    break;
-        case ISDIR:    ret = "ISDIR";    break;
-        case ISFILE:   ret = "ISFILE";   break;
-        case SET:      ret = "SET";      break;
-        case UNSET:    ret = "UNSET";    break;
-        case EXEC:     ret = "EXEC";     break;
-        case LAUNCH:   ret = "LAUNCH";   break;
-    }
-    return ret;
-}
-
-static char* nextline(char** raw)
-{
-    char* line = NULL;
-    char* eol = strchr(*raw, '\n');
-    if (eol)
-    {
-        *eol = '\0';
-        line = *raw;
-        *raw = eol+1;
-    }
-    if (line)
-    {
-        line = strdup(line);
-    }
-    return line;
-}
-
-static char* nextfield(char** raw)
-{
-    char* field = *raw;
-    /* skip whitespace */
-    for (; *field && isspace(*field); field++);
-
-    char* eof = field;
-    for (; *eof && !isspace(*eof); eof++);
-    *eof = '\0';
-    *raw = eof + 1;
-
-    return (field && *field ? field : NULL);
-}
-
-static char* lastfield(char** raw)
-{
-    char* field = *raw;
-    /* skip whitespace */
-    for (; *field && isspace(*field); field++);
-
-    char* eof = field;
-    for (; *eof && *eof != '\n'; eof++);
-    *eof = '\0';
-    *raw = eof + 1;
-
-    return (field && *field ? field : NULL);
-}
-
-
-static void parse_args1(int type, Rule* rule, char* args)
-{
-    rule->type = type;
-    rule->arg1 = args;
-    if (!rule->arg1)
-    {
-        printf("action '%s' requires an argument\n", type2str(type));
-        exit(1);
-    }
-}
-
-static void parse_args2(int type, Rule* rule, char* args)
-{
-    rule->type = type;
-    rule->arg1 = nextfield(&args);
-    rule->arg2 = lastfield(&args);
-    if (!rule->arg1 || !rule->arg2)
-    {
-        printf("action '%s' requires two arguments\n", type2str(type));
-        exit(1);
-    }
-}
-
-static Rule* parse_rule(char* act, char* args)
-{
-    Rule* rule = calloc(1, sizeof(Rule));
-    if (!strcmp(act, "is"))
-    {
-        parse_args2(IS, rule, args);
-    }
-    else if (!strcmp(act, "isset"))
-    {
-        parse_args1(ISSET, rule, args);
-    }
-    else if (!strcmp(act, "isdir"))
-    {
-        parse_args1(ISDIR, rule, args);
-    }
-    else if (!strcmp(act, "isfile"))
-    {
-        parse_args1(ISFILE, rule, args);
-    }
-    else if (!strcmp(act, "set"))
-    {
-        parse_args2(SET, rule, args);
-    }
-    else if (!strcmp(act, "unset"))
-    {
-        parse_args1(UNSET, rule, args);
-    }
-    else if (!strcmp(act, "exec"))
-    {
-        parse_args1(EXEC, rule, args);
-    }
-    else if (!strcmp(act, "launch"))
-    {
-        parse_args1(LAUNCH, rule, args);
-    }
-    else if (!strcmp(act, "matches"))
-    {
-        parse_args2(MATCHES, rule, args);
-    }
-    else
-    {
-        printf("error: unknown action '%s'\n", act);
-        exit(1);
-    }
-    return rule;
-}
-
-static void add_ruleset(Rule** rules, size_t nrules, Rule* rule)
-{
-    if (rules)
-    {
-        rules = realloc(rules, sizeof(Rule) * ++nrules);
-        rules[nrules-1] = rule;
-    }
-    Rulesets = realloc(Rulesets, sizeof(Rule) * ++NumRulesets);
-    Rulesets[NumRulesets-1] = rules;
-}
-
-static void parse_rules(char* path)
-{
-    char* line = NULL;
-    char* raw = readfile(path);
-    telem_send("RULES: %s\n", path);
-    if (raw)
-    {
-        Rule** rules = NULL;
-        size_t nrules = 0;
-
-        while ((line = nextline(&raw)) != NULL)
-        {
-            char* cmd = line;
-            /* skip whitespace */
-            for (; *cmd && isspace(*cmd); cmd++);
-
-            if (!*cmd)
-            {
-                add_ruleset(rules, nrules, calloc(1, sizeof(Rule)));
-                rules = NULL;
-                nrules = 0;
-            }
-            else if (*cmd != '#')
-            {
-                char* action = nextfield(&cmd);
-                rules = realloc(rules, sizeof(Rule) * ++nrules);
-                rules[nrules-1] = parse_rule(action, cmd);
-            }
-            else
-            {
-                free(line);
-            }
-            line = NULL;
-        }
-
-        if (rules)
-        {
-            add_ruleset(rules, nrules, calloc(1, sizeof(Rule)));
-        }
-    }
-}
-
-static void check_ruleset(Rule** rule)
-{
-    Launched = false;
-    for (; (*rule)->type != COMPLETE; rule++)
-    {
-        telem_send("  RULE(%s '%s' '%s')\n", type2str((*rule)->type), (*rule)->arg1, (*rule)->arg2);
-        if (!apply_rule(*rule))
-        {
-            break;
-        }
-    }
-
-    if (Launched && (*rule)->type == COMPLETE)
-    {
-        telem_send("  ACCEPT\n");
-        exit(0);
-    }
-    else
-    {
-        telem_send("  NEXT\n");
-    }
-}
-
-int main(int argc, char** argv)
-{
-    ARGV0 = *argv;
-    if (argc != 2)
-    {
-        usage(ARGV0);
-    }
-    else
-    {
-        /* load rules from files */
-        parse_rules("fetch.rules");
-        parse_rules(homedir_path("config/tide/fetch.rules"));
-        add_ruleset(NULL, 0, NULL); // terminate the parsed set of rules
-
-        telem_send("FETCH(%s)\n", argv[1]);
-        setenv("data", argv[1], 1);
-
-        /* process parsed rules */
-        for (; Rulesets && *Rulesets; Rulesets++)
-        {
-            check_ruleset(*Rulesets);
-        }
-
-        /* process builtin rules */
-        for (unsigned int i = 0; BuiltinRules[i]; i++)
-        {
-            check_ruleset(BuiltinRules[i]);
-        }
-    }
-    return 1;
-}
similarity index 100%
rename from src/fetchsel.c
rename to src/fetchsel/fetchsel.c
diff --git a/src/pick.1.adoc b/src/pick.1.adoc
deleted file mode 100644 (file)
index 5532298..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-= pick(1)
-:doctype: manpage
-
-== NAME
-
-registrar - registry service for tracking open tide(1) windows
-
-== SYNOPSIS
-
-*registrar*
-
-== DESCRIPTION
-
-
-== OPTIONS
-
-
-== ENVIRONMENT
-
-
-== SEE ALSO
-
-registrar(1), tide(1), edit(1), fetch(1), fetchsel(1)
\ No newline at end of file
diff --git a/src/pick.c b/src/pick.c
deleted file mode 100644 (file)
index 8f0655b..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-#include <stdc.h>
-#include <vec.h>
-#include <x11.h>
-
-#define INCLUDE_DEFS
-#include "config.h"
-
-static void xkeypress(XConf* x, XEvent* e);
-static void xbtnpress(XConf* x, XEvent* e);
-static void redraw(XConf* x);
-static void xinit(XConf* x);
-
-typedef struct {
-    float score;
-    char* string;
-    size_t length;
-    size_t match_start;
-    size_t match_end;
-} Choice;
-
-char Query[8192] = {0};
-size_t QueryIdx = 0;
-vec_t Choices = {0};
-size_t ChoiceIdx = 0;
-size_t Offset = 0;
-
-static int peekc(FILE* in)
-{
-    int c = fgetc(in);
-    ungetc(c, in);
-    return c;
-}
-
-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 == '\r') continue;
-        if (ch == EOF || ch == '\n') break;
-        str[index++] = ch;
-        str[index]   = '\0';
-    }
-    if (len) *len = index;
-    return str;
-}
-
-static int by_score(const void* a, const void* b)
-{
-    Choice* ca = ((Choice*)a);
-    Choice* cb = ((Choice*)b);
-    if (ca->score < cb->score)
-        return 1;
-    else if (ca->score > cb->score)
-        return -1;
-    else
-        return strcmp(ca->string, cb->string);
-}
-
-static void load_choices(XConf* x)
-{
-    size_t choice_len;
-    char* choice_text;
-    bool shown = false;
-    Choice choice = {0};
-    vec_init(&Choices, sizeof(Choice));
-    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;
-            if (!shown && peekc(stdin) != EOF)
-            {
-                x11_show(x);
-                redraw(x);
-                shown = true;
-            }
-            vec_push_back(&Choices, &choice);
-        }
-        else
-        {
-            free(choice_text);
-        }
-    }
-}
-
-static char* find_char(char* str, int ch)
-{
-    for (; *str; str++)
-        if (tolower(*str) == tolower(ch))
-            return str;
-    return NULL;
-}
-
-static inline bool find_match(char *string, char* query, size_t offset, char **start, char **end)
-{
-    char *s, *e;
-    /* find first match char or bail */
-    s = e = find_char(&string[offset], *query);
-    if (s == NULL) return false;
-
-    /* find the end of the match */
-    for (query++; *query; query++)
-        if ((e = find_char(e+1, *query)) == NULL)
-            return false;
-
-    /* if we made it this far, we found a match */
-    *start = s, *end = e;
-    return true;
-}
-
-static bool match(char *string, size_t offset, size_t *start, size_t *end)
-{
-    char *s1 = 0, *e1 = 0, *s2, *e2;
-    /* first check if we match at all */
-    if (!find_match(string, Query, offset, &s1, &e1))
-        return false;
-    s2 = s1, e2 = e1; // Init s2 and e2 before use below
-
-    /* next find the longest match. If multiple, take the left most one */
-    while (find_match(string, Query, ++offset, &s1, &e1) && ((e1-s1) <= (e2-s2)))
-        s1 = s2, e1 = e2;
-
-    /* return the best match */
-    *start = s1 - string;
-    *end   = e1 - string;
-    return true;
-}
-
-static void score(void)
-{
-    unsigned int nchoices = vec_size(&Choices);
-    for (unsigned int i = 0; i < nchoices; i++) {
-        Choice* choice = (Choice*)vec_at(&Choices, i);
-        float qlen = (float)QueryIdx;
-        if (match(choice->string, 0, &choice->match_start, &choice->match_end))
-        {
-            float clen = (float)(choice->match_end - choice->match_start) + 1;
-            choice->score = qlen / clen / (float)(choice->length);
-        }
-        else
-        {
-            choice->match_start = 0;
-            choice->match_end   = 0;
-            choice->score       = 0.0f;
-        }
-    }
-    vec_sort(&Choices, by_score);
-}
-
-int main(int argc, char** argv)
-{
-    XConf x = {0};
-    if (argc >= 2) {
-        size_t sz = min(strlen(argv[1]), sizeof(Query)-1);
-        strncpy(Query, argv[1], sz);
-        QueryIdx = sz;
-    }
-    xinit(&x);
-    load_choices(&x);
-    score();
-    if (vec_size(&Choices) > 1)
-        x11_event_loop(&x, redraw);
-    Choice* choice = (Choice*)vec_at(&Choices, ChoiceIdx);
-    if (vec_size(&Choices) && ChoiceIdx != SIZE_MAX)
-        printf("%s\n", choice->string);
-    return 0;
-}
-
-static void xkeypress(XConf* x, XEvent* e)
-{
-    char buf[8];
-    KeySym key;
-    Status status;
-    if (x->xic)
-        Xutf8LookupString(x->xic, &(e->xkey), buf, sizeof(buf), &key, &status);
-    else
-        XLookupString(&(e->xkey), buf, sizeof(buf), &key, 0);
-    if (key == XK_Return)
-    {
-        x->state = QUITTING;
-    }
-    else if (key == XK_Escape)
-    {
-        x->state = QUITTING;
-        ChoiceIdx = SIZE_MAX;
-    }
-    else if (key == XK_Up)
-    {
-        if (ChoiceIdx > 0)
-            ChoiceIdx--;
-        if (ChoiceIdx < Offset)
-            Offset--;
-    }
-    else if (key == XK_Down)
-    {
-        size_t nlines = ((x->height - x->font->height - 4) / x->font->height) - 1;
-        size_t maxidx = Offset + nlines;
-        if (ChoiceIdx+1 < vec_size(&Choices))
-            ChoiceIdx++;
-        if (ChoiceIdx > maxidx)
-            Offset++;
-    }
-    else if (key == XK_BackSpace)
-    {
-        if (QueryIdx > 0)
-            Query[--QueryIdx] = '\0';
-        score();
-    }
-    else if (key >= 0x20 && key <= 0x7F)
-    {
-        if (QueryIdx < sizeof(Query)-1)
-            Query[QueryIdx++] = key;
-        Offset = ChoiceIdx = 0;
-        score();
-    }
-}
-
-static void xbtnpress(XConf* x, XEvent* e)
-{
-    (void)x;
-    if (e->xbutton.button == Button1)
-    {
-        int starty = x->font->height + 4;
-        e->xbutton.y = (e->xbutton.y < starty ? starty : e->xbutton.y - starty);
-        ChoiceIdx = Offset + (e->xbutton.y / x->font->height);
-        if (ChoiceIdx >= vec_size(&Choices))
-            ChoiceIdx = vec_size(&Choices)-1;
-    }
-    else if (e->xbutton.button == Button2)
-    {
-        x->state = QUITTING;
-    }
-    else if (e->xbutton.button == Button3)
-    {
-        x->state = QUITTING;
-        ChoiceIdx = SIZE_MAX;
-    }
-    else if (e->xbutton.button == Button4)
-    {
-        if (Offset > 0) Offset--;
-    }
-    else if (e->xbutton.button == Button5)
-    {
-        if (Offset < vec_size(&Choices)) Offset++;
-    }
-}
-
-static void redraw(XConf* x)
-{
-    /* draw the background colors and border */
-    size_t fheight = x->font->height;
-    size_t nlines = ((x->height - x->font->height - 4) / x->font->height) - 1;
-    size_t scroll_height = x->height - fheight - 4;
-    size_t start = (size_t)((float)Offset / (float)vec_size(&Choices) * scroll_height);
-    size_t size = (size_t)((float)nlines / (float)vec_size(&Choices) * scroll_height);
-
-    x11_draw_rect(x, Palette[EditBg], 0, 0, x->width, x->height);
-    x11_draw_rect(x, Palette[TagsBg], 0, 0, x->width, fheight + 4);
-    x11_draw_rect(x, Palette[HorBdr], 0, fheight + 4, x->width, 1);
-    x11_draw_rect(x, Palette[ScrollBg], 0, fheight + 5, ScrollWidth+1, scroll_height);
-    x11_draw_rect(x, Palette[ScrollFg], 0, fheight + 5 + start, ScrollWidth, (size ? size : 5));
-
-    /* get size of the query when printed */
-    XGlyphInfo glyphinfo;
-    XftTextExtentsUtf8(x->display, x->font, (const FcChar8*)Query,  strlen(Query), &glyphinfo);
-    int offset = 0;
-    if (glyphinfo.width >= (x->width - 4))
-        offset = ((x->width - 4) - glyphinfo.width);
-
-    /* draw the query and the cursor to the query region */
-    int posx = 2 + glyphinfo.width + offset;
-    x11_draw_rect(x, Palette[TagsFg], posx-1, 2, 3, 3);
-    x11_draw_rect(x, Palette[TagsFg], posx, 2, 1, fheight);
-    x11_draw_rect(x, Palette[TagsFg], posx-1, 2+fheight-3, 3, 3);
-    x11_draw_string(x, x->font, offset + 2, fheight, Palette[TagsFg], Query);
-
-    /* draw the scored and sorted results */
-    if (vec_size(&Choices))
-    {
-        for (int i = Offset, y = 2 * fheight + 4; ((size_t)i < vec_size(&Choices)) && ((size_t)i <= Offset+nlines); i++, y += fheight)
-        {
-            if ((size_t)i == ChoiceIdx)
-                x11_draw_rect(x, Palette[EditSel], ScrollWidth+3, y - x->font->ascent, x->width, fheight);
-            x11_draw_string(x, x->font, ScrollWidth+3, y, Palette[TagsFg], ((Choice*)vec_at(&Choices, i))->string);
-        }
-    }
-    else
-    {
-        x11_draw_string(x, x->font, ScrollWidth+3, 2 * fheight + 4, Palette[TagsFg], "Loading...");
-    }
-    x11_flip(x);
-}
-
-static void xinit(XConf* x)
-{
-    x11_init(x);
-    x11_mkdialog(x, 640, 480, 0
-        | StructureNotifyMask
-        | KeyPressMask
-        | ButtonPressMask
-        | ExposureMask
-    );
-    x11_init_gc(x);
-    x11_centerwin(x);
-    if (!(x->font = x11_font_load(x, Fonts[0])))
-    {
-        perror("unable to load base font");
-        exit(EXIT_FAILURE);
-    }
-    x->eventfns[KeyPress] = xkeypress;
-    x->eventfns[ButtonPress] = xbtnpress;
-}
diff --git a/src/registrar.1.adoc b/src/registrar.1.adoc
deleted file mode 100644 (file)
index 5b9b777..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-= registrar(1)
-:doctype: manpage
-
-== NAME
-
-registrar - registry service for tracking open tide(1) windows
-
-== SYNOPSIS
-
-*registrar*
-
-== DESCRIPTION
-
-
-== SEE ALSO
-
-tide(1), edit(1), pick(1), fetch(1), fetchsel(1)
\ No newline at end of file
diff --git a/src/registrar.c b/src/registrar.c
deleted file mode 100644 (file)
index f9d4c87..0000000
+++ /dev/null
@@ -1,294 +0,0 @@
-#include <stdc.h>
-#include <x11.h>
-#include <io.h>
-#include "config.h"
-
-typedef struct TWindow {
-    struct TWindow* next;
-    Window win;
-    char* path;
-    char* host;
-} TWindow;
-
-Atom XA_REGISTRAR, XA_ADD, XA_DEL, XA_OPEN, XA_DONE, XA_TIDE;
-TWindow* Windows = NULL;
-
-static void* readprop(XConf* x, Window win, char* prop, Atom type, size_t* length)
-{
-    Atom rtype, xa_prop = XInternAtom(x->display, prop, False);
-    int format;
-    unsigned long datalen, nleft;
-    unsigned char* data = NULL;
-    XGetWindowProperty(
-        x->display, win, xa_prop, 0, -1, False, type,
-        &rtype, &format, &datalen, &nleft, &data);
-    if (length) *length = datalen;
-    if (rtype != type)
-    {
-        if (data) XFree(data);
-        data = 0;
-        if (length) *length = 0;
-    }
-    return (void*)data;
-}
-
-static char* read_path(XConf* x, Window id)
-{
-    int nprops;
-    char* path = NULL;
-    Atom xa_file = XInternAtom(x->display, "FILE", False);
-    Atom* props = XListProperties(x->display, id, &nprops);
-    if (props)
-    {
-        for (int i = 0; i < nprops; i++)
-        {
-            if (props[i] == xa_file)
-            {
-                path = readprop(x, id, "FILE", XA_STRING, 0);
-                break;
-            }
-        }
-        XFree(props);
-    }
-    return path;
-}
-
-static void win_add(XConf* x, Window id)
-{
-    char* path = read_path(x, id);
-    if (!path) return;
-    telem_send("WIN_ADD(0x%x: '%s')\n", (unsigned int)id, path);
-    TWindow* win = calloc(1, sizeof(TWindow));
-    win->win = id;
-    win->next = Windows;
-    win->path = path;
-    win->host = readprop(x, id, "HOST", XA_STRING, NULL);
-    Windows = win;
-}
-
-static void win_del(Window id)
-{
-    if (!Windows) return;
-    telem_send("WIN_DEL(0x%x)\n", id);
-    if (Windows->win == id)
-    {
-        TWindow* deadite = Windows;
-        Windows = deadite->next;
-        free(deadite);
-    }
-    else
-    {
-        TWindow* w = Windows;
-        for (;w && w->next && (w->next->win != id); w = w->next);
-        if (w && w->next)
-        {
-            TWindow* deadite = w->next;
-            w->next = deadite->next;
-            free(deadite->path), deadite->path = NULL;
-            free(deadite->host), deadite->host = NULL;
-            free(deadite);
-        }
-    }
-}
-
-static void win_send(XConf* x, Window from, Window to, int mask, char* atom, size_t val)
-{
-    telem_send("WIN_SEND(from: %lx, to: %lx, atom: %d)\n", from, to, atom);
-    XEvent ev = {0};
-    ev.xclient.type = ClientMessage;
-    ev.xclient.send_event = True;
-    ev.xclient.message_type = XInternAtom(x->display, atom, False);
-    ev.xclient.window = from;
-    ev.xclient.format = 32;
-    ev.xclient.data.l[0] = val;
-    XSendEvent(x->display, to, False, mask, &ev);
-}
-
-static void win_open(XConf* x, Window winid, char* path, char* addr, char* host)
-{
-    if (path)
-    {
-        telem_send("WIN_OPEN(%lx '%s' '%s')\n", winid, path, host);
-        /* search for an existing window */
-        for (TWindow* win = Windows; win; win = win->next)
-        {
-            /* refresh the filepath and crudely determine if window still valid */
-            free(win->path);
-            win->path = NULL;
-            char* file = readprop(x, win->win, "FILE", XA_STRING, NULL);
-            win->path = (file ? file : NULL);
-            telem_send("    %lx '%s' '%s'\n", win->win, win->path, win->host);
-            if (win->host && !strcmp(win->host, host) &&
-                win->path && !strcmp(win->path, path))
-            {
-                /* double check that the window id didnt get reassigned to a non-tide window */
-                telem_send("WIN_ACTIVATE(0x%x '%s')\n", (unsigned int)win->win, win->path);
-                x11_error_clear();
-                char* type = readprop(x, win->win, "TIDE", XA_STRING, 0);
-                if (!type || x11_error_get())
-                {
-                    free(win->path), win->path = NULL;
-                    free(win->host), win->host = NULL;
-                    free(type);
-                    break;
-                }
-                else
-                {
-                    XEvent ev = {0};
-                    ev.xclient.type = ClientMessage;
-                    ev.xclient.send_event = True;
-                    ev.xclient.message_type = XInternAtom(x->display, "_NET_ACTIVE_WINDOW", False);
-                    ev.xclient.window = win->win;
-                    ev.xclient.format = 32;
-                    ev.xclient.data.l[0] = 1;
-                    ev.xclient.data.l[1] = CurrentTime;
-                    ev.xclient.data.l[2] = 0;
-                    XSendEvent(x->display, x->root, False, SubstructureRedirectMask|SubstructureNotifyMask, &ev);
-                    win_send(x, x->self, win->win, 0,  "GOTO", strtoul(addr, NULL, 0));
-                    win_send(x, x->self, winid, 0,  "DONE", 0);
-                    free(type);
-                    return;
-                }
-            }
-        }
-
-        /* if we don't find it, tell sender to spawn a new one */
-        win_send(x, x->self, winid, 0,  "OPEN", 0);
-    }
-}
-
-static void selclear(XConf* x, XEvent* e)
-{
-    (void)e;
-    XSync(x->display, False);
-    telem_send("EXITING\n");
-    exit(0);
-}
-
-static void clientmsg(XConf* x, XEvent* e)
-{
-    if (XA_REGISTRAR != e->xclient.message_type)
-        return;
-    if (XA_ADD == (Atom)(e->xclient.data.l[0]))
-        win_add(x, e->xclient.window);
-    else if (XA_DEL == (Atom)(e->xclient.data.l[0]))
-        win_del(e->xclient.window);
-    XSync(x->display, False);
-}
-
-static TWindow* win_sweep(TWindow* win)
-{
-    if (win)
-    {
-        if (win->path)
-        {
-            win->next = win_sweep(win->next);
-        }
-        else
-        {
-            TWindow* dead = win;
-            telem_send("WIN_SWEEP(%x)\n", (unsigned)win->win);
-            win = win_sweep(win->next);
-            free(dead);
-        }
-    }
-    return win;
-}
-
-static void propnotify(XConf* x, XEvent* e)
-{
-    (void)e;
-    Atom type;
-    int format;
-    unsigned long datalen, nleft;
-    unsigned char* data = NULL;
-    XGetWindowProperty(
-        x->display, x->self, XA_OPEN, 0, -1, True, XA_WINDOW,
-        &type, &format, &datalen, &nleft, &data);
-    /* handle all of the window requests */
-    for (Window* win = (Window*)data; datalen && win && *win; win++, datalen--)
-    {
-        char* file = readprop(x, *win, "FILE", XA_STRING, NULL);
-        char* addr = readprop(x, *win, "ADDR", XA_STRING, NULL);
-        char* host = readprop(x, *win, "HOST", XA_STRING, NULL);
-        win_open(x, *win, file, (addr ? addr : "0"), host);
-        if(file) XFree(file);
-        if(addr) XFree(addr);
-    }
-    XSync(x->display, False);
-
-    /* cleanup any invalid windows */
-    Windows = win_sweep(Windows);
-}
-
-static void find_windows(XConf* x)
-{
-    XGrabServer(x->display);
-    size_t nwindows = 0;
-    Window* windows = readprop(x, x->root, "_NET_CLIENT_LIST", XA_WINDOW, &nwindows);
-    telem_send("FIND_WINS(nwins: %lu)\n", nwindows);
-    XUngrabServer(x->display);
-    for (size_t i = 0; i < nwindows; i++)
-        win_add(x, windows[i]);
-    if (windows) XFree(windows);
-}
-
-static int daemonize(void)
-{
-    int status;
-    /* fork into the background first */
-    if ((status = fork()) < 0)
-        return -1;
-    else if (status > 0)
-        _exit(0);
-
-    /* create a new session */
-    if (setsid() < 0) return -1;
-
-    /* fork again so we don't reattach to the terminal */
-    if ((status = fork()) < 0)
-        return -1;
-    else if (status > 0)
-        _exit(0);
-
-    /* clear any inherited umask(2) value */
-    umask(0);
-    (void)chdir("/");
-    close(0), close(1), close(2);
-    return 0;
-}
-
-int main(int argc, char** argv)
-{
-    (void)argc, (void)argv;
-    ARGV0 = argv[0];
-    if (daemonize() >= 0)
-    {
-        XConf x = {0};
-        x11_init(&x);
-        x11_mkwin(&x, 1, 1, PropertyChangeMask);
-        XA_REGISTRAR = XInternAtom(x.display, "TIDE_REGISTRAR", 0);
-        XA_ADD = XInternAtom(x.display, "ADD", 0);
-        XA_DEL = XInternAtom(x.display, "DEL", 0);
-        XA_OPEN = XInternAtom(x.display, "OPEN", 0);
-        XA_DONE = XInternAtom(x.display, "DONE", 0);
-        XA_TIDE = XInternAtom(x.display, "TIDE", 0);
-        x.eventfns[SelectionClear] = selclear;
-        x.eventfns[ClientMessage] = clientmsg;
-        x.eventfns[PropertyNotify] = propnotify;
-        if (None == XGetSelectionOwner(x.display, XA_REGISTRAR))
-        {
-            XSetSelectionOwner(x.display, XA_REGISTRAR, x.self, CurrentTime);
-            if (x.self == XGetSelectionOwner(x.display, XA_REGISTRAR))
-            {
-                find_windows(&x);
-                x11_event_loop(&x, 0);
-            }
-            else
-            {
-                telem_send("FAILED\n");
-            }
-        }
-    }
-    return 1;
-}
similarity index 100%
rename from src/tide.1.adoc
rename to src/tide/tide.1.adoc
similarity index 100%
rename from src/tide.c
rename to src/tide/tide.c