aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2019-08-21 01:55:12 +0200
committerJustin M. Keyes <justinkz@gmail.com>2019-08-27 21:19:10 +0200
commit5ae6849517d2a025c3359e771ac1e01a68ec24c8 (patch)
treee0aed7c5a93206235ed1304079f6201f6d07ad2e /src
parent93e5f0235b8e85423d0284231661ba4b0d7caa07 (diff)
downloadrneovim-5ae6849517d2a025c3359e771ac1e01a68ec24c8.tar.gz
rneovim-5ae6849517d2a025c3359e771ac1e01a68ec24c8.tar.bz2
rneovim-5ae6849517d2a025c3359e771ac1e01a68ec24c8.zip
paste: phases, dots
- Send `phase` parameter to the paste handler. - Redraw at intervals and when paste terminates. - Show "..." throbber during paste to indicate activity.
Diffstat (limited to 'src')
-rw-r--r--src/nvim/lua/vim.lua46
-rw-r--r--src/nvim/tui/input.c48
-rw-r--r--src/nvim/tui/input.h2
3 files changed, 63 insertions, 33 deletions
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index 0b94417b3e..dca61d814a 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -94,19 +94,39 @@ local function _os_proc_children(ppid)
end
-- Default paste function.
-local function _paste(lines)
- -- local eof = (lines == {''})
- local call = vim.api.nvim_call_function
- local mode = call('mode', {})
- local curline = call('line', {'.'})
- -- vim.api.nvim_set_option('paste', true)
- vim.api.nvim_put(lines, 'c', true, true)
- -- vim.api.nvim_set_option('paste', false)
- -- TODO: do not redraw (slow!) until paste is finished.
- -- if eof then
- vim.api.nvim_command('redraw')
- return true -- Paste will not continue if not returning `true`.
-end
+local _paste = (function()
+ local tdots = 0
+ local tredraw = 0
+ local tick = 0
+ return function(lines, phase)
+ local call = vim.api.nvim_call_function
+ local now = vim.loop.now()
+ if phase == 1 then
+ tdots = now
+ tredraw = now
+ tick = 0
+ if (call('mode', {})):find('[vV]') then
+ vim.api.nvim_feedkeys('', 'n', false)
+ end
+ end
+ vim.api.nvim_put(lines, 'c', true, true)
+ if (now - tredraw >= 1000) or phase == 1 or phase == 3 then
+ tredraw = now
+ vim.api.nvim_command('redraw')
+ vim.api.nvim_command('redrawstatus')
+ end
+ if (now - tdots >= 100) then
+ local dots = ('.'):rep(tick % 4)
+ tdots = now
+ tick = tick + 1
+ vim.api.nvim_command(('echo "%s"'):format(dots))
+ end
+ if phase == 3 then
+ vim.api.nvim_command('echo ""')
+ end
+ return true -- Paste will not continue if not returning `true`.
+ end
+end)()
-- TODO(ZyX-I): Create compatibility layer.
--{{{1 package.path updater function
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 8ee9640f9f..fc06f21339 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -25,7 +25,7 @@
void tinput_init(TermInput *input, Loop *loop)
{
input->loop = loop;
- input->paste_enabled = false;
+ input->paste = 0;
input->in_fd = 0;
input->key_buffer = rbuffer_new(KEY_BUFFER_SIZE);
uv_mutex_init(&input->key_buffer_mutex);
@@ -130,19 +130,20 @@ static void tinput_wait_enqueue(void **argv)
TermInput *input = argv[0];
RBUFFER_UNTIL_EMPTY(input->key_buffer, buf, len) {
const String keys = { .data = buf, .size = len };
- if (input->paste_enabled) {
- Object keys_array = ARRAY_OBJ(string_to_array(keys));
- Array args = { .capacity = 1, .size = 1, .items = &keys_array };
+ if (input->paste) {
Error err = ERROR_INIT;
- Object fret
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, ARRAY_OBJ(string_to_array(keys)));
+ ADD(args, INTEGER_OBJ(input->paste));
+ Object rv
= nvim_execute_lua(STATIC_CSTR_AS_STRING("return vim._paste(...)"),
args, &err);
- if (fret.type != kObjectTypeBoolean || !fret.data.boolean) {
- // Abort paste if handler does not return true.
- input->paste_enabled = false;
- }
- api_free_object(fret);
- api_free_object(keys_array);
+ input->paste = (rv.type == kObjectTypeBoolean && rv.data.boolean)
+ ? 2 // Paste phase: "continue".
+ : 0; // Abort paste if handler does not return true.
+
+ api_free_object(rv);
+ api_free_array(args);
rbuffer_consumed(input->key_buffer, len);
rbuffer_reset(input->key_buffer);
if (ERROR_SET(&err)) {
@@ -392,18 +393,27 @@ static bool handle_bracketed_paste(TermInput *input)
&& (!rbuffer_cmp(input->read_stream.buffer, "\x1b[200~", 6)
|| !rbuffer_cmp(input->read_stream.buffer, "\x1b[201~", 6))) {
bool enable = *rbuffer_get(input->read_stream.buffer, 4) == '0';
- if (input->paste_enabled && enable) {
- // Pasting "enable paste" code literally.
- return false;
+ if (input->paste && enable) {
+ return false; // Pasting "start paste" code literally.
}
// Advance past the sequence
rbuffer_consumed(input->read_stream.buffer, 6);
- if (input->paste_enabled == enable) {
- return true;
+ if (!!input->paste == enable) {
+ return true; // Spurious "disable paste" code.
}
- tinput_flush(input, true);
- input->paste_enabled = enable;
+ if (enable) {
+ // Flush before starting paste.
+ tinput_flush(input, true);
+ // Paste phase: "first-chunk".
+ input->paste = 1;
+ } else {
+ // Paste phase: "last-chunk".
+ input->paste = 3;
+ tinput_flush(input, true);
+ // Paste phase: "disabled".
+ input->paste = 0;
+ }
return true;
}
return false;
@@ -548,7 +558,7 @@ static void tinput_read_cb(Stream *stream, RBuffer *buf, size_t count_,
}
}
// Push bytes directly (paste).
- if (input->paste_enabled) {
+ if (input->paste) {
RBUFFER_UNTIL_EMPTY(input->read_stream.buffer, ptr, len) {
size_t consumed = MIN(count, len);
assert(consumed <= input->read_stream.buffer->size);
diff --git a/src/nvim/tui/input.h b/src/nvim/tui/input.h
index 7d59cf5c6a..26a8447eb2 100644
--- a/src/nvim/tui/input.h
+++ b/src/nvim/tui/input.h
@@ -9,7 +9,7 @@
typedef struct term_input {
int in_fd;
- bool paste_enabled;
+ uint8_t paste; // Phases: 0=disabled 1=first-chunk 2=continue 3=last-chunk
bool waiting;
TermKey *tk;
#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18