commit f4e4e27c77714c1187ed15c8081b837ec88a71f3
parent 1dc2cbdc25a06e5312792fa9e990cf687edd7f58
Author: Rafael Garcia <rafael.garcia.gallego@gmail.com>
Date: Sun, 5 Jun 2011 02:57:27 +0200
Grouped undos, repeat last operation.
Diffstat:
3 files changed, 53 insertions(+), 7 deletions(-)
diff --git a/TODO b/TODO
@@ -8,9 +8,8 @@ In no particular order, at sandy.c:
- BUG: Deal with the bigger-than-window line
- Improve regex search (backwards!!)
- Improve syntax highlight, multiline?
-- Groups Undos
-- Repeat operation (or last pipe at least!)
-- Clarify on undo/redo/repeat
+- Group delete undos?
+- Limit insertion undo grouping?
At config.def.h:
- Bindings!
diff --git a/config.def.h b/config.def.h
@@ -134,7 +134,7 @@ static const Key stdkeys[] = {
{ CONTROL('\\'),{ 0, 0, 0, 0 }, f_spawn, PIPE },
{ CONTROL(']'), { 0, 0, 0, 0 }, f_extsel, { .i = ExtDefault } },
{ CONTROL('^'), { t_redo,t_rw, 0, 0 }, f_undo, { .i = -1 } },
-/*{ CONTROL('^'), { t_rw, 0, 0, 0 }, f_undo, { .i = 0 } }, */ /* TODO: repeat, implement */
+{ CONTROL('^'), { t_rw, 0, 0, 0 }, f_repeat, { 0 } },
{ CONTROL('_'), { t_undo,t_rw, 0, 0 }, f_undo, { .i = 1 } },
{ CONTROL('?'), { t_sel, t_rw, 0, 0 }, f_pipe, TOCLIP },
{ CONTROL('?'), { t_rw, 0, 0, 0 }, f_delete, { .m = m_prevchar } },
diff --git a/sandy.c b/sandy.c
@@ -109,7 +109,7 @@ enum { DefBG, CurBG, SelBG, /* Warning: BGs MUST have a matching FG */ LastB
enum { ExtDefault, ExtWord, ExtLines, ExtAll, };
/* To use in lastaction */
-enum { LastNone, LastDelete, LastInsert, LastPipe, };
+enum { LastNone, LastDelete, LastInsert, LastPipe, LastPipeRO, };
/* Environment variables index */
enum { EnvFind, EnvPipe, EnvLine, EnvOffset, EnvFile, EnvSyntax, EnvFifo, EnvLast, };
@@ -187,6 +187,7 @@ static void f_offset(const Arg*);
static void f_pipe(const Arg*);
static void f_pipelines(const Arg*);
static void f_pipero(const Arg*);
+static void f_repeat(const Arg*);
static void f_save(const Arg*);
static void f_select(const Arg*);
static void f_spawn(const Arg*);
@@ -198,6 +199,7 @@ static void f_warn(const Arg *arg);
/* i_* funcions are called from inside the main code only */
static Filepos i_addtext(char*, Filepos);
+static void i_addtoundo(Filepos, const char*);
static void i_addundo(bool, Filepos, Filepos, char*);
static void i_advpos(Filepos *pos, int o);
static void i_calcvlen(Line *l);
@@ -284,6 +286,7 @@ f_delete(const Arg *arg) {
fcur=fsel=pos0;
statusflags|=S_Modified;
statusflags&=~S_Selecting;
+ lastaction=LastDelete;
}
void /* Extend the selection as per arg->i (see enums above) */
@@ -333,11 +336,15 @@ f_insert(const Arg *arg) {
undos->flags^=RedoMore;
}
fsel=i_addtext((char*)arg->v, fcur);
- i_addundo(TRUE, fcur, fsel, i_strdup(arg->v));
+ if(!killsel && undos && (undos->flags & UndoIns) && fcur.o == undos->endo && undos->endl == i_lineno(fcur.l)) {
+ i_addtoundo(fsel, arg->v);
+ } else
+ i_addundo(TRUE, fcur, fsel, i_strdup(arg->v));
if(killsel) undos->flags^=UndoMore;
fcur=fsel;
statusflags|=S_Modified;
statusflags&=~S_Selecting;
+ lastaction=LastInsert;
}
void /* Go to atoi(arg->v) line */
@@ -374,6 +381,7 @@ void /* Pipe selection through arg->v external command. Your responsibility: cal
f_pipe(const Arg *arg) {
i_pipetext(arg->v);
statusflags|=S_Modified;
+ lastaction=LastPipe;
}
void /* Pipe full lines including the selection through arg->v external command. Your responsibility: call only if t_rw() */
@@ -381,6 +389,7 @@ f_pipelines(const Arg *arg) {
f_extsel(&(const Arg){ .i = ExtLines });
i_pipetext(arg->v);
statusflags|=S_Modified;
+ lastaction=LastPipe;
}
void /* Pipe selection through arg->v external command but do not update text on screen */
@@ -390,6 +399,32 @@ f_pipero(const Arg *arg) {
statusflags|=S_Readonly;
i_pipetext(arg->v);
statusflags=oldsf&(~S_Selecting);
+ lastaction=LastPipeRO;
+}
+
+void /* Repeat the last action */
+f_repeat(const Arg *arg) {
+ Filepos pos;
+ i_sortpos(&fsel, &fcur);
+ switch(lastaction) {
+ case LastDelete:
+ if(t_sel()) f_delete(&(const Arg){ .m = m_tosel });
+ break;
+ case LastInsert:
+ if(undos && undos->flags & UndoIns) {
+ pos=fsel;
+ f_insert(&(const Arg){ .v = undos->str });
+ fsel=pos;
+ }
+ break;
+ case LastPipe:
+ f_pipe(&(const Arg) { .v = getenv(envs[EnvPipe]) });
+ break;
+ case LastPipeRO:
+ f_pipero(&(const Arg) { .v = getenv(envs[EnvPipe]) });
+ break;
+ }
+ statusflags&=~S_Selecting;
}
void /* Save file with arg->v filename, same if NULL. Your responsibility: call only if t_mod() */
@@ -530,7 +565,19 @@ f_warn(const Arg *arg) {
/* I_* FUNCTIONS
Called internally from the program code */
-void /* Add undo information to the undo ring */
+void /* Add information to the last undo in the ring */
+i_addtoundo(Filepos newend, const char *s) {
+ int oldsiz, newsiz;
+
+ oldsiz=strlen(undos->str), newsiz=strlen(s);
+ undos->endl=i_lineno(newend.l);
+ undos->endo=newend.o;
+ if((undos->str=(char*)realloc(undos->str, 1+oldsiz+newsiz)) == NULL)
+ i_die("Can't malloc.\n");
+ strncat(undos->str, s, newsiz);
+}
+
+void /* Add new undo information to the undo ring */
i_addundo(bool ins, Filepos start, Filepos end, char *s) {
Undo *u;