mirror of
https://github.com/neovim/neovim.git
synced 2025-09-11 05:48:17 +00:00
vim-patch:8.2.2324: not easy to get mark en cursor posotion by character count
Problem: Not easy to get mark en cursor posotion by character count.
Solution: Add functions that use character index. (Yegappan Lakshmanan,
closes vim/vim#7648)
6f02b00bb0
This commit is contained in:
@@ -75,12 +75,13 @@ changenr() Number current change number
|
|||||||
chanclose({id}[, {stream}]) Number Closes a channel or one of its streams
|
chanclose({id}[, {stream}]) Number Closes a channel or one of its streams
|
||||||
chansend({id}, {data}) Number Writes {data} to channel
|
chansend({id}, {data}) Number Writes {data} to channel
|
||||||
char2nr({expr}[, {utf8}]) Number ASCII/UTF-8 value of first char in {expr}
|
char2nr({expr}[, {utf8}]) Number ASCII/UTF-8 value of first char in {expr}
|
||||||
|
charcol({expr}) Number column number of cursor or mark
|
||||||
charidx({string}, {idx} [, {countcc}])
|
charidx({string}, {idx} [, {countcc}])
|
||||||
Number char index of byte {idx} in {string}
|
Number char index of byte {idx} in {string}
|
||||||
chdir({dir}) String change current working directory
|
chdir({dir}) String change current working directory
|
||||||
cindent({lnum}) Number C indent for line {lnum}
|
cindent({lnum}) Number C indent for line {lnum}
|
||||||
clearmatches([{win}]) none clear all matches
|
clearmatches([{win}]) none clear all matches
|
||||||
col({expr}) Number column nr of cursor or mark
|
col({expr}) Number column byte index of cursor or mark
|
||||||
complete({startcol}, {matches}) none set Insert mode completion
|
complete({startcol}, {matches}) none set Insert mode completion
|
||||||
complete_add({expr}) Number add completion match
|
complete_add({expr}) Number add completion match
|
||||||
complete_check() Number check for key typed during completion
|
complete_check() Number check for key typed during completion
|
||||||
@@ -170,6 +171,7 @@ getchangelist([{buf}]) List list of change list items
|
|||||||
getchar([expr]) Number or String
|
getchar([expr]) Number or String
|
||||||
get one character from the user
|
get one character from the user
|
||||||
getcharmod() Number modifiers for the last typed character
|
getcharmod() Number modifiers for the last typed character
|
||||||
|
getcharpos({expr}) List position of cursor, mark, etc.
|
||||||
getcharsearch() Dict last character search
|
getcharsearch() Dict last character search
|
||||||
getcharstr([expr]) String get one character from the user
|
getcharstr([expr]) String get one character from the user
|
||||||
getcmdline() String return the current command-line
|
getcmdline() String return the current command-line
|
||||||
@@ -179,6 +181,7 @@ getcmdwintype() String return current command-line window type
|
|||||||
getcompletion({pat}, {type} [, {filtered}])
|
getcompletion({pat}, {type} [, {filtered}])
|
||||||
List list of cmdline completion matches
|
List list of cmdline completion matches
|
||||||
getcurpos([{winnr}]) List position of the cursor
|
getcurpos([{winnr}]) List position of the cursor
|
||||||
|
getcursorcharpos([{winnr}]) List character position of the cursor
|
||||||
getcwd([{winnr} [, {tabnr}]]) String get the current working directory
|
getcwd([{winnr} [, {tabnr}]]) String get the current working directory
|
||||||
getenv({name}) String return environment variable
|
getenv({name}) String return environment variable
|
||||||
getfontname([{name}]) String name of font being used
|
getfontname([{name}]) String name of font being used
|
||||||
@@ -387,8 +390,10 @@ setbufline( {expr}, {lnum}, {line})
|
|||||||
Number set line {lnum} to {line} in buffer
|
Number set line {lnum} to {line} in buffer
|
||||||
{expr}
|
{expr}
|
||||||
setbufvar({buf}, {varname}, {val}) set {varname} in buffer {buf} to {val}
|
setbufvar({buf}, {varname}, {val}) set {varname} in buffer {buf} to {val}
|
||||||
|
setcharpos({expr}, {list}) Number set the {expr} position to {list}
|
||||||
setcharsearch({dict}) Dict set character search from {dict}
|
setcharsearch({dict}) Dict set character search from {dict}
|
||||||
setcmdpos({pos}) Number set cursor position in command-line
|
setcmdpos({pos}) Number set cursor position in command-line
|
||||||
|
setcursorcharpos({list}) Number move cursor to position in {list}
|
||||||
setenv({name}, {val}) none set environment variable
|
setenv({name}, {val}) none set environment variable
|
||||||
setfperm({fname}, {mode} Number set {fname} file permissions to {mode}
|
setfperm({fname}, {mode} Number set {fname} file permissions to {mode}
|
||||||
setline({lnum}, {line}) Number set line {lnum} to {line}
|
setline({lnum}, {line}) Number set line {lnum} to {line}
|
||||||
@@ -949,8 +954,8 @@ byteidxcomp({expr}, {nr}) *byteidxcomp()*
|
|||||||
< The first and third echo result in 3 ('e' plus composing
|
< The first and third echo result in 3 ('e' plus composing
|
||||||
character is 3 bytes), the second echo results in 1 ('e' is
|
character is 3 bytes), the second echo results in 1 ('e' is
|
||||||
one byte).
|
one byte).
|
||||||
Only works differently from byteidx() when 'encoding' is set to
|
Only works differently from byteidx() when 'encoding' is set
|
||||||
a Unicode encoding.
|
to a Unicode encoding.
|
||||||
|
|
||||||
Can also be used as a |method|: >
|
Can also be used as a |method|: >
|
||||||
GetName()->byteidxcomp(idx)
|
GetName()->byteidxcomp(idx)
|
||||||
@@ -1034,6 +1039,18 @@ char2nr({string} [, {utf8}]) *char2nr()*
|
|||||||
|
|
||||||
Can also be used as a |method|: >
|
Can also be used as a |method|: >
|
||||||
GetChar()->char2nr()
|
GetChar()->char2nr()
|
||||||
|
<
|
||||||
|
*charcol()*
|
||||||
|
charcol({expr}) Same as |col()| but returns the character index of the column
|
||||||
|
position given with {expr} instead of the byte position.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
With the cursor on '세' in line 5 with text "여보세요": >
|
||||||
|
charcol('.') returns 3
|
||||||
|
col('.') returns 7
|
||||||
|
|
||||||
|
< Can also be used as a |method|: >
|
||||||
|
GetPos()->col()
|
||||||
<
|
<
|
||||||
*charidx()*
|
*charidx()*
|
||||||
charidx({string}, {idx} [, {countcc}])
|
charidx({string}, {idx} [, {countcc}])
|
||||||
@@ -1120,7 +1137,8 @@ col({expr}) The result is a Number, which is the byte index of the column
|
|||||||
out of range then col() returns zero.
|
out of range then col() returns zero.
|
||||||
To get the line number use |line()|. To get both use
|
To get the line number use |line()|. To get both use
|
||||||
|getpos()|.
|
|getpos()|.
|
||||||
For the screen column position use |virtcol()|.
|
For the screen column position use |virtcol()|. For the
|
||||||
|
character position use |charcol()|.
|
||||||
Note that only marks in the current file can be used.
|
Note that only marks in the current file can be used.
|
||||||
Examples: >
|
Examples: >
|
||||||
col(".") column of cursor
|
col(".") column of cursor
|
||||||
@@ -1443,6 +1461,9 @@ cursor({list})
|
|||||||
This is like the return value of |getpos()| or |getcurpos()|,
|
This is like the return value of |getpos()| or |getcurpos()|,
|
||||||
but without the first item.
|
but without the first item.
|
||||||
|
|
||||||
|
To position the cursor using the character count, use
|
||||||
|
|setcursorcharpos()|.
|
||||||
|
|
||||||
Does not change the jumplist.
|
Does not change the jumplist.
|
||||||
If {lnum} is greater than the number of lines in the buffer,
|
If {lnum} is greater than the number of lines in the buffer,
|
||||||
the cursor will be positioned at the last line in the buffer.
|
the cursor will be positioned at the last line in the buffer.
|
||||||
@@ -2652,6 +2673,20 @@ getcharmod() *getcharmod()*
|
|||||||
character itself are obtained. Thus Shift-a results in "A"
|
character itself are obtained. Thus Shift-a results in "A"
|
||||||
without a modifier.
|
without a modifier.
|
||||||
|
|
||||||
|
*getcharpos()*
|
||||||
|
getcharpos({expr})
|
||||||
|
Get the position for {expr}. Same as |getpos()| but the column
|
||||||
|
number in the returned List is a character index instead of
|
||||||
|
a byte index.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
With the cursor on '세' in line 5 with text "여보세요": >
|
||||||
|
getcharpos('.') returns [0, 5, 3, 0]
|
||||||
|
getpos('.') returns [0, 5, 7, 0]
|
||||||
|
<
|
||||||
|
Can also be used as a |method|: >
|
||||||
|
GetMark()->getcharpos()
|
||||||
|
|
||||||
getcharsearch() *getcharsearch()*
|
getcharsearch() *getcharsearch()*
|
||||||
Return the current character search information as a {dict}
|
Return the current character search information as a {dict}
|
||||||
with the following entries:
|
with the following entries:
|
||||||
@@ -2791,8 +2826,11 @@ getcurpos([{winid}])
|
|||||||
includes an extra "curswant" in the list:
|
includes an extra "curswant" in the list:
|
||||||
[0, lnum, col, off, curswant] ~
|
[0, lnum, col, off, curswant] ~
|
||||||
The "curswant" number is the preferred column when moving the
|
The "curswant" number is the preferred column when moving the
|
||||||
cursor vertically. Also see |getpos()|.
|
cursor vertically. Also see |getcursorcharpos()| and
|
||||||
The first "bufnum" item is always zero.
|
|getpos()|.
|
||||||
|
The first "bufnum" item is always zero. The byte position of
|
||||||
|
the cursor is returned in 'col'. To get the character
|
||||||
|
position, use |getcursorcharpos()|.
|
||||||
|
|
||||||
The optional {winid} argument can specify the window. It can
|
The optional {winid} argument can specify the window. It can
|
||||||
be the window number or the |window-ID|. The last known
|
be the window number or the |window-ID|. The last known
|
||||||
@@ -2807,6 +2845,22 @@ getcurpos([{winid}])
|
|||||||
< Note that this only works within the window. See
|
< Note that this only works within the window. See
|
||||||
|winrestview()| for restoring more state.
|
|winrestview()| for restoring more state.
|
||||||
|
|
||||||
|
Can also be used as a |method|: >
|
||||||
|
GetWinid()->getcurpos()
|
||||||
|
|
||||||
|
< *getcursorcharpos()*
|
||||||
|
getcursorcharpos([{winid}])
|
||||||
|
Same as |getcurpos()| but the column number in the returned
|
||||||
|
List is a character index instead of a byte index.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
With the cursor on '보' in line 3 with text "여보세요": >
|
||||||
|
getcursorcharpos() returns [0, 3, 2, 0, 3]
|
||||||
|
getcurpos() returns [0, 3, 4, 0, 3]
|
||||||
|
|
||||||
|
< Can also be used as a |method|: >
|
||||||
|
GetWinid()->getcursorcharpos()
|
||||||
|
|
||||||
getcwd([{winnr}[, {tabnr}]]) *getcwd()*
|
getcwd([{winnr}[, {tabnr}]]) *getcwd()*
|
||||||
With no arguments, returns the name of the effective
|
With no arguments, returns the name of the effective
|
||||||
|current-directory|. With {winnr} or {tabnr} the working
|
|current-directory|. With {winnr} or {tabnr} the working
|
||||||
@@ -3086,14 +3140,15 @@ getpos({expr}) Get the position for String {expr}. For possible values of
|
|||||||
(visual line mode) the column of '< is zero and the column of
|
(visual line mode) the column of '< is zero and the column of
|
||||||
'> is a large number.
|
'> is a large number.
|
||||||
The column number in the returned List is the byte position
|
The column number in the returned List is the byte position
|
||||||
within the line.
|
within the line. To get the character position in the line,
|
||||||
|
use |getcharpos()|
|
||||||
The column number can be very large, e.g. 2147483647, in which
|
The column number can be very large, e.g. 2147483647, in which
|
||||||
case it means "after the end of the line".
|
case it means "after the end of the line".
|
||||||
This can be used to save and restore the position of a mark: >
|
This can be used to save and restore the position of a mark: >
|
||||||
let save_a_mark = getpos("'a")
|
let save_a_mark = getpos("'a")
|
||||||
...
|
...
|
||||||
call setpos("'a", save_a_mark)
|
call setpos("'a", save_a_mark)
|
||||||
< Also see |getcurpos()| and |setpos()|.
|
< Also see |getcharpos()|, |getcurpos()| and |setpos()|.
|
||||||
|
|
||||||
Can also be used as a |method|: >
|
Can also be used as a |method|: >
|
||||||
GetMark()->getpos()
|
GetMark()->getpos()
|
||||||
@@ -4855,8 +4910,10 @@ matchstrpos({expr}, {pat} [, {start} [, {count}]]) *matchstrpos()*
|
|||||||
GetText()->matchstrpos('word')
|
GetText()->matchstrpos('word')
|
||||||
<
|
<
|
||||||
*max()*
|
*max()*
|
||||||
max({expr}) Return the maximum value of all items in {expr}.
|
max({expr}) Return the maximum value of all items in {expr}. Example: >
|
||||||
{expr} can be a |List| or a |Dictionary|. For a Dictionary,
|
echo max([apples, pears, oranges])
|
||||||
|
|
||||||
|
< {expr} can be a |List| or a |Dictionary|. For a Dictionary,
|
||||||
it returns the maximum of all values in the Dictionary.
|
it returns the maximum of all values in the Dictionary.
|
||||||
If {expr} is neither a List nor a Dictionary, or one of the
|
If {expr} is neither a List nor a Dictionary, or one of the
|
||||||
items in {expr} cannot be used as a Number this results in
|
items in {expr} cannot be used as a Number this results in
|
||||||
@@ -4912,8 +4969,10 @@ menu_get({path} [, {modes}]) *menu_get()*
|
|||||||
<
|
<
|
||||||
|
|
||||||
*min()*
|
*min()*
|
||||||
min({expr}) Return the minimum value of all items in {expr}.
|
min({expr}) Return the minimum value of all items in {expr}. Example: >
|
||||||
{expr} can be a |List| or a |Dictionary|. For a Dictionary,
|
echo min([apples, pears, oranges])
|
||||||
|
|
||||||
|
< {expr} can be a |List| or a |Dictionary|. For a Dictionary,
|
||||||
it returns the minimum of all values in the Dictionary.
|
it returns the minimum of all values in the Dictionary.
|
||||||
If {expr} is neither a List nor a Dictionary, or one of the
|
If {expr} is neither a List nor a Dictionary, or one of the
|
||||||
items in {expr} cannot be used as a Number this results in
|
items in {expr} cannot be used as a Number this results in
|
||||||
@@ -6454,6 +6513,20 @@ setbufvar({buf}, {varname}, {val}) *setbufvar()*
|
|||||||
third argument: >
|
third argument: >
|
||||||
GetValue()->setbufvar(buf, varname)
|
GetValue()->setbufvar(buf, varname)
|
||||||
|
|
||||||
|
setcharpos({expr}, {list}) *setcharpos()*
|
||||||
|
Same as |setpos()| but uses the specified column number as the
|
||||||
|
character index instead of the byte index in the line.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
With the text "여보세요" in line 8: >
|
||||||
|
call setcharpos('.', [0, 8, 4, 0])
|
||||||
|
< positions the cursor on the fourth character '요'. >
|
||||||
|
call setpos('.', [0, 8, 4, 0])
|
||||||
|
< positions the cursor on the second character '보'.
|
||||||
|
|
||||||
|
Can also be used as a |method|: >
|
||||||
|
GetPosition()->setcharpos('.')
|
||||||
|
|
||||||
setcharsearch({dict}) *setcharsearch()*
|
setcharsearch({dict}) *setcharsearch()*
|
||||||
Set the current character search information to {dict},
|
Set the current character search information to {dict},
|
||||||
which contains one or more of the following entries:
|
which contains one or more of the following entries:
|
||||||
@@ -6495,6 +6568,21 @@ setcmdpos({pos}) *setcmdpos()*
|
|||||||
Can also be used as a |method|: >
|
Can also be used as a |method|: >
|
||||||
GetPos()->setcmdpos()
|
GetPos()->setcmdpos()
|
||||||
|
|
||||||
|
setcursorcharpos({lnum}, {col} [, {off}]) *setcursorcharpos()*
|
||||||
|
setcursorcharpos({list})
|
||||||
|
Same as |cursor()| but uses the specified column number as the
|
||||||
|
character index instead of the byte index in the line.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
With the text "여보세요" in line 4: >
|
||||||
|
call setcursorcharpos(4, 3)
|
||||||
|
< positions the cursor on the third character '세'. >
|
||||||
|
call cursor(4, 3)
|
||||||
|
< positions the cursor on the first character '여'.
|
||||||
|
|
||||||
|
Can also be used as a |method|: >
|
||||||
|
GetCursorPos()->setcursorcharpos()
|
||||||
|
|
||||||
setenv({name}, {val}) *setenv()*
|
setenv({name}, {val}) *setenv()*
|
||||||
Set environment variable {name} to {val}. Example: >
|
Set environment variable {name} to {val}. Example: >
|
||||||
call setenv('HOME', '/home/myhome')
|
call setenv('HOME', '/home/myhome')
|
||||||
@@ -6607,7 +6695,8 @@ setpos({expr}, {list})
|
|||||||
|
|
||||||
"lnum" and "col" are the position in the buffer. The first
|
"lnum" and "col" are the position in the buffer. The first
|
||||||
column is 1. Use a zero "lnum" to delete a mark. If "col" is
|
column is 1. Use a zero "lnum" to delete a mark. If "col" is
|
||||||
smaller than 1 then 1 is used.
|
smaller than 1 then 1 is used. To use the character count
|
||||||
|
instead of the byte count, use |setcharpos()|.
|
||||||
|
|
||||||
The "off" number is only used when 'virtualedit' is set. Then
|
The "off" number is only used when 'virtualedit' is set. Then
|
||||||
it is the offset in screen columns from the start of the
|
it is the offset in screen columns from the start of the
|
||||||
@@ -6627,7 +6716,7 @@ setpos({expr}, {list})
|
|||||||
Returns 0 when the position could be set, -1 otherwise.
|
Returns 0 when the position could be set, -1 otherwise.
|
||||||
An error message is given if {expr} is invalid.
|
An error message is given if {expr} is invalid.
|
||||||
|
|
||||||
Also see |getpos()| and |getcurpos()|.
|
Also see |setcharpos()|, |getpos()| and |getcurpos()|.
|
||||||
|
|
||||||
This does not restore the preferred column for moving
|
This does not restore the preferred column for moving
|
||||||
vertically; if you set the cursor position with this, |j| and
|
vertically; if you set the cursor position with this, |j| and
|
||||||
|
@@ -1066,7 +1066,7 @@ expr7 *expr7*
|
|||||||
|
|
||||||
For '!' |TRUE| becomes |FALSE|, |FALSE| becomes |TRUE| (one).
|
For '!' |TRUE| becomes |FALSE|, |FALSE| becomes |TRUE| (one).
|
||||||
For '-' the sign of the number is changed.
|
For '-' the sign of the number is changed.
|
||||||
For '+' the number is unchanged.
|
For '+' the number is unchanged. Note: "++" has no effect.
|
||||||
|
|
||||||
A String will be converted to a Number first.
|
A String will be converted to a Number first.
|
||||||
|
|
||||||
@@ -1228,8 +1228,8 @@ And NOT: >
|
|||||||
number
|
number
|
||||||
------
|
------
|
||||||
number number constant *expr-number*
|
number number constant *expr-number*
|
||||||
*hex-number* *octal-number* *binary-number*
|
|
||||||
|
|
||||||
|
*0x* *hex-number* *0o* *octal-number* *binary-number*
|
||||||
Decimal, Hexadecimal (starting with 0x or 0X), Binary (starting with 0b or 0B)
|
Decimal, Hexadecimal (starting with 0x or 0X), Binary (starting with 0b or 0B)
|
||||||
and Octal (starting with 0, 0o or 0O).
|
and Octal (starting with 0, 0o or 0O).
|
||||||
|
|
||||||
@@ -1486,7 +1486,7 @@ Notice how execute() is used to execute an Ex command. That's ugly though.
|
|||||||
|
|
||||||
Lambda expressions have internal names like '<lambda>42'. If you get an error
|
Lambda expressions have internal names like '<lambda>42'. If you get an error
|
||||||
for a lambda expression, you can find what it is with the following command: >
|
for a lambda expression, you can find what it is with the following command: >
|
||||||
:function {'<lambda>42'}
|
:function <lambda>42
|
||||||
See also: |numbered-function|
|
See also: |numbered-function|
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
@@ -746,6 +746,11 @@ Cursor and mark position: *cursor-functions* *mark-functions*
|
|||||||
screenchar() get character code at a screen line/row
|
screenchar() get character code at a screen line/row
|
||||||
screenchars() get character codes at a screen line/row
|
screenchars() get character codes at a screen line/row
|
||||||
screenstring() get string of characters at a screen line/row
|
screenstring() get string of characters at a screen line/row
|
||||||
|
charcol() character number of the cursor or a mark
|
||||||
|
getcharpos() get character position of cursor, mark, etc.
|
||||||
|
setcharpos() set character position of cursor, mark, etc.
|
||||||
|
getcursorcharpos() get character position of the cursor
|
||||||
|
setcursorcharpos() set character position of the cursor
|
||||||
|
|
||||||
Working with text in the current buffer: *text-functions*
|
Working with text in the current buffer: *text-functions*
|
||||||
getline() get a line or list of lines from the buffer
|
getline() get a line or list of lines from the buffer
|
||||||
|
105
src/nvim/eval.c
105
src/nvim/eval.c
@@ -8151,6 +8151,52 @@ char *save_tv_as_string(typval_T *tv, ptrdiff_t *const len, bool endnl)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert the specified byte index of line 'lnum' in buffer 'buf' to a
|
||||||
|
/// character index. Works only for loaded buffers. Returns -1 on failure.
|
||||||
|
/// The index of the first character is one.
|
||||||
|
int buf_byteidx_to_charidx(buf_T *buf, int lnum, int byteidx)
|
||||||
|
{
|
||||||
|
if (buf == NULL || buf->b_ml.ml_mfp == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lnum > buf->b_ml.ml_line_count) {
|
||||||
|
lnum = buf->b_ml.ml_line_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
char_u *str = ml_get_buf(buf, lnum, false);
|
||||||
|
|
||||||
|
if (*str == NUL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mb_charlen_len(str, byteidx + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert the specified character index of line 'lnum' in buffer 'buf' to a
|
||||||
|
/// byte index. Works only for loaded buffers. Returns -1 on failure. The index
|
||||||
|
/// of the first byte and the first character is one.
|
||||||
|
int buf_charidx_to_byteidx(buf_T *buf, int lnum, int charidx)
|
||||||
|
{
|
||||||
|
if (buf == NULL || buf->b_ml.ml_mfp == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lnum > buf->b_ml.ml_line_count) {
|
||||||
|
lnum = buf->b_ml.ml_line_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
char_u *str = ml_get_buf(buf, lnum, false);
|
||||||
|
|
||||||
|
// Convert the character offset to a byte offset
|
||||||
|
char_u *t = str;
|
||||||
|
while (*t != NUL && --charidx > 0) {
|
||||||
|
t += utfc_ptr2len(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
return t - str + 1;
|
||||||
|
}
|
||||||
|
|
||||||
/// Translate a VimL object into a position
|
/// Translate a VimL object into a position
|
||||||
///
|
///
|
||||||
/// Accepts VAR_LIST and VAR_STRING objects. Does not give an error for invalid
|
/// Accepts VAR_LIST and VAR_STRING objects. Does not give an error for invalid
|
||||||
@@ -8159,9 +8205,11 @@ char *save_tv_as_string(typval_T *tv, ptrdiff_t *const len, bool endnl)
|
|||||||
/// @param[in] tv Object to translate.
|
/// @param[in] tv Object to translate.
|
||||||
/// @param[in] dollar_lnum True when "$" is last line.
|
/// @param[in] dollar_lnum True when "$" is last line.
|
||||||
/// @param[out] ret_fnum Set to fnum for marks.
|
/// @param[out] ret_fnum Set to fnum for marks.
|
||||||
|
/// @param[in] charcol True to return character column.
|
||||||
///
|
///
|
||||||
/// @return Pointer to position or NULL in case of error (e.g. invalid type).
|
/// @return Pointer to position or NULL in case of error (e.g. invalid type).
|
||||||
pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret_fnum)
|
pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret_fnum,
|
||||||
|
const bool charcol)
|
||||||
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
static pos_T pos;
|
static pos_T pos;
|
||||||
@@ -8191,7 +8239,11 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret
|
|||||||
if (error) {
|
if (error) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
len = (long)STRLEN(ml_get(pos.lnum));
|
if (charcol) {
|
||||||
|
len = mb_charlen(ml_get(pos.lnum));
|
||||||
|
} else {
|
||||||
|
len = STRLEN(ml_get(pos.lnum));
|
||||||
|
}
|
||||||
|
|
||||||
// We accept "$" for the column number: last column.
|
// We accept "$" for the column number: last column.
|
||||||
li = tv_list_find(l, 1L);
|
li = tv_list_find(l, 1L);
|
||||||
@@ -8222,19 +8274,31 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (name[0] == '.') { // Cursor.
|
if (name[0] == '.') { // Cursor.
|
||||||
return &curwin->w_cursor;
|
pos = curwin->w_cursor;
|
||||||
|
if (charcol) {
|
||||||
|
pos.col = buf_byteidx_to_charidx(curbuf, pos.lnum, pos.col) - 1;
|
||||||
|
}
|
||||||
|
return &pos;
|
||||||
}
|
}
|
||||||
if (name[0] == 'v' && name[1] == NUL) { // Visual start.
|
if (name[0] == 'v' && name[1] == NUL) { // Visual start.
|
||||||
if (VIsual_active) {
|
if (VIsual_active) {
|
||||||
return &VIsual;
|
pos = VIsual;
|
||||||
|
} else {
|
||||||
|
pos = curwin->w_cursor;
|
||||||
}
|
}
|
||||||
return &curwin->w_cursor;
|
if (charcol) {
|
||||||
|
pos.col = buf_byteidx_to_charidx(curbuf, pos.lnum, pos.col) - 1;
|
||||||
|
}
|
||||||
|
return &pos;
|
||||||
}
|
}
|
||||||
if (name[0] == '\'') { // Mark.
|
if (name[0] == '\'') { // Mark.
|
||||||
pp = getmark_buf_fnum(curbuf, (uint8_t)name[1], false, ret_fnum);
|
pp = getmark_buf_fnum(curbuf, (uint8_t)name[1], false, ret_fnum);
|
||||||
if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0) {
|
if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (charcol) {
|
||||||
|
pp->col = buf_byteidx_to_charidx(curbuf, pp->lnum, pp->col) - 1;
|
||||||
|
}
|
||||||
return pp;
|
return pp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8260,22 +8324,24 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret
|
|||||||
pos.col = 0;
|
pos.col = 0;
|
||||||
} else {
|
} else {
|
||||||
pos.lnum = curwin->w_cursor.lnum;
|
pos.lnum = curwin->w_cursor.lnum;
|
||||||
pos.col = (colnr_T)STRLEN(get_cursor_line_ptr());
|
if (charcol) {
|
||||||
|
pos.col = (colnr_T)mb_charlen(get_cursor_line_ptr());
|
||||||
|
} else {
|
||||||
|
pos.col = (colnr_T)STRLEN(get_cursor_line_ptr());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return &pos;
|
return &pos;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Convert list in "arg" into a position and optional file number.
|
||||||
* Convert list in "arg" into a position and optional file number.
|
/// When "fnump" is NULL there is no file number, only 3 items.
|
||||||
* When "fnump" is NULL there is no file number, only 3 items.
|
/// Note that the column is passed on as-is, the caller may want to decrement
|
||||||
* Note that the column is passed on as-is, the caller may want to decrement
|
/// it to use 1 for the first column.
|
||||||
* it to use 1 for the first column.
|
/// Return FAIL when conversion is not possible, doesn't check the position for
|
||||||
* Return FAIL when conversion is not possible, doesn't check the position for
|
/// validity.
|
||||||
* validity.
|
int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp, bool charcol)
|
||||||
*/
|
|
||||||
int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp)
|
|
||||||
{
|
{
|
||||||
list_T *l;
|
list_T *l;
|
||||||
long i = 0;
|
long i = 0;
|
||||||
@@ -8311,6 +8377,15 @@ int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp)
|
|||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
// If character position is specified, then convert to byte position
|
||||||
|
if (charcol) {
|
||||||
|
// Get the text for the specified line in a loaded buffer
|
||||||
|
buf_T *buf = buflist_findnr(fnump == NULL ? curbuf->b_fnum : *fnump);
|
||||||
|
if (buf == NULL || buf->b_ml.ml_mfp == NULL) {
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
n = buf_charidx_to_byteidx(buf, posp->lnum, n);
|
||||||
|
}
|
||||||
posp->col = n;
|
posp->col = n;
|
||||||
|
|
||||||
n = tv_list_find_nr(l, i, NULL); // off
|
n = tv_list_find_nr(l, i, NULL); // off
|
||||||
|
@@ -71,6 +71,7 @@ return {
|
|||||||
chanclose={args={1, 2}},
|
chanclose={args={1, 2}},
|
||||||
chansend={args=2},
|
chansend={args=2},
|
||||||
char2nr={args={1, 2}, base=1},
|
char2nr={args={1, 2}, base=1},
|
||||||
|
charcol={args=1, base=1},
|
||||||
charidx={args={2, 3}, base=1},
|
charidx={args={2, 3}, base=1},
|
||||||
chdir={args=1, base=1},
|
chdir={args=1, base=1},
|
||||||
cindent={args=1, base=1},
|
cindent={args=1, base=1},
|
||||||
@@ -144,6 +145,7 @@ return {
|
|||||||
getchangelist={args={0, 1}, base=1},
|
getchangelist={args={0, 1}, base=1},
|
||||||
getchar={args={0, 1}},
|
getchar={args={0, 1}},
|
||||||
getcharmod={},
|
getcharmod={},
|
||||||
|
getcharpos={args=1, base=1},
|
||||||
getcharsearch={},
|
getcharsearch={},
|
||||||
getcharstr={args={0, 1}},
|
getcharstr={args={0, 1}},
|
||||||
getcmdline={},
|
getcmdline={},
|
||||||
@@ -152,6 +154,7 @@ return {
|
|||||||
getcmdwintype={},
|
getcmdwintype={},
|
||||||
getcompletion={args={2, 3}, base=1},
|
getcompletion={args={2, 3}, base=1},
|
||||||
getcurpos={args={0, 1}, base=1},
|
getcurpos={args={0, 1}, base=1},
|
||||||
|
getcursorcharpos={args={0, 1}, base=1},
|
||||||
getcwd={args={0, 2}, base=1},
|
getcwd={args={0, 2}, base=1},
|
||||||
getenv={args=1, base=1},
|
getenv={args=1, base=1},
|
||||||
getfontname={args={0, 1}},
|
getfontname={args={0, 1}},
|
||||||
@@ -312,8 +315,10 @@ return {
|
|||||||
serverstop={args=1},
|
serverstop={args=1},
|
||||||
setbufline={args=3, base=3},
|
setbufline={args=3, base=3},
|
||||||
setbufvar={args=3, base=3},
|
setbufvar={args=3, base=3},
|
||||||
|
setcharpos={args=2, base=2},
|
||||||
setcharsearch={args=1, base=1},
|
setcharsearch={args=1, base=1},
|
||||||
setcmdpos={args=1, base=1},
|
setcmdpos={args=1, base=1},
|
||||||
|
setcursorcharpos={args={1, 3}, base=1},
|
||||||
setenv={args=2, base=2},
|
setenv={args=2, base=2},
|
||||||
setfperm={args=2, base=1},
|
setfperm={args=2, base=1},
|
||||||
setline={args=2, base=2},
|
setline={args=2, base=2},
|
||||||
|
@@ -1020,6 +1020,49 @@ static void f_char2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
rettv->vval.v_number = utf_ptr2char((const char_u *)tv_get_string(&argvars[0]));
|
rettv->vval.v_number = utf_ptr2char((const char_u *)tv_get_string(&argvars[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the current cursor column and store it in 'rettv'. If 'charcol' is true,
|
||||||
|
/// returns the character index of the column. Otherwise, returns the byte index
|
||||||
|
/// of the column.
|
||||||
|
static void get_col(typval_T *argvars, typval_T *rettv, bool charcol)
|
||||||
|
{
|
||||||
|
colnr_T col = 0;
|
||||||
|
pos_T *fp;
|
||||||
|
int fnum = curbuf->b_fnum;
|
||||||
|
|
||||||
|
fp = var2fpos(&argvars[0], false, &fnum, charcol);
|
||||||
|
if (fp != NULL && fnum == curbuf->b_fnum) {
|
||||||
|
if (fp->col == MAXCOL) {
|
||||||
|
// '> can be MAXCOL, get the length of the line then
|
||||||
|
if (fp->lnum <= curbuf->b_ml.ml_line_count) {
|
||||||
|
col = (colnr_T)STRLEN(ml_get(fp->lnum)) + 1;
|
||||||
|
} else {
|
||||||
|
col = MAXCOL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
col = fp->col + 1;
|
||||||
|
// col(".") when the cursor is on the NUL at the end of the line
|
||||||
|
// because of "coladd" can be seen as an extra column.
|
||||||
|
if (virtual_active() && fp == &curwin->w_cursor) {
|
||||||
|
char_u *p = get_cursor_pos_ptr();
|
||||||
|
if (curwin->w_cursor.coladd >=
|
||||||
|
(colnr_T)win_chartabsize(curwin, p, curwin->w_virtcol - curwin->w_cursor.coladd)) {
|
||||||
|
int l;
|
||||||
|
if (*p != NUL && p[(l = utfc_ptr2len(p))] == NUL) {
|
||||||
|
col += l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rettv->vval.v_number = col;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// "charcol()" function
|
||||||
|
static void f_charcol(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
|
{
|
||||||
|
get_col(argvars, rettv, true);
|
||||||
|
}
|
||||||
|
|
||||||
// "charidx()" function
|
// "charidx()" function
|
||||||
static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
@@ -1148,45 +1191,10 @@ static void f_clearmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// "col(string)" function
|
||||||
* "col(string)" function
|
|
||||||
*/
|
|
||||||
static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
colnr_T col = 0;
|
get_col(argvars, rettv, false);
|
||||||
pos_T *fp;
|
|
||||||
int fnum = curbuf->b_fnum;
|
|
||||||
|
|
||||||
fp = var2fpos(&argvars[0], FALSE, &fnum);
|
|
||||||
if (fp != NULL && fnum == curbuf->b_fnum) {
|
|
||||||
if (fp->col == MAXCOL) {
|
|
||||||
// '> can be MAXCOL, get the length of the line then
|
|
||||||
if (fp->lnum <= curbuf->b_ml.ml_line_count) {
|
|
||||||
col = (colnr_T)STRLEN(ml_get(fp->lnum)) + 1;
|
|
||||||
} else {
|
|
||||||
col = MAXCOL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
col = fp->col + 1;
|
|
||||||
// col(".") when the cursor is on the NUL at the end of the line
|
|
||||||
// because of "coladd" can be seen as an extra column.
|
|
||||||
if (virtual_active() && fp == &curwin->w_cursor) {
|
|
||||||
char_u *p = get_cursor_pos_ptr();
|
|
||||||
|
|
||||||
if (curwin->w_cursor.coladd
|
|
||||||
>= (colnr_T)win_chartabsize(curwin, p,
|
|
||||||
(curwin->w_virtcol
|
|
||||||
- curwin->w_cursor.coladd))) {
|
|
||||||
int l;
|
|
||||||
|
|
||||||
if (*p != NUL && p[(l = utfc_ptr2len(p))] == NUL) {
|
|
||||||
col += l;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rettv->vval.v_number = col;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1549,24 +1557,21 @@ static void f_ctxsize(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
rettv->vval.v_number = ctx_size();
|
rettv->vval.v_number = ctx_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// "cursor(lnum, col)" function, or
|
/// Set the cursor position.
|
||||||
/// "cursor(list)"
|
/// If 'charcol' is true, then use the column number as a character offet.
|
||||||
///
|
/// Otherwise use the column number as a byte offset.
|
||||||
/// Moves the cursor to the specified line and column.
|
static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol)
|
||||||
///
|
|
||||||
/// @returns 0 when the position could be set, -1 otherwise.
|
|
||||||
static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|
||||||
{
|
{
|
||||||
long line, col;
|
long line, col;
|
||||||
long coladd = 0;
|
long coladd = 0;
|
||||||
bool set_curswant = true;
|
bool set_curswant = true;
|
||||||
|
|
||||||
rettv->vval.v_number = -1;
|
rettv->vval.v_number = -1;
|
||||||
if (argvars[1].v_type == VAR_UNKNOWN) {
|
if (argvars[0].v_type == VAR_LIST) {
|
||||||
pos_T pos;
|
pos_T pos;
|
||||||
colnr_T curswant = -1;
|
colnr_T curswant = -1;
|
||||||
|
|
||||||
if (list2fpos(argvars, &pos, NULL, &curswant) == FAIL) {
|
if (list2fpos(argvars, &pos, NULL, &curswant, charcol) == FAIL) {
|
||||||
emsg(_(e_invarg));
|
emsg(_(e_invarg));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1578,16 +1583,22 @@ static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
curwin->w_curswant = curswant - 1;
|
curwin->w_curswant = curswant - 1;
|
||||||
set_curswant = false;
|
set_curswant = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else if ((argvars[0].v_type == VAR_NUMBER || argvars[0].v_type == VAR_STRING)
|
||||||
|
&& argvars[1].v_type == VAR_NUMBER) {
|
||||||
line = tv_get_lnum(argvars);
|
line = tv_get_lnum(argvars);
|
||||||
col = (long)tv_get_number_chk(&argvars[1], NULL);
|
col = (long)tv_get_number_chk(&argvars[1], NULL);
|
||||||
|
if (charcol) {
|
||||||
|
col = buf_charidx_to_byteidx(curbuf, line, col);
|
||||||
|
}
|
||||||
if (argvars[2].v_type != VAR_UNKNOWN) {
|
if (argvars[2].v_type != VAR_UNKNOWN) {
|
||||||
coladd = (long)tv_get_number_chk(&argvars[2], NULL);
|
coladd = (long)tv_get_number_chk(&argvars[2], NULL);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
emsg(_(e_invarg));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (line < 0 || col < 0
|
if (line < 0 || col < 0 || coladd < 0) {
|
||||||
|| coladd < 0) {
|
return; // type error; errmsg already given
|
||||||
return; // type error; errmsg already given
|
|
||||||
}
|
}
|
||||||
if (line > 0) {
|
if (line > 0) {
|
||||||
curwin->w_cursor.lnum = line;
|
curwin->w_cursor.lnum = line;
|
||||||
@@ -1606,6 +1617,16 @@ static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
rettv->vval.v_number = 0;
|
rettv->vval.v_number = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// "cursor(lnum, col)" function, or
|
||||||
|
/// "cursor(list)"
|
||||||
|
///
|
||||||
|
/// Moves the cursor to the specified line and column.
|
||||||
|
/// Returns 0 when the position could be set, -1 otherwise.
|
||||||
|
static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
|
{
|
||||||
|
set_cursorpos(argvars, rettv, false);
|
||||||
|
}
|
||||||
|
|
||||||
// "debugbreak()" function
|
// "debugbreak()" function
|
||||||
static void f_debugbreak(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
static void f_debugbreak(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
@@ -3288,6 +3309,67 @@ static void f_getcharmod(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
rettv->vval.v_number = mod_mask;
|
rettv->vval.v_number = mod_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void getpos_both(typval_T *argvars, typval_T *rettv, bool getcurpos, bool charcol)
|
||||||
|
{
|
||||||
|
pos_T *fp = NULL;
|
||||||
|
pos_T pos;
|
||||||
|
win_T *wp = curwin;
|
||||||
|
int fnum = -1;
|
||||||
|
|
||||||
|
if (getcurpos) {
|
||||||
|
if (argvars[0].v_type != VAR_UNKNOWN) {
|
||||||
|
wp = find_win_by_nr_or_id(&argvars[0]);
|
||||||
|
if (wp != NULL) {
|
||||||
|
fp = &wp->w_cursor;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fp = &curwin->w_cursor;
|
||||||
|
}
|
||||||
|
if (fp != NULL && charcol) {
|
||||||
|
pos = *fp;
|
||||||
|
pos.col = buf_byteidx_to_charidx(wp->w_buffer, pos.lnum, pos.col) - 1;
|
||||||
|
fp = &pos;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fp = var2fpos(&argvars[0], true, &fnum, charcol);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_T *const l = tv_list_alloc_ret(rettv, 4 + getcurpos);
|
||||||
|
tv_list_append_number(l, (fnum != -1) ? (varnumber_T)fnum : (varnumber_T)0);
|
||||||
|
tv_list_append_number(l, ((fp != NULL) ? (varnumber_T)fp->lnum : (varnumber_T)0));
|
||||||
|
tv_list_append_number(l, ((fp != NULL)
|
||||||
|
? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1)
|
||||||
|
: (varnumber_T)0));
|
||||||
|
tv_list_append_number(l, (fp != NULL) ? (varnumber_T)fp->coladd : (varnumber_T)0);
|
||||||
|
if (getcurpos) {
|
||||||
|
const int save_set_curswant = curwin->w_set_curswant;
|
||||||
|
const colnr_T save_curswant = curwin->w_curswant;
|
||||||
|
const colnr_T save_virtcol = curwin->w_virtcol;
|
||||||
|
|
||||||
|
if (wp == curwin) {
|
||||||
|
update_curswant();
|
||||||
|
}
|
||||||
|
tv_list_append_number(l, (wp == NULL) ? 0 : ((wp->w_curswant == MAXCOL)
|
||||||
|
? (varnumber_T)MAXCOL
|
||||||
|
: (varnumber_T)wp->w_curswant + 1));
|
||||||
|
|
||||||
|
// Do not change "curswant", as it is unexpected that a get
|
||||||
|
// function has a side effect.
|
||||||
|
if (wp == curwin && save_set_curswant) {
|
||||||
|
curwin->w_set_curswant = save_set_curswant;
|
||||||
|
curwin->w_curswant = save_curswant;
|
||||||
|
curwin->w_virtcol = save_virtcol;
|
||||||
|
curwin->w_valid &= ~VALID_VIRTCOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// "getcharpos()" function
|
||||||
|
static void f_getcharpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
|
{
|
||||||
|
getpos_both(argvars, rettv, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "getcharsearch()" function
|
* "getcharsearch()" function
|
||||||
*/
|
*/
|
||||||
@@ -3843,69 +3925,21 @@ static void f_getpid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
rettv->vval.v_number = os_get_pid();
|
rettv->vval.v_number = os_get_pid();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void getpos_both(typval_T *argvars, typval_T *rettv, bool getcurpos)
|
/// "getcurpos(string)" function
|
||||||
{
|
|
||||||
pos_T *fp = NULL;
|
|
||||||
win_T *wp = curwin;
|
|
||||||
int fnum = -1;
|
|
||||||
|
|
||||||
if (getcurpos) {
|
|
||||||
if (argvars[0].v_type != VAR_UNKNOWN) {
|
|
||||||
wp = find_win_by_nr_or_id(&argvars[0]);
|
|
||||||
if (wp != NULL) {
|
|
||||||
fp = &wp->w_cursor;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fp = &curwin->w_cursor;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fp = var2fpos(&argvars[0], true, &fnum);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_T *const l = tv_list_alloc_ret(rettv, 4 + (!!getcurpos));
|
|
||||||
tv_list_append_number(l, (fnum != -1) ? (varnumber_T)fnum : (varnumber_T)0);
|
|
||||||
tv_list_append_number(l, ((fp != NULL) ? (varnumber_T)fp->lnum : (varnumber_T)0));
|
|
||||||
tv_list_append_number(l, ((fp != NULL)
|
|
||||||
? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1)
|
|
||||||
: (varnumber_T)0));
|
|
||||||
tv_list_append_number(l, (fp != NULL) ? (varnumber_T)fp->coladd : (varnumber_T)0);
|
|
||||||
if (getcurpos) {
|
|
||||||
const int save_set_curswant = curwin->w_set_curswant;
|
|
||||||
const colnr_T save_curswant = curwin->w_curswant;
|
|
||||||
const colnr_T save_virtcol = curwin->w_virtcol;
|
|
||||||
|
|
||||||
if (wp == curwin) {
|
|
||||||
update_curswant();
|
|
||||||
}
|
|
||||||
tv_list_append_number(l, (wp == NULL) ? 0 : (wp->w_curswant == MAXCOL)
|
|
||||||
? (varnumber_T)MAXCOL
|
|
||||||
: (varnumber_T)wp->w_curswant + 1);
|
|
||||||
|
|
||||||
// Do not change "curswant", as it is unexpected that a get
|
|
||||||
// function has a side effect.
|
|
||||||
if (wp == curwin && save_set_curswant) {
|
|
||||||
curwin->w_set_curswant = save_set_curswant;
|
|
||||||
curwin->w_curswant = save_curswant;
|
|
||||||
curwin->w_virtcol = save_virtcol;
|
|
||||||
curwin->w_valid &= ~VALID_VIRTCOL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* "getcurpos(string)" function
|
|
||||||
*/
|
|
||||||
static void f_getcurpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
static void f_getcurpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
getpos_both(argvars, rettv, true);
|
getpos_both(argvars, rettv, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void f_getcursorcharpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
* "getpos(string)" function
|
{
|
||||||
*/
|
getpos_both(argvars, rettv, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// "getpos(string)" function
|
||||||
static void f_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
static void f_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
getpos_both(argvars, rettv, false);
|
getpos_both(argvars, rettv, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// "getqflist()" functions
|
/// "getqflist()" functions
|
||||||
@@ -5889,13 +5923,13 @@ static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
switchwin_T switchwin;
|
switchwin_T switchwin;
|
||||||
if (switch_win_noblock(&switchwin, wp, tp, true) == OK) {
|
if (switch_win_noblock(&switchwin, wp, tp, true) == OK) {
|
||||||
check_cursor();
|
check_cursor();
|
||||||
fp = var2fpos(&argvars[0], true, &fnum);
|
fp = var2fpos(&argvars[0], true, &fnum, false);
|
||||||
}
|
}
|
||||||
restore_win_noblock(&switchwin, true);
|
restore_win_noblock(&switchwin, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// use current window
|
// use current window
|
||||||
fp = var2fpos(&argvars[0], true, &fnum);
|
fp = var2fpos(&argvars[0], true, &fnum, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fp != NULL) {
|
if (fp != NULL) {
|
||||||
@@ -9000,6 +9034,49 @@ static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the cursor or mark position.
|
||||||
|
/// If 'charpos' is TRUE, then use the column number as a character offet.
|
||||||
|
/// Otherwise use the column number as a byte offset.
|
||||||
|
static void set_position(typval_T *argvars, typval_T *rettv, bool charpos)
|
||||||
|
{
|
||||||
|
pos_T pos;
|
||||||
|
int fnum;
|
||||||
|
colnr_T curswant = -1;
|
||||||
|
|
||||||
|
rettv->vval.v_number = -1;
|
||||||
|
const char *const name = tv_get_string_chk(argvars);
|
||||||
|
if (name != NULL) {
|
||||||
|
if (list2fpos(&argvars[1], &pos, &fnum, &curswant, charpos) == OK) {
|
||||||
|
if (pos.col != MAXCOL && --pos.col < 0) {
|
||||||
|
pos.col = 0;
|
||||||
|
}
|
||||||
|
if (name[0] == '.' && name[1] == NUL) {
|
||||||
|
// set cursor; "fnum" is ignored
|
||||||
|
curwin->w_cursor = pos;
|
||||||
|
if (curswant >= 0) {
|
||||||
|
curwin->w_curswant = curswant - 1;
|
||||||
|
curwin->w_set_curswant = false;
|
||||||
|
}
|
||||||
|
check_cursor();
|
||||||
|
rettv->vval.v_number = 0;
|
||||||
|
} else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL) {
|
||||||
|
// set mark
|
||||||
|
if (setmark_pos((uint8_t)name[1], &pos, fnum) == OK) {
|
||||||
|
rettv->vval.v_number = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emsg(_(e_invarg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// "setcharpos()" function
|
||||||
|
static void f_setcharpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
|
{
|
||||||
|
set_position(argvars, rettv, true);
|
||||||
|
}
|
||||||
|
|
||||||
static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
dict_T *d;
|
dict_T *d;
|
||||||
@@ -9042,6 +9119,12 @@ static void f_setcmdpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// "setcursorcharpos" function
|
||||||
|
static void f_setcursorcharpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
|
{
|
||||||
|
set_cursorpos(argvars, rettv, true);
|
||||||
|
}
|
||||||
|
|
||||||
/// "setenv()" function
|
/// "setenv()" function
|
||||||
static void f_setenv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
static void f_setenv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
@@ -9298,41 +9381,10 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// "setpos()" function
|
||||||
* "setpos()" function
|
|
||||||
*/
|
|
||||||
static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
pos_T pos;
|
set_position(argvars, rettv, false);
|
||||||
int fnum;
|
|
||||||
colnr_T curswant = -1;
|
|
||||||
|
|
||||||
rettv->vval.v_number = -1;
|
|
||||||
const char *const name = tv_get_string_chk(argvars);
|
|
||||||
if (name != NULL) {
|
|
||||||
if (list2fpos(&argvars[1], &pos, &fnum, &curswant) == OK) {
|
|
||||||
if (pos.col != MAXCOL && --pos.col < 0) {
|
|
||||||
pos.col = 0;
|
|
||||||
}
|
|
||||||
if (name[0] == '.' && name[1] == NUL) {
|
|
||||||
// set cursor; "fnum" is ignored
|
|
||||||
curwin->w_cursor = pos;
|
|
||||||
if (curswant >= 0) {
|
|
||||||
curwin->w_curswant = curswant - 1;
|
|
||||||
curwin->w_set_curswant = false;
|
|
||||||
}
|
|
||||||
check_cursor();
|
|
||||||
rettv->vval.v_number = 0;
|
|
||||||
} else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL) {
|
|
||||||
// set mark
|
|
||||||
if (setmark_pos((uint8_t)name[1], &pos, fnum) == OK) {
|
|
||||||
rettv->vval.v_number = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
emsg(_(e_invarg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -12015,7 +12067,7 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
pos_T *fp;
|
pos_T *fp;
|
||||||
int fnum = curbuf->b_fnum;
|
int fnum = curbuf->b_fnum;
|
||||||
|
|
||||||
fp = var2fpos(&argvars[0], FALSE, &fnum);
|
fp = var2fpos(&argvars[0], false, &fnum, false);
|
||||||
if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count
|
if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count
|
||||||
&& fnum == curbuf->b_fnum) {
|
&& fnum == curbuf->b_fnum) {
|
||||||
// Limit the column to a valid value, getvvcol() doesn't check.
|
// Limit the column to a valid value, getvvcol() doesn't check.
|
||||||
|
@@ -3091,7 +3091,7 @@ linenr_T tv_get_lnum(const typval_T *const tv)
|
|||||||
linenr_T lnum = (linenr_T)tv_get_number_chk(tv, NULL);
|
linenr_T lnum = (linenr_T)tv_get_number_chk(tv, NULL);
|
||||||
if (lnum == 0) { // No valid number, try using same function as line() does.
|
if (lnum == 0) { // No valid number, try using same function as line() does.
|
||||||
int fnum;
|
int fnum;
|
||||||
pos_T *const fp = var2fpos(tv, true, &fnum);
|
pos_T *const fp = var2fpos(tv, true, &fnum, false);
|
||||||
if (fp != NULL) {
|
if (fp != NULL) {
|
||||||
lnum = fp->lnum;
|
lnum = fp->lnum;
|
||||||
}
|
}
|
||||||
|
@@ -3408,7 +3408,7 @@ static void tagstack_push_items(win_T *wp, list_T *l)
|
|||||||
if ((di = tv_dict_find(itemdict, "from", -1)) == NULL) {
|
if ((di = tv_dict_find(itemdict, "from", -1)) == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (list2fpos(&di->di_tv, &mark, &fnum, NULL) != OK) {
|
if (list2fpos(&di->di_tv, &mark, &fnum, NULL, false) != OK) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((tagname = (char_u *)tv_dict_get_string(itemdict, "tagname", true))
|
if ((tagname = (char_u *)tv_dict_get_string(itemdict, "tagname", true))
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
" Tests for cursor().
|
" Tests for cursor() and other functions that get/set the cursor position
|
||||||
|
|
||||||
func Test_wrong_arguments()
|
func Test_wrong_arguments()
|
||||||
call assert_fails('call cursor(1. 3)', 'E474:')
|
call assert_fails('call cursor(1. 3)', 'E474:')
|
||||||
@@ -119,3 +119,188 @@ func Test_screenpos_number()
|
|||||||
close
|
close
|
||||||
bwipe!
|
bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func SaveVisualStartCharPos()
|
||||||
|
call add(g:VisualStartPos, getcharpos('v'))
|
||||||
|
return ''
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test for the getcharpos() function
|
||||||
|
func Test_getcharpos()
|
||||||
|
call assert_fails('call getcharpos({})', 'E731:')
|
||||||
|
call assert_equal([0, 0, 0, 0], getcharpos(0))
|
||||||
|
new
|
||||||
|
call setline(1, ['', "01\tà4è678", 'Ⅵ', '012345678'])
|
||||||
|
|
||||||
|
" Test for '.' and '$'
|
||||||
|
normal 1G
|
||||||
|
call assert_equal([0, 1, 1, 0], getcharpos('.'))
|
||||||
|
call assert_equal([0, 4, 1, 0], getcharpos('$'))
|
||||||
|
normal 2G6l
|
||||||
|
call assert_equal([0, 2, 7, 0], getcharpos('.'))
|
||||||
|
normal 3G$
|
||||||
|
call assert_equal([0, 3, 1, 0], getcharpos('.'))
|
||||||
|
normal 4G$
|
||||||
|
call assert_equal([0, 4, 9, 0], getcharpos('.'))
|
||||||
|
|
||||||
|
" Test for a mark
|
||||||
|
normal 2G7lmmgg
|
||||||
|
call assert_equal([0, 2, 8, 0], getcharpos("'m"))
|
||||||
|
delmarks m
|
||||||
|
call assert_equal([0, 0, 0, 0], getcharpos("'m"))
|
||||||
|
|
||||||
|
" Test for the visual start column
|
||||||
|
vnoremap <expr> <F3> SaveVisualStartCharPos()
|
||||||
|
let g:VisualStartPos = []
|
||||||
|
exe "normal 2G6lv$\<F3>ohh\<F3>o\<F3>"
|
||||||
|
call assert_equal([[0, 2, 7, 0], [0, 2, 9, 0], [0, 2, 5, 0]], g:VisualStartPos)
|
||||||
|
call assert_equal([0, 2, 9, 0], getcharpos('v'))
|
||||||
|
let g:VisualStartPos = []
|
||||||
|
exe "normal 3Gv$\<F3>o\<F3>"
|
||||||
|
call assert_equal([[0, 3, 1, 0], [0, 3, 1, 0]], g:VisualStartPos)
|
||||||
|
let g:VisualStartPos = []
|
||||||
|
exe "normal 1Gv$\<F3>o\<F3>"
|
||||||
|
call assert_equal([[0, 1, 1, 0], [0, 1, 1, 0]], g:VisualStartPos)
|
||||||
|
vunmap <F3>
|
||||||
|
|
||||||
|
%bw!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test for the setcharpos() function
|
||||||
|
func Test_setcharpos()
|
||||||
|
call assert_equal(-1, setcharpos('.', v:_null_list))
|
||||||
|
new
|
||||||
|
call setline(1, ['', "01\tà4è678", 'Ⅵ', '012345678'])
|
||||||
|
call setcharpos('.', [0, 1, 1, 0])
|
||||||
|
call assert_equal([1, 1], [line('.'), col('.')])
|
||||||
|
call setcharpos('.', [0, 2, 7, 0])
|
||||||
|
call assert_equal([2, 9], [line('.'), col('.')])
|
||||||
|
call setcharpos('.', [0, 3, 4, 0])
|
||||||
|
call assert_equal([3, 1], [line('.'), col('.')])
|
||||||
|
call setcharpos('.', [0, 3, 1, 0])
|
||||||
|
call assert_equal([3, 1], [line('.'), col('.')])
|
||||||
|
call setcharpos('.', [0, 4, 0, 0])
|
||||||
|
call assert_equal([4, 1], [line('.'), col('.')])
|
||||||
|
call setcharpos('.', [0, 4, 20, 0])
|
||||||
|
call assert_equal([4, 9], [line('.'), col('.')])
|
||||||
|
|
||||||
|
" Test for mark
|
||||||
|
delmarks m
|
||||||
|
call setcharpos("'m", [0, 2, 9, 0])
|
||||||
|
normal `m
|
||||||
|
call assert_equal([2, 11], [line('.'), col('.')])
|
||||||
|
|
||||||
|
%bw!
|
||||||
|
call assert_equal(-1, setcharpos('.', [10, 3, 1, 0]))
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func SaveVisualStartCharCol()
|
||||||
|
call add(g:VisualStartCol, charcol('v'))
|
||||||
|
return ''
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test for the charcol() function
|
||||||
|
func Test_charcol()
|
||||||
|
call assert_fails('call charcol({})', 'E731:')
|
||||||
|
call assert_equal(0, charcol(0))
|
||||||
|
new
|
||||||
|
call setline(1, ['', "01\tà4è678", 'Ⅵ', '012345678'])
|
||||||
|
|
||||||
|
" Test for '.' and '$'
|
||||||
|
normal 1G
|
||||||
|
call assert_equal(1, charcol('.'))
|
||||||
|
call assert_equal(1, charcol('$'))
|
||||||
|
normal 2G6l
|
||||||
|
call assert_equal(7, charcol('.'))
|
||||||
|
call assert_equal(10, charcol('$'))
|
||||||
|
normal 3G$
|
||||||
|
call assert_equal(1, charcol('.'))
|
||||||
|
call assert_equal(2, charcol('$'))
|
||||||
|
normal 4G$
|
||||||
|
call assert_equal(9, charcol('.'))
|
||||||
|
call assert_equal(10, charcol('$'))
|
||||||
|
|
||||||
|
" Test for [lnum, '$']
|
||||||
|
call assert_equal(1, charcol([1, '$']))
|
||||||
|
call assert_equal(10, charcol([2, '$']))
|
||||||
|
call assert_equal(2, charcol([3, '$']))
|
||||||
|
call assert_equal(0, charcol([5, '$']))
|
||||||
|
|
||||||
|
" Test for a mark
|
||||||
|
normal 2G7lmmgg
|
||||||
|
call assert_equal(8, charcol("'m"))
|
||||||
|
delmarks m
|
||||||
|
call assert_equal(0, charcol("'m"))
|
||||||
|
|
||||||
|
" Test for the visual start column
|
||||||
|
vnoremap <expr> <F3> SaveVisualStartCharCol()
|
||||||
|
let g:VisualStartCol = []
|
||||||
|
exe "normal 2G6lv$\<F3>ohh\<F3>o\<F3>"
|
||||||
|
call assert_equal([7, 9, 5], g:VisualStartCol)
|
||||||
|
call assert_equal(9, charcol('v'))
|
||||||
|
let g:VisualStartCol = []
|
||||||
|
exe "normal 3Gv$\<F3>o\<F3>"
|
||||||
|
call assert_equal([1, 1], g:VisualStartCol)
|
||||||
|
let g:VisualStartCol = []
|
||||||
|
exe "normal 1Gv$\<F3>o\<F3>"
|
||||||
|
call assert_equal([1, 1], g:VisualStartCol)
|
||||||
|
vunmap <F3>
|
||||||
|
|
||||||
|
%bw!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test for getcursorcharpos()
|
||||||
|
func Test_getcursorcharpos()
|
||||||
|
call assert_equal(getcursorcharpos(), getcursorcharpos(0))
|
||||||
|
call assert_equal([0, 0, 0, 0, 0], getcursorcharpos(-1))
|
||||||
|
call assert_equal([0, 0, 0, 0, 0], getcursorcharpos(1999))
|
||||||
|
|
||||||
|
new
|
||||||
|
call setline(1, ['', "01\tà4è678", 'Ⅵ', '012345678'])
|
||||||
|
normal 1G9l
|
||||||
|
call assert_equal([0, 1, 1, 0, 1], getcursorcharpos())
|
||||||
|
normal 2G9l
|
||||||
|
call assert_equal([0, 2, 9, 0, 14], getcursorcharpos())
|
||||||
|
normal 3G9l
|
||||||
|
call assert_equal([0, 3, 1, 0, 1], getcursorcharpos())
|
||||||
|
normal 4G9l
|
||||||
|
call assert_equal([0, 4, 9, 0, 9], getcursorcharpos())
|
||||||
|
|
||||||
|
let winid = win_getid()
|
||||||
|
normal 2G5l
|
||||||
|
wincmd w
|
||||||
|
call assert_equal([0, 2, 6, 0, 11], getcursorcharpos(winid))
|
||||||
|
%bw!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test for setcursorcharpos()
|
||||||
|
func Test_setcursorcharpos()
|
||||||
|
call assert_fails('call setcursorcharpos(v:_null_list)', 'E474:')
|
||||||
|
call assert_fails('call setcursorcharpos([1])', 'E474:')
|
||||||
|
call assert_fails('call setcursorcharpos([1, 1, 1, 1, 1])', 'E474:')
|
||||||
|
new
|
||||||
|
call setline(1, ['', "01\tà4è678", 'Ⅵ', '012345678'])
|
||||||
|
normal G
|
||||||
|
call setcursorcharpos([1, 1])
|
||||||
|
call assert_equal([1, 1], [line('.'), col('.')])
|
||||||
|
call setcursorcharpos([2, 7, 0])
|
||||||
|
call assert_equal([2, 9], [line('.'), col('.')])
|
||||||
|
call setcursorcharpos(3, 4)
|
||||||
|
call assert_equal([3, 1], [line('.'), col('.')])
|
||||||
|
call setcursorcharpos([3, 1])
|
||||||
|
call assert_equal([3, 1], [line('.'), col('.')])
|
||||||
|
call setcursorcharpos([4, 0, 0, 0])
|
||||||
|
call assert_equal([4, 1], [line('.'), col('.')])
|
||||||
|
call setcursorcharpos([4, 20])
|
||||||
|
call assert_equal([4, 9], [line('.'), col('.')])
|
||||||
|
normal 1G
|
||||||
|
call setcursorcharpos([100, 100, 100, 100])
|
||||||
|
call assert_equal([4, 9], [line('.'), col('.')])
|
||||||
|
normal 1G
|
||||||
|
call setcursorcharpos('$', 1)
|
||||||
|
call assert_equal([4, 1], [line('.'), col('.')])
|
||||||
|
|
||||||
|
%bw!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
Reference in New Issue
Block a user