Skip to content

Commit 4e69a2d

Browse files
committed
Merge remote-tracking branch 'vim/master'
2 parents 61202ec + 247bf0d commit 4e69a2d

34 files changed

Lines changed: 788 additions & 167 deletions

runtime/doc/eval.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2535,6 +2535,7 @@ or({expr}, {expr}) Number bitwise OR
25352535
pathshorten({expr}) String shorten directory names in a path
25362536
perleval({expr}) any evaluate |Perl| expression
25372537
popup_atcursor({what}, {options}) Number create popup window near the cursor
2538+
popup_beval({what}, {options}) Number create popup window for 'ballooneval'
25382539
popup_clear() none close all popup windows
25392540
popup_close({id} [, {result}]) none close popup window {id}
25402541
popup_create({what}, {options}) Number create a popup window
@@ -2613,6 +2614,7 @@ screenattr({row}, {col}) Number attribute at screen position
26132614
screenchar({row}, {col}) Number character at screen position
26142615
screenchars({row}, {col}) List List of characters at screen position
26152616
screencol() Number current cursor column
2617+
screenpos({winid}, {lnum}, {col}) Dict screen row and col of a text character
26162618
screenrow() Number current cursor row
26172619
screenstring({row}, {col}) String characters at screen position
26182620
search({pattern} [, {flags} [, {stopline} [, {timeout}]]])
@@ -7907,6 +7909,23 @@ screencol() *screencol()*
79077909
nnoremap <expr> GG ":echom ".screencol()."\n"
79087910
nnoremap <silent> GG :echom screencol()<CR>
79097911
<
7912+
screenpos({winid}, {lnum}, {col}) *screenpos()*
7913+
The result is a Dict with the screen position of the text
7914+
character in window {winid} at buffer line {lnum} and column
7915+
{col}. {col} is a one-based byte index.
7916+
The Dict has these members:
7917+
row screen row
7918+
col first screen column
7919+
endcol last screen column
7920+
curscol cursor screen column
7921+
If the specified position is not visible, all values are zero.
7922+
The "endcol" value differs from "col" when the character
7923+
occupies more than one screen cell. E.g. for a Tab "col" can
7924+
be 1 and "endcol" can be 8.
7925+
The "curscol" value is where the cursor would be placed. For
7926+
a Tab it would be the same as "endcol", while for a double
7927+
width character it would be the same as "col".
7928+
79107929
screenrow() *screenrow()*
79117930
The result is a Number, which is the current screen row of the
79127931
cursor. The top line has number one.

runtime/doc/popup.txt

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ Creating a popup window:
146146
|popup_create()| centered in the screen
147147
|popup_atcursor()| just above the cursor position, closes when
148148
the cursor moves away
149+
|popup_beval()| at the position indicated by v:beval_
150+
variables, closes when the mouse moves away
149151
|popup_notification()| show a notification for three seconds
150152
|popup_dialog()| centered with padding and border
151153
|popup_menu()| prompt for selecting an item from a list
@@ -184,6 +186,20 @@ popup_atcursor({what}, {options}) *popup_atcursor()*
184186
< Use {options} to change the properties.
185187

186188

189+
popup_beval({what}, {options}) *popup_beval()*
190+
Show the {what} above the position from 'ballooneval' and
191+
close it when the mouse moves. This works like: >
192+
let pos = screenpos(v:beval_winnr, v:beval_lnum, v:beval_col)
193+
call popup_create({what}, {
194+
\ 'pos': 'botleft',
195+
\ 'line': pos.row - 1,
196+
\ 'col': pos.col,
197+
\ 'mousemoved': 'WORD',
198+
\ })
199+
< Use {options} to change the properties.
200+
See |popup_beval_example| for an example use.
201+
202+
187203
*popup_clear()*
188204
popup_clear() Emergency solution to a misbehaving plugin: close all popup
189205
windows for the current tab and global popups.
@@ -276,8 +292,11 @@ popup_getoptions({id}) *popup_getoptions()*
276292
A zero value means the option was not set. For "zindex" the
277293
default value is returned, not zero.
278294

