vis

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

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

commit fb783c04ac0d472808d1984e4309325ac8059335
parent 93a14d7bea6f200d6d93decb6f9beba4d33c6e39
Author: alex <alex@cloudware.io>
Date:   Fri, 21 Feb 2020 18:12:28 +0100

sam: re-take range after pre-save hooks are run

A vis.events.FILE_SAVE_PRE callback may mutate the file text,
making the original range passed to cmd_write incorrect.

It is unclear how to realign the range after the callback
is done for the cases where an active selection in visual mode
is present or an explicit range like :1,2w! was specified.

However, this commit resolves the issue for the case where
the whole file is expected to be written.

Diffstat:
Msam.c | 16++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/sam.c b/sam.c @@ -1573,6 +1573,10 @@ static bool cmd_substitute(Vis *vis, Win *win, Command *cmd, const char *argv[], return false; } +/* cmd_write stores win->file's contents end emits pre/post events. + * If the range r covers the whole file, it is updated to account for + * potential file's text mutation by a FILE_SAVE_PRE callback. + */ static bool cmd_write(Vis *vis, Win *win, Command *cmd, const char *argv[], Selection *sel, Filerange *r) { if (!win) return false; @@ -1582,6 +1586,9 @@ static bool cmd_write(Vis *vis, Win *win, Command *cmd, const char *argv[], Sele return false; Text *text = file->text; + Filerange range_all = text_range_new(0, text_size(text)); + bool write_entire_file = text_range_equal(r, &range_all); + const char *filename = argv[1]; if (!filename) filename = file->name; @@ -1599,6 +1606,9 @@ static bool cmd_write(Vis *vis, Win *win, Command *cmd, const char *argv[], Sele vis_info_show(vis, "Rejected write to stdout by pre-save hook"); return false; } + /* a pre-save hook may have changed the text; need to re-take the range */ + if (write_entire_file) + *r = text_range_new(0, text_size(text)); bool visual = vis->mode->visual; @@ -1624,8 +1634,7 @@ static bool cmd_write(Vis *vis, Win *win, Command *cmd, const char *argv[], Sele vis_info_show(vis, "WARNING: file will be reduced to active selection"); return false; } - Filerange all = text_range_new(0, text_size(text)); - if (!text_range_equal(r, &all)) { + if (!write_entire_file) { vis_info_show(vis, "WARNING: file will be reduced to provided range"); return false; } @@ -1648,6 +1657,9 @@ static bool cmd_write(Vis *vis, Win *win, Command *cmd, const char *argv[], Sele vis_info_show(vis, "Rejected write to `%s' by pre-save hook", path); goto err; } + /* a pre-save hook may have changed the text; need to re-take the range */ + if (write_entire_file) + *r = text_range_new(0, text_size(text)); TextSave *ctx = text_save_begin(text, path, file->save_method); if (!ctx) {