--- I like these commands but I assume not everybody does. Before spending more time on this implementation I thought I would gather some feedback. config.def.h | 2 ++ main.c | 12 ++++++++++++ text-motions.c | 13 +++++++++++++ text-motions.h | 9 +++++++++ vis.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ vis.h | 4 ++++ 6 files changed, 93 insertions(+) diff --git a/config.def.h b/config.def.h index 47ed326..af4b2b2 100644 --- a/config.def.h +++ b/config.def.h _AT_@ -227,6 +227,8 @@ static const KeyBinding bindings_normal[] = { { "m", ACTION(MARK_SET) }, { "<F1>", ALIAS(":help<Enter>") }, { "ga", ACTION(UNICODE_INFO) }, + { "gf", ACTION(OPEN_FILE_UNDER_CURSOR) }, + { "<C-w>gf", ACTION(OPEN_FILE_UNDER_CURSOR_NEW_WINDOW) }, { "p", ACTION(PUT_AFTER) }, { "P", ACTION(PUT_BEFORE) }, { "gp", ACTION(PUT_AFTER_END) }, diff --git a/main.c b/main.c index 918f4c8..2404522 100644 --- a/main.c +++ b/main.c _AT_@ -213,6 +213,8 @@ enum { VIS_ACTION_INSERT_LINE_START, VIS_ACTION_OPEN_LINE_ABOVE, VIS_ACTION_OPEN_LINE_BELOW, + VIS_ACTION_OPEN_FILE_UNDER_CURSOR, + VIS_ACTION_OPEN_FILE_UNDER_CURSOR_NEW_WINDOW, VIS_ACTION_JOIN_LINE_BELOW, VIS_ACTION_JOIN_LINES, VIS_ACTION_PROMPT_SHOW, _AT_@ -757,6 +759,16 @@ static KeyAction vis_action[] = { "Focus previous window", call, { .f = vis_window_prev } }, + [VIS_ACTION_OPEN_FILE_UNDER_CURSOR] = { + "open-file-under-cursor", + "Open file under the cursor", + call, { .f = vis_open_file } + }, + [VIS_ACTION_OPEN_FILE_UNDER_CURSOR_NEW_WINDOW] = { + "open-file-under-cursor-new_window", + "Open file under the cursor in a new window", + call, { .f = vis_open_file_new_window } + }, [VIS_ACTION_APPEND_CHAR_NEXT] = { "append-char-next", "Append text after the cursor", diff --git a/text-motions.c b/text-motions.c index f406da3..2752158 100644 --- a/text-motions.c +++ b/text-motions.c _AT_@ -26,6 +26,11 @@ int is_word_boundry(int c) { ('A' <= c && c <= 'Z') || c == '_'); } +int is_filename_boundry(int c) { + return isspace(c) || (c == ';' || + c == '"' || c == '\'' ); +} + size_t text_begin(Text *txt, size_t pos) { return 0; } _AT_@ -357,6 +362,14 @@ size_t text_word_start_prev(Text *txt, size_t pos) { return text_customword_start_prev(txt, pos, is_word_boundry); } +size_t text_filename_start_prev(Text *txt, size_t pos) { + return text_customword_start_prev(txt, pos, is_filename_boundry); +} + +size_t text_filename_end_next(Text *txt, size_t pos) { + return text_customword_end_next(txt, pos, is_filename_boundry); +} + static size_t text_paragraph_sentence_next(Text *txt, size_t pos, bool sentence) { char c; bool content = false, paragraph = false; diff --git a/text-motions.h b/text-motions.h index 32e4a1f..67a366b 100644 --- a/text-motions.h +++ b/text-motions.h _AT_@ -66,6 +66,15 @@ size_t text_longword_end_next(Text*, size_t pos); size_t text_longword_end_prev(Text*, size_t pos); size_t text_longword_start_next(Text*, size_t pos); size_t text_longword_start_prev(Text*, size_t pos); + +/* + * Get the beginning and the end of a file name. Every non-punctuation + * character except white space is being considered a file name + * character. TODO?: handle escaped space characters in filenames. + */ +size_t text_filename_start_prev(Text*, size_t pos); +size_t text_filename_end_next(Text*, size_t pos); + /* * A word consists of a sequence of letters, digits and underscores, or a * sequence of other non-blank characters, separated with white space. diff --git a/vis.c b/vis.c index b65724c..795dd7d 100644 --- a/vis.c +++ b/vis.c _AT_@ -335,6 +335,59 @@ err: return NULL; } +/* Gets file name under cursor. Freeing the allocated memory is the + * caller's responsibility. + */ +static char* vis_get_filename_under_cursor(Vis *vis) { + Win *win = vis->win; + Cursor *c = view_cursors(win->view); + size_t pos = view_cursors_pos(c); + Text *txt = vis->win->file->text; + // We have to put in some pos offsets here because the custom + // text motion function will skip over boundaries. + size_t startpos = text_filename_start_prev(txt, pos+1); + size_t endpos = text_filename_end_next(txt, pos-1); + if (startpos == endpos) { + vis_info_show(vis, "No filename found under cursor."); + return NULL; + } + + char *fn = text_bytes_alloc0(txt, startpos, endpos-startpos+1); + return fn; +} + +void vis_open_file(Vis *vis) { + Win *win = vis->win; + if (text_modified(win->file->text)) { + vis_info_show(vis, "This window does contains unsaved text so we cannot close it."); + return; + } + Win *oldwin = vis->win; + + char *fn = vis_get_filename_under_cursor(vis); + if (!fn) + return; + if (!vis_window_new(vis, fn)) { + vis_info_show(vis, "Could not open `%s' %s", fn, + errno ? strerror(errno) : ""); + free(fn); + return; + } + + vis_window_close(oldwin); + free(fn); +} + +void vis_open_file_new_window(Vis *vis) { + char *fn = vis_get_filename_under_cursor(vis); + if (!fn) + return; + if (!vis_window_new(vis, fn)) + vis_info_show(vis, "Could not open `%s' %s", fn, + errno ? strerror(errno) : ""); + free(fn); +} + void vis_free(Vis *vis) { if (!vis) return; diff --git a/vis.h b/vis.h index 3bcd9c7..d357f0f 100644 --- a/vis.h +++ b/vis.h _AT_@ -79,6 +79,10 @@ void vis_window_next(Vis*); void vis_window_prev(Vis*); /* display a user prompt with a certain title and default text */ void vis_prompt_show(Vis*, const char *title); +/* open file under cursor in current window */ +void vis_open_file(Vis *vis); +/* open file under cursor in new window */ +void vis_open_file_new_window(Vis *vis); /* display a one line message to the user, will be hidden upon keypress */ void vis_info_show(Vis*, const char *msg, ...); -- 2.7.0Received on Mon Feb 01 2016 - 21:55:32 CET
This archive was generated by hypermail 2.3.0 : Mon Feb 01 2016 - 22:00:17 CET