279-
The "moved" entry is a list with minimum and maximum column,
280-
[0, 0] when not set.
295+
The "moved" entry is a list with line number, minimum and
296+
maximum column, [0, 0, 0] when not set.
297+
298+
The "mousemoved" entry is a list with screen row, minimum and
299+
maximum screen column, [0, 0, 0] when not set.
281300

282301
"border" and "padding" are not included when all values are
283302
zero. When all values are one then an empty list is included.
@@ -566,6 +585,7 @@ The second argument of |popup_create()| is a dictionary with options:
566585
- "any": if the cursor moved at all
567586
- "word": if the cursor moved outside |<cword>|
568587
- "WORD": if the cursor moved outside |<cWORD>|
588+
- "expr": if the cursor moved outside |<cexpr>|
569589
- [{start}, {end}]: if the cursor moved before column
570590
{start} or after {end}
571591
The popup also closes if the cursor moves to another
@@ -736,5 +756,56 @@ Extend popup_filter_menu() with shortcut keys: >
736756
return popup_filter_menu(a:id, a:key)
737757
endfunc
738758
<
759+
*popup_beval_example*
760+
Example for using a popup window for 'ballooneval': >
761+
762+
set ballooneval balloonevalterm
763+
set balloonexpr=BalloonExpr()
764+
let s:winid = 0
765+
let s:last_text = ''
766+
767+
func BalloonExpr()
768+
if s:winid && popup_getpos(s:winid) != {}
769+
" previous popup window still shows
770+
if v:beval_text == s:last_text
771+
" Still the same text, keep the existing popup
772+
return ''
773+
endif
774+
call popup_close(s:winid)
775+
endif
776+
let s:winid = popup_beval(v:beval_text, {'mousemoved': 'word'})
777+
let s:last_text = v:beval_text
778+
return ''
779+
endfunc
780+
<
781+
If the text has to be obtained asynchronously return an empty string from the
782+
expression function and call popup_beval() once the text is available. In
783+
this example simulated with a timer callback: >
784+
785+
set ballooneval balloonevalterm
786+
set balloonexpr=BalloonExpr()
787+
let s:winid = 0
788+
let s:balloonText = ''
789+
790+
func BalloonExpr()
791+
if s:winid && popup_getpos(s:winid) != {}
792+
" previous popup window still shows
793+
if v:beval_text == s:balloonText
794+
" Still the same text, keep the existing popup
795+
return ''
796+
endif
797+
call popup_close(s:winid)
798+
let s:winid = 0
799+
endif
800+
" simulate an asynchronous loopup for the text to display
801+
let s:balloonText = v:beval_text
802+
call timer_start(100, 'ShowPopup')
803+
return ''
804+
endfunc
805+
806+
func ShowPopup(id)
807+
let s:winid = popup_beval(s:balloonText, {'mousemoved': 'word'})
808+
endfunc
809+
<
739810

740811
vim:tw=78:ts=8:noet:ft=help:norl:

runtime/doc/usr_41.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,7 @@ Cursor and mark position: *cursor-functions* *mark-functions*
720720
cursor() position the cursor at a line/column
721721
screencol() get screen column of the cursor
722722
screenrow() get screen row of the cursor
723+
screenpos() screen row and col of a text character
723724
getcurpos() get position of the cursor
724725
getpos() get position of cursor, mark, etc.
725726
setpos() set position of cursor, mark, etc.
@@ -1046,6 +1047,8 @@ Popup window: *popup-window-functions*
10461047
popup_create() create popup centered in the screen
10471048
popup_atcursor() create popup just above the cursor position,
10481049
closes when the cursor moves away
1050+
popup_beval() at the position indicated by v:beval_
1051+
variables, closes when the mouse moves away
10491052
popup_notification() show a notification for three seconds
10501053
popup_dialog() create popup centered with padding and border
10511054
popup_menu() prompt for selecting an item from a list

src/beval.c

Lines changed: 95 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -10,61 +10,50 @@
1010

1111
#include "vim.h"
1212

