aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--builtin_commandline.cpp29
-rw-r--r--highlight.h5
-rw-r--r--input.cpp10
-rw-r--r--input.h4
-rw-r--r--reader.cpp111
-rw-r--r--reader.h7
-rw-r--r--screen.cpp4
-rw-r--r--screen.h6
-rw-r--r--share/functions/fish_vi_key_bindings.fish17
-rw-r--r--share/functions/fish_vi_prompt.fish3
10 files changed, 172 insertions, 24 deletions
diff --git a/builtin_commandline.cpp b/builtin_commandline.cpp
index f6dc2b03..39a5037b 100644
--- a/builtin_commandline.cpp
+++ b/builtin_commandline.cpp
@@ -211,6 +211,7 @@ static int builtin_commandline(parser_t &parser, wchar_t **argv)
int append_mode=0;
int function_mode = 0;
+ int selection_mode = 0;
int tokenize = 0;
@@ -316,6 +317,10 @@ static int builtin_commandline(parser_t &parser, wchar_t **argv)
}
,
{
+ L"selection", no_argument, 0, 's'
+ }
+ ,
+ {
0, 0, 0, 0
}
}
@@ -402,6 +407,10 @@ static int builtin_commandline(parser_t &parser, wchar_t **argv)
search_mode = 1;
break;
+ case 's':
+ selection_mode = 1;
+ break;
+
case 'h':
builtin_print_help(parser, argv[0], stdout_buffer);
return 0;
@@ -465,6 +474,26 @@ static int builtin_commandline(parser_t &parser, wchar_t **argv)
return 0;
}
+ if (selection_mode)
+ {
+ size_t sel_start, sel_stop;
+ const wchar_t *buffer = reader_get_buffer();
+ if(reader_get_selection_pos(sel_start, sel_stop))
+ {
+ size_t len = std::min(sel_stop - sel_start + 1, wcslen(buffer));
+ wchar_t *selection = new wchar_t[len];
+ selection = wcsncpy(selection, current_buffer + sel_start, len);
+
+ append_format(stdout_buffer, selection);
+ delete selection;
+ }
+ else
+ {
+ append_format(stdout_buffer, L"");
+ }
+ return 0;
+ }
+
/*
Check for invalid switch combinations
*/
diff --git a/highlight.h b/highlight.h
index 6747bba5..00b4d4b9 100644
--- a/highlight.h
+++ b/highlight.h
@@ -70,6 +70,11 @@
*/
#define HIGHLIGHT_AUTOSUGGESTION 0x2000
+/**
+ Internal value representing highlighting an active selection
+*/
+#define HIGHLIGHT_SELECTION 0x80
+
class history_item_t;
struct file_detection_context_t;
diff --git a/input.cpp b/input.cpp
index ba0f6035..75e0b33c 100644
--- a/input.cpp
+++ b/input.cpp
@@ -137,7 +137,9 @@ static const wchar_t * const name_arr[] =
L"up-line",
L"down-line",
L"suppress-autosuggestion",
- L"accept-autosuggestion"
+ L"accept-autosuggestion",
+ L"begin-selection",
+ L"end-selection",
}
;
@@ -227,7 +229,9 @@ static const wchar_t code_arr[] =
R_UP_LINE,
R_DOWN_LINE,
R_SUPPRESS_AUTOSUGGESTION,
- R_ACCEPT_AUTOSUGGESTION
+ R_ACCEPT_AUTOSUGGESTION,
+ R_BEGIN_SELECTION,
+ R_END_SELECTION
}
;
@@ -265,7 +269,7 @@ const wchar_t *input_get_bind_mode()
const env_var_t bind_mode_var = env_get_string(FISH_BIND_MODE_VAR);
if(!bind_mode_var.missing())
{
- bind_mode = bind_mode_var.c_str();
+ bind_mode = bind_mode_var.c_str();
}
return bind_mode;
}
diff --git a/input.h b/input.h
index fdcb82b4..78f7ec72 100644
--- a/input.h
+++ b/input.h
@@ -61,11 +61,13 @@ enum
R_DOWN_LINE,
R_SUPPRESS_AUTOSUGGESTION,
R_ACCEPT_AUTOSUGGESTION,
+ R_BEGIN_SELECTION,
+ R_END_SELECTION
}
;
#define R_MIN R_NULL
-#define R_MAX R_ACCEPT_AUTOSUGGESTION
+#define R_MAX R_END_SELECTION
/**
Initialize the terminal by calling setupterm, and set up arrays
diff --git a/reader.cpp b/reader.cpp
index 37f35fac..34fe0d23 100644
--- a/reader.cpp
+++ b/reader.cpp
@@ -172,6 +172,13 @@ commence.
History search mode. This value means we are searching forwards.
*/
#define SEARCH_FORWARD 1
+/**
+ The color used to display an active selection
+ */
+#define FISH_SELECTION_COLOR_VAR L"fish-selection-color"
+
+/** The color used if the variable above is not set */
+#define DEFAULT_SELECTION_COLOR L"gray"
/* Any time the contents of a buffer changes, we update the generation count. This allows for our background highlighting thread to notice it and skip doing work that it would otherwise have to do. This variable should really be of some kind of interlocked or atomic type that guarantees we're not reading stale cache values. With C++11 we should use atomics, but until then volatile should work as well, at least on x86.*/
static volatile unsigned int s_generation_count;
@@ -258,6 +265,9 @@ public:
/** Indicates whether a selection is currently active */
bool sel_active;
+ /** The position of the cursor, when selection was initiated. */
+ size_t sel_begin_pos;
+
/** The start position of the current selection, if one. */
size_t sel_start_pos;
@@ -349,6 +359,7 @@ public:
search_pos(0),
buff_pos(0),
sel_active(0),
+ sel_begin_pos(0),
sel_start_pos(0),
sel_stop_pos(0),
complete_func(0),
@@ -448,9 +459,22 @@ static void term_donate()
/**
Update the cursor position
*/
-static void update_buff_pos(int buff_pos)
+static void update_buff_pos(size_t buff_pos)
{
data->buff_pos = buff_pos;
+ if(data->sel_active)
+ {
+ if(data->sel_begin_pos <= buff_pos)
+ {
+ data->sel_start_pos = data->sel_begin_pos;
+ data->sel_stop_pos = buff_pos;
+ }
+ else
+ {
+ data->sel_start_pos = buff_pos;
+ data->sel_stop_pos = data->sel_begin_pos;
+ }
+ }
}
@@ -536,7 +560,6 @@ wcstring combine_command_and_autosuggestion(const wcstring &cmdline, const wcstr
commandline, write the prompt, perform syntax highlighting, write
the commandline and move the cursor.
*/
-
static void reader_repaint()
{
// Update the indentation
@@ -552,6 +575,15 @@ static void reader_repaint()
std::vector<color_t> colors = data->colors;
colors.resize(len, HIGHLIGHT_AUTOSUGGESTION);
+ if(data->sel_active)
+ {
+ int selection_color = HIGHLIGHT_SELECTION << 16;
+ for(int i = data->sel_start_pos; i <= std::min(len - 1, data->sel_stop_pos); i++)
+ {
+ colors[i] = selection_color;
+ }
+ }
+
std::vector<int> indents = data->indents;
indents.resize(len);
@@ -562,11 +594,14 @@ static void reader_repaint()
data->command_length(),
&colors[0],
&indents[0],
- data->buff_pos);
+ data->buff_pos,
+ data->sel_start_pos,
+ data->sel_stop_pos);
data->repaint_needed = false;
}
+
static void reader_repaint_without_autosuggestion()
{
// Swap in an empty autosuggestion, repaint, then swap it out
@@ -606,7 +641,7 @@ static void reader_kill(size_t begin_idx, size_t length, int mode, int newv)
{
/* Move the buff position back by the number of characters we deleted, but don't go past buff_pos */
size_t backtrack = mini(data->buff_pos - begin_idx, length);
- data->buff_pos -= backtrack;
+ update_buff_pos(data->buff_pos - backtrack);
}
data->command_line.erase(begin_idx, length);
@@ -1101,7 +1136,7 @@ static void remove_backward()
int width;
do
{
- data->buff_pos -= 1;
+ update_buff_pos(data->buff_pos - 1);
width = fish_wcwidth(data->command_line.at(data->buff_pos));
data->command_line.erase(data->buff_pos, 1);
}
@@ -1129,7 +1164,7 @@ static bool insert_string(const wcstring &str, bool should_expand_abbreviations
return false;
data->command_line.insert(data->buff_pos, str);
- data->buff_pos += len;
+ update_buff_pos(data->buff_pos + len);
data->command_line_changed();
data->suppress_autosuggestion = false;
@@ -2475,6 +2510,26 @@ size_t reader_get_cursor_pos()
return data->buff_pos;
}
+bool reader_get_selection_pos(size_t &start, size_t &stop)
+{
+ if (!data)
+ {
+ return false;
+ }
+ else
+ {
+ if(!data->sel_active)
+ return false;
+ else
+ {
+ start = data->sel_start_pos;
+ stop = data->sel_stop_pos;
+ return true;
+ }
+ }
+}
+
+
#define ENV_CMD_DURATION L"CMD_DURATION"
void set_env_cmd_duration(struct timeval *after, struct timeval *before)
@@ -2572,6 +2627,8 @@ int reader_shell_test(const wchar_t *b)
0,
tmp,
tmp2,
+ 0,
+ 0,
0);
@@ -2945,7 +3002,7 @@ static int read_i(void)
else if (tmp)
{
wcstring command = tmp;
- data->buff_pos=0;
+ update_buff_pos(0);
data->command_line.clear();
data->command_line_changed();
reader_run_command(parser, command);
@@ -3136,7 +3193,7 @@ const wchar_t *reader_readline(void)
while ((data->buff_pos>0) &&
(buff[data->buff_pos-1] != L'\n'))
{
- data->buff_pos--;
+ update_buff_pos(data->buff_pos - 1);
}
reader_repaint();
@@ -3150,7 +3207,7 @@ const wchar_t *reader_readline(void)
while (buff[data->buff_pos] &&
buff[data->buff_pos] != L'\n')
{
- data->buff_pos++;
+ update_buff_pos(data->buff_pos + 1);
}
}
else
@@ -3174,8 +3231,6 @@ const wchar_t *reader_readline(void)
/* go to EOL*/
case R_END_OF_BUFFER:
{
- data->buff_pos = data->command_length();
-
update_buff_pos(data->command_length());
reader_repaint();
@@ -3442,7 +3497,7 @@ const wchar_t *reader_readline(void)
*/
if (data->buff_pos < data->command_length())
{
- data->buff_pos++;
+ update_buff_pos(data->buff_pos + 1);
remove_backward();
}
break;
@@ -3496,7 +3551,7 @@ const wchar_t *reader_readline(void)
}
}
finished=1;
- data->buff_pos=data->command_length();
+ update_buff_pos(data->command_length());
reader_repaint();
break;
}
@@ -3617,7 +3672,7 @@ const wchar_t *reader_readline(void)
{
if (data->buff_pos > 0)
{
- data->buff_pos--;
+ update_buff_pos(data->buff_pos - 1);
reader_repaint();
}
break;
@@ -3628,7 +3683,7 @@ const wchar_t *reader_readline(void)
{
if (data->buff_pos < data->command_length())
{
- data->buff_pos++;
+ update_buff_pos(data->buff_pos + 1);
reader_repaint();
}
else
@@ -3760,7 +3815,7 @@ const wchar_t *reader_readline(void)
/* If the cursor is at the end, transpose the last two characters of the line */
if (data->buff_pos == data->command_length())
{
- data->buff_pos--;
+ update_buff_pos(data->buff_pos - 1);
}
/*
@@ -3783,8 +3838,11 @@ const wchar_t *reader_readline(void)
const wchar_t *tok_begin, *tok_end, *prev_begin, *prev_end;
/* If we are not in a token, look for one ahead */
- while (data->buff_pos != len && !iswalnum(buff[data->buff_pos]))
- data->buff_pos++;
+ size_t buff_pos = data->buff_pos;
+ while (buff_pos != len && !iswalnum(buff[buff_pos]))
+ buff_pos++;
+
+ update_buff_pos(buff_pos);
parse_util_token_extent(buff, data->buff_pos, &tok_begin, &tok_end, &prev_begin, &prev_end);
@@ -3852,6 +3910,23 @@ const wchar_t *reader_readline(void)
break;
}
+ case R_BEGIN_SELECTION:
+ {
+ data->sel_active = true;
+ data->sel_begin_pos = data->buff_pos;
+ data->sel_start_pos = data->buff_pos;
+ data->sel_stop_pos = data->buff_pos;
+ break;
+ }
+
+ case R_END_SELECTION:
+ {
+ data->sel_active = false;
+ data->sel_start_pos = data->buff_pos;
+ data->sel_stop_pos = data->buff_pos;
+ break;
+ }
+
/* Other, if a normal character, we add it to the command */
default:
{
diff --git a/reader.h b/reader.h
index b954c1be..7e1cadf6 100644
--- a/reader.h
+++ b/reader.h
@@ -114,6 +114,13 @@ void reader_set_buffer(const wcstring &b, size_t p);
*/
size_t reader_get_cursor_pos();
+
+/**
+ Get the current selection range in the command line.
+ Returns false if there is no active selection, true otherwise.
+*/
+bool reader_get_selection_pos(size_t &start, size_t &stop);
+
/**
Return the value of the interrupted flag, which is set by the sigint
handler, and clear it if it was set.
diff --git a/screen.cpp b/screen.cpp
index 711aebab..9db678ff 100644
--- a/screen.cpp
+++ b/screen.cpp
@@ -1234,7 +1234,9 @@ void s_write(screen_t *s,
size_t explicit_len,
const int *colors,
const int *indent,
- size_t cursor_pos)
+ size_t cursor_pos,
+ size_t sel_start_pos,
+ size_t sel_stop_pos)
{
screen_data_t::cursor_t cursor_arr;
diff --git a/screen.h b/screen.h
index ef74383d..3b242147 100644
--- a/screen.h
+++ b/screen.h
@@ -181,6 +181,8 @@ public:
\param colors the colors to use for the comand line
\param indent the indent to use for the command line
\param cursor_pos where the cursor is
+ \param sel_start_pos where the selections starts (inclusive)
+ \param sel_stop_pos where the selections ends (inclusive)
*/
void s_write(screen_t *s,
const wcstring &left_prompt,
@@ -189,7 +191,9 @@ void s_write(screen_t *s,
size_t explicit_len,
const int *colors,
const int *indent,
- size_t cursor_pos);
+ size_t cursor_pos,
+ size_t sel_start_pos,
+ size_t sel_stop_pos);
/**
This function resets the screen buffers internal knowledge about
diff --git a/share/functions/fish_vi_key_bindings.fish b/share/functions/fish_vi_key_bindings.fish
index 9d8f3f5b..bd030967 100644
--- a/share/functions/fish_vi_key_bindings.fish
+++ b/share/functions/fish_vi_key_bindings.fish
@@ -28,6 +28,7 @@ function fish_vi_key_bindings -d "vi-like key bindings for fish"
bind -m insert I beginning-of-line force-repaint
bind -m insert a forward-char force-repaint
bind -m insert A end-of-line force-repaint
+ bind -m visual v begin-selection force-repaint
bind -m insert o "commandline -a \n" down-line force-repaint
#bind -m insert O beginning-of-line "commandline -i \n" up-line force-repaint # doesn't work
@@ -148,4 +149,20 @@ function fish_vi_key_bindings -d "vi-like key bindings for fish"
bind -M insert \cd exit
bind -M insert \ef forward-word
+
+
+
+ #
+ # visual mode
+ #
+
+ bind -M visual \e\[C forward-char
+ bind -M visual \e\[D backward-char
+ bind -M visual -k right forward-char
+ bind -M visual -k left backward-char
+ bind -M visual h backward-char
+ bind -M visual l forward-char
+
+ bind -M visual -m default \cc end-selection force-repaint
+ bind -M visual -m default \e end-selection force-repaint
end
diff --git a/share/functions/fish_vi_prompt.fish b/share/functions/fish_vi_prompt.fish
index bae594cf..fe780e40 100644
--- a/share/functions/fish_vi_prompt.fish
+++ b/share/functions/fish_vi_prompt.fish
@@ -7,6 +7,9 @@ function fish_vi_prompt_cm --description "Displays the current mode"
case insert
set_color --bold --background red white
echo "[I]"
+ case visual
+ set_color --bold --background magenta white
+ echo "[V]"
end
set_color normal
end