From: Michael D. Lowis Date: Thu, 13 Jul 2017 01:05:18 +0000 (-0400) Subject: added logic to highlight command output upon completion X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=48efa7a50958e7ee90b57087836df44a93dd9b70;p=projs%2Ftide.git added logic to highlight command output upon completion --- diff --git a/inc/edit.h b/inc/edit.h index 01e535d..da3cbc4 100644 --- a/inc/edit.h +++ b/inc/edit.h @@ -224,12 +224,12 @@ Rune view_getrune(View* view); /* Command Executions *****************************************************************************/ -void cmdreap(void); int cmdspawn(char** cmd, int* in, int* out); int cmdrun(char** cmd, char** err); char* cmdread(char** cmd, char** err); void cmdwrite(char** cmd, char* text, char** err); char* cmdwriteread(char** cmd, char* text, char** err); +void exec_reap(void); void exec_job(char** cmd, char* data, size_t ndata, View* dest); /* Configuration Data diff --git a/lib/buf.c b/lib/buf.c index bd21118..51732b9 100644 --- a/lib/buf.c +++ b/lib/buf.c @@ -183,12 +183,12 @@ size_t buf_delete(Buf* buf, size_t beg, size_t end) { size_t buf_change(Buf* buf, size_t beg, size_t end) { /* delete the range first */ size_t off = buf_delete(buf, beg, end); - /* now create a new insert item of length 0 witht he same transaction id as + /* now create a new insert item of length 0 with the same transaction id as the delete. This will cause subsequent inserts to be coalesced into the same transaction */ Log* dellog = buf->undo; Log* inslog = (Log*)calloc(sizeof(Log), 1); - inslog->transid = dellog->transid; + inslog->transid = (dellog ? dellog->transid : buf->transid); inslog->insert = true; inslog->data.ins.beg = beg; inslog->data.ins.end = beg; diff --git a/lib/exec.c b/lib/exec.c index 488fe1c..053d56e 100644 --- a/lib/exec.c +++ b/lib/exec.c @@ -54,11 +54,6 @@ static int execute(char** cmd, Proc* proc) { return proc->pid; } -void cmdreap(void) { - while(NumChildren && (waitpid(-1, NULL, WNOHANG) > 0)) - NumChildren--; -} - int cmdspawn(char** cmd, int* in, int* out) { Proc proc; if (execute(cmd, &proc) < 0) { @@ -140,24 +135,71 @@ char* cmdwriteread(char** cmd, char* text, char** err) { typedef struct Job Job; typedef struct { - View* view; - char nbytes; - char bytes[6]; -} Recvr; + View* view; /* destination view */ + size_t count; /* number of bytes written */ +} Rcvr; struct Job { - Job* next; /* Pointer to previous job in the job list */ - Job* prev; /* Pointer to next job in the job list */ - size_t ndata; /* number of bytes to write to stdout */ - size_t nwrite; /* number of bytes written to stdout so far */ - char* data; /* data to write to stdout */ - Recvr err_recvr; /* view in which the error output will be placed */ - Recvr out_recvr; /* view in which the output will be placed */ - int pid; /* process id of the running job */ + Job* next; /* Pointer to previous job in the job list */ + Job* prev; /* Pointer to next job in the job list */ + int pid; /* process id of the running job */ + size_t ndata; /* number of bytes to write to stdout */ + size_t nwrite; /* number of bytes written to stdout so far */ + char* data; /* data to write to stdout */ + Rcvr err_rcvr; /* reciever for the error output of the job */ + Rcvr out_rcvr; /* receiver for the normal output of the job */ + View* dest; /* destination view where output will be placed */ }; static Job* JobList = NULL; +static void send_data(int fd, void* data); +static void recv_data(int fd, void* data); +static void watch_or_close(bool valid, int dir, int fd, void* data); + +void exec_reap(void) { + int pid; + while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) { + Job* job = JobList; + for (; job && job->pid != pid; job = job->next); + if (job && job->pid == pid) { + if (job->prev) { + job->prev->next = job->next; + job->next->prev = job->prev; + } else { + JobList = job->next; + } + free(job); + } + } +} + +void exec_job(char** cmd, char* data, size_t ndata, View* dest) { + Proc proc; + Job* job = calloc(1, sizeof(Job)); + job->pid = execute(cmd, &proc); + if (job->pid < 0) { + die("job_start() :"); + } else { + /* add the job to the job list */ + job->err_rcvr.view = win_view(TAGS); + job->out_rcvr.view = dest; + job->ndata = ndata; + job->nwrite = 0; + job->data = data; + job->next = JobList; + if (JobList) JobList->prev = job; + JobList = job; + /* register watch events for file descriptors */ + bool need_in = (job->data != NULL), + need_out = (dest != NULL), + need_err = (need_in || need_out); + watch_or_close(need_in, OUTPUT, proc.in, job); + watch_or_close(need_out, INPUT, proc.out, &(job->out_rcvr)); + watch_or_close(need_err, INPUT, proc.err, &(job->err_rcvr)); + } +} + static void send_data(int fd, void* data) { Job* job = data; long nwrite = write(fd, (job->data + job->nwrite), job->ndata); @@ -170,13 +212,19 @@ static void send_data(int fd, void* data) { static void recv_data(int fd, void* data) { static char buf[4096]; long i = 0, nread = read(fd, buf, sizeof(buf)); - Recvr* rcvr = data; - if (nread <= 0) { close(fd); return; } - for (; i < nread;) { - Rune r; - size_t len = 0; - while (!utf8decode(&r, &len, buf[i++])); - view_insert(rcvr->view, false, r); + Rcvr* rcvr = data; + if (nread > 0) { + for (; i < nread;) { + Rune r; + size_t len = 0; + while (!utf8decode(&r, &len, buf[i++])); + view_insert(rcvr->view, false, r); + rcvr->count++; + } + } else { + close(fd); + if (rcvr->count) + view_selprev(rcvr->view); } } @@ -187,26 +235,3 @@ static void watch_or_close(bool valid, int dir, int fd, void* data) { else close(fd); } - -void exec_job(char** cmd, char* data, size_t ndata, View* dest) { - Proc proc; - Job* job = calloc(1, sizeof(Job)); - job->pid = execute(cmd, &proc); - if (job->pid < 0) { - die("job_start() :"); - } else { - /* add the job to the job list */ - job->err_recvr.view = win_view(TAGS); - job->out_recvr.view = dest; - job->ndata = ndata; - job->nwrite = 0; - job->data = data; - job->next = JobList; - if (JobList) JobList->prev = job; - JobList = job; - /* register watch events for file descriptors */ - watch_or_close((job->data != NULL), OUTPUT, proc.in, job); - watch_or_close((dest != NULL), INPUT, proc.out, &(job->out_recvr)); - watch_or_close(true, INPUT, proc.err, &(job->err_recvr)); - } -} diff --git a/lib/win.c b/lib/win.c index e103f3f..73dd399 100644 --- a/lib/win.c +++ b/lib/win.c @@ -80,6 +80,7 @@ void win_loop(void) { x11_flip(); } x11_flush(); + exec_reap(); } x11_finish(); } diff --git a/tide.c b/tide.c index 9617ae4..60ef10d 100644 --- a/tide.c +++ b/tide.c @@ -84,18 +84,14 @@ static void cmd_exec(char* cmd) { View *tags = win_view(TAGS), *edit = win_view(EDIT), *curr = win_view(FOCUSED); /* execute the job */ - printf("sigil: '%c'\n", op); - printf("data: %d '%s'\n", len, input); - if (op == '!') { - free(input); - exec_job(execcmd, NULL, 0, NULL); - } else if (op == '>') { + if (op == '!') + free(input), exec_job(execcmd, NULL, 0, NULL); + else if (op == '>') exec_job(execcmd, input, len, tags); - } else if (op == '|' || op == ':') { + else if (op == '|' || op == ':') exec_job(execcmd, input, len, edit); - } else { + else exec_job(execcmd, input, len, (op != '<' ? curr : edit)); - } #else char op = '\0';