aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2014-10-17 15:43:48 +0200
committerMarc André Tanner <mat@brain-dump.org>2014-10-17 15:43:48 +0200
commite9180cf83ade29192d8407337f614e5a024017a9 (patch)
tree0aa207c91d5bdb999a260ba54de015916dfbea5b
parent6be820495d70e6f10a92fbdaf6a1e4a278b02ab6 (diff)
downloadvis-e9180cf83ade29192d8407337f614e5a024017a9.tar.gz
vis-e9180cf83ade29192d8407337f614e5a024017a9.tar.xz
Make editor usable as a filter: echo foo | vis - | cat
The terminal output is by default redirected to stderr, making stdout available for communications purposes. If a file is "opened" from stdin (i.e. vis is given '-' as argument) and a subsequent write without a filename is performed as in ":wq" the output is written to stdout.
-rw-r--r--config.def.h2
-rw-r--r--text.c32
-rw-r--r--text.h6
-rw-r--r--vis.c26
4 files changed, 53 insertions, 13 deletions
diff --git a/config.def.h b/config.def.h
index 9ecb018..9cd686a 100644
--- a/config.def.h
+++ b/config.def.h
@@ -1,5 +1,5 @@
/** start by reading from the top of vis.c up until config.h is included */
-
+#define DEFAULT_TERM "xterm" /* default term to use if $TERM isn't set */
/* macros used to specify keys for key bindings */
#define ESC 0x1B
#define NONE(k) { .str = { k }, .code = 0 }
diff --git a/text.c b/text.c
index 7757e70..235c98c 100644
--- a/text.c
+++ b/text.c
@@ -645,12 +645,36 @@ err:
return -1;
}
+ssize_t text_write(Text *txt, int fd) {
+ ssize_t len = 0;
+ text_iterate(txt, it, 0) {
+ size_t plen = it.end - it.start, poff = 0;
+ while (plen > 0) {
+ ssize_t res = write(fd, it.start + poff, plen);
+ if (res < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ return -1;
+ }
+ if (res == 0)
+ break;
+ poff += res;
+ plen -= res;
+ }
+ len += plen;
+ }
+ txt->saved_action = txt->undo;
+ text_snapshot(txt);
+ return len;
+}
+
/* load the given file as starting point for further editing operations.
* to start with an empty document, pass NULL as filename. */
Text *text_load(const char *filename) {
Text *txt = calloc(1, sizeof(Text));
if (!txt)
return NULL;
+ txt->fd = -1;
txt->begin.index = 1;
txt->end.index = 2;
txt->piece_count = 2;
@@ -686,8 +710,10 @@ Text *text_load(const char *filename) {
}
return txt;
out:
- if (txt->fd > 2)
+ if (txt->fd > 2) {
close(txt->fd);
+ txt->fd = -1;
+ }
text_free(txt);
return NULL;
}
@@ -1124,6 +1150,10 @@ void text_mark_clear_all(Text *txt) {
text_mark_clear(txt, mark);
}
+int text_fd_get(Text *txt) {
+ return txt->fd;
+}
+
const char *text_filename_get(Text *txt) {
return txt->filename;
}
diff --git a/text.h b/text.h
index 34e350d..44c9f69 100644
--- a/text.h
+++ b/text.h
@@ -2,7 +2,7 @@
#define TEXT_H
#include <stdbool.h>
-#include <stddef.h>
+#include <sys/types.h>
#define EPOS ((size_t)-1) /* invalid position */
@@ -34,6 +34,9 @@ typedef struct {
Text *text_load(const char *file);
Text *text_load_fd(int fd);
+/* return the fd from which this text was loaded or -1 if it was
+ * loaded from a filename */
+int text_fd_get(Text*);
/* the filename from which this text was loaded or first saved to */
const char *text_filename_get(Text*);
/* associate a filename with the yet unnamed buffer */
@@ -82,6 +85,7 @@ bool text_modified(Text*);
/* test whether the underlying file uses UNIX style \n or Windows style \r\n newlines */
bool text_newlines_crnl(Text*);
int text_save(Text*, const char *file);
+ssize_t text_write(Text*, int fd);
void text_free(Text*);
typedef struct Regex Regex;
diff --git a/vis.c b/vis.c
index 9054ccc..554b4f7 100644
--- a/vis.c
+++ b/vis.c
@@ -1416,6 +1416,8 @@ static bool cmd_write(const char *argv[]) {
if (!argv[1])
argv[1] = text_filename_get(text);
if (!argv[1]) {
+ if (text_fd_get(text) == STDIN_FILENO)
+ return text_write(text, STDOUT_FILENO) >= 0;
editor_info_show(vis, "Filename expected");
return false;
}
@@ -1490,6 +1492,15 @@ static struct Screen {
bool need_resize;
} screen = { .need_resize = true };
+static void die(const char *errstr, ...) {
+ va_list ap;
+ endwin();
+ va_start(ap, errstr);
+ vfprintf(stderr, errstr, ap);
+ va_end(ap);
+ exit(EXIT_FAILURE);
+}
+
static void sigwinch_handler(int sig) {
screen.need_resize = true;
}
@@ -1513,7 +1524,11 @@ static void setup() {
setlocale(LC_CTYPE, "");
if (!getenv("ESCDELAY"))
set_escdelay(50);
- initscr();
+ char *term = getenv("TERM");
+ if (!term)
+ term = DEFAULT_TERM;
+ if (!newterm(term, stderr, stdin) == ERR)
+ die("Can not initialize terminal\n");
start_color();
raw();
noecho();
@@ -1574,15 +1589,6 @@ static Key getkey(void) {
return key;
}
-static void die(const char *errstr, ...) {
- va_list ap;
- endwin();
- va_start(ap, errstr);
- vfprintf(stderr, errstr, ap);
- va_end(ap);
- exit(EXIT_FAILURE);
-}
-
static void mainloop() {
struct timeval idle = { .tv_usec = 0 }, *timeout = NULL;
Key key, key_prev, *key_mod = NULL;