commit 7506d2b23b4acd57fd074db5b758070dbc3392de
parent 7e4948cb916bb9da2ff8803f243460c8e475fabd
Author: Dimitris Zervas <dzervas@dzervas.gr>
Date: Fri, 11 Jul 2014 13:38:21 +0300
Added visual mode
Diffstat:
config.h | | | 66 | ++++++++++++++++++++++++++++++------------------------------------ |
sandy.c | | | 18 | ++++++++++++++---- |
2 files changed, 44 insertions(+), 40 deletions(-)
diff --git a/config.h b/config.h
@@ -23,7 +23,6 @@ static const char nlstr[1] = { 0 };
#endif
/* Helper config functions, not used in main code */
-static void f_moveboth(const Arg*);
static void f_pipeai(const Arg*);
static void f_pipeline(const Arg*);
static void f_pipenull(const Arg*);
@@ -74,31 +73,31 @@ static void f_pipenull(const Arg*);
static const Key curskeys[] = { /* Plain keys here, no CONTROL or META */
/* keyv.i, tests, func, arg */
{ .keyv.i = KEY_BACKSPACE, { t_rw, t_nocomm,0,0 }, f_delete, { .m = m_prevchar } },
-{ .keyv.i = KEY_BACKSPACE, { 0, 0, 0, 0 }, f_moveboth, { .m = m_prevchar } },
+{ .keyv.i = KEY_BACKSPACE, { 0, 0, 0, 0 }, f_move, { .m = m_prevchar } },
{ .keyv.i = KEY_DC, { t_sel, t_rw, 0, 0 }, f_delete, { .m = m_tosel } },
{ .keyv.i = KEY_DC, { t_rw, 0, 0, 0 }, f_delete, { .m = m_nextchar } },
{ .keyv.i = KEY_SDC, { t_sel, t_rw, 0, 0 }, f_delete, { .m = m_tosel } },
{ .keyv.i = KEY_SDC, { t_rw, 0, 0, 0 }, f_delete, { .m = m_nextchar } },
{ .keyv.i = KEY_IC, { t_sel, 0, 0, 0 }, f_pipero, { .v = TOCLIP } },
{ .keyv.i = KEY_SIC, { t_rw, 0, 0, 0 }, f_pipenull, { .v = FROMCLIP } },
-{ .keyv.i = KEY_HOME, { t_ai, 0, 0, 0 }, f_moveboth, { .m = m_smartbol } },
-{ .keyv.i = KEY_HOME, { 0, 0, 0, 0 }, f_moveboth, { .m = m_bol } },
-{ .keyv.i = KEY_END, { 0, 0, 0, 0 }, f_moveboth, { .m = m_eol } },
-{ .keyv.i = KEY_SHOME, { 0, 0, 0, 0 }, f_moveboth, { .m = m_bof } },
-{ .keyv.i = KEY_SEND, { 0, 0, 0, 0 }, f_moveboth, { .m = m_eof } },
-{ .keyv.i = KEY_PPAGE, { 0, 0, 0, 0 }, f_moveboth, { .m = m_prevscr } },
-{ .keyv.i = KEY_NPAGE, { 0, 0, 0, 0 }, f_moveboth, { .m = m_nextscr } },
+{ .keyv.i = KEY_HOME, { t_ai, 0, 0, 0 }, f_move, { .m = m_smartbol } },
+{ .keyv.i = KEY_HOME, { 0, 0, 0, 0 }, f_move, { .m = m_bol } },
+{ .keyv.i = KEY_END, { 0, 0, 0, 0 }, f_move, { .m = m_eol } },
+{ .keyv.i = KEY_SHOME, { 0, 0, 0, 0 }, f_move, { .m = m_bof } },
+{ .keyv.i = KEY_SEND, { 0, 0, 0, 0 }, f_move, { .m = m_eof } },
+{ .keyv.i = KEY_PPAGE, { 0, 0, 0, 0 }, f_move, { .m = m_prevscr } },
+{ .keyv.i = KEY_NPAGE, { 0, 0, 0, 0 }, f_move, { .m = m_nextscr } },
{ .keyv.i = KEY_UP, { t_sent,0, 0, 0 }, f_adjective, { .m = m_prevline } },
-{ .keyv.i = KEY_UP, { 0, 0, 0, 0 }, f_moveboth, { .m = m_prevline } },
+{ .keyv.i = KEY_UP, { 0, 0, 0, 0 }, f_move, { .m = m_prevline } },
// FIXME: Does not actually act to next line
{ .keyv.i = KEY_DOWN, { t_sent,0, 0, 0 }, f_adjective, { .m = m_nextline } },
-{ .keyv.i = KEY_DOWN, { 0, 0, 0, 0 }, f_moveboth, { .m = m_nextline } },
+{ .keyv.i = KEY_DOWN, { 0, 0, 0, 0 }, f_move, { .m = m_nextline } },
{ .keyv.i = KEY_LEFT, { t_sent,0, 0, 0 }, f_adjective, { .m = m_prevchar } },
-{ .keyv.i = KEY_LEFT, { 0, 0, 0, 0 }, f_moveboth, { .m = m_prevchar } },
+{ .keyv.i = KEY_LEFT, { 0, 0, 0, 0 }, f_move, { .m = m_prevchar } },
{ .keyv.i = KEY_RIGHT, { t_sent,0, 0, 0 }, f_adjective, { .m = m_nextchar } },
-{ .keyv.i = KEY_RIGHT, { 0, 0, 0, 0 }, f_moveboth, { .m = m_nextchar } },
-{ .keyv.i = KEY_SLEFT, { 0, 0, 0, 0 }, f_moveboth, { .m = m_prevword } },
-{ .keyv.i = KEY_SRIGHT, { 0, 0, 0, 0 }, f_moveboth, { .m = m_nextword } },
+{ .keyv.i = KEY_RIGHT, { 0, 0, 0, 0 }, f_move, { .m = m_nextchar } },
+{ .keyv.i = KEY_SLEFT, { 0, 0, 0, 0 }, f_move, { .m = m_prevword } },
+{ .keyv.i = KEY_SRIGHT, { 0, 0, 0, 0 }, f_move, { .m = m_nextword } },
};
static const Key stdkeys[] = {
@@ -118,7 +117,7 @@ static const Key stdkeys[] = {
{ .keyv.c = CONTROL('I'), { t_rw, t_nocomm,0,0 }, f_insert, { .v = "\t" } },
{ .keyv.c = CONTROL('J'), { t_rw, t_ai, 0, 0 }, f_pipeai, { .v = AUTOINDENT } },
{ .keyv.c = CONTROL('J'), { t_rw, t_nocomm,0,0 }, f_insert, { .v = "\n" } },
-{ .keyv.c = CONTROL('J'), { 0, 0, 0, 0 }, f_moveboth, { .m = m_nextline } },
+{ .keyv.c = CONTROL('J'), { 0, 0, 0, 0 }, f_move, { .m = m_nextline } },
{ .keyv.c = CONTROL('K'), { t_eol, t_rw, 0, 0 }, f_delete, { .m = m_nextchar } },
{ .keyv.c = CONTROL('K'), { t_rw, 0, 0, 0 }, f_delete, { .m = m_eol } },
{ .keyv.c = CONTROL('L'), { 0, 0, 0, 0 }, f_center, { 0 } },
@@ -141,8 +140,9 @@ static const Key stdkeys[] = {
{ .keyv.c = CONTROL('V'), { 0, 0, 0, 0 }, f_move, { .m = m_prevscr } },
{ .keyv.c = META('v'), { 0, 0, 0, 0 }, f_move, { .m = m_nextscr } },
{ .keyv.c = CONTROL('W'), { t_rw, 0, 0, 0 }, f_delete, { .m = m_prevword } },
-{ .keyv.c = CONTROL('Z'), { 0 ,0, 0, 0 }, f_suspend, { 0 } },
+{ .keyv.c = CONTROL('Z'), { 0, 0, 0, 0 }, f_suspend, { 0 } },
#if VIM_BINDINGS
+{ .keyv.c = CONTROL('['), { t_vis, 0, 0, 0 }, f_toggle, { .i = S_Visual } },
{ .keyv.c = CONTROL('['), { t_nocomm,0, 0, 0 }, f_toggle, { .i = S_Command } },
#endif
//{ .keyv.c = CONTROL('['), { 0, 0, 0, 0 }, 0, { 0 } },
@@ -165,30 +165,30 @@ static const Key commkeys[] = { /* Command mode keys here */
/* keyv.c, tests, func, arg */
{ .keyv.c = { '$' }, { t_sent,0, 0, 0 }, f_adjective, { .m = m_eol } },
{ .keyv.c = { '^' }, { t_sent,0, 0, 0 }, f_adjective, { .m = m_bol } },
-{ .keyv.c = { 'a' }, { 0, 0, 0, 0 }, f_moveboth, { .m = m_nextchar } },
+{ .keyv.c = { 'a' }, { 0, 0, 0, 0 }, f_move, { .m = m_nextchar } },
{ .keyv.c = { 'a' }, { 0, 0, 0, 0 }, f_toggle, { .i = S_Command } },
{ .keyv.c = { 'b' }, { t_sent,0, 0, 0 }, f_adjective, { .m = m_prevword } },
-{ .keyv.c = { 'b' }, { 0, 0, 0, 0 }, f_moveboth, { .m = m_prevword } },
+{ .keyv.c = { 'b' }, { 0, 0, 0, 0 }, f_move, { .m = m_prevword } },
{ .keyv.c = { 'c' }, { t_rw, 0, 0, 0 }, f_delete, { .i = 0 } },
{ .keyv.c = { 'd' }, { t_rw, 0, 0, 0 }, f_delete, { .i = 0 } },
-{ .keyv.c = { 'g' }, { 0, 0, 0, 0 }, f_moveboth, { .m = m_bof } },
-{ .keyv.c = { 'G' }, { 0, 0, 0, 0 }, f_moveboth, { .m = m_eof } },
+{ .keyv.c = { 'g' }, { 0, 0, 0, 0 }, f_move, { .m = m_bof } },
+{ .keyv.c = { 'G' }, { 0, 0, 0, 0 }, f_move, { .m = m_eof } },
{ .keyv.c = { 'h' }, { t_sent,0, 0, 0 }, f_adjective, { .m = m_prevchar } },
-{ .keyv.c = { 'h' }, { 0, 0, 0, 0 }, f_moveboth, { .m = m_prevchar } },
+{ .keyv.c = { 'h' }, { 0, 0, 0, 0 }, f_move, { .m = m_prevchar } },
{ .keyv.c = { 'i' }, { 0, 0, 0, 0 }, f_toggle, { .i = S_Command } },
{ .keyv.c = { 'j' }, { t_sent,0, 0, 0 }, f_adjective, { .m = m_nextline } },
-{ .keyv.c = { 'j' }, { 0, 0, 0, 0 }, f_moveboth, { .m = m_nextline } },
+{ .keyv.c = { 'j' }, { 0, 0, 0, 0 }, f_move, { .m = m_nextline } },
{ .keyv.c = { 'k' }, { t_sent,0, 0, 0 }, f_adjective, { .m = m_prevline } },
-{ .keyv.c = { 'k' }, { 0, 0, 0, 0 }, f_moveboth, { .m = m_prevline } },
+{ .keyv.c = { 'k' }, { 0, 0, 0, 0 }, f_move, { .m = m_prevline } },
{ .keyv.c = { 'l' }, { t_sent,0, 0, 0 }, f_adjective, { .m = m_nextchar } },
-{ .keyv.c = { 'l' }, { 0, 0, 0, 0 }, f_moveboth, { .m = m_nextchar } },
+{ .keyv.c = { 'l' }, { 0, 0, 0, 0 }, f_move, { .m = m_nextchar } },
{ .keyv.c = { 'm' }, { 0, 0, 0, 0 }, f_mark, { 0 } },
{ .keyv.c = { 'n' }, { t_sel, 0, 0, 0 }, f_findfw, { 0 } },
{ .keyv.c = { 'N' }, { t_sel, 0, 0, 0 }, f_findbw, { 0 } },
-{ .keyv.c = { 'o' }, { t_rw, 0, 0, 0 }, f_moveboth, { .m = m_eol } },
+{ .keyv.c = { 'o' }, { t_rw, 0, 0, 0 }, f_move, { .m = m_eol } },
{ .keyv.c = { 'o' }, { t_rw, 0, 0, 0 }, f_insert, { .v = "\n" } },
{ .keyv.c = { 'o' }, { t_rw, 0, 0, 0 }, f_toggle, { .i = S_Command } },
-{ .keyv.c = { 'O' }, { t_rw, 0, 0, 0 }, f_moveboth, { .m = m_bol } },
+{ .keyv.c = { 'O' }, { t_rw, 0, 0, 0 }, f_move, { .m = m_bol } },
{ .keyv.c = { 'O' }, { t_rw, 0, 0, 0 }, f_insert, { .v = "\n" } },
{ .keyv.c = { 'O' }, { t_rw, 0, 0, 0 }, f_toggle, { .i = S_Command } },
{ .keyv.c = { 'p' }, { t_rw, 0, 0, 0 }, f_pipenull, { .v = FROMCLIP } },
@@ -197,8 +197,9 @@ static const Key commkeys[] = { /* Command mode keys here */
{ .keyv.c = { 's' }, { t_rw, 0, 0, 0 }, f_delete, { .m = m_nextchar } },
{ .keyv.c = { 's' }, { t_rw, 0, 0, 0 }, f_toggle, { .i = S_Command } },
{ .keyv.c = { 'u' }, { t_undo,t_rw, 0, 0 }, f_undo, { .i = 1 } },
+{ .keyv.c = { 'v' }, { 0, 0, 0, 0 }, f_toggle, { .i = S_Visual } },
{ .keyv.c = { 'w' }, { t_sent,0, 0, 0 }, f_adjective, { .m = m_nextword } },
-{ .keyv.c = { 'w' }, { 0, 0, 0, 0 }, f_moveboth, { .m = m_nextword } },
+{ .keyv.c = { 'w' }, { 0, 0, 0, 0 }, f_move, { .m = m_nextword } },
{ .keyv.c = { 'x' }, { t_sel, t_rw, 0, 0 }, f_delete, { .m = m_tosel } },
{ .keyv.c = { 'x' }, { t_rw, 0, 0, 0 }, f_delete, { .m = m_nextchar } },
{ .keyv.c = { 'X' }, { t_sel, t_rw, 0, 0 }, f_delete, { .m = m_tosel } },
@@ -209,14 +210,12 @@ static const Key commkeys[] = { /* Command mode keys here */
{ .keyv.c = { '\'' }, { 0, 0, 0, 0 }, f_move, { .m = m_tomark } },
{ .keyv.c = { '.' }, { t_rw, 0, 0, 0 }, f_repeat, { 0 } },
{ .keyv.c = { '/' }, { 0, 0, 0, 0 }, f_spawn, FIND },
-{ .keyv.c = { ' ' }, { 0, 0, 0, 0 }, f_moveboth, { .m = m_nextchar } },
+{ .keyv.c = { ' ' }, { 0, 0, 0, 0 }, f_move, { .m = m_nextchar } },
/* TODO: Keybindings left:
- * q record macro (?)
* e/E go to the end of the word (adj) (?)
* r replace char (verb)
* t/T do until char (adj)
* i do inside (adj) (ex. diw deletes current word)
- * {/} start/end of paragraph (?)
* v visual mode. may not be implemented.
* </> ident
*/
@@ -399,11 +398,6 @@ static const short bgcolors[LastBG] = {
};
/* Helper config functions implementation */
-void /* Move both cursor and selection point, thus cancelling the selection */
-f_moveboth(const Arg *arg) {
- fsel=fcur=arg->m(fcur);
-}
-
void /* Pipe selection from bol, then select last line only, special for autoindenting */
f_pipeai(const Arg *arg) {
i_sortpos(&fsel, &fcur);
diff --git a/sandy.c b/sandy.c
@@ -141,6 +141,7 @@ enum { /* To use in statusflags */
S_Sentence = 1<<13, /* Sentence mode. Pass the next command's parameters (if adjective) to the verb's function */
S_Parameter = 1<<14, /* Parameter mode. Pass the next character as parameter to the function of the command */
S_Multiply = 1<<15, /* Multiply mode. Replay a command x times */
+ S_Visual = 1<<16, /* Visual mode. You just select things */
};
enum { /* To use in Undo.flags */
@@ -259,6 +260,7 @@ static bool t_redo(void);
static bool t_sel(void);
static bool t_sent(void);
static bool t_undo(void);
+static bool t_vis(void);
static bool t_warn(void);
/* m_ functions represent a cursor movement and can be passed in an Arg */
@@ -392,6 +394,7 @@ f_mark(const Arg *arg) {
void /* Move cursor and extend/shrink selection as per arg->m */
f_move(const Arg *arg) {
fcur=arg->m(fcur);
+ if(!t_vis()) fsel=fcur;
}
void /* Got to atoi(arg->v) position in the current line */
@@ -1556,10 +1559,12 @@ i_update(void) {
statusflags&=~S_Warned; /* Reset warning */
snprintf(buf, 4, "%ld%%", (100*ncur)/nlst);
#if VIM_BINDINGS
- snprintf(title, BUFSIZ, "%s %s [%s]%s%s%s%s %ld,%d %s %s",
- (statusflags&S_Command?"Command":"Insert"),
+ snprintf(title, BUFSIZ, "%s %s [%s]%s%s%s%s %ld,%d %s",
+ t_vis()?
+ "Visual":
+ (t_nocomm()?"Insert":"Command"),
#else
- snprintf(title, BUFSIZ, "%s [%s]%s%s%s%s %ld,%d %s %s",
+ snprintf(title, BUFSIZ, "%s [%s]%s%s%s%s %ld,%d %s",
#endif
(statusflags&S_DumpStdout?"<Stdout>":(filename == NULL?"<No file>":filename)),
(syntx>=0 ? syntaxes[syntx].name : "none"),
@@ -1571,7 +1576,7 @@ i_update(void) {
(scrline==fstline?
(nlst<lines3?"All":"Top"):
(nlst-nscr<lines3?"Bot":buf)
- ), (statusflags&S_Sentence?"s":""));
+ ));
}
if(titlewin) {
int i;
@@ -1846,6 +1851,11 @@ t_undo(void) {
return (undos != NULL);
}
+bool /* TRUE if we are in visual mode */
+t_vis(void) {
+ return (statusflags & S_Visual);
+}
+
bool /* TRUE if we have warned the file is modified */
t_warn(void) {
return (statusflags & S_Warned);