vis

a vi-like editor based on Plan 9's structural regular expressions

git clone https://9o.is/git/vis.git

commit 8d395ba4f4a762b8fc910fd4c78b455f7aa9017f
parent 57b71a697df3db5338b8c1079fc5f75f65db9553
Author: Marc André Tanner <mat@brain-dump.org>
Date:   Tue, 22 Nov 2016 00:15:32 +0100

vis-lua: introduce pre-save hook

The first argument is the file object while the second argument denotes
the full path to which it will be written. Path might be `nil` if the
file is going to be written to stdout.

The Lua function is expected to return a boolean value indicating whether
the write operation should proceed or be aborted.

Diffstat:
MREADME.md | 1+
Mmain.c | 1+
Msam.c | 5+++++
Mvis-core.h | 1+
Mvis-lua.c | 18++++++++++++++++++
Mvis-lua.h | 1+
Mvis.c | 4++++
Mvis.h | 1+
8 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/README.md b/README.md @@ -590,6 +590,7 @@ At this time there exists no API stability guarantees. - `start()` - `quit()` - `file_open(file)` + - `file_save_pre(file, path)` triggered *before* an attempted write to `path` boolean return value determines whether write will be proceeded - `file_save_post(file, path)` triggered *after* a successfull write to `path` - `file_close(file)` - `win_open(win)` diff --git a/main.c b/main.c @@ -2203,6 +2203,7 @@ int main(int argc, char *argv[]) { .vis_start = vis_lua_start, .vis_quit = vis_lua_quit, .file_open = vis_lua_file_open, + .file_save_pre = vis_lua_file_save_pre, .file_save_post = vis_lua_file_save_post, .file_close = vis_lua_file_close, .win_open = vis_lua_win_open, diff --git a/sam.c b/sam.c @@ -1295,6 +1295,11 @@ static bool cmd_write(Vis *vis, Win *win, Command *cmd, const char *argv[], Curs return false; } + if (!vis_event_emit(vis, VIS_EVENT_FILE_SAVE_PRE, file, *name) && cmd->flags != '!') { + vis_info_show(vis, "Rejected write to `%s' by pre-save hook", *name); + return false; + } + TextSave *ctx = text_save_begin(text, *name); if (!ctx) { vis_info_show(vis, "Can't write `%s': %s", *name, strerror(errno)); diff --git a/vis-core.h b/vis-core.h @@ -191,6 +191,7 @@ enum VisEvents { VIS_EVENT_START, VIS_EVENT_QUIT, VIS_EVENT_FILE_OPEN, + VIS_EVENT_FILE_SAVE_PRE, VIS_EVENT_FILE_SAVE_POST, VIS_EVENT_FILE_CLOSE, VIS_EVENT_WIN_OPEN, diff --git a/vis-lua.c b/vis-lua.c @@ -128,6 +128,7 @@ void vis_lua_init(Vis *vis) { } void vis_lua_start(Vis *vis) { } void vis_lua_quit(Vis *vis) { } void vis_lua_file_open(Vis *vis, File *file) { } +bool vis_lua_file_save_pre(Vis *vis, File *file, const char *path) { return true; } void vis_lua_file_save_post(Vis *vis, File *file, const char *path) { } void vis_lua_file_close(Vis *vis, File *file) { } void vis_lua_win_open(Vis *vis, Win *win) { } @@ -1544,6 +1545,23 @@ void vis_lua_file_open(Vis *vis, File *file) { lua_pop(L, 1); } +bool vis_lua_file_save_pre(Vis *vis, File *file, const char *path) { + lua_State *L = vis->lua; + vis_lua_event_get(L, "file_save_pre"); + if (lua_isfunction(L, -1)) { + obj_ref_new(L, file, "vis.file"); + if (path) + lua_pushstring(L, path); + else + lua_pushnil(L); + if (pcall(vis, L, 2, 1) != 0) + return false; + return lua_toboolean(L, -1); + } + lua_pop(L, 1); + return true; +} + void vis_lua_file_save_post(Vis *vis, File *file, const char *path) { lua_State *L = vis->lua; vis_lua_event_get(L, "file_save_post"); diff --git a/vis-lua.h b/vis-lua.h @@ -23,6 +23,7 @@ void vis_lua_init(Vis*); void vis_lua_start(Vis*); void vis_lua_quit(Vis*); void vis_lua_file_open(Vis*, File*); +bool vis_lua_file_save_pre(Vis*, File*, const char *path); void vis_lua_file_save_post(Vis*, File*, const char *path); void vis_lua_file_close(Vis*, File*); void vis_lua_win_open(Vis*, Win*); diff --git a/vis.c b/vis.c @@ -58,6 +58,7 @@ bool vis_event_emit(Vis *vis, enum VisEvents id, ...) { vis->event->vis_start(vis); break; case VIS_EVENT_FILE_OPEN: + case VIS_EVENT_FILE_SAVE_PRE: case VIS_EVENT_FILE_SAVE_POST: case VIS_EVENT_FILE_CLOSE: { @@ -66,6 +67,9 @@ bool vis_event_emit(Vis *vis, enum VisEvents id, ...) { break; if (id == VIS_EVENT_FILE_OPEN && vis->event->file_open) { vis->event->file_open(vis, file); + } else if (id == VIS_EVENT_FILE_SAVE_PRE && vis->event->file_save_pre) { + const char *path = va_arg(ap, const char*); + ret = vis->event->file_save_pre(vis, file, path); } else if (id == VIS_EVENT_FILE_SAVE_POST && vis->event->file_save_post) { const char *path = va_arg(ap, const char*); vis->event->file_save_post(vis, file, path); diff --git a/vis.h b/vis.h @@ -32,6 +32,7 @@ typedef struct { void (*vis_start)(Vis*); void (*vis_quit)(Vis*); void (*file_open)(Vis*, File*); + bool (*file_save_pre)(Vis*, File*, const char *path); void (*file_save_post)(Vis*, File*, const char *path); void (*file_close)(Vis*, File*); void (*win_open)(Vis*, Win*);