+++ /dev/null
-#include <unistd.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <regex.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-
-#include <stdbool.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-
-#define nelem(x) (sizeof(x)/sizeof((x)[0]))
-
-#ifdef __MACH__
- #define OPENCMD "open"
-#else
- #define OPENCMD "xdg-open"
-#endif
-
-typedef struct {
- enum {
- COMPLETE=0, MATCHES, IS, ISSET, ISDIR, ISFILE,
- SET, UNSET, FINDFILE, EXEC, LAUNCH
- } type;
- char* arg1;
- char* arg2;
-} Rule;
-
-char* Matches[10];
-
-Rule* BuiltinRules[] = {
- (Rule[]){ // Look up .c or .h files in Code/
- { ISSET, "EDITOR", NULL },
- { MATCHES, "data", "\\.[ch]$" },
- { ISDIR, "Code", NULL },
- { EXEC, "[[ $(find Code -type f -name '*$data') ]]", NULL },
- { LAUNCH, "find Code -type f -name '*$data' | xargs -r $EDITOR", NULL },
- { COMPLETE, NULL, NULL }
- },
- (Rule[]){ // Match URLS and open them with the browser
- { ISSET, "BROWSER", NULL },
- { MATCHES, "data", "^(https?|ftp)://.*" },
- { LAUNCH, "$BROWSER $0", NULL },
- { COMPLETE, NULL, NULL }
- },
- (Rule[]){ // Open files with addresses in the editor
- { ISSET, "EDITOR", NULL },
- { MATCHES, "data", "^([^:]+):([0-9]+)" },
- { ISFILE, "$1", NULL },
- { LAUNCH, "tctl $0", NULL },
- { COMPLETE, NULL, NULL }
- },
- (Rule[]){ // If it's an existing text file, open it with editor
- { ISSET, "EDITOR", NULL },
- { ISFILE, "$data", NULL },
- { EXEC, "file --mime '$file' | grep -q 'text/'", NULL },
- { LAUNCH, "$EDITOR '$file'", NULL },
- { COMPLETE, NULL, NULL }
- },
- (Rule[]){ // Look it up in ctags database
- { ISSET, "EDITOR", NULL },
- { ISFILE, "tags", NULL },
- { EXEC, "grep -q '^$data\\s\\+' tags", NULL },
- { LAUNCH, "picktag fetch tags '$data' | xargs -r tide", NULL },
- { COMPLETE, NULL, NULL }
- },
- (Rule[]){ // If it's an existing directory, open it with system default
- { ISDIR, "$data", NULL },
- { LAUNCH, OPENCMD " $data", NULL },
- { COMPLETE, NULL, NULL }
- },
-};
-
-/******************************************************************************/
-
-char* getvar(char* val) {
- if (strlen(val) == 1 && isdigit(*val))
- val = Matches[*val - '0'];
- else
- 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(®ex, patt, REG_EXTENDED) < 0)) {
- perror("regcomp() :");
- exit(1);
- }
-
- regmatch_t matches[2] = {0};
- if (regexec(®ex, str, nelem(matches), matches, 0) < 0) {
- return str;
- } else if (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);
- return eval(exp);
- } else {
- return str;
- }
-}
-
-/******************************************************************************/
-
-bool matches(char* var, char* patt) {
- regex_t regex = {0};
- regmatch_t matches[10] = {0};
- if (regcomp(®ex, patt, REG_EXTENDED) == 0) {
- var = getvar(var);
- memset(Matches, 0, sizeof(Matches));
- int err = regexec(®ex, var, nelem(matches), matches, 0);
- for (int i = 0; i < 10 && matches[i].rm_so >= 0; i++) {
- Matches[i] = strndup(var+matches[i].rm_so, matches[i].rm_eo-matches[i].rm_so);
- }
- return (err == 0);
- }
- return false;
-}
-
-bool var_is(char* var, char* val) {
- return (strcmp(getvar(var), eval(val)) == 0);
-}
-
-bool var_isset(char* var) {
- return (getenv(var) != NULL);
-}
-
-bool var_isdir(char* var) {
- struct stat st = {0};
- char* path = eval(var);
- if ((stat(path, &st) < 0) && (errno == ENOENT)) {
- return false;
- } else if (S_ISDIR(st.st_mode)) {
- setenv("dir", var, 1);
- return true;
- } else {
- return false;
- }
-}
-
-bool var_isfile(char* var) {
- struct stat st = {0};
- char* path = eval(var);
- if ((stat(eval(var), &st) < 0) && (errno == ENOENT)) {
- return false;
- } else if (!S_ISDIR(st.st_mode)) {
- setenv("file", path, 1);
- return true;
- } else {
- return false;
- }
-}
-
-bool var_set(char* var, char* val) {
- return (setenv(var, eval(val), 1) == 0);
-}
-
-bool var_unset(char* var) {
- return (unsetenv(var) == 0);
-}
-
-bool find_file(char* file) {
- return false;
-}
-
-void runcmd(char* cmd) {
- char* shellcmd[] = { getvar("SHELL"), "-c", NULL, NULL };
- if (!shellcmd[0]) shellcmd[0] = "/bin/sh";
- shellcmd[2] = eval(cmd);
- _exit(execvp(shellcmd[0], shellcmd));
-}
-
-bool exec(char* cmd) {
- int pid, status, outpipe[2];
- if ((pid = fork()) < 0) return false;
- if (pid == 0) {
- runcmd(cmd);
- } else {
- waitpid(pid, &status, 0);
- return (status == 0);
- }
- return false;
-}
-
-bool launch(char* cmd) {
- int pid = fork();
- if (pid > 0)
- return true;
- else if (pid == 0)
- runcmd(cmd);
- return false;
-}
-
-bool apply_rule(Rule* rule) {
- switch (rule->type) {
- case COMPLETE: exit(0);
- case MATCHES: return matches(rule->arg1, rule->arg2);
- case IS: return var_is(rule->arg1, rule->arg2);
- case ISSET: return var_isset(rule->arg1);
- case ISDIR: return var_isdir(rule->arg1);
- case ISFILE: return var_isfile(rule->arg1);
- case SET: return var_set(rule->arg1, rule->arg2);
- case UNSET: return var_unset(rule->arg1);
- case FINDFILE: return find_file(rule->arg1);
- case EXEC: return exec(rule->arg1);
- case LAUNCH: return launch(rule->arg1);
- }
- return false;
-}
-
-void apply_ruleset(char* text) {
- setenv("data", text, 1);
- for (int i = 0; i < nelem(BuiltinRules); i++) {
- Rule* rule = BuiltinRules[i];
- for (; rule->type != COMPLETE; rule++)
- if (!apply_rule(rule))
- break;
- if (rule->type == COMPLETE)
- exit(0);
- }
-}
-
-/******************************************************************************/
-
-int fifo_open(char* path, mode_t mode) {
- mkfifo(path, mode);
- int fd = open(path, O_WRONLY|O_NONBLOCK);
- if (fd >= 0) { close(fd); return -1; }
- return open(path, O_RDONLY);
-}
-
-int main(int argc, char** argv) {
- int ret = 0, nread, fd = fifo_open("./myfifo", 0655);
- if (fd >= 0) {
- char buf[1024];
- while ((nread = read(fd, buf, sizeof(buf)-1)) >= 0) {
- if (nread == 0) continue;
- buf[nread] = '\0';
- printf("fetch: '%s'\n", buf);
- if (fork() == 0) apply_ruleset(buf);
- }
- } else {
- perror("open()");
- ret = 1;
- }
- return ret;
-}
+++ /dev/null
-#include <stdc.h>
-#include <utf.h>
-#include <edit.h>
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <X11/Xft/Xft.h>
-#include <unistd.h>
-
-char* SelText; // The text of the clipboard selection
-Atom SelType; // The X11 selection name. Always CLIPBOARD
-Atom SelTarget; // The conversion target for the selection (always string or utf8)
-Display* XDisplay; // Handle for the X connection
-Window XRoot; // The root X window
-Window XWindow; // Our window used to serve the selection up
-
-void serve_selection(void) {
- if (!(XDisplay = XOpenDisplay(0)))
- die("could not open display");
- XRoot = DefaultRootWindow(XDisplay);
- XWindow = XCreateSimpleWindow(XDisplay, XRoot, 0, 0, 1, 1, 0, 0, 0);
- SelType = XInternAtom(XDisplay, "CLIPBOARD", 0);
- SelTarget = XInternAtom(XDisplay, "UTF8_STRING", 0);
- if (SelTarget == None)
- SelTarget = XInternAtom(XDisplay, "STRING", 0);
- XSetSelectionOwner(XDisplay, SelType, XWindow, CurrentTime);
-
- for (XEvent e;;) {
- XNextEvent(XDisplay, &e);
- if (e.type == SelectionRequest) {
- XEvent s;
- s.xselection.type = SelectionNotify;
- s.xselection.property = e.xselectionrequest.property;
- s.xselection.requestor = e.xselectionrequest.requestor;
- s.xselection.selection = e.xselectionrequest.selection;
- s.xselection.target = e.xselectionrequest.target;
- s.xselection.time = e.xselectionrequest.time;
- Atom target = e.xselectionrequest.target;
- Atom xatargets = XInternAtom(XDisplay, "TARGETS", 0);
- Atom xastring = XInternAtom(XDisplay, "STRING", 0);
- if (target == xatargets) {
- /* respond with the supported type */
- XChangeProperty(
- XDisplay, s.xselection.requestor, s.xselection.property,
- XA_ATOM, 32, PropModeReplace,
- (unsigned char*)&SelTarget, 1);
- } else if (target == SelTarget || target == xastring) {
- XChangeProperty(
- XDisplay, s.xselection.requestor, s.xselection.property,
- SelTarget, 8, PropModeReplace,
- (unsigned char*)SelText, strlen(SelText));
- }
- XSendEvent(XDisplay, s.xselection.requestor, True, 0, &s);
- } else if (e.type == SelectionClear) {
- break; // Someone else took over. We're done here.
- }
- }
-}
-
-int main(int argc, char** argv) {
- SelText = fdgets(STDIN_FILENO);
- if (SelText) {
- if (daemonize() == 0)
- serve_selection();
- else
- die("daemonize() failed");
- }
- return 0;
-}