13-
#if defined(FEAT_BEVAL) || defined(PROTO)
14-
13+
#if defined(FEAT_BEVAL) || defined(FEAT_TEXT_PROP) || defined(PROT)
1514
/*
16-
* Get the text and position to be evaluated for "beval".
17-
* If "getword" is true the returned text is not the whole line but the
18-
* relevant word in allocated memory.
19-
* Returns OK or FAIL.
15+
* Find text under the mouse position "row" / "col".
16+
* If "getword" is TRUE the returned text in "*textp" is not the whole line but
17+
* the relevant word in allocated memory.
18+
* Return OK if found.
19+
* Return FAIL if not found, no text at the mouse position.
2020
*/
2121
int
22-
get_beval_info(
23-
BalloonEval *beval,
24-
int getword,
25-
win_T **winp,
26-
linenr_T *lnump,
27-
char_u **textp,
28-
int *colp)
22+
find_word_under_cursor(
23+
int mouserow,
24+
int mousecol,
25+
int getword,
26+
int flags, // flags for find_ident_at_pos()
27+
win_T **winp, // can be NULL
28+
linenr_T *lnump, // can be NULL
29+
char_u **textp,
30+
int *colp, // column where mouse hovers, can be NULL
31+
int *startcolp) // column where text starts, can be NULL
2932
{
33+
int row = mouserow;
34+
int col = mousecol;
35+
int scol;
3036
win_T *wp;
31-
int row, col;
3237
char_u *lbuf;
3338
linenr_T lnum;
3439

3540
*textp = NULL;
36-
# ifdef FEAT_BEVAL_TERM
37-
# ifdef FEAT_GUI
38-
if (!gui.in_use)
39-
# endif
40-
{
41-
row = mouse_row;
42-
col = mouse_col;
43-
}
44-
# endif
45-
# ifdef FEAT_GUI
46-
if (gui.in_use)
47-
{
48-
row = Y_2_ROW(beval->y);
49-
col = X_2_COL(beval->x);
50-
}
51-
#endif
5241
wp = mouse_find_win(&row, &col, FAIL_POPUP);
5342
if (wp != NULL && row >= 0 && row < wp->w_height && col < wp->w_width)
5443
{
55-
/* Found a window and the cursor is in the text. Now find the line
56-
* number. */
44+
// Found a window and the cursor is in the text. Now find the line
45+
// number.
5746
if (!mouse_comp_pos(wp, &row, &col, &lnum))
5847
{
59-
/* Not past end of the file. */
48+
// Not past end of the file.
6049
lbuf = ml_get_buf(wp->w_buffer, lnum, FALSE);
6150
if (col <= win_linetabsize(wp, lbuf, (colnr_T)MAXCOL))
6251
{
63-
/* Not past end of line. */
52+
// Not past end of line.
6453
if (getword)
6554
{
66-
/* For Netbeans we get the relevant part of the line
67-
* instead of the whole line. */
55+
// For Netbeans we get the relevant part of the line
56+
// instead of the whole line.
6857
int len;
6958
pos_T *spos = NULL, *epos = NULL;
7059

@@ -93,9 +82,9 @@ get_beval_info(
9382
? col <= (int)epos->col
9483
: lnum < epos->lnum))
9584
{
96-
/* Visual mode and pointing to the line with the
97-
* Visual selection: return selected text, with a
98-
* maximum of one line. */
85+
// Visual mode and pointing to the line with the
86+
// Visual selection: return selected text, with a
87+
// maximum of one line.
9988
if (spos->lnum != epos->lnum || spos->col == epos->col)
10089
return FAIL;
10190

@@ -109,32 +98,78 @@ get_beval_info(
10998
}
11099
else
111100
{
112-
/* Find the word under the cursor. */
101+
// Find the word under the cursor.
113102
++emsg_off;
114-
len = find_ident_at_pos(wp, lnum, (colnr_T)col, &lbuf,
115-
FIND_IDENT + FIND_STRING + FIND_EVAL);
103+
len = find_ident_at_pos(wp, lnum, (colnr_T)col,
104+
&lbuf, &scol, flags);
116105
--emsg_off;
117106
if (len == 0)
118107
return FAIL;
119108
lbuf = vim_strnsave(lbuf, len);
120109
}
121110
}
122111

123-
*winp = wp;
124-
*lnump = lnum;
112+
if (winp != NULL)
113+
*winp = wp;
114+
if (lnump != NULL)
115+
*lnump = lnum;
125116
*textp = lbuf;
126-
*colp = col;
127-
#ifdef FEAT_VARTABS
128-
vim_free(beval->vts);
129-
beval->vts = tabstop_copy(wp->w_buffer->b_p_vts_array);
130-
if (wp->w_buffer->b_p_vts_array != NULL && beval->vts == NULL)
131-
return FAIL;
132-
#endif
133-
beval->ts = wp->w_buffer->b_p_ts;
117+
if (colp != NULL)
118+
*colp = col;
119+
if (startcolp != NULL)
120+
*startcolp = scol;
134121
return OK;
135122
}
136123
}
137124
}
125+
return FAIL;
126+
}
127+
#endif
128+
129+
#if defined(FEAT_BEVAL) || defined(PROTO)
130+
131+
/*
132+
* Get the text and position to be evaluated for "beval".
133+
* If "getword" is TRUE the returned text is not the whole line but the
134+
* relevant word in allocated memory.
135+
* Returns OK or FAIL.
136+
*/
137+
int
138+
get_beval_info(
139+
BalloonEval *beval,
140+
int getword,
141+
win_T **winp,
142+
linenr_T *lnump,
143+
char_u **textp,
144+
int *colp)
145+
{
146+
int row = mouse_row;
147+
int col = mouse_col;
148+
149+
# ifdef FEAT_GUI
150+
if (gui.in_use)
151+
{
152+
row = Y_2_ROW(beval->y);
153+
col = X_2_COL(beval->x);
154+
}
155+
#endif
156+
if (find_word_under_cursor(row, col, getword,
157+
FIND_IDENT + FIND_STRING + FIND_EVAL,
158+
winp, lnump, textp, colp, NULL) == OK)
159+
{
160+
#ifdef FEAT_VARTABS
161+
vim_free(beval->vts);
162+
beval->vts = tabstop_copy((*winp)->w_buffer->b_p_vts_array);
163+
if ((*winp)->w_buffer->b_p_vts_array != NULL && beval->vts == NULL)
164+
{
165+
if (getword)
166+
vim_free(*textp);
167+
return FAIL;
168+
}
169+
#endif
170+
beval->ts = (*winp)->w_buffer->b_p_ts;
171+
return OK;
172+
}
138173

139174
return FAIL;
140175
}
@@ -264,11 +299,15 @@ general_beval_cb(BalloonEval *beval, int state UNUSED)
264299

