From 349d7aa1be8b62c23392c96051e617d560740b4a Mon Sep 17 00:00:00 2001 From: Daniel Carl Date: Fri, 30 May 2014 22:26:02 +0200 Subject: [PATCH] Added support for different yank registers. Allow to yank, and paste from different registers. --- doc/vimb.1 | 20 +++--- src/command.c | 6 +- src/command.h | 2 +- src/ex.c | 174 +++++++++++++++++++++++++++++++------------------- src/hints.c | 2 +- src/main.c | 49 ++++++++++++++ src/main.h | 7 ++ src/normal.c | 30 +++++++-- src/normal.h | 2 - 9 files changed, 207 insertions(+), 85 deletions(-) diff --git a/doc/vimb.1 b/doc/vimb.1 index 9a829e3..296c5db 100644 --- a/doc/vimb.1 +++ b/doc/vimb.1 @@ -112,11 +112,12 @@ Open the last closed page into a new window. Open the oldest entry from read it later queue in current browser window, if vimb has been compiled with QUEUE feature. .TP -.B p -Open the URI out of the clipboard. +.BI [ \[char34]x ]p +Open the URI out of the register \fIx\fP or if not given from clipboard. .TP -.B P -Open the URI out of the clipboard into new window. +.BI [ \[char34]x ]P +Open the URI out of the register \fIx\fP or if not given from clipboard into +new window. .TP .BI [ N ]CTRL\-O Go back \fIN\fP steps in the browser history. @@ -324,11 +325,11 @@ Full-Content Zoom-Out the page by \fIN\fP steps. Reset Zoom. .SS Yank .TP -.B y -Yank the URI or current page into clipboard. +.BI [ \[char34]x ]y +Yank the URI or current page into register \fIx\fP and clipboard. .TP -.B Y -Yank the current selection into clipboard. +.BI [ \[char34]x ]Y +Yank the current selection into register \fIx\fP and clipboard. .SH COMMAND MODE .SS Command Line Editing .TP @@ -355,6 +356,9 @@ Moves the cursor after the char in inputbox. .TP .B CTRL\-V Pass the next key press directly to gtk. +.TP +.B CTRL\-R {0-9a-z} +Insert the content of given buffer at cursor position. .SS Command Line History .TP .B diff --git a/src/command.c b/src/command.c index 5133598..de32cbb 100644 --- a/src/command.c +++ b/src/command.c @@ -82,7 +82,7 @@ gboolean command_search(const Arg *arg) return true; } -gboolean command_yank(const Arg *arg) +gboolean command_yank(const Arg *arg, char buf) { static char *tmpl = "Yanked: %s"; @@ -95,6 +95,8 @@ gboolean command_yank(const Arg *arg) text = gtk_clipboard_wait_for_text(SECONDARY_CLIPBOARD()); } if (text) { + /* put the text into the yank buffer */ + vb_register_add(buf, text); vb_echo(VB_MSG_NORMAL, false, tmpl, text); g_free(text); @@ -113,7 +115,9 @@ gboolean command_yank(const Arg *arg) a.s = arg->s; } if (a.s) { + /* put the text into the yank buffer */ vb_set_clipboard(&a); + vb_register_add(buf, a.s); vb_echo(VB_MSG_NORMAL, false, tmpl, a.s); return true; diff --git a/src/command.h b/src/command.h index c552963..3377f83 100644 --- a/src/command.h +++ b/src/command.h @@ -41,7 +41,7 @@ enum { #endif gboolean command_search(const Arg *arg); -gboolean command_yank(const Arg *arg); +gboolean command_yank(const Arg *arg, char buf); gboolean command_save(const Arg *arg); #ifdef FEATURE_QUEUE gboolean command_queue(const Arg *arg); diff --git a/src/ex.c b/src/ex.c index 121bc3d..5cc44b6 100644 --- a/src/ex.c +++ b/src/ex.c @@ -39,6 +39,7 @@ #include "handlers.h" #include "map.h" #include "js.h" +#include "normal.h" typedef enum { EX_BMA, @@ -74,6 +75,11 @@ typedef enum { EX_TABOPEN, } ExCode; +typedef enum { + PHASE_START, + PHASE_CUTBUF, +} Phase; + typedef struct { int count; /* commands count */ int idx; /* index in commands array */ @@ -99,6 +105,11 @@ typedef struct { int flags; } ExInfo; +static struct { + char cutbuf; /* char for the cut buffer */ + Phase phase; /* current parsing phase */ +} info = {'\0', PHASE_START}; + static void input_activate(void); static gboolean parse(const char **input, ExArg *arg); static gboolean parse_count(const char **input, ExArg *arg); @@ -215,92 +226,125 @@ VbResult ex_keypress(int key) GtkTextIter start, end; GtkTextBuffer *buffer = vb.gui.buffer; GtkTextMark *mark; + VbResult res; + const char *text; /* delegate call to the submode */ if (RESULT_COMPLETE == hints_keypress(key)) { return RESULT_COMPLETE; } - switch (key) { - case KEY_TAB: - complete(1); - break; + /* process the custbuffer */ + if (info.phase == PHASE_CUTBUF) { + info.cutbuf = (char)key; + info.phase = PHASE_CUTBUF; - case KEY_SHIFT_TAB: - complete(-1); - break; + /* insert the cutbuffer text at cursor position */ + text = vb_register_get((char)key); + if (text) { + gtk_text_buffer_insert_at_cursor(buffer, text, strlen(text)); + } - case CTRL('['): - case CTRL('C'): - mode_enter('n'); - vb_set_input_text(""); - break; + res = RESULT_COMPLETE; + } else { + res = RESULT_COMPLETE; + switch (key) { + case KEY_TAB: + complete(1); + break; - case KEY_CR: - input_activate(); - break; + case KEY_SHIFT_TAB: + complete(-1); + break; - case KEY_UP: - history(true); - break; + case CTRL('['): + case CTRL('C'): + mode_enter('n'); + vb_set_input_text(""); + break; - case KEY_DOWN: - history(false); - break; + case KEY_CR: + input_activate(); + break; - /* basic command line editing */ - case CTRL('H'): - /* delete the last char before the cursor */ - mark = gtk_text_buffer_get_insert(buffer); - gtk_text_buffer_get_iter_at_mark(buffer, &start, mark); - gtk_text_buffer_backspace(buffer, &start, true, true); - break; + case KEY_UP: + history(true); + break; - case CTRL('W'): - /* delete word backward from cursor */ - mark = gtk_text_buffer_get_insert(buffer); - gtk_text_buffer_get_iter_at_mark(buffer, &end, mark); + case KEY_DOWN: + history(false); + break; - /* copy the iter to build start and end point for deletion */ - start = end; + /* basic command line editing */ + case CTRL('H'): + /* delete the last char before the cursor */ + mark = gtk_text_buffer_get_insert(buffer); + gtk_text_buffer_get_iter_at_mark(buffer, &start, mark); + gtk_text_buffer_backspace(buffer, &start, true, true); + break; - /* move the iterator to the beginning of previous word */ - if (gtk_text_iter_backward_word_start(&start)) { - gtk_text_buffer_delete(buffer, &start, &end); - } - break; + case CTRL('W'): + /* delete word backward from cursor */ + mark = gtk_text_buffer_get_insert(buffer); + gtk_text_buffer_get_iter_at_mark(buffer, &end, mark); - case CTRL('B'): - /* move the cursor direct behind the prompt */ - gtk_text_buffer_get_iter_at_offset(buffer, &start, strlen(vb.state.prompt)); - gtk_text_buffer_place_cursor(buffer, &start); - break; + /* copy the iter to build start and end point for deletion */ + start = end; - case CTRL('E'): - /* move the cursor to the end of line */ - gtk_text_buffer_get_end_iter(buffer, &start); - gtk_text_buffer_place_cursor(buffer, &start); - break; + /* move the iterator to the beginning of previous word */ + if (gtk_text_iter_backward_word_start(&start)) { + gtk_text_buffer_delete(buffer, &start, &end); + } + break; - case CTRL('U'): - /* remove everythings between cursor and prompt */ - mark = gtk_text_buffer_get_insert(buffer); - gtk_text_buffer_get_iter_at_mark(buffer, &end, mark); - gtk_text_buffer_get_iter_at_offset(buffer, &start, strlen(vb.state.prompt)); - gtk_text_buffer_delete(buffer, &start, &end); - break; + case CTRL('B'): + /* move the cursor direct behind the prompt */ + gtk_text_buffer_get_iter_at_offset(buffer, &start, strlen(vb.state.prompt)); + gtk_text_buffer_place_cursor(buffer, &start); + break; - default: - /* if is printable ascii char, than write it at the cursor - * position into input box */ - if (key >= 0x20 && key <= 0x7e) { - gtk_text_buffer_insert_at_cursor(buffer, (char[2]){key, 0}, 1); - } else { - vb.state.processed_key = false; - } + case CTRL('E'): + /* move the cursor to the end of line */ + gtk_text_buffer_get_end_iter(buffer, &start); + gtk_text_buffer_place_cursor(buffer, &start); + break; + + case CTRL('U'): + /* remove everythings between cursor and prompt */ + mark = gtk_text_buffer_get_insert(buffer); + gtk_text_buffer_get_iter_at_mark(buffer, &end, mark); + gtk_text_buffer_get_iter_at_offset(buffer, &start, strlen(vb.state.prompt)); + gtk_text_buffer_delete(buffer, &start, &end); + break; + + case CTRL('R'): + info.cutbuf = (char)key; + info.phase = PHASE_CUTBUF; + vb.mode->flags |= FLAG_NOMAP; + res = RESULT_MORE; + break; + + default: + /* if is printable ascii char, than write it at the cursor + * position into input box */ + if (key >= 0x20 && key <= 0x7e) { + gtk_text_buffer_insert_at_cursor(buffer, (char[2]){key, 0}, 1); + } else { + vb.state.processed_key = false; + } + } + } + + if (res == RESULT_COMPLETE) { + info.cutbuf = 0; + info.phase = PHASE_START; + } else { + /* if the key sequence is not complete show the already typed keys in + * status bar */ + normal_showcmd(key); } - return RESULT_COMPLETE; + return res; } /** diff --git a/src/hints.c b/src/hints.c index 31f995d..9616550 100644 --- a/src/hints.c +++ b/src/hints.c @@ -327,7 +327,7 @@ static gboolean call_hints_function(const char *func, int count, JSValueRef para case 'Y': a.i = COMMAND_YANK_ARG; a.s = v; - command_yank(&a); + command_yank(&a, '\0'); break; #ifdef FEATURE_QUEUE diff --git a/src/main.c b/src/main.c index 04920b6..6efbb51 100644 --- a/src/main.c +++ b/src/main.c @@ -97,6 +97,8 @@ static void setup_signals(); static void init_files(void); static void session_init(void); static void session_cleanup(void); +static void register_init(void); +static void register_cleanup(void); static gboolean hide_message(); static void set_status(const StatusType status); static void input_print(gboolean force, const MessageType type, gboolean hide, const char *message); @@ -381,6 +383,7 @@ void vb_quit(void) setting_cleanup(); history_cleanup(); session_cleanup(); + register_cleanup(); for (int i = 0; i < FILES_LAST; i++) { g_free(vb.files[i]); @@ -747,6 +750,7 @@ static void init_core(void) init_files(); session_init(); setting_init(); + register_init(); read_config(); /* initially apply input style */ @@ -962,6 +966,51 @@ static void session_cleanup(void) #endif } +static void register_init(void) +{ + memset(vb.state.reg, 0, sizeof(char*)); +} + +void vb_register_add(char buf, const char *value) +{ + char *mark; + int idx; + + /* make sure the mark is a valid mark char */ + if ((mark = strchr(VB_REG_CHARS, buf))) { + /* get the index of the mark char */ + idx = mark - VB_REG_CHARS; + + OVERWRITE_STRING(vb.state.reg[idx], value); + } +} + +const char *vb_register_get(char buf) +{ + char *mark; + int idx; + + /* make sure the mark is a valid mark char */ + if ((mark = strchr(VB_REG_CHARS, buf))) { + /* get the index of the mark char */ + idx = mark - VB_REG_CHARS; + + return vb.state.reg[idx]; + } + + return NULL; +} + +static void register_cleanup(void) +{ + int i; + for (i = 0; i < VB_REG_SIZE; i++) { + if (vb.state.reg[i]) { + g_free(vb.state.reg[i]); + } + } +} + static gboolean button_relase_cb(WebKitWebView *webview, GdkEventButton *event) { gboolean propagate = false; diff --git a/src/main.h b/src/main.h index 3ff9030..e9fd42e 100644 --- a/src/main.h +++ b/src/main.h @@ -115,6 +115,9 @@ #define VB_MARK_TICK 0 #define VB_MARK_SIZE (sizeof(VB_MARK_CHARS) - 1) +#define VB_REG_CHARS "0123456789abcdefghijklmnopqrstuvwxyz" +#define VB_REG_SIZE (sizeof(VB_REG_CHARS) - 1) + /* enums */ typedef enum { RESULT_COMPLETE, @@ -290,6 +293,8 @@ typedef struct { char prompt[PROMPT_SIZE]; /* current prompt ':', 'g;t', '/' including nul */ gdouble marks[VB_MARK_SIZE]; /* holds marks set to page with 'm{markchar}' */ char *linkhover; /* the uri of the curret hovered link */ + GHashTable *buffer; /* holds the yank buffer */ + char *reg[VB_REG_SIZE]; /* holds the yank buffer */ } State; typedef struct { @@ -364,6 +369,8 @@ void vb_update_statusbar(void); void vb_update_status_style(void); void vb_update_input_style(void); void vb_update_urlbar(const char *uri); +void vb_register_add(char buf, const char *value); +const char *vb_register_get(char buf); gboolean vb_download(WebKitWebView *view, WebKitDownload *download, const char *path); void vb_quit(void); diff --git a/src/normal.c b/src/normal.c index 856a28a..efaf469 100644 --- a/src/normal.c +++ b/src/normal.c @@ -37,15 +37,19 @@ typedef enum { PHASE_KEY2, PHASE_KEY3, PHASE_COMPLETE, + PHASE_CUTBUF, } Phase; -struct NormalCmdInfo_s { +typedef struct NormalCmdInfo_s { int count; /* count used for the command */ char key; /* command key */ char key2; /* second command key (optional) */ char key3; /* third command key only for hinting */ + char cutbuf; /* char for the cut buffer */ Phase phase; /* current parsing phase */ -} info = {0, '\0', '\0', PHASE_START}; +} NormalCmdInfo; + +static NormalCmdInfo info = {0, '\0', '\0', PHASE_START}; typedef VbResult (*NormalCommand)(const NormalCmdInfo *info); @@ -263,6 +267,12 @@ VbResult normal_keypress(int key) info.phase = PHASE_KEY2; info.key = key; vb.mode->flags |= FLAG_NOMAP; + } else if ((char)key == '"') { + info.phase = PHASE_CUTBUF; + vb.mode->flags |= FLAG_NOMAP; + } else if (info.phase == PHASE_CUTBUF) { + info.cutbuf = (char)key; + info.phase = PHASE_START; } else { info.key = key; info.phase = PHASE_COMPLETE; @@ -284,7 +294,7 @@ VbResult normal_keypress(int key) if (res == RESULT_COMPLETE) { /* unset the info */ - info.key = info.key2 = info.key3 = info.count = 0; + info.key = info.key2 = info.key3 = info.count = info.cutbuf = 0; info.phase = PHASE_START; } else if (res == RESULT_MORE) { normal_showcmd(key); @@ -564,9 +574,15 @@ static VbResult normal_open_clipboard(const NormalCmdInfo *info) { Arg a = {info->key == 'P' ? VB_TARGET_NEW : VB_TARGET_CURRENT}; - a.s = gtk_clipboard_wait_for_text(PRIMARY_CLIPBOARD()); - if (!a.s) { - a.s = gtk_clipboard_wait_for_text(SECONDARY_CLIPBOARD()); + /* if cutbuffer is not the default - read out of the internal cutbuffer */ + if (info->cutbuf) { + a.s = g_strdup(vb_register_get(info->cutbuf)); + } else { + /* if no cutbuffer is given use the system clipboard */ + a.s = gtk_clipboard_wait_for_text(PRIMARY_CLIPBOARD()); + if (!a.s) { + a.s = gtk_clipboard_wait_for_text(SECONDARY_CLIPBOARD()); + } } if (a.s) { @@ -763,7 +779,7 @@ static VbResult normal_yank(const NormalCmdInfo *info) { Arg a = {info->key == 'Y' ? COMMAND_YANK_SELECTION : COMMAND_YANK_URI}; - return command_yank(&a) ? RESULT_COMPLETE : RESULT_ERROR; + return command_yank(&a, info->cutbuf) ? RESULT_COMPLETE : RESULT_ERROR; } static VbResult normal_zoom(const NormalCmdInfo *info) diff --git a/src/normal.h b/src/normal.h index e027688..38a51cb 100644 --- a/src/normal.h +++ b/src/normal.h @@ -23,8 +23,6 @@ #include "config.h" #include "main.h" -typedef struct NormalCmdInfo_s NormalCmdInfo; - void normal_enter(void); void normal_leave(void); VbResult normal_keypress(int key); -- 2.20.1