Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita9c2152

Browse files
committed
fix(events): make CursorHold behave as documented
1 parentbf6de51 commita9c2152

File tree

4 files changed

+70
-13
lines changed

4 files changed

+70
-13
lines changed

‎src/nvim/getchar.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1665,7 +1665,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
16651665
if (!char_avail()) {
16661666
// flush output before waiting
16671667
ui_flush();
1668-
(void)os_inchar(NULL,0,-1,0,main_loop.events);
1668+
(void)os_inchar(NULL,0,-1,typebuf.tb_change_cnt,main_loop.events);
16691669
if (!multiqueue_empty(main_loop.events)) {
16701670
state_handle_k_event();
16711671
continue;

‎src/nvim/os/input.c‎

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ static RBuffer *input_buffer = NULL;
3838
staticboolinput_eof= false;
3939
staticintglobal_fd=-1;
4040
staticboolblocking= false;
41+
staticintcursorhold_time=0;///< time waiting for CursorHold event
42+
staticintcursorhold_tb_change_cnt=0;///< tb_change_cnt when waiting started
4143

4244
#ifdefINCLUDE_GENERATED_DECLARATIONS
4345
# include"os/input.c.generated.h"
@@ -97,13 +99,26 @@ static void create_cursorhold_event(bool events_enabled)
9799
multiqueue_put(main_loop.events,cursorhold_event,0);
98100
}
99101

102+
staticvoidrestart_cursorhold_wait(inttb_change_cnt)
103+
{
104+
cursorhold_time=0;
105+
cursorhold_tb_change_cnt=tb_change_cnt;
106+
}
107+
100108
/// Low level input function
101109
///
102110
/// wait until either the input buffer is non-empty or, if `events` is not NULL
103111
/// until `events` is non-empty.
104112
intos_inchar(uint8_t*buf,intmaxlen,intms,inttb_change_cnt,MultiQueue*events)
105113
{
114+
// This check is needed so that feeding typeahead from RPC can prevent CursorHold.
115+
// tb_change_cnt == 0 usually doesn't matter.
116+
if (tb_change_cnt!=cursorhold_tb_change_cnt) {
117+
restart_cursorhold_wait(tb_change_cnt);
118+
}
119+
106120
if (maxlen&&rbuffer_size(input_buffer)) {
121+
restart_cursorhold_wait(tb_change_cnt);
107122
return (int)rbuffer_read(input_buffer, (char*)buf, (size_t)maxlen);
108123
}
109124

@@ -118,18 +133,23 @@ int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *e
118133
return0;
119134
}
120135
}else {
121-
if ((result=inbuf_poll((int)p_ut,events))==kInputNone) {
136+
uint64_twait_start=os_hrtime();
137+
assert((int)p_ut >=cursorhold_time);
138+
if ((result=inbuf_poll((int)p_ut-cursorhold_time,events))==kInputNone) {
122139
if (read_stream.closed&&silent_mode) {
123140
// Drained eventloop & initial input; exit silent/batch-mode (-es/-Es).
124141
read_error_exit();
125142
}
126-
143+
restart_cursorhold_wait(tb_change_cnt);
127144
if (trigger_cursorhold()&& !typebuf_changed(tb_change_cnt)) {
128145
create_cursorhold_event(events==main_loop.events);
129146
}else {
130147
before_blocking();
131148
result=inbuf_poll(-1,events);
132149
}
150+
}else {
151+
cursorhold_time+= (int)(os_hrtime()-wait_start) /1000000;
152+
cursorhold_time=MIN(cursorhold_time, (int)p_ut);
133153
}
134154
}
135155

@@ -141,6 +161,7 @@ int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *e
141161
}
142162

143163
if (maxlen&&rbuffer_size(input_buffer)) {
164+
restart_cursorhold_wait(tb_change_cnt);
144165
// Safe to convert rbuffer_read to int, it will never overflow since we use
145166
// relatively small buffers.
146167
return (int)rbuffer_read(input_buffer, (char*)buf, (size_t)maxlen);

‎src/nvim/state.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ void state_enter(VimState *s)
6565
// Call `os_inchar` directly to block for events or user input without
6666
// consuming anything from `input_buffer`(os/input.c) or calling the
6767
// mapping engine.
68-
(void)os_inchar(NULL,0,-1,0,main_loop.events);
68+
(void)os_inchar(NULL,0,-1,typebuf.tb_change_cnt,main_loop.events);
6969
// If an event was put into the queue, we send K_EVENT directly.
7070
if (!multiqueue_empty(main_loop.events)) {
7171
key=K_EVENT;

‎test/functional/autocmd/cursorhold_spec.lua‎

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,58 @@ local eq = helpers.eq
55
localeval=helpers.eval
66
localfeed=helpers.feed
77
localretry=helpers.retry
8-
localsource=helpers.source
8+
localexec=helpers.source
99
localsleep=helpers.sleep
10+
localmeths=helpers.meths
1011

11-
describe('CursorHoldI',function()
12-
before_each(clear)
12+
before_each(clear)
13+
14+
describe('CursorHold',function()
15+
it('is triggered correctly #12587',function()
16+
exec([[
17+
set updatetime=40
18+
19+
let g:cursorhold = 0
20+
augroup test
21+
au CursorHold * let g:cursorhold += 1
22+
augroup END
23+
]])
24+
25+
localfunctiontest_cursorhold(fn,early)
26+
feed('0')-- reset did_cursorhold
27+
meths.set_var('cursorhold',0)
28+
sleep(10)
29+
fn()
30+
eq(0,meths.get_var('cursorhold'))
31+
sleep(20)
32+
fn()
33+
eq(0,meths.get_var('cursorhold'))
34+
sleep(20)
35+
eq(early,meths.get_var('cursorhold'))
36+
sleep(30)
37+
eq(1,meths.get_var('cursorhold'))
38+
end
1339

40+
localignore_key=meths.replace_termcodes('<Ignore>',true,true,true)
41+
test_cursorhold(function()end,1)
42+
test_cursorhold(function()feed('')end,1)
43+
test_cursorhold(function()meths.feedkeys('','n',true)end,1)
44+
test_cursorhold(function()feed('<Ignore>')end,0)
45+
test_cursorhold(function()meths.feedkeys(ignore_key,'n',true)end,0)
46+
end)
47+
end)
48+
49+
describe('CursorHoldI',function()
1450
-- NOTE: since this test uses RPC it is not necessary to trigger the initial
1551
-- issue (#3757) via timer's or RPC callbacks in the first place.
1652
it('is triggered after input',function()
17-
source([[
18-
set updatetime=1
53+
exec([[
54+
set updatetime=1
1955
20-
let g:cursorhold = 0
21-
augroup test
22-
au CursorHoldI * let g:cursorhold += 1
23-
augroup END
56+
let g:cursorhold = 0
57+
augroup test
58+
au CursorHoldI * let g:cursorhold += 1
59+
augroup END
2460
]])
2561
feed('ifoo')
2662
retry(5,nil,function()

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp