# Implementation Tweaks and Bug Fixes
* Should not be able to undo initial tag line text insertion
-* capture stderr of executed commands and place it in tags view
* Disallow scrolling past end of buffer
-* track down double click bug for selecting whole line
+* track down double click bug for selecting whole line
* Add tag for ctags lookup
* Implement minimal regex search (per Kernighan article)
* Implement fuzzy file/buffer/tag picker
/* Command Executions
*****************************************************************************/
-typedef struct {
- int pid; /* process id of the child process */
- int in; /* file descriptor for the child process's standard input */
- int out; /* file descriptor for the child process's standard output */
- int err; /* file descriptor for the child process's standard error */
-} Process;
-
-void detach(Process* proc);
-void terminate(Process* proc, int sig);
-char* cmdread(char** cmd);
-void cmdwrite(char** cmd, char* text);
-char* cmdwriteread(char** cmd, char* text);
+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);
/* Color Scheme Handling
*****************************************************************************/
} action;
} Tag;
-
/* Configuration
*****************************************************************************/
enum {
#define PIPE_READ 0
#define PIPE_WRITE 1
+typedef struct {
+ int pid; /* process id of the child process */
+ int in; /* file descriptor for the child process's standard input */
+ int out; /* file descriptor for the child process's standard output */
+ int err; /* file descriptor for the child process's standard error */
+} Process;
+
static int execute(char** cmd, Process* proc) {
int inpipe[2], outpipe[2], errpipe[2];
/* create the pipes */
return proc->pid;
}
-void detach(Process* proc) {
+static void detach(Process* proc) {
close(proc->in);
close(proc->out);
close(proc->err);
}
-void terminate(Process* proc, int sig) {
- detach(proc);
- kill(proc->pid, sig);
+int cmdrun(char** cmd, char** err) {
+ Process proc;
+ if (execute(cmd, &proc) < 0) {
+ perror("failed to execute");
+ return -1;
+ }
+ if (err) *err = fdgets(proc.err);
+ detach(&proc);
+ return proc.pid;
}
-char* cmdread(char** cmd) {
+char* cmdread(char** cmd, char** err) {
Process proc;
if (execute(cmd, &proc) < 0) {
perror("failed to execute");
return NULL;
}
char* str = fdgets(proc.out);
+ if (err) *err = fdgets(proc.err);
detach(&proc);
waitpid(proc.pid, NULL, 0);
return str;
}
-void cmdwrite(char** cmd, char* text) {
+void cmdwrite(char** cmd, char* text, char** err) {
Process proc;
if (execute(cmd, &proc) < 0) {
perror("failed to execute");
perror("failed to write");
return;
}
+ if (err) *err = fdgets(proc.err);
detach(&proc);
waitpid(proc.pid, NULL, 0);
}
-char* cmdwriteread(char** cmd, char* text) {
+char* cmdwriteread(char** cmd, char* text, char** err) {
Process proc;
if (execute(cmd, &proc) < 0) {
perror("failed to execute");
}
close(proc.in);
char* str = fdgets(proc.out);
+ if (err) *err = fdgets(proc.err);
detach(&proc);
waitpid(proc.pid, NULL, 0);
return str;
static void cut(void) {
char* str = view_getstr(currview(), NULL);
if (str && *str) {
- cmdwrite(CopyCmd, str);
+ cmdwrite(CopyCmd, str, NULL);
delete();
}
free(str);
static void copy(void) {
char* str = view_getstr(currview(), NULL);
if (str && *str)
- cmdwrite(CopyCmd, str);
+ cmdwrite(CopyCmd, str, NULL);
free(str);
}
static void paste(void) {
- char* str = cmdread(PasteCmd);
+ char* str = cmdread(PasteCmd, NULL);
if (str && *str)
view_putstr(currview(), str);
free(str);
}
static void open_file(void) {
- char* file = cmdread(PickFileCmd);
+ char* file = cmdread(PickFileCmd, NULL);
if (file) {
file[strlen(file)-1] = '\0';
if (!getbuf(EDIT)->path && !getbuf(EDIT)->modified) {
buf_load(getbuf(EDIT), file);
} else {
OpenCmd[1] = file;
- free(cmdread(OpenCmd));
+ free(cmdread(OpenCmd, NULL));
}
}
free(file);
free(arg);
}
+static char* chomp(char* in) {
+ return (in[strlen(in)-1] = '\0', in);
+}
static void cmd_exec(char* cmd) {
char op = '\0';
if (*cmd == '!' || *cmd == '<' || *cmd == '|' || *cmd == '>')
op = *cmd, cmd++;
ShellCmd[2] = cmd;
/* execute the command */
- char *input = NULL, *output = NULL;
+ char *input = NULL, *output = NULL, *error = NULL;
enum RegionId dest = EDIT;
input = view_getstr(getview(EDIT), NULL);
if (op == '!') {
printf("null: '%s'\n", cmd);
} else if (op == '>') {
- cmdwrite(ShellCmd, input);
+ cmdwrite(ShellCmd, input, &error);
} else if (op == '|') {
- output = cmdwriteread(ShellCmd, input);
+ output = cmdwriteread(ShellCmd, input, &error);
} else {
if (op != '<') dest = Focused;
- output = cmdread(ShellCmd);
+ output = cmdread(ShellCmd, &error);
}
+ if (error)
+ view_append(getview(TAGS), chomp(error));
if (output) {
view_putstr(getview(dest), output);
view_selprev(getview(dest));
/* cleanup */
free(input);
free(output);
+ free(error);
}
static void exec(char* cmd) {