265300
set_vim_var_string(VV_BEVAL_TEXT, NULL, -1);
266301
if (result != NULL && result[0] != NUL)
267-
{
268302
post_balloon(beval, result, NULL);
269-
recursive = FALSE;
270-
return;
271-
}
303+
304+
// The 'balloonexpr' evaluation may show something on the screen
305+
// that requires a screen update.
306+
if (must_redraw)
307+
redraw_after_callback(FALSE);
308+
309+
recursive = FALSE;
310+
return;
272311
}
273312
}
274313
#endif

src/channel.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4032,7 +4032,7 @@ channel_send(
40324032
writeq_T *last = wq->wq_prev;
40334033

40344034
/* append to the last entry */
4035-
if (ga_grow(&last->wq_ga, len) == OK)
4035+
if (len > 0 && ga_grow(&last->wq_ga, len) == OK)
40364036
{
40374037
mch_memmove((char *)last->wq_ga.ga_data
40384038
+ last->wq_ga.ga_len,
@@ -4054,7 +4054,7 @@ channel_send(
40544054
wq->wq_prev->wq_next = last;
40554055
wq->wq_prev = last;
40564056
ga_init2(&last->wq_ga, 1, 1000);
4057-
if (ga_grow(&last->wq_ga, len) == OK)
4057+
if (len > 0 && ga_grow(&last->wq_ga, len) == OK)
40584058
{
40594059
mch_memmove(last->wq_ga.ga_data, buf, len);
40604060
last->wq_ga.ga_len = len;

0 commit comments

Comments
 (0)