---
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.0
Received 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