aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2014-09-24 10:23:51 +0200
committerMarc André Tanner <mat@brain-dump.org>2014-09-24 10:39:05 +0200
commit1b1cedc6666d99f6e9886439dca93278c47d131c (patch)
tree937b472f5e5f6323188c202b192836603dcfd65c
parent0c581075c55fe3c7839fdc293282a9544280bfab (diff)
downloadvis-1b1cedc6666d99f6e9886439dca93278c47d131c.tar.gz
vis-1b1cedc6666d99f6e9886439dca93278c47d131c.tar.xz
Implement 'gU' and 'gu'
This obviously only works for ascii characters.
-rw-r--r--config.def.h2
-rw-r--r--vis.c33
2 files changed, 35 insertions, 0 deletions
diff --git a/config.def.h b/config.def.h
index 993f2a0..ba0c290 100644
--- a/config.def.h
+++ b/config.def.h
@@ -204,6 +204,8 @@ static KeyBinding vis_operators[] = {
{ { NONE('P') }, put, { .i = -1 } },
{ { NONE('>') }, operator, { .i = OP_SHIFT_RIGHT } },
{ { NONE('<') }, operator, { .i = OP_SHIFT_LEFT } },
+ { { NONE('g'), NONE('U') }, changecase, { .i = +1 } },
+ { { NONE('g'), NONE('u') }, changecase, { .i = -1 } },
{ /* empty last element, array terminator */ },
};
diff --git a/vis.c b/vis.c
index a04b6f7..2df6f7d 100644
--- a/vis.c
+++ b/vis.c
@@ -25,6 +25,7 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
+#include <ctype.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -158,6 +159,7 @@ static void op_put(OperatorContext *c);
static void op_delete(OperatorContext *c);
static void op_shift_right(OperatorContext *c);
static void op_shift_left(OperatorContext *c);
+static void op_case_change(OperatorContext *c);
/* these can be passed as int argument to operator(&(const Arg){ .i = OP_*}) */
enum {
@@ -167,6 +169,7 @@ enum {
OP_PUT,
OP_SHIFT_RIGHT,
OP_SHIFT_LEFT,
+ OP_CASE_CHANGE,
};
static Operator ops[] = {
@@ -176,6 +179,7 @@ static Operator ops[] = {
[OP_PUT] = { op_put },
[OP_SHIFT_RIGHT] = { op_shift_right },
[OP_SHIFT_LEFT] = { op_shift_left },
+ [OP_CASE_CHANGE] = { op_case_change },
};
#define PAGE INT_MAX
@@ -370,6 +374,8 @@ static void linewise(const Arg *arg);
static void operator(const Arg *arg);
/* execute operator twice useful for synonyms (e.g. 'cc') */
static void operator_twice(const Arg *arg);
+/* change case of a file range to upper (arg->i > 0) or lowercase (arg->i < 0) */
+static void changecase(const Arg *arg);
/* blocks to read a key and performs movement indicated by arg->i which
* should be one of MOVE_{RIGHT,LEFT}_{TO,TILL} */
static void movement_key(const Arg *arg);
@@ -552,6 +558,28 @@ static void op_shift_left(OperatorContext *c) {
editor_draw(vis);
}
+static void op_case_change(OperatorContext *c) {
+ size_t len = c->range.end - c->range.start;
+ char *buf = malloc(len+1);
+ if (!buf)
+ return;
+ len = text_bytes_get(vis->win->text, c->range.start, len, buf);
+ size_t rem = len;
+ for (char *cur = buf; rem > 0; cur++, rem--) {
+ if (isascii((unsigned char)*cur)) {
+ if (c->arg->i > 0)
+ *cur = toupper((unsigned char)*cur);
+ else
+ *cur = tolower((unsigned char)*cur);
+ }
+ }
+
+ text_delete(vis->win->text, c->range.start, len);
+ text_insert(vis->win->text, c->range.start, buf, len);
+ editor_draw(vis);
+ free(buf);
+}
+
/** movement implementations of type: size_t (*move)(const Arg*) */
static size_t search_forward(const Arg *arg) {
@@ -673,6 +701,11 @@ static void operator_twice(const Arg *arg) {
operator(arg);
}
+static void changecase(const Arg *arg) {
+ action.arg = *arg;
+ operator(&(const Arg){ .i = OP_CASE_CHANGE });
+}
+
static void movement_key(const Arg *arg) {
Key k = getkey();
if (!k.str[0]) {