mirror of
https://github.com/zoriya/vim.git
synced 2025-12-14 19:26:18 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6349e9411f | ||
|
|
0d3cb73012 | ||
|
|
8055d17388 | ||
|
|
787880a86d | ||
|
|
80e737cc6a | ||
|
|
bfd451283f | ||
|
|
dabfde04fe | ||
|
|
0ebe12be86 | ||
|
|
5c65e6a062 | ||
|
|
17aca707f9 | ||
|
|
dda4144d39 | ||
|
|
eda652215a | ||
|
|
45dd07f10a | ||
|
|
fe1ade0a78 | ||
|
|
fb222df28d |
@@ -173,6 +173,16 @@ Page custom SetCustom ValidateCustom
|
|||||||
!include "lang\tradchinese.nsi"
|
!include "lang\tradchinese.nsi"
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
|
##########################################################
|
||||||
|
# Version resources
|
||||||
|
|
||||||
|
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "Vim"
|
||||||
|
VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" "Vim Developers"
|
||||||
|
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalTrademarks" "Vim"
|
||||||
|
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "Copyright (C) 1996"
|
||||||
|
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "Vi Improved - A Text Editor"
|
||||||
|
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "${VER_MAJOR}.${VER_MINOR}.0.0"
|
||||||
|
VIProductVersion "${VER_MAJOR}.${VER_MINOR}.0.0"
|
||||||
|
|
||||||
# Global variables
|
# Global variables
|
||||||
Var vim_dialog
|
Var vim_dialog
|
||||||
|
|||||||
@@ -2459,6 +2459,7 @@ lispindent({lnum}) Number Lisp indent for line {lnum}
|
|||||||
list2str({list} [, {utf8}]) String turn numbers in {list} into a String
|
list2str({list} [, {utf8}]) String turn numbers in {list} into a String
|
||||||
listener_add({callback} [, {buf}])
|
listener_add({callback} [, {buf}])
|
||||||
Number add a callback to listen to changes
|
Number add a callback to listen to changes
|
||||||
|
listener_flush([{buf}]) none invoke listener callbacks
|
||||||
listener_remove({id}) none remove a listener callback
|
listener_remove({id}) none remove a listener callback
|
||||||
localtime() Number current time
|
localtime() Number current time
|
||||||
log({expr}) Float natural logarithm (base e) of {expr}
|
log({expr}) Float natural logarithm (base e) of {expr}
|
||||||
@@ -2700,6 +2701,7 @@ test_alloc_fail({id}, {countdown}, {repeat})
|
|||||||
test_autochdir() none enable 'autochdir' during startup
|
test_autochdir() none enable 'autochdir' during startup
|
||||||
test_feedinput({string}) none add key sequence to input buffer
|
test_feedinput({string}) none add key sequence to input buffer
|
||||||
test_garbagecollect_now() none free memory right now for testing
|
test_garbagecollect_now() none free memory right now for testing
|
||||||
|
test_getvalue({string}) any get value of an internal variable
|
||||||
test_ignore_error({expr}) none ignore a specific error
|
test_ignore_error({expr}) none ignore a specific error
|
||||||
test_null_blob() Blob null value for testing
|
test_null_blob() Blob null value for testing
|
||||||
test_null_channel() Channel null value for testing
|
test_null_channel() Channel null value for testing
|
||||||
@@ -6322,8 +6324,21 @@ listener_add({callback} [, {buf}]) *listener_add()*
|
|||||||
buffer is used.
|
buffer is used.
|
||||||
Returns a unique ID that can be passed to |listener_remove()|.
|
Returns a unique ID that can be passed to |listener_remove()|.
|
||||||
|
|
||||||
The {callback} is invoked with a list of items that indicate a
|
The {callback} is invoked with four arguments:
|
||||||
change. The list cannot be changed. Each list item is a
|
a:bufnr the buffer that was changed
|
||||||
|
a:start first changed line number
|
||||||
|
a:end first line number below the change
|
||||||
|
a:added total number of lines added, negative if lines
|
||||||
|
were deleted
|
||||||
|
a:changes a List of items with details about the changes
|
||||||
|
|
||||||
|
Example: >
|
||||||
|
func Listener(bufnr, start, end, added, changes)
|
||||||
|
echo 'lines ' .. a:start .. ' until ' .. a:end .. ' changed'
|
||||||
|
endfunc
|
||||||
|
call listener_add('Listener', bufnr)
|
||||||
|
|
||||||
|
< The List cannot be changed. Each item in a:changes is a
|
||||||
dictionary with these entries:
|
dictionary with these entries:
|
||||||
lnum the first line number of the change
|
lnum the first line number of the change
|
||||||
end the first line below the change
|
end the first line below the change
|
||||||
@@ -6337,35 +6352,32 @@ listener_add({callback} [, {buf}]) *listener_add()*
|
|||||||
lnum line below which the new line is added
|
lnum line below which the new line is added
|
||||||
end equal to "lnum"
|
end equal to "lnum"
|
||||||
added number of lines inserted
|
added number of lines inserted
|
||||||
col one
|
col 1
|
||||||
When lines are deleted the values are:
|
When lines are deleted the values are:
|
||||||
lnum the first deleted line
|
lnum the first deleted line
|
||||||
end the line below the first deleted line, before
|
end the line below the first deleted line, before
|
||||||
the deletion was done
|
the deletion was done
|
||||||
added negative, number of lines deleted
|
added negative, number of lines deleted
|
||||||
col one
|
col 1
|
||||||
When lines are changed:
|
When lines are changed:
|
||||||
lnum the first changed line
|
lnum the first changed line
|
||||||
end the line below the last changed line
|
end the line below the last changed line
|
||||||
added zero
|
added 0
|
||||||
col first column with a change or one
|
col first column with a change or 1
|
||||||
|
|
||||||
The entries are in the order the changes was made, thus the
|
The entries are in the order the changes were made, thus the
|
||||||
most recent change is at the end. One has to go through the
|
most recent change is at the end. The line numbers are valid
|
||||||
list from end to start to compute the line numbers in the
|
when the callback is invoked, but later changes may make them
|
||||||
current state of the text.
|
invalid, thus keeping a copy for later might not work.
|
||||||
|
|
||||||
When using the same function for multiple buffers, you can
|
The {callback} is invoked just before the screen is updated,
|
||||||
pass the buffer to that function using a |Partial|.
|
when |listener_flush()| is called or when a change is being
|
||||||
Example: >
|
made that changes the line count in a way it causes a line
|
||||||
func Listener(bufnr, changes)
|
number in the list of changes to become invalid.
|
||||||
" ...
|
|
||||||
endfunc
|
|
||||||
let bufnr = ...
|
|
||||||
call listener_add(function('Listener', [bufnr]), bufnr)
|
|
||||||
|
|
||||||
< The {callback} is invoked just before the screen is updated.
|
The {callback} is invoked with the text locked, see
|
||||||
To trigger this in a script use the `:redraw` command.
|
|textlock|. If you do need to make changes to the buffer, use
|
||||||
|
a timer to do this later |timer_start()|.
|
||||||
|
|
||||||
The {callback} is not invoked when the buffer is first loaded.
|
The {callback} is not invoked when the buffer is first loaded.
|
||||||
Use the |BufReadPost| autocmd event to handle the initial text
|
Use the |BufReadPost| autocmd event to handle the initial text
|
||||||
@@ -6373,6 +6385,14 @@ listener_add({callback} [, {buf}]) *listener_add()*
|
|||||||
The {callback} is also not invoked when the buffer is
|
The {callback} is also not invoked when the buffer is
|
||||||
unloaded, use the |BufUnload| autocmd event for that.
|
unloaded, use the |BufUnload| autocmd event for that.
|
||||||
|
|
||||||
|
listener_flush([{buf}]) *listener_flush()*
|
||||||
|
Invoke listener callbacks for buffer {buf}. If there are no
|
||||||
|
pending changes then no callbacks are invoked.
|
||||||
|
|
||||||
|
{buf} refers to a buffer name or number. For the accepted
|
||||||
|
values, see |bufname()|. When {buf} is omitted the current
|
||||||
|
buffer is used.
|
||||||
|
|
||||||
listener_remove({id}) *listener_remove()*
|
listener_remove({id}) *listener_remove()*
|
||||||
Remove a listener previously added with listener_add().
|
Remove a listener previously added with listener_add().
|
||||||
|
|
||||||
@@ -9875,6 +9895,11 @@ test_garbagecollect_now() *test_garbagecollect_now()*
|
|||||||
internally, and |v:testing| must have been set before calling
|
internally, and |v:testing| must have been set before calling
|
||||||
any function.
|
any function.
|
||||||
|
|
||||||
|
test_getvalue({name}) *test_getvalue()*
|
||||||
|
Get the value of an internal variable. These values for
|
||||||
|
{name} are supported:
|
||||||
|
need_fileinfo
|
||||||
|
|
||||||
test_ignore_error({expr}) *test_ignore_error()*
|
test_ignore_error({expr}) *test_ignore_error()*
|
||||||
Ignore any error containing {expr}. A normal message is given
|
Ignore any error containing {expr}. A normal message is given
|
||||||
instead.
|
instead.
|
||||||
|
|||||||
@@ -2179,7 +2179,7 @@ test_libvterm:
|
|||||||
test1 \
|
test1 \
|
||||||
test_eval \
|
test_eval \
|
||||||
test3 \
|
test3 \
|
||||||
test29 test30 test37 test39 \
|
test30 test37 test39 \
|
||||||
test42 test44 test48 test49 \
|
test42 test44 test48 test49 \
|
||||||
test52 test59 \
|
test52 test59 \
|
||||||
test64 test69 \
|
test64 test69 \
|
||||||
|
|||||||
@@ -1742,9 +1742,12 @@ enter_buffer(buf_T *buf)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!msg_silent)
|
if (!msg_silent && !shortmess(SHM_FILEINFO))
|
||||||
need_fileinfo = TRUE; /* display file info after redraw */
|
need_fileinfo = TRUE; // display file info after redraw
|
||||||
(void)buf_check_timestamp(curbuf, FALSE); /* check if file changed */
|
|
||||||
|
// check if file changed
|
||||||
|
(void)buf_check_timestamp(curbuf, FALSE);
|
||||||
|
|
||||||
curwin->w_topline = 1;
|
curwin->w_topline = 1;
|
||||||
#ifdef FEAT_DIFF
|
#ifdef FEAT_DIFF
|
||||||
curwin->w_topfill = 0;
|
curwin->w_topfill = 0;
|
||||||
|
|||||||
171
src/change.c
171
src/change.c
@@ -152,11 +152,76 @@ changed_internal(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
static list_T *recorded_changes = NULL;
|
|
||||||
static long next_listener_id = 0;
|
static long next_listener_id = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the change at "lnum" / "col" is above or overlaps with an existing
|
||||||
|
* changed. If above then flush changes and invoke listeners.
|
||||||
|
* If "merge" is TRUE do the merge.
|
||||||
|
* Returns TRUE if the change was merged.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
check_recorded_changes(
|
||||||
|
buf_T *buf,
|
||||||
|
linenr_T lnum,
|
||||||
|
colnr_T col,
|
||||||
|
linenr_T lnume,
|
||||||
|
long xtra,
|
||||||
|
int merge)
|
||||||
|
{
|
||||||
|
if (buf->b_recorded_changes != NULL && xtra != 0)
|
||||||
|
{
|
||||||
|
listitem_T *li;
|
||||||
|
linenr_T nr;
|
||||||
|
|
||||||
|
for (li = buf->b_recorded_changes->lv_first; li != NULL;
|
||||||
|
li = li->li_next)
|
||||||
|
{
|
||||||
|
nr = (linenr_T)dict_get_number(
|
||||||
|
li->li_tv.vval.v_dict, (char_u *)"lnum");
|
||||||
|
if (nr >= lnum || nr > lnume)
|
||||||
|
{
|
||||||
|
if (li->li_next == NULL && lnum == nr
|
||||||
|
&& col + 1 == (colnr_T)dict_get_number(
|
||||||
|
li->li_tv.vval.v_dict, (char_u *)"col"))
|
||||||
|
{
|
||||||
|
if (merge)
|
||||||
|
{
|
||||||
|
dictitem_T *di;
|
||||||
|
|
||||||
|
// Same start point and nothing is following, entries
|
||||||
|
// can be merged.
|
||||||
|
di = dict_find(li->li_tv.vval.v_dict,
|
||||||
|
(char_u *)"end", -1);
|
||||||
|
if (di != NULL)
|
||||||
|
{
|
||||||
|
nr = tv_get_number(&di->di_tv);
|
||||||
|
if (lnume > nr)
|
||||||
|
di->di_tv.vval.v_number = lnume;
|
||||||
|
}
|
||||||
|
di = dict_find(li->li_tv.vval.v_dict,
|
||||||
|
(char_u *)"added", -1);
|
||||||
|
if (di != NULL)
|
||||||
|
di->di_tv.vval.v_number += xtra;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// the current change is going to make the line number in
|
||||||
|
// the older change invalid, flush now
|
||||||
|
invoke_listeners(curbuf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Record a change for listeners added with listener_add().
|
* Record a change for listeners added with listener_add().
|
||||||
|
* Always for the current buffer.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
may_record_change(
|
may_record_change(
|
||||||
@@ -169,13 +234,19 @@ may_record_change(
|
|||||||
|
|
||||||
if (curbuf->b_listener == NULL)
|
if (curbuf->b_listener == NULL)
|
||||||
return;
|
return;
|
||||||
if (recorded_changes == NULL)
|
|
||||||
|
// If the new change is going to change the line numbers in already listed
|
||||||
|
// changes, then flush.
|
||||||
|
if (check_recorded_changes(curbuf, lnum, col, lnume, xtra, TRUE))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (curbuf->b_recorded_changes == NULL)
|
||||||
{
|
{
|
||||||
recorded_changes = list_alloc();
|
curbuf->b_recorded_changes = list_alloc();
|
||||||
if (recorded_changes == NULL) // out of memory
|
if (curbuf->b_recorded_changes == NULL) // out of memory
|
||||||
return;
|
return;
|
||||||
++recorded_changes->lv_refcount;
|
++curbuf->b_recorded_changes->lv_refcount;
|
||||||
recorded_changes->lv_lock = VAR_FIXED;
|
curbuf->b_recorded_changes->lv_lock = VAR_FIXED;
|
||||||
}
|
}
|
||||||
|
|
||||||
dict = dict_alloc();
|
dict = dict_alloc();
|
||||||
@@ -186,7 +257,7 @@ may_record_change(
|
|||||||
dict_add_number(dict, "added", (varnumber_T)xtra);
|
dict_add_number(dict, "added", (varnumber_T)xtra);
|
||||||
dict_add_number(dict, "col", (varnumber_T)col + 1);
|
dict_add_number(dict, "col", (varnumber_T)col + 1);
|
||||||
|
|
||||||
list_append_dict(recorded_changes, dict);
|
list_append_dict(curbuf->b_recorded_changes, dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -230,6 +301,23 @@ f_listener_add(typval_T *argvars, typval_T *rettv)
|
|||||||
rettv->vval.v_number = lnr->lr_id;
|
rettv->vval.v_number = lnr->lr_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* listener_flush() function
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
f_listener_flush(typval_T *argvars, typval_T *rettv UNUSED)
|
||||||
|
{
|
||||||
|
buf_T *buf = curbuf;
|
||||||
|
|
||||||
|
if (argvars[0].v_type != VAR_UNKNOWN)
|
||||||
|
{
|
||||||
|
buf = get_buf_arg(&argvars[0]);
|
||||||
|
if (buf == NULL)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
invoke_listeners(buf);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* listener_remove() function
|
* listener_remove() function
|
||||||
*/
|
*/
|
||||||
@@ -259,32 +347,73 @@ f_listener_remove(typval_T *argvars, typval_T *rettv UNUSED)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called before inserting a line above "lnum"/"lnum3" or deleting line "lnum"
|
||||||
|
* to "lnume".
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
may_invoke_listeners(buf_T *buf, linenr_T lnum, linenr_T lnume, int added)
|
||||||
|
{
|
||||||
|
check_recorded_changes(buf, lnum, 0, lnume, added, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called when a sequence of changes is done: invoke listeners added with
|
* Called when a sequence of changes is done: invoke listeners added with
|
||||||
* listener_add().
|
* listener_add().
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
invoke_listeners(void)
|
invoke_listeners(buf_T *buf)
|
||||||
{
|
{
|
||||||
listener_T *lnr;
|
listener_T *lnr;
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
int dummy;
|
int dummy;
|
||||||
typval_T argv[2];
|
typval_T argv[6];
|
||||||
|
listitem_T *li;
|
||||||
|
linenr_T start = MAXLNUM;
|
||||||
|
linenr_T end = 0;
|
||||||
|
linenr_T added = 0;
|
||||||
|
|
||||||
if (recorded_changes == NULL) // nothing changed
|
if (buf->b_recorded_changes == NULL // nothing changed
|
||||||
|
|| buf->b_listener == NULL) // no listeners
|
||||||
return;
|
return;
|
||||||
argv[0].v_type = VAR_LIST;
|
|
||||||
argv[0].vval.v_list = recorded_changes;
|
|
||||||
|
|
||||||
for (lnr = curbuf->b_listener; lnr != NULL; lnr = lnr->lr_next)
|
argv[0].v_type = VAR_NUMBER;
|
||||||
|
argv[0].vval.v_number = buf->b_fnum; // a:bufnr
|
||||||
|
|
||||||
|
|
||||||
|
for (li = buf->b_recorded_changes->lv_first; li != NULL; li = li->li_next)
|
||||||
|
{
|
||||||
|
varnumber_T lnum;
|
||||||
|
|
||||||
|
lnum = dict_get_number(li->li_tv.vval.v_dict, (char_u *)"lnum");
|
||||||
|
if (start > lnum)
|
||||||
|
start = lnum;
|
||||||
|
lnum = dict_get_number(li->li_tv.vval.v_dict, (char_u *)"end");
|
||||||
|
if (lnum > end)
|
||||||
|
end = lnum;
|
||||||
|
added = dict_get_number(li->li_tv.vval.v_dict, (char_u *)"added");
|
||||||
|
}
|
||||||
|
argv[1].v_type = VAR_NUMBER;
|
||||||
|
argv[1].vval.v_number = start;
|
||||||
|
argv[2].v_type = VAR_NUMBER;
|
||||||
|
argv[2].vval.v_number = end;
|
||||||
|
argv[3].v_type = VAR_NUMBER;
|
||||||
|
argv[3].vval.v_number = added;
|
||||||
|
|
||||||
|
argv[4].v_type = VAR_LIST;
|
||||||
|
argv[4].vval.v_list = buf->b_recorded_changes;
|
||||||
|
++textlock;
|
||||||
|
|
||||||
|
for (lnr = buf->b_listener; lnr != NULL; lnr = lnr->lr_next)
|
||||||
{
|
{
|
||||||
call_func(lnr->lr_callback, -1, &rettv,
|
call_func(lnr->lr_callback, -1, &rettv,
|
||||||
1, argv, NULL, 0L, 0L, &dummy, TRUE, lnr->lr_partial, NULL);
|
5, argv, NULL, 0L, 0L, &dummy, TRUE, lnr->lr_partial, NULL);
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_unref(recorded_changes);
|
--textlock;
|
||||||
recorded_changes = NULL;
|
list_unref(buf->b_recorded_changes);
|
||||||
|
buf->b_recorded_changes = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -553,12 +682,12 @@ changed_bytes(linenr_T lnum, colnr_T col)
|
|||||||
void
|
void
|
||||||
inserted_bytes(linenr_T lnum, colnr_T col, int added UNUSED)
|
inserted_bytes(linenr_T lnum, colnr_T col, int added UNUSED)
|
||||||
{
|
{
|
||||||
changed_bytes(lnum, col);
|
|
||||||
|
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
if (curbuf->b_has_textprop && added != 0)
|
if (curbuf->b_has_textprop && added != 0)
|
||||||
adjust_prop_columns(lnum, col, added);
|
adjust_prop_columns(lnum, col, added);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
changed_bytes(lnum, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2045,6 +2174,12 @@ open_line(
|
|||||||
)
|
)
|
||||||
mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L);
|
mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L);
|
||||||
did_append = TRUE;
|
did_append = TRUE;
|
||||||
|
#ifdef FEAT_TEXT_PROP
|
||||||
|
if ((State & INSERT) && !(State & VREPLACE_FLAG))
|
||||||
|
// properties after the split move to the next line
|
||||||
|
adjust_props_for_split(curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
||||||
|
curwin->w_cursor.col + 1, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -442,6 +442,7 @@ static void f_tempname(typval_T *argvars, typval_T *rettv);
|
|||||||
static void f_test_alloc_fail(typval_T *argvars, typval_T *rettv);
|
static void f_test_alloc_fail(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_test_autochdir(typval_T *argvars, typval_T *rettv);
|
static void f_test_autochdir(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_test_feedinput(typval_T *argvars, typval_T *rettv);
|
static void f_test_feedinput(typval_T *argvars, typval_T *rettv);
|
||||||
|
static void f_test_getvalue(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_test_option_not_set(typval_T *argvars, typval_T *rettv);
|
static void f_test_option_not_set(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_test_override(typval_T *argvars, typval_T *rettv);
|
static void f_test_override(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_test_refcount(typval_T *argvars, typval_T *rettv);
|
static void f_test_refcount(typval_T *argvars, typval_T *rettv);
|
||||||
@@ -768,6 +769,7 @@ static struct fst
|
|||||||
{"lispindent", 1, 1, f_lispindent},
|
{"lispindent", 1, 1, f_lispindent},
|
||||||
{"list2str", 1, 2, f_list2str},
|
{"list2str", 1, 2, f_list2str},
|
||||||
{"listener_add", 1, 2, f_listener_add},
|
{"listener_add", 1, 2, f_listener_add},
|
||||||
|
{"listener_flush", 0, 1, f_listener_flush},
|
||||||
{"listener_remove", 1, 1, f_listener_remove},
|
{"listener_remove", 1, 1, f_listener_remove},
|
||||||
{"localtime", 0, 0, f_localtime},
|
{"localtime", 0, 0, f_localtime},
|
||||||
#ifdef FEAT_FLOAT
|
#ifdef FEAT_FLOAT
|
||||||
@@ -990,6 +992,7 @@ static struct fst
|
|||||||
{"test_autochdir", 0, 0, f_test_autochdir},
|
{"test_autochdir", 0, 0, f_test_autochdir},
|
||||||
{"test_feedinput", 1, 1, f_test_feedinput},
|
{"test_feedinput", 1, 1, f_test_feedinput},
|
||||||
{"test_garbagecollect_now", 0, 0, f_test_garbagecollect_now},
|
{"test_garbagecollect_now", 0, 0, f_test_garbagecollect_now},
|
||||||
|
{"test_getvalue", 1, 1, f_test_getvalue},
|
||||||
{"test_ignore_error", 1, 1, f_test_ignore_error},
|
{"test_ignore_error", 1, 1, f_test_ignore_error},
|
||||||
{"test_null_blob", 0, 0, f_test_null_blob},
|
{"test_null_blob", 0, 0, f_test_null_blob},
|
||||||
#ifdef FEAT_JOB_CHANNEL
|
#ifdef FEAT_JOB_CHANNEL
|
||||||
@@ -14411,6 +14414,25 @@ f_test_feedinput(typval_T *argvars, typval_T *rettv UNUSED)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "test_getvalue({name})" function
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
f_test_getvalue(typval_T *argvars, typval_T *rettv)
|
||||||
|
{
|
||||||
|
if (argvars[0].v_type != VAR_STRING)
|
||||||
|
emsg(_(e_invarg));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char_u *name = tv_get_string(&argvars[0]);
|
||||||
|
|
||||||
|
if (STRCMP(name, (char_u *)"need_fileinfo") == 0)
|
||||||
|
rettv->vval.v_number = need_fileinfo;
|
||||||
|
else
|
||||||
|
semsg(_(e_invarg2), name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "test_option_not_set({name})" function
|
* "test_option_not_set({name})" function
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5555,28 +5555,25 @@ do_sub(exarg_T *eap)
|
|||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
if (subflags.do_count)
|
if (subflags.do_count)
|
||||||
{
|
{
|
||||||
/* prevent accidentally changing the buffer by a function */
|
// prevent accidentally changing the buffer by a function
|
||||||
save_ma = curbuf->b_p_ma;
|
|
||||||
curbuf->b_p_ma = FALSE;
|
curbuf->b_p_ma = FALSE;
|
||||||
sandbox++;
|
sandbox++;
|
||||||
}
|
}
|
||||||
/* Save flags for recursion. They can change for e.g.
|
// Save flags for recursion. They can change for e.g.
|
||||||
* :s/^/\=execute("s#^##gn") */
|
// :s/^/\=execute("s#^##gn")
|
||||||
subflags_save = subflags;
|
subflags_save = subflags;
|
||||||
|
save_ma = curbuf->b_p_ma;
|
||||||
#endif
|
#endif
|
||||||
/* get length of substitution part */
|
// get length of substitution part
|
||||||
sublen = vim_regsub_multi(®match,
|
sublen = vim_regsub_multi(®match,
|
||||||
sub_firstlnum - regmatch.startpos[0].lnum,
|
sub_firstlnum - regmatch.startpos[0].lnum,
|
||||||
sub, sub_firstline, FALSE, p_magic, TRUE);
|
sub, sub_firstline, FALSE, p_magic, TRUE);
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
// If getting the substitute string caused an error, don't do
|
// If getting the substitute string caused an error, don't do
|
||||||
// the replacement.
|
// the replacement.
|
||||||
if (aborting())
|
|
||||||
goto skip;
|
|
||||||
|
|
||||||
// Don't keep flags set by a recursive call.
|
// Don't keep flags set by a recursive call.
|
||||||
subflags = subflags_save;
|
subflags = subflags_save;
|
||||||
if (subflags.do_count)
|
if (aborting() || subflags.do_count)
|
||||||
{
|
{
|
||||||
curbuf->b_p_ma = save_ma;
|
curbuf->b_p_ma = save_ma;
|
||||||
if (sandbox > 0)
|
if (sandbox > 0)
|
||||||
@@ -5728,7 +5725,7 @@ do_sub(exarg_T *eap)
|
|||||||
last_line = lnum + 1;
|
last_line = lnum + 1;
|
||||||
}
|
}
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
adjust_props_for_split(lnum, plen, 1);
|
adjust_props_for_split(lnum + 1, lnum, plen, 1);
|
||||||
#endif
|
#endif
|
||||||
// all line numbers increase
|
// all line numbers increase
|
||||||
++sub_firstlnum;
|
++sub_firstlnum;
|
||||||
|
|||||||
@@ -1874,7 +1874,7 @@ recover_names(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for out-of-memory */
|
// check for out-of-memory
|
||||||
for (i = 0; i < num_names; ++i)
|
for (i = 0; i < num_names; ++i)
|
||||||
{
|
{
|
||||||
if (names[i] == NULL)
|
if (names[i] == NULL)
|
||||||
@@ -2101,7 +2101,7 @@ get_ctime(time_t thetime, int add_newline)
|
|||||||
# endif
|
# endif
|
||||||
/* MSVC returns NULL for an invalid value of seconds. */
|
/* MSVC returns NULL for an invalid value of seconds. */
|
||||||
if (curtime == NULL)
|
if (curtime == NULL)
|
||||||
STRCPY(buf, _("(Invalid)"));
|
vim_strncpy((char_u *)buf, (char_u *)_("(Invalid)"), sizeof(buf) - 1);
|
||||||
else
|
else
|
||||||
(void)strftime(buf, sizeof(buf) - 1, "%a %b %d %H:%M:%S %Y", curtime);
|
(void)strftime(buf, sizeof(buf) - 1, "%a %b %d %H:%M:%S %Y", curtime);
|
||||||
#else
|
#else
|
||||||
@@ -2790,6 +2790,12 @@ ml_append_int(
|
|||||||
if (len == 0)
|
if (len == 0)
|
||||||
len = (colnr_T)STRLEN(line) + 1; // space needed for the text
|
len = (colnr_T)STRLEN(line) + 1; // space needed for the text
|
||||||
|
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
// When inserting above recorded changes: flush the changes before changing
|
||||||
|
// the text.
|
||||||
|
may_invoke_listeners(buf, lnum + 1, lnum + 1, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
if (curbuf->b_has_textprop && lnum > 0)
|
if (curbuf->b_has_textprop && lnum > 0)
|
||||||
// Add text properties that continue from the previous line.
|
// Add text properties that continue from the previous line.
|
||||||
@@ -3368,7 +3374,8 @@ ml_replace_len(
|
|||||||
if (newline != NULL)
|
if (newline != NULL)
|
||||||
{
|
{
|
||||||
mch_memmove(newline, line, len);
|
mch_memmove(newline, line, len);
|
||||||
mch_memmove(newline + len, curbuf->b_ml.ml_line_ptr + oldtextlen, textproplen);
|
mch_memmove(newline + len, curbuf->b_ml.ml_line_ptr
|
||||||
|
+ oldtextlen, textproplen);
|
||||||
vim_free(line);
|
vim_free(line);
|
||||||
line = newline;
|
line = newline;
|
||||||
len += (colnr_T)textproplen;
|
len += (colnr_T)textproplen;
|
||||||
@@ -3526,6 +3533,11 @@ ml_delete_int(buf_T *buf, linenr_T lnum, int message)
|
|||||||
if (lnum < 1 || lnum > buf->b_ml.ml_line_count)
|
if (lnum < 1 || lnum > buf->b_ml.ml_line_count)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
// When inserting above recorded changes: flush the changes before changing
|
||||||
|
// the text.
|
||||||
|
may_invoke_listeners(buf, lnum, lnum + 1, -1);
|
||||||
|
#endif
|
||||||
if (lowest_marked && lowest_marked > lnum)
|
if (lowest_marked && lowest_marked > lnum)
|
||||||
lowest_marked--;
|
lowest_marked--;
|
||||||
|
|
||||||
|
|||||||
11
src/misc1.c
11
src/misc1.c
@@ -434,8 +434,15 @@ set_indent(
|
|||||||
saved_cursor.col = (colnr_T)(s - newline);
|
saved_cursor.col = (colnr_T)(s - newline);
|
||||||
}
|
}
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
adjust_prop_columns(curwin->w_cursor.lnum, (colnr_T)(p - oldline),
|
{
|
||||||
ind_len - (colnr_T)(p - oldline));
|
int added = ind_len - (colnr_T)(p - oldline);
|
||||||
|
|
||||||
|
// When increasing indent this behaves like spaces were inserted at
|
||||||
|
// the old indent, when decreasing indent it behaves like spaces
|
||||||
|
// were deleted at the new indent.
|
||||||
|
adjust_prop_columns(curwin->w_cursor.lnum,
|
||||||
|
(colnr_T)(added > 0 ? (p - oldline) : ind_len), added);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
retval = TRUE;
|
retval = TRUE;
|
||||||
}
|
}
|
||||||
|
|||||||
68
src/ops.c
68
src/ops.c
@@ -1211,7 +1211,8 @@ do_execreg(
|
|||||||
int retval = OK;
|
int retval = OK;
|
||||||
int remap;
|
int remap;
|
||||||
|
|
||||||
if (regname == '@') /* repeat previous one */
|
// repeat previous one
|
||||||
|
if (regname == '@')
|
||||||
{
|
{
|
||||||
if (execreg_lastc == NUL)
|
if (execreg_lastc == NUL)
|
||||||
{
|
{
|
||||||
@@ -1220,7 +1221,7 @@ do_execreg(
|
|||||||
}
|
}
|
||||||
regname = execreg_lastc;
|
regname = execreg_lastc;
|
||||||
}
|
}
|
||||||
/* check for valid regname */
|
// check for valid regname
|
||||||
if (regname == '%' || regname == '#' || !valid_yank_reg(regname, FALSE))
|
if (regname == '%' || regname == '#' || !valid_yank_reg(regname, FALSE))
|
||||||
{
|
{
|
||||||
emsg_invreg(regname);
|
emsg_invreg(regname);
|
||||||
@@ -1232,11 +1233,13 @@ do_execreg(
|
|||||||
regname = may_get_selection(regname);
|
regname = may_get_selection(regname);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (regname == '_') /* black hole: don't stuff anything */
|
// black hole: don't stuff anything
|
||||||
|
if (regname == '_')
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
#ifdef FEAT_CMDHIST
|
#ifdef FEAT_CMDHIST
|
||||||
if (regname == ':') /* use last command line */
|
// use last command line
|
||||||
|
if (regname == ':')
|
||||||
{
|
{
|
||||||
if (last_cmdline == NULL)
|
if (last_cmdline == NULL)
|
||||||
{
|
{
|
||||||
@@ -1913,10 +1916,9 @@ op_delete(oparg_T *oap)
|
|||||||
curwin->w_cursor.coladd = 0;
|
curwin->w_cursor.coladd = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* n == number of chars deleted
|
// "n" == number of chars deleted
|
||||||
* If we delete a TAB, it may be replaced by several characters.
|
// If we delete a TAB, it may be replaced by several characters.
|
||||||
* Thus the number of characters may increase!
|
// Thus the number of characters may increase!
|
||||||
*/
|
|
||||||
n = bd.textlen - bd.startspaces - bd.endspaces;
|
n = bd.textlen - bd.startspaces - bd.endspaces;
|
||||||
oldp = ml_get(lnum);
|
oldp = ml_get(lnum);
|
||||||
newp = alloc_check((unsigned)STRLEN(oldp) + 1 - n);
|
newp = alloc_check((unsigned)STRLEN(oldp) + 1 - n);
|
||||||
@@ -1932,6 +1934,11 @@ op_delete(oparg_T *oap)
|
|||||||
STRMOVE(newp + bd.textcol + bd.startspaces + bd.endspaces, oldp);
|
STRMOVE(newp + bd.textcol + bd.startspaces + bd.endspaces, oldp);
|
||||||
/* replace the line */
|
/* replace the line */
|
||||||
ml_replace(lnum, newp, FALSE);
|
ml_replace(lnum, newp, FALSE);
|
||||||
|
|
||||||
|
#ifdef FEAT_TEXT_PROP
|
||||||
|
if (curbuf->b_has_textprop && n != 0)
|
||||||
|
adjust_prop_columns(lnum, bd.textcol, -n);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
check_cursor_col();
|
check_cursor_col();
|
||||||
@@ -4438,7 +4445,10 @@ do_join(
|
|||||||
&& has_format_option(FO_REMOVE_COMS);
|
&& has_format_option(FO_REMOVE_COMS);
|
||||||
int prev_was_comment;
|
int prev_was_comment;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef FEAT_TEXT_PROP
|
||||||
|
textprop_T **prop_lines = NULL;
|
||||||
|
int *prop_lengths = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (save_undo && u_save((linenr_T)(curwin->w_cursor.lnum - 1),
|
if (save_undo && u_save((linenr_T)(curwin->w_cursor.lnum - 1),
|
||||||
(linenr_T)(curwin->w_cursor.lnum + count)) == FAIL)
|
(linenr_T)(curwin->w_cursor.lnum + count)) == FAIL)
|
||||||
@@ -4463,8 +4473,9 @@ do_join(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't move anything, just compute the final line length
|
* Don't move anything yet, just compute the final line length
|
||||||
* and setup the array of space strings lengths
|
* and setup the array of space strings lengths
|
||||||
|
* This loops forward over the joined lines.
|
||||||
*/
|
*/
|
||||||
for (t = 0; t < count; ++t)
|
for (t = 0; t < count; ++t)
|
||||||
{
|
{
|
||||||
@@ -4556,8 +4567,24 @@ do_join(
|
|||||||
cend = newp + sumsize;
|
cend = newp + sumsize;
|
||||||
*cend = 0;
|
*cend = 0;
|
||||||
|
|
||||||
|
#ifdef FEAT_TEXT_PROP
|
||||||
|
// We need to move properties of the lines that are going to be deleted to
|
||||||
|
// the new long one.
|
||||||
|
if (curbuf->b_has_textprop && !text_prop_frozen)
|
||||||
|
{
|
||||||
|
// Allocate an array to copy the text properties of joined lines into.
|
||||||
|
// And another array to store the number of properties in each line.
|
||||||
|
prop_lines = (textprop_T **)alloc_clear(
|
||||||
|
(int)(count - 1) * sizeof(textprop_T *));
|
||||||
|
prop_lengths = (int *)alloc_clear((int)(count - 1) * sizeof(int));
|
||||||
|
if (prop_lengths == NULL)
|
||||||
|
VIM_CLEAR(prop_lines);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Move affected lines to the new long one.
|
* Move affected lines to the new long one.
|
||||||
|
* This loops backwards over the joined lines, including the original line.
|
||||||
*
|
*
|
||||||
* Move marks from each deleted line to the joined line, adjusting the
|
* Move marks from each deleted line to the joined line, adjusting the
|
||||||
* column. This is not Vi compatible, but Vi deletes the marks, thus that
|
* column. This is not Vi compatible, but Vi deletes the marks, thus that
|
||||||
@@ -4583,8 +4610,15 @@ do_join(
|
|||||||
(long)(cend - newp - spaces_removed), spaces_removed);
|
(long)(cend - newp - spaces_removed), spaces_removed);
|
||||||
if (t == 0)
|
if (t == 0)
|
||||||
break;
|
break;
|
||||||
|
#ifdef FEAT_TEXT_PROP
|
||||||
|
if (prop_lines != NULL)
|
||||||
|
adjust_props_for_join(curwin->w_cursor.lnum + t,
|
||||||
|
prop_lines + t - 1, prop_lengths + t - 1,
|
||||||
|
(long)(cend - newp - spaces_removed), spaces_removed);
|
||||||
|
#endif
|
||||||
|
|
||||||
curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1));
|
curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1));
|
||||||
#if defined(FEAT_COMMENTS) || defined(PROTO)
|
#if defined(FEAT_COMMENTS)
|
||||||
if (remove_comments)
|
if (remove_comments)
|
||||||
curr += comments[t - 1];
|
curr += comments[t - 1];
|
||||||
#endif
|
#endif
|
||||||
@@ -4592,20 +4626,26 @@ do_join(
|
|||||||
curr = skipwhite(curr);
|
curr = skipwhite(curr);
|
||||||
currsize = (int)STRLEN(curr);
|
currsize = (int)STRLEN(curr);
|
||||||
}
|
}
|
||||||
ml_replace(curwin->w_cursor.lnum, newp, FALSE);
|
|
||||||
|
#ifdef FEAT_TEXT_PROP
|
||||||
|
if (prop_lines != NULL)
|
||||||
|
join_prop_lines(curwin->w_cursor.lnum, newp,
|
||||||
|
prop_lines, prop_lengths, count);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
ml_replace(curwin->w_cursor.lnum, newp, FALSE);
|
||||||
|
|
||||||
if (setmark)
|
if (setmark)
|
||||||
{
|
{
|
||||||
/* Set the '] mark. */
|
/* Set the '] mark. */
|
||||||
curwin->w_buffer->b_op_end.lnum = curwin->w_cursor.lnum;
|
curwin->w_buffer->b_op_end.lnum = curwin->w_cursor.lnum;
|
||||||
curwin->w_buffer->b_op_end.col = (colnr_T)STRLEN(newp);
|
curwin->w_buffer->b_op_end.col = (colnr_T)sumsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only report the change in the first line here, del_lines() will report
|
/* Only report the change in the first line here, del_lines() will report
|
||||||
* the deleted line. */
|
* the deleted line. */
|
||||||
changed_lines(curwin->w_cursor.lnum, currsize,
|
changed_lines(curwin->w_cursor.lnum, currsize,
|
||||||
curwin->w_cursor.lnum + 1, 0L);
|
curwin->w_cursor.lnum + 1, 0L);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Delete following lines. To do this we move the cursor there
|
* Delete following lines. To do this we move the cursor there
|
||||||
* briefly, and then move it back. After del_lines() the cursor may
|
* briefly, and then move it back. After del_lines() the cursor may
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ void change_warning(int col);
|
|||||||
void changed(void);
|
void changed(void);
|
||||||
void changed_internal(void);
|
void changed_internal(void);
|
||||||
void f_listener_add(typval_T *argvars, typval_T *rettv);
|
void f_listener_add(typval_T *argvars, typval_T *rettv);
|
||||||
|
void f_listener_flush(typval_T *argvars, typval_T *rettv);
|
||||||
void f_listener_remove(typval_T *argvars, typval_T *rettv);
|
void f_listener_remove(typval_T *argvars, typval_T *rettv);
|
||||||
void invoke_listeners(void);
|
void may_invoke_listeners(buf_T *buf, linenr_T lnum, linenr_T lnume, int added);
|
||||||
|
void invoke_listeners(buf_T *buf);
|
||||||
void changed_bytes(linenr_T lnum, colnr_T col);
|
void changed_bytes(linenr_T lnum, colnr_T col);
|
||||||
void inserted_bytes(linenr_T lnum, colnr_T col, int added);
|
void inserted_bytes(linenr_T lnum, colnr_T col, int added);
|
||||||
void appended_lines(linenr_T lnum, long count);
|
void appended_lines(linenr_T lnum, long count);
|
||||||
|
|||||||
@@ -14,5 +14,7 @@ void f_prop_type_list(typval_T *argvars, typval_T *rettv);
|
|||||||
void clear_global_prop_types(void);
|
void clear_global_prop_types(void);
|
||||||
void clear_buf_prop_types(buf_T *buf);
|
void clear_buf_prop_types(buf_T *buf);
|
||||||
void adjust_prop_columns(linenr_T lnum, colnr_T col, int bytes_added);
|
void adjust_prop_columns(linenr_T lnum, colnr_T col, int bytes_added);
|
||||||
void adjust_props_for_split(linenr_T lnum, int kept, int deleted);
|
void adjust_props_for_split(linenr_T lnum_props, linenr_T lnum_top, int kept, int deleted);
|
||||||
|
void adjust_props_for_join(linenr_T lnum, textprop_T **prop_line, int *prop_length, long col, int removed);
|
||||||
|
void join_prop_lines(linenr_T lnum, char_u *newp, textprop_T **prop_lines, int *prop_lengths, int count);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
|||||||
35
src/screen.c
35
src/screen.c
@@ -565,8 +565,13 @@ update_screen(int type_arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
// Before updating the screen, notify any listeners of changed text.
|
{
|
||||||
invoke_listeners();
|
buf_T *buf;
|
||||||
|
|
||||||
|
// Before updating the screen, notify any listeners of changed text.
|
||||||
|
FOR_ALL_BUFFERS(buf)
|
||||||
|
invoke_listeners(buf);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (must_redraw)
|
if (must_redraw)
|
||||||
@@ -3171,7 +3176,6 @@ win_line(
|
|||||||
int vcol_off = 0; /* offset for concealed characters */
|
int vcol_off = 0; /* offset for concealed characters */
|
||||||
int did_wcol = FALSE;
|
int did_wcol = FALSE;
|
||||||
int match_conc = 0; /* cchar for match functions */
|
int match_conc = 0; /* cchar for match functions */
|
||||||
int has_match_conc = 0; /* match wants to conceal */
|
|
||||||
int old_boguscols = 0;
|
int old_boguscols = 0;
|
||||||
# define VCOL_HLC (vcol - vcol_off)
|
# define VCOL_HLC (vcol - vcol_off)
|
||||||
# define FIX_FOR_BOGUSCOLS \
|
# define FIX_FOR_BOGUSCOLS \
|
||||||
@@ -3742,7 +3746,8 @@ win_line(
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
#ifdef FEAT_CONCEAL
|
#ifdef FEAT_CONCEAL
|
||||||
has_match_conc = 0;
|
int has_match_conc = 0; // match wants to conceal
|
||||||
|
int did_decrement_ptr = FALSE;
|
||||||
#endif
|
#endif
|
||||||
/* Skip this quickly when working on the text. */
|
/* Skip this quickly when working on the text. */
|
||||||
if (draw_state != WL_LINE)
|
if (draw_state != WL_LINE)
|
||||||
@@ -4301,11 +4306,15 @@ win_line(
|
|||||||
char_attr = hl_combine_attr(line_attr, area_attr);
|
char_attr = hl_combine_attr(line_attr, area_attr);
|
||||||
else if (search_attr != 0)
|
else if (search_attr != 0)
|
||||||
char_attr = hl_combine_attr(line_attr, search_attr);
|
char_attr = hl_combine_attr(line_attr, search_attr);
|
||||||
/* Use line_attr when not in the Visual or 'incsearch' area
|
# ifdef FEAT_TEXT_PROP
|
||||||
* (area_attr may be 0 when "noinvcur" is set). */
|
else if (text_prop_type != NULL)
|
||||||
|
char_attr = hl_combine_attr(line_attr, text_prop_attr);
|
||||||
|
# endif
|
||||||
else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL)
|
else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL)
|
||||||
|| vcol < fromcol || vcol_prev < fromcol_prev
|
|| vcol < fromcol || vcol_prev < fromcol_prev
|
||||||
|| vcol >= tocol))
|
|| vcol >= tocol))
|
||||||
|
// Use line_attr when not in the Visual or 'incsearch' area
|
||||||
|
// (area_attr may be 0 when "noinvcur" is set).
|
||||||
char_attr = line_attr;
|
char_attr = line_attr;
|
||||||
#else
|
#else
|
||||||
if (area_attr != 0)
|
if (area_attr != 0)
|
||||||
@@ -4591,9 +4600,12 @@ win_line(
|
|||||||
mb_utf8 = FALSE;
|
mb_utf8 = FALSE;
|
||||||
mb_l = 1;
|
mb_l = 1;
|
||||||
multi_attr = HL_ATTR(HLF_AT);
|
multi_attr = HL_ATTR(HLF_AT);
|
||||||
/* Put pointer back so that the character will be
|
// Put pointer back so that the character will be
|
||||||
* displayed at the start of the next line. */
|
// displayed at the start of the next line.
|
||||||
--ptr;
|
--ptr;
|
||||||
|
#ifdef FEAT_CONCEAL
|
||||||
|
did_decrement_ptr = TRUE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if (*ptr != NUL)
|
else if (*ptr != NUL)
|
||||||
ptr += mb_l - 1;
|
ptr += mb_l - 1;
|
||||||
@@ -5256,7 +5268,12 @@ win_line(
|
|||||||
prev_syntax_id = 0;
|
prev_syntax_id = 0;
|
||||||
is_concealing = FALSE;
|
is_concealing = FALSE;
|
||||||
}
|
}
|
||||||
#endif /* FEAT_CONCEAL */
|
|
||||||
|
if (n_skip > 0 && did_decrement_ptr)
|
||||||
|
// not showing the '>', put pointer back to avoid getting stuck
|
||||||
|
++ptr;
|
||||||
|
|
||||||
|
#endif // FEAT_CONCEAL
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_CONCEAL
|
#ifdef FEAT_CONCEAL
|
||||||
|
|||||||
@@ -2439,6 +2439,7 @@ struct file_buffer
|
|||||||
dict_T *b_vars; /* internal variables, local to buffer */
|
dict_T *b_vars; /* internal variables, local to buffer */
|
||||||
|
|
||||||
listener_T *b_listener;
|
listener_T *b_listener;
|
||||||
|
list_T *b_recorded_changes;
|
||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
int b_has_textprop; // TRUE when text props were added
|
int b_has_textprop; // TRUE when text props were added
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ SCRIPTS_FIRST = \
|
|||||||
# Tests that run on all systems.
|
# Tests that run on all systems.
|
||||||
SCRIPTS_ALL = \
|
SCRIPTS_ALL = \
|
||||||
test3.out \
|
test3.out \
|
||||||
test29.out \
|
|
||||||
test37.out \
|
test37.out \
|
||||||
test39.out \
|
test39.out \
|
||||||
test42.out \
|
test42.out \
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ VIMPROG = <->vim.exe
|
|||||||
.SUFFIXES : .out .in
|
.SUFFIXES : .out .in
|
||||||
|
|
||||||
SCRIPT = test1.out test3.out \
|
SCRIPT = test1.out test3.out \
|
||||||
test29.out \
|
|
||||||
test30.out test37.out test39.out \
|
test30.out test37.out test39.out \
|
||||||
test42.out test44.out test48.out test49.out \
|
test42.out test44.out test48.out test49.out \
|
||||||
test64.out test69.out \
|
test64.out test69.out \
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
| +0#af5f00255#ffffff0@1|1| |O+0#0000000&|n|e| +0&#ffff4012|t|w|o| +0&#ffffff0@63
|
| +0#af5f00255#ffffff0@1|1| |O+0#0000000&|n|e| +0&#ffff4012|t|w|o| +0&#ffffff0@63
|
||||||
| +0#af5f00255&@1|2| |N+0#0000000#ffff4012|u|m|b|é|r| |1+0#4040ff13&|2|3| +0#0000000&|ä|n|d| |t|h|œ|n| |4+0#4040ff13&|¾|7|.+0#0000000&| +0&#ffffff0@46
|
| +0#af5f00255&@1|2| |N+0#0000000#ffff4012|u|m|b|é|r| |1+0#4040ff13&|2|3| +0#0000000&|ä|n|d| |t|h|œ|n| |4+0#4040ff13&|¾|7|.+0#0000000&| +0&#ffffff0@46
|
||||||
| +0#af5f00255&@1|3| >-+0#0000000#ffff4012|x+0&#ffffff0|a+0#4040ff13&@1|x+0#0000000&|-@1|x+0#4040ff13&|b@1|x+0#0000000&|-@1|x|c+0#4040ff13&@1|x|-+0#0000000&@1|x+0#4040ff13&|d@1|x|-+0#0000000&@1| @45
|
| +0#af5f00255&@1|3| >-+8#0000000#ffff4012|x+8&#ffffff0|a+8#4040ff13&@1|x+8#0000000&|-@1|x+8#4040ff13&|b@1|x+8#0000000&|-@1|x|c+8#4040ff13&@1|x|-+8#0000000&@1|x+8#4040ff13&|d@1|x|-+8#0000000&@1| @45
|
||||||
| +0#af5f00255&@1|4| |/+0#40ff4011&@1| |c|o|m@1|e|n|t| |w+0&#e0e0e08|i|t|h| |e+8&&|r@1|o|r| +0&#ffffff0|i|n| |i|t| +0#0000000&@43
|
| +0#af5f00255&@1|4| |/+0#40ff4011&@1| |c|o|m@1|e|n|t| |w+0&#e0e0e08|i|t|h| |e+8&&|r@1|o|r| +0&#ffffff0|i|n| |i|t| +0#0000000&@43
|
||||||
|
| +0#af5f00255&@1|5| |f+0#0000000&|i|r|s|t| |l+0&#ffff4012|i|n|e| @1|s|e|c|o|n|d| +0&#ffffff0|l|i|n|e| @1|t|h|i|r|d| |l|i|n|e| |f|o|u|r|t|h| |l+0&#ffff4012|i|n|e| +0&#ffffff0@23
|
||||||
|~+0#4040ff13&| @73
|
|~+0#4040ff13&| @73
|
||||||
|~| @73
|
|~| @73
|
||||||
| +0#0000000&@56|3|,|1| @10|A|l@1|
|
| +0#0000000&@56|3|,|1| @10|A|l@1|
|
||||||
|
|||||||
12
src/testdir/dumps/Test_textprop_vis_01.dump
Normal file
12
src/testdir/dumps/Test_textprop_vis_01.dump
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
|x+0&#ffffff0@4>x@1| |1+0&#ffff4012|2|3| +0&#ffffff0|x| @61
|
||||||
|
|x@5| |1+0&#ffff4012|2|3| +0&#ffffff0|x| @62
|
||||||
|
|x@4| |1+0&#ffff4012|2|3| +0&#ffffff0|x| @63
|
||||||
|
|x@4|1+0&#ffff4012|2|3| +0&#ffffff0|x| @64
|
||||||
|
|x@4|2+0&#ffff4012|3| +0&#ffffff0|x| @65
|
||||||
|
|x@3| |3+0&#ffff4012| +0&#ffffff0|x@1| @65
|
||||||
|
|x@2| |1+0&#ffff4012| +0&#ffffff0|x@2| @65
|
||||||
|
|x@1| |1+0&#ffff4012|2|x+0&#ffffff0@3| @65
|
||||||
|
|x| |1+0&#ffff4012|2|3|x+0&#ffffff0@3| @65
|
||||||
|
@1|1+0&#ffff4012|2|3| +0&#ffffff0|x@3| @65
|
||||||
|
|~+0#4040ff13&| @73
|
||||||
|
| +0#0000000&@56|1|,|6| @10|A|l@1|
|
||||||
12
src/testdir/dumps/Test_textprop_vis_02.dump
Normal file
12
src/testdir/dumps/Test_textprop_vis_02.dump
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
|x+0&#ffffff0@4> |1+0&#ffff4012|2|3| +0&#ffffff0|x| @63
|
||||||
|
|x@4|1+0&#ffff4012|2|3| +0&#ffffff0|x| @64
|
||||||
|
|x@4|2+0&#ffff4012|3| +0&#ffffff0|x| @65
|
||||||
|
|x@4|3+0&#ffff4012| +0&#ffffff0|x| @66
|
||||||
|
|x@4| |x| @67
|
||||||
|
|x@3| |x@1| @67
|
||||||
|
|x@2| |1+0&#ffff4012|x+0&#ffffff0@1| @67
|
||||||
|
|x@1| |1+0&#ffff4012|2|x+0&#ffffff0@1| @67
|
||||||
|
|x| |1+0&#ffff4012|2|3|x+0&#ffffff0@1| @67
|
||||||
|
@1|1+0&#ffff4012|2|3| +0&#ffffff0|x@1| @67
|
||||||
|
|~+0#4040ff13&| @73
|
||||||
|
| +0#0000000&@56|1|,|6| @10|A|l@1|
|
||||||
@@ -1,231 +0,0 @@
|
|||||||
Test for joining lines and marks in them
|
|
||||||
in compatible and nocompatible modes
|
|
||||||
and with 'joinspaces' set or not
|
|
||||||
and with 'cpoptions' flag 'j' set or not
|
|
||||||
|
|
||||||
STARTTEST
|
|
||||||
:so small.vim
|
|
||||||
:set nocompatible viminfo+=nviminfo
|
|
||||||
:set nojoinspaces
|
|
||||||
:set cpoptions-=j
|
|
||||||
/firstline/
|
|
||||||
j"td/^STARTTEST/-1
|
|
||||||
PJjJjJjJjJjJjJjJjJjJjJjJjJjJj05lmx2j06lmy2k4Jy3l$p`xyl$p`yy2l$p:set cpoptions+=j
|
|
||||||
j05lmx2j06lmy2k4Jy3l$p`xyl$p`yy2l$p:set cpoptions-=j joinspaces
|
|
||||||
j"tpJjJjJjJjJjJjJjJjJjJjJjJjJjJj05lmx2j06lmy2k4Jy3l$p`xyl$p`yy2l$p:set cpoptions+=j
|
|
||||||
j05lmx2j06lmy2k4Jy3l$p`xyl$p`yy2l$p:set cpoptions-=j nojoinspaces compatible
|
|
||||||
j"tpJjJjJjJjJjJjJjJjJjJjJjJjJjJj4Jy3l$pjd/STARTTEST/-2
|
|
||||||
ENDTEST
|
|
||||||
|
|
||||||
firstline
|
|
||||||
asdfasdf.
|
|
||||||
asdf
|
|
||||||
asdfasdf.
|
|
||||||
asdf
|
|
||||||
asdfasdf.
|
|
||||||
asdf
|
|
||||||
asdfasdf.
|
|
||||||
asdf
|
|
||||||
asdfasdf.
|
|
||||||
asdf
|
|
||||||
asdfasdf.
|
|
||||||
asdf
|
|
||||||
asdfasdf.
|
|
||||||
asdf
|
|
||||||
asdfasdf
|
|
||||||
asdf
|
|
||||||
asdfasdf
|
|
||||||
asdf
|
|
||||||
asdfasdf
|
|
||||||
asdf
|
|
||||||
asdfasdf
|
|
||||||
asdf
|
|
||||||
asdfasdf
|
|
||||||
asdf
|
|
||||||
asdfasdf
|
|
||||||
asdf
|
|
||||||
asdfasdf
|
|
||||||
asdf
|
|
||||||
zx cvn.
|
|
||||||
as dfg?
|
|
||||||
hjkl iop!
|
|
||||||
ert
|
|
||||||
zx cvn.
|
|
||||||
as dfg?
|
|
||||||
hjkl iop!
|
|
||||||
ert
|
|
||||||
|
|
||||||
STARTTEST
|
|
||||||
/^{/+1
|
|
||||||
:set comments=s1:/*,mb:*,ex:*/,://
|
|
||||||
:set nojoinspaces fo=j
|
|
||||||
:set backspace=eol,start
|
|
||||||
:.,+3join
|
|
||||||
j4J
|
|
||||||
:.,+2join
|
|
||||||
j3J
|
|
||||||
:.,+2join
|
|
||||||
j3J
|
|
||||||
:.,+2join
|
|
||||||
jj3J
|
|
||||||
ENDTEST
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure the previous comment leader is not removed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure the previous comment leader is not removed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Should the next comment leader be left alone?
|
|
||||||
// Yes.
|
|
||||||
|
|
||||||
// Should the next comment leader be left alone?
|
|
||||||
// Yes.
|
|
||||||
|
|
||||||
/* Here the comment leader should be left intact. */
|
|
||||||
// And so should this one.
|
|
||||||
|
|
||||||
/* Here the comment leader should be left intact. */
|
|
||||||
// And so should this one.
|
|
||||||
|
|
||||||
if (condition) // Remove the next comment leader!
|
|
||||||
// OK, I will.
|
|
||||||
action();
|
|
||||||
|
|
||||||
if (condition) // Remove the next comment leader!
|
|
||||||
// OK, I will.
|
|
||||||
action();
|
|
||||||
}
|
|
||||||
|
|
||||||
STARTTEST
|
|
||||||
:" Test with backspace set to the non-compatible setting
|
|
||||||
:set belloff=all
|
|
||||||
/^\d\+ this
|
|
||||||
:set cp bs=2
|
|
||||||
Avim1
|
|
||||||
Avim2u
|
|
||||||
:set cpo-=<
|
|
||||||
:inoremap <c-u> <left><c-u>
|
|
||||||
Avim3
|
|
||||||
:iunmap <c-u>
|
|
||||||
Avim4
|
|
||||||
:" Test with backspace set to the compatible setting
|
|
||||||
:set backspace= visualbell
|
|
||||||
A vim5A
|
|
||||||
A vim6Azweiu
|
|
||||||
:inoremap <c-u> <left><c-u>
|
|
||||||
A vim7
|
|
||||||
:set compatible novisualbell
|
|
||||||
ENDTEST
|
|
||||||
1 this shouldn't be deleted
|
|
||||||
2 this shouldn't be deleted
|
|
||||||
3 this shouldn't be deleted
|
|
||||||
4 this should be deleted
|
|
||||||
5 this shouldn't be deleted
|
|
||||||
6 this shouldn't be deleted
|
|
||||||
7 this shouldn't be deleted
|
|
||||||
8 this shouldn't be deleted (not touched yet)
|
|
||||||
|
|
||||||
STARTTEST
|
|
||||||
/^{/+1
|
|
||||||
:set comments=sO:*\ -,mO:*\ \ ,exO:*/
|
|
||||||
:set comments+=s1:/*,mb:*,ex:*/,://
|
|
||||||
:set comments+=s1:>#,mb:#,ex:#<,:<
|
|
||||||
:set cpoptions-=j joinspaces fo=j
|
|
||||||
:set backspace=eol,start
|
|
||||||
:.,+3join
|
|
||||||
j4J
|
|
||||||
:.,+8join
|
|
||||||
j9J
|
|
||||||
:.,+2join
|
|
||||||
j3J
|
|
||||||
:.,+2join
|
|
||||||
j3J
|
|
||||||
:.,+2join
|
|
||||||
jj3J
|
|
||||||
j:.,+2join
|
|
||||||
jj3J
|
|
||||||
j:.,+5join
|
|
||||||
j6J
|
|
||||||
oSome code!
|
|
||||||
// Make sure backspacing does not remove this comment leader.0i
|
|
||||||
ENDTEST
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure the previous comment leader is not removed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure the previous comment leader is not removed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* List:
|
|
||||||
* - item1
|
|
||||||
* foo bar baz
|
|
||||||
* foo bar baz
|
|
||||||
* - item2
|
|
||||||
* foo bar baz
|
|
||||||
* foo bar baz
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* List:
|
|
||||||
* - item1
|
|
||||||
* foo bar baz
|
|
||||||
* foo bar baz
|
|
||||||
* - item2
|
|
||||||
* foo bar baz
|
|
||||||
* foo bar baz
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Should the next comment leader be left alone?
|
|
||||||
// Yes.
|
|
||||||
|
|
||||||
// Should the next comment leader be left alone?
|
|
||||||
// Yes.
|
|
||||||
|
|
||||||
/* Here the comment leader should be left intact. */
|
|
||||||
// And so should this one.
|
|
||||||
|
|
||||||
/* Here the comment leader should be left intact. */
|
|
||||||
// And so should this one.
|
|
||||||
|
|
||||||
if (condition) // Remove the next comment leader!
|
|
||||||
// OK, I will.
|
|
||||||
action();
|
|
||||||
|
|
||||||
if (condition) // Remove the next comment leader!
|
|
||||||
// OK, I will.
|
|
||||||
action();
|
|
||||||
|
|
||||||
int i = 7 /* foo *// 3
|
|
||||||
// comment
|
|
||||||
;
|
|
||||||
|
|
||||||
int i = 7 /* foo *// 3
|
|
||||||
// comment
|
|
||||||
;
|
|
||||||
|
|
||||||
># Note that the last character of the ending comment leader (left angle
|
|
||||||
# bracket) is a comment leader itself. Make sure that this comment leader is
|
|
||||||
# not removed from the next line #<
|
|
||||||
< On this line a new comment is opened which spans 2 lines. This comment should
|
|
||||||
< retain its comment leader.
|
|
||||||
|
|
||||||
># Note that the last character of the ending comment leader (left angle
|
|
||||||
# bracket) is a comment leader itself. Make sure that this comment leader is
|
|
||||||
# not removed from the next line #<
|
|
||||||
< On this line a new comment is opened which spans 2 lines. This comment should
|
|
||||||
< retain its comment leader.
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
STARTTEST
|
|
||||||
:g/^STARTTEST/.,/^ENDTEST/d
|
|
||||||
:?firstline?+1,$w! test.out
|
|
||||||
:qa!
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
zx cvn. as dfg? hjkl iop! ert ernop
|
|
||||||
zx cvn. as dfg? hjkl iop! ert ernop
|
|
||||||
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
zx cvn. as dfg? hjkl iop! ert enop
|
|
||||||
zx cvn. as dfg? hjkl iop! ert ernop
|
|
||||||
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf. asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
asdfasdf asdf
|
|
||||||
zx cvn. as dfg? hjkl iop! ert a
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
/* Make sure the previous comment leader is not removed. */
|
|
||||||
/* Make sure the previous comment leader is not removed. */
|
|
||||||
// Should the next comment leader be left alone? Yes.
|
|
||||||
// Should the next comment leader be left alone? Yes.
|
|
||||||
/* Here the comment leader should be left intact. */ // And so should this one.
|
|
||||||
/* Here the comment leader should be left intact. */ // And so should this one.
|
|
||||||
if (condition) // Remove the next comment leader! OK, I will.
|
|
||||||
action();
|
|
||||||
if (condition) // Remove the next comment leader! OK, I will.
|
|
||||||
action();
|
|
||||||
}
|
|
||||||
|
|
||||||
1 this shouldn't be deleted
|
|
||||||
2 this shouldn't be deleted
|
|
||||||
3 this shouldn't be deleted
|
|
||||||
4 this should be deleted3
|
|
||||||
|
|
||||||
6 this shouldn't be deleted vim5
|
|
||||||
7 this shouldn't be deleted vim6
|
|
||||||
8 this shouldn't be deleted (not touched yet) vim7
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
/* Make sure the previous comment leader is not removed. */
|
|
||||||
/* Make sure the previous comment leader is not removed. */
|
|
||||||
/* List: item1 foo bar baz foo bar baz item2 foo bar baz foo bar baz */
|
|
||||||
/* List: item1 foo bar baz foo bar baz item2 foo bar baz foo bar baz */
|
|
||||||
// Should the next comment leader be left alone? Yes.
|
|
||||||
// Should the next comment leader be left alone? Yes.
|
|
||||||
/* Here the comment leader should be left intact. */ // And so should this one.
|
|
||||||
/* Here the comment leader should be left intact. */ // And so should this one.
|
|
||||||
if (condition) // Remove the next comment leader! OK, I will.
|
|
||||||
action();
|
|
||||||
if (condition) // Remove the next comment leader! OK, I will.
|
|
||||||
action();
|
|
||||||
int i = 7 /* foo *// 3 // comment
|
|
||||||
;
|
|
||||||
int i = 7 /* foo *// 3 // comment
|
|
||||||
;
|
|
||||||
># Note that the last character of the ending comment leader (left angle bracket) is a comment leader itself. Make sure that this comment leader is not removed from the next line #< < On this line a new comment is opened which spans 2 lines. This comment should retain its comment leader.
|
|
||||||
># Note that the last character of the ending comment leader (left angle bracket) is a comment leader itself. Make sure that this comment leader is not removed from the next line #< < On this line a new comment is opened which spans 2 lines. This comment should retain its comment leader.
|
|
||||||
|
|
||||||
Some code!// Make sure backspacing does not remove this comment leader.
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -56,4 +56,55 @@ func Test_backspace_option()
|
|||||||
set nocompatible viminfo+=nviminfo
|
set nocompatible viminfo+=nviminfo
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Test with backspace set to the non-compatible setting
|
||||||
|
func Test_backspace_ctrl_u()
|
||||||
|
new
|
||||||
|
call append(0, [
|
||||||
|
\ "1 this shouldn't be deleted",
|
||||||
|
\ "2 this shouldn't be deleted",
|
||||||
|
\ "3 this shouldn't be deleted",
|
||||||
|
\ "4 this should be deleted",
|
||||||
|
\ "5 this shouldn't be deleted",
|
||||||
|
\ "6 this shouldn't be deleted",
|
||||||
|
\ "7 this shouldn't be deleted",
|
||||||
|
\ "8 this shouldn't be deleted (not touched yet)"])
|
||||||
|
call cursor(2, 1)
|
||||||
|
|
||||||
|
set compatible
|
||||||
|
set backspace=2
|
||||||
|
|
||||||
|
exe "normal Avim1\<C-U>\<Esc>\<CR>"
|
||||||
|
exe "normal Avim2\<C-G>u\<C-U>\<Esc>\<CR>"
|
||||||
|
|
||||||
|
set cpo-=<
|
||||||
|
inoremap <c-u> <left><c-u>
|
||||||
|
exe "normal Avim3\<C-U>\<Esc>\<CR>"
|
||||||
|
iunmap <c-u>
|
||||||
|
exe "normal Avim4\<C-U>\<C-U>\<Esc>\<CR>"
|
||||||
|
|
||||||
|
" Test with backspace set to the compatible setting
|
||||||
|
set backspace= visualbell
|
||||||
|
exe "normal A vim5\<Esc>A\<C-U>\<C-U>\<Esc>\<CR>"
|
||||||
|
exe "normal A vim6\<Esc>Azwei\<C-G>u\<C-U>\<Esc>\<CR>"
|
||||||
|
|
||||||
|
inoremap <c-u> <left><c-u>
|
||||||
|
exe "normal A vim7\<C-U>\<C-U>\<Esc>\<CR>"
|
||||||
|
|
||||||
|
call assert_equal([
|
||||||
|
\ "1 this shouldn't be deleted",
|
||||||
|
\ "2 this shouldn't be deleted",
|
||||||
|
\ "3 this shouldn't be deleted",
|
||||||
|
\ "4 this should be deleted3",
|
||||||
|
\ "",
|
||||||
|
\ "6 this shouldn't be deleted vim5",
|
||||||
|
\ "7 this shouldn't be deleted vim6",
|
||||||
|
\ "8 this shouldn't be deleted (not touched yet) vim7",
|
||||||
|
\ ""], getline(1, '$'))
|
||||||
|
|
||||||
|
set compatible&vim
|
||||||
|
set visualbell&vim
|
||||||
|
set backspace&vim
|
||||||
|
close!
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ func Test_setbufline_getbufline()
|
|||||||
hide
|
hide
|
||||||
call assert_equal(0, setbufline(b, 1, ['foo', 'bar']))
|
call assert_equal(0, setbufline(b, 1, ['foo', 'bar']))
|
||||||
call assert_equal(['foo'], getbufline(b, 1))
|
call assert_equal(['foo'], getbufline(b, 1))
|
||||||
call assert_equal(['bar'], getbufline(b, 2))
|
call assert_equal(['bar'], getbufline(b, '$'))
|
||||||
call assert_equal(['foo', 'bar'], getbufline(b, 1, 2))
|
call assert_equal(['foo', 'bar'], getbufline(b, 1, 2))
|
||||||
exe "bd!" b
|
exe "bd!" b
|
||||||
call assert_equal([], getbufline(b, 1, 2))
|
call assert_equal([], getbufline(b, 1, 2))
|
||||||
@@ -81,6 +81,7 @@ func Test_appendbufline()
|
|||||||
call setline(1, ['a', 'b', 'c'])
|
call setline(1, ['a', 'b', 'c'])
|
||||||
let b = bufnr('%')
|
let b = bufnr('%')
|
||||||
wincmd w
|
wincmd w
|
||||||
|
call assert_equal(1, appendbufline(b, -1, ['x']))
|
||||||
call assert_equal(1, appendbufline(b, 4, ['x']))
|
call assert_equal(1, appendbufline(b, 4, ['x']))
|
||||||
call assert_equal(1, appendbufline(1234, 1, ['x']))
|
call assert_equal(1, appendbufline(1234, 1, ['x']))
|
||||||
call assert_equal(0, appendbufline(b, 3, ['d', 'e']))
|
call assert_equal(0, appendbufline(b, 3, ['d', 'e']))
|
||||||
@@ -130,8 +131,11 @@ func Test_deletebufline()
|
|||||||
exe "bd!" b
|
exe "bd!" b
|
||||||
call assert_equal(1, deletebufline(b, 1))
|
call assert_equal(1, deletebufline(b, 1))
|
||||||
|
|
||||||
|
call assert_equal(1, deletebufline(-1, 1))
|
||||||
|
|
||||||
split Xtest
|
split Xtest
|
||||||
call setline(1, ['a', 'b', 'c'])
|
call setline(1, ['a', 'b', 'c'])
|
||||||
|
call cursor(line('$'), 1)
|
||||||
let b = bufnr('%')
|
let b = bufnr('%')
|
||||||
wincmd w
|
wincmd w
|
||||||
call assert_equal(1, deletebufline(b, 4))
|
call assert_equal(1, deletebufline(b, 4))
|
||||||
|
|||||||
@@ -102,4 +102,14 @@ func Test_cindent_expr()
|
|||||||
bw!
|
bw!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_cindent_func()
|
||||||
|
new
|
||||||
|
setlocal cindent
|
||||||
|
call setline(1, ['int main(void)', '{', 'return 0;', '}'])
|
||||||
|
call assert_equal(cindent(0), -1)
|
||||||
|
call assert_equal(cindent(3), &sw)
|
||||||
|
call assert_equal(cindent(line('$')+1), -1)
|
||||||
|
bwipe!
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
|||||||
@@ -25,6 +25,12 @@ func Test_move_cursor()
|
|||||||
call cursor(9, 1)
|
call cursor(9, 1)
|
||||||
call assert_equal([4, 1, 0, 1], getcurpos()[1:])
|
call assert_equal([4, 1, 0, 1], getcurpos()[1:])
|
||||||
|
|
||||||
|
call setline(1, ["\<TAB>"])
|
||||||
|
call cursor(1, 1, 1)
|
||||||
|
call assert_equal([1, 1, 1], getcurpos()[1:3])
|
||||||
|
|
||||||
|
call assert_equal(-1, cursor(-1, -1))
|
||||||
|
|
||||||
quit!
|
quit!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
|||||||
@@ -105,3 +105,8 @@ func Test_symlink_recursive_delete()
|
|||||||
bwipe Xdir3/subdir/Xfile
|
bwipe Xdir3/subdir/Xfile
|
||||||
bwipe Xdir4/Xfile
|
bwipe Xdir4/Xfile
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_delete_errors()
|
||||||
|
call assert_fails('call delete('''')', 'E474:')
|
||||||
|
call assert_fails('call delete(''foo'', 0)', 'E15:')
|
||||||
|
endfunc
|
||||||
|
|||||||
@@ -64,3 +64,12 @@ func Test_expand_sflnum()
|
|||||||
call assert_equal(64, str2nr(trim(execute('Flnum'))))
|
call assert_equal(64, str2nr(trim(execute('Flnum'))))
|
||||||
delcommand Flnum
|
delcommand Flnum
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_expand()
|
||||||
|
new
|
||||||
|
call assert_equal("", expand('%:S'))
|
||||||
|
call assert_equal('3', expand('<slnum>'))
|
||||||
|
call assert_equal(['4'], expand('<slnum>', v:false, v:true))
|
||||||
|
" Don't add any line above this, otherwise <slnum> will change.
|
||||||
|
quit
|
||||||
|
endfunc
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ func Test_abs()
|
|||||||
call assert_equal('inf', string(abs(1.0/0.0)))
|
call assert_equal('inf', string(abs(1.0/0.0)))
|
||||||
call assert_equal('inf', string(abs(-1.0/0.0)))
|
call assert_equal('inf', string(abs(-1.0/0.0)))
|
||||||
call assert_equal('nan', string(abs(0.0/0.0)))
|
call assert_equal('nan', string(abs(0.0/0.0)))
|
||||||
|
call assert_equal('12', string(abs('12abc')))
|
||||||
call assert_equal('12', string(abs('-12abc')))
|
call assert_equal('12', string(abs('-12abc')))
|
||||||
call assert_fails("call abs([])", 'E745:')
|
call assert_fails("call abs([])", 'E745:')
|
||||||
call assert_fails("call abs({})", 'E728:')
|
call assert_fails("call abs({})", 'E728:')
|
||||||
|
|||||||
@@ -45,9 +45,3 @@ func Test_fnamemodify()
|
|||||||
let $HOME = save_home
|
let $HOME = save_home
|
||||||
let &shell = save_shell
|
let &shell = save_shell
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_expand()
|
|
||||||
new
|
|
||||||
call assert_equal("", expand('%:S'))
|
|
||||||
quit
|
|
||||||
endfunc
|
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ func Test_empty()
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
call assert_equal(0, empty(function('Test_empty')))
|
call assert_equal(0, empty(function('Test_empty')))
|
||||||
|
call assert_equal(0, empty(function('Test_empty', [0])))
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_len()
|
func Test_len()
|
||||||
@@ -869,6 +870,7 @@ func Test_count()
|
|||||||
call assert_equal(1, count(l, 'a', 0, 1))
|
call assert_equal(1, count(l, 'a', 0, 1))
|
||||||
call assert_equal(2, count(l, 'a', 1, 1))
|
call assert_equal(2, count(l, 'a', 1, 1))
|
||||||
call assert_fails('call count(l, "a", 0, 10)', 'E684:')
|
call assert_fails('call count(l, "a", 0, 10)', 'E684:')
|
||||||
|
call assert_fails('call count(l, "a", [])', 'E745:')
|
||||||
|
|
||||||
let d = {1: 'a', 2: 'a', 3: 'A', 4: 'b'}
|
let d = {1: 'a', 2: 'a', 3: 'A', 4: 'b'}
|
||||||
call assert_equal(2, count(d, 'a'))
|
call assert_equal(2, count(d, 'a'))
|
||||||
@@ -896,6 +898,8 @@ func Test_count()
|
|||||||
call assert_equal(2, count("foo", "O", 1))
|
call assert_equal(2, count("foo", "O", 1))
|
||||||
call assert_equal(2, count("fooooo", "oo"))
|
call assert_equal(2, count("fooooo", "oo"))
|
||||||
call assert_equal(0, count("foo", ""))
|
call assert_equal(0, count("foo", ""))
|
||||||
|
|
||||||
|
call assert_fails('call count(0, 0)', 'E712:')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_changenr()
|
func Test_changenr()
|
||||||
@@ -1431,3 +1435,23 @@ func Test_readdir()
|
|||||||
|
|
||||||
call delete('Xdir', 'rf')
|
call delete('Xdir', 'rf')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_call()
|
||||||
|
call assert_equal(3, call('len', [123]))
|
||||||
|
call assert_fails("call call('len', 123)", 'E714:')
|
||||||
|
call assert_equal(0, call('', []))
|
||||||
|
|
||||||
|
function Mylen() dict
|
||||||
|
return len(self.data)
|
||||||
|
endfunction
|
||||||
|
let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")}
|
||||||
|
call assert_fails("call call('Mylen', [], 0)", 'E715:')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_char2nr()
|
||||||
|
call assert_equal(12354, char2nr('あ', 1))
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_eventhandler()
|
||||||
|
call assert_equal(0, eventhandler())
|
||||||
|
endfunc
|
||||||
|
|||||||
@@ -33,3 +33,391 @@ func Test_join_marks()
|
|||||||
call assert_equal([0, 4, 67, 0], getpos("']"))
|
call assert_equal([0, 4, 67, 0], getpos("']"))
|
||||||
enew!
|
enew!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Test for joining lines and marks in them
|
||||||
|
" in compatible and nocompatible modes
|
||||||
|
" and with 'joinspaces' set or not
|
||||||
|
" and with 'cpoptions' flag 'j' set or not
|
||||||
|
func Test_join_spaces_marks()
|
||||||
|
new
|
||||||
|
" Text used for the test
|
||||||
|
insert
|
||||||
|
asdfasdf.
|
||||||
|
asdf
|
||||||
|
asdfasdf.
|
||||||
|
asdf
|
||||||
|
asdfasdf.
|
||||||
|
asdf
|
||||||
|
asdfasdf.
|
||||||
|
asdf
|
||||||
|
asdfasdf.
|
||||||
|
asdf
|
||||||
|
asdfasdf.
|
||||||
|
asdf
|
||||||
|
asdfasdf.
|
||||||
|
asdf
|
||||||
|
asdfasdf
|
||||||
|
asdf
|
||||||
|
asdfasdf
|
||||||
|
asdf
|
||||||
|
asdfasdf
|
||||||
|
asdf
|
||||||
|
asdfasdf
|
||||||
|
asdf
|
||||||
|
asdfasdf
|
||||||
|
asdf
|
||||||
|
asdfasdf
|
||||||
|
asdf
|
||||||
|
asdfasdf
|
||||||
|
asdf
|
||||||
|
zx cvn.
|
||||||
|
as dfg?
|
||||||
|
hjkl iop!
|
||||||
|
ert
|
||||||
|
zx cvn.
|
||||||
|
as dfg?
|
||||||
|
hjkl iop!
|
||||||
|
ert
|
||||||
|
.
|
||||||
|
let text = getline(1, '$')
|
||||||
|
normal gg
|
||||||
|
|
||||||
|
set nojoinspaces
|
||||||
|
set cpoptions-=j
|
||||||
|
normal JjJjJjJjJjJjJjJjJjJjJjJjJjJ
|
||||||
|
normal j05lmx
|
||||||
|
normal 2j06lmy
|
||||||
|
normal 2k4Jy3l$p
|
||||||
|
normal `xyl$p
|
||||||
|
normal `yy2l$p
|
||||||
|
|
||||||
|
set cpoptions+=j
|
||||||
|
normal j05lmx
|
||||||
|
normal 2j06lmy
|
||||||
|
normal 2k4Jy3l$p
|
||||||
|
normal `xyl$p
|
||||||
|
normal `yy2l$p
|
||||||
|
|
||||||
|
normal G
|
||||||
|
let last_line = line('$')
|
||||||
|
|
||||||
|
" Expected output
|
||||||
|
append
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
zx cvn. as dfg? hjkl iop! ert ernop
|
||||||
|
zx cvn. as dfg? hjkl iop! ert ernop
|
||||||
|
.
|
||||||
|
|
||||||
|
call assert_equal(getline(last_line + 1, '$'), getline(1, last_line))
|
||||||
|
|
||||||
|
enew!
|
||||||
|
call append(0, text)
|
||||||
|
normal gg
|
||||||
|
|
||||||
|
set cpoptions-=j
|
||||||
|
set joinspaces
|
||||||
|
normal JjJjJjJjJjJjJjJjJjJjJjJjJjJ
|
||||||
|
normal j05lmx
|
||||||
|
normal 2j06lmy
|
||||||
|
normal 2k4Jy3l$p
|
||||||
|
normal `xyl$p
|
||||||
|
normal `yy2l$p
|
||||||
|
|
||||||
|
set cpoptions+=j
|
||||||
|
normal j05lmx
|
||||||
|
normal 2j06lmy
|
||||||
|
normal 2k4Jy3l$p
|
||||||
|
normal `xyl$p
|
||||||
|
normal `yy2l$p
|
||||||
|
|
||||||
|
normal G
|
||||||
|
let last_line = line('$')
|
||||||
|
|
||||||
|
" Expected output
|
||||||
|
append
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
zx cvn. as dfg? hjkl iop! ert enop
|
||||||
|
zx cvn. as dfg? hjkl iop! ert ernop
|
||||||
|
|
||||||
|
.
|
||||||
|
|
||||||
|
call assert_equal(getline(last_line + 1, '$'), getline(1, last_line))
|
||||||
|
|
||||||
|
enew!
|
||||||
|
call append(0, text)
|
||||||
|
normal gg
|
||||||
|
|
||||||
|
set cpoptions-=j
|
||||||
|
set nojoinspaces
|
||||||
|
set compatible
|
||||||
|
|
||||||
|
normal JjJjJjJjJjJjJjJjJjJjJjJjJjJ
|
||||||
|
normal j4Jy3l$pjdG
|
||||||
|
|
||||||
|
normal G
|
||||||
|
let last_line = line('$')
|
||||||
|
|
||||||
|
" Expected output
|
||||||
|
append
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf. asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
asdfasdf asdf
|
||||||
|
zx cvn. as dfg? hjkl iop! ert a
|
||||||
|
.
|
||||||
|
|
||||||
|
call assert_equal(getline(last_line + 1, '$'), getline(1, last_line))
|
||||||
|
|
||||||
|
set nocompatible
|
||||||
|
set cpoptions&vim
|
||||||
|
set joinspaces&vim
|
||||||
|
close!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test for joining lines with comments
|
||||||
|
func Test_join_lines_with_comments()
|
||||||
|
new
|
||||||
|
|
||||||
|
" Text used by the test
|
||||||
|
insert
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the previous comment leader is not removed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the previous comment leader is not removed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Should the next comment leader be left alone?
|
||||||
|
// Yes.
|
||||||
|
|
||||||
|
// Should the next comment leader be left alone?
|
||||||
|
// Yes.
|
||||||
|
|
||||||
|
/* Here the comment leader should be left intact. */
|
||||||
|
// And so should this one.
|
||||||
|
|
||||||
|
/* Here the comment leader should be left intact. */
|
||||||
|
// And so should this one.
|
||||||
|
|
||||||
|
if (condition) // Remove the next comment leader!
|
||||||
|
// OK, I will.
|
||||||
|
action();
|
||||||
|
|
||||||
|
if (condition) // Remove the next comment leader!
|
||||||
|
// OK, I will.
|
||||||
|
action();
|
||||||
|
}
|
||||||
|
.
|
||||||
|
|
||||||
|
call cursor(2, 1)
|
||||||
|
set comments=s1:/*,mb:*,ex:*/,://
|
||||||
|
set nojoinspaces fo=j
|
||||||
|
set backspace=eol,start
|
||||||
|
|
||||||
|
.,+3join
|
||||||
|
exe "normal j4J\<CR>"
|
||||||
|
.,+2join
|
||||||
|
exe "normal j3J\<CR>"
|
||||||
|
.,+2join
|
||||||
|
exe "normal j3J\<CR>"
|
||||||
|
.,+2join
|
||||||
|
exe "normal jj3J\<CR>"
|
||||||
|
|
||||||
|
normal G
|
||||||
|
let last_line = line('$')
|
||||||
|
|
||||||
|
" Expected output
|
||||||
|
append
|
||||||
|
{
|
||||||
|
/* Make sure the previous comment leader is not removed. */
|
||||||
|
/* Make sure the previous comment leader is not removed. */
|
||||||
|
// Should the next comment leader be left alone? Yes.
|
||||||
|
// Should the next comment leader be left alone? Yes.
|
||||||
|
/* Here the comment leader should be left intact. */ // And so should this one.
|
||||||
|
/* Here the comment leader should be left intact. */ // And so should this one.
|
||||||
|
if (condition) // Remove the next comment leader! OK, I will.
|
||||||
|
action();
|
||||||
|
if (condition) // Remove the next comment leader! OK, I will.
|
||||||
|
action();
|
||||||
|
}
|
||||||
|
.
|
||||||
|
|
||||||
|
call assert_equal(getline(last_line + 1, '$'), getline(1, last_line))
|
||||||
|
|
||||||
|
set comments&vim
|
||||||
|
set joinspaces&vim
|
||||||
|
set fo&vim
|
||||||
|
set backspace&vim
|
||||||
|
close!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test for joining lines with different comment leaders
|
||||||
|
func Test_join_comments_2()
|
||||||
|
new
|
||||||
|
|
||||||
|
insert
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the previous comment leader is not removed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the previous comment leader is not removed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* List:
|
||||||
|
* - item1
|
||||||
|
* foo bar baz
|
||||||
|
* foo bar baz
|
||||||
|
* - item2
|
||||||
|
* foo bar baz
|
||||||
|
* foo bar baz
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* List:
|
||||||
|
* - item1
|
||||||
|
* foo bar baz
|
||||||
|
* foo bar baz
|
||||||
|
* - item2
|
||||||
|
* foo bar baz
|
||||||
|
* foo bar baz
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Should the next comment leader be left alone?
|
||||||
|
// Yes.
|
||||||
|
|
||||||
|
// Should the next comment leader be left alone?
|
||||||
|
// Yes.
|
||||||
|
|
||||||
|
/* Here the comment leader should be left intact. */
|
||||||
|
// And so should this one.
|
||||||
|
|
||||||
|
/* Here the comment leader should be left intact. */
|
||||||
|
// And so should this one.
|
||||||
|
|
||||||
|
if (condition) // Remove the next comment leader!
|
||||||
|
// OK, I will.
|
||||||
|
action();
|
||||||
|
|
||||||
|
if (condition) // Remove the next comment leader!
|
||||||
|
// OK, I will.
|
||||||
|
action();
|
||||||
|
|
||||||
|
int i = 7 /* foo *// 3
|
||||||
|
// comment
|
||||||
|
;
|
||||||
|
|
||||||
|
int i = 7 /* foo *// 3
|
||||||
|
// comment
|
||||||
|
;
|
||||||
|
|
||||||
|
># Note that the last character of the ending comment leader (left angle
|
||||||
|
# bracket) is a comment leader itself. Make sure that this comment leader is
|
||||||
|
# not removed from the next line #<
|
||||||
|
< On this line a new comment is opened which spans 2 lines. This comment should
|
||||||
|
< retain its comment leader.
|
||||||
|
|
||||||
|
># Note that the last character of the ending comment leader (left angle
|
||||||
|
# bracket) is a comment leader itself. Make sure that this comment leader is
|
||||||
|
# not removed from the next line #<
|
||||||
|
< On this line a new comment is opened which spans 2 lines. This comment should
|
||||||
|
< retain its comment leader.
|
||||||
|
|
||||||
|
}
|
||||||
|
.
|
||||||
|
|
||||||
|
call cursor(2, 1)
|
||||||
|
set comments=sO:*\ -,mO:*\ \ ,exO:*/
|
||||||
|
set comments+=s1:/*,mb:*,ex:*/,://
|
||||||
|
set comments+=s1:>#,mb:#,ex:#<,:<
|
||||||
|
set cpoptions-=j joinspaces fo=j
|
||||||
|
set backspace=eol,start
|
||||||
|
|
||||||
|
.,+3join
|
||||||
|
exe "normal j4J\<CR>"
|
||||||
|
.,+8join
|
||||||
|
exe "normal j9J\<CR>"
|
||||||
|
.,+2join
|
||||||
|
exe "normal j3J\<CR>"
|
||||||
|
.,+2join
|
||||||
|
exe "normal j3J\<CR>"
|
||||||
|
.,+2join
|
||||||
|
exe "normal jj3J\<CR>j"
|
||||||
|
.,+2join
|
||||||
|
exe "normal jj3J\<CR>j"
|
||||||
|
.,+5join
|
||||||
|
exe "normal j6J\<CR>"
|
||||||
|
exe "normal oSome code!\<CR>// Make sure backspacing does not remove this comment leader.\<Esc>0i\<C-H>\<Esc>"
|
||||||
|
|
||||||
|
normal G
|
||||||
|
let last_line = line('$')
|
||||||
|
|
||||||
|
" Expected output
|
||||||
|
append
|
||||||
|
{
|
||||||
|
/* Make sure the previous comment leader is not removed. */
|
||||||
|
/* Make sure the previous comment leader is not removed. */
|
||||||
|
/* List: item1 foo bar baz foo bar baz item2 foo bar baz foo bar baz */
|
||||||
|
/* List: item1 foo bar baz foo bar baz item2 foo bar baz foo bar baz */
|
||||||
|
// Should the next comment leader be left alone? Yes.
|
||||||
|
// Should the next comment leader be left alone? Yes.
|
||||||
|
/* Here the comment leader should be left intact. */ // And so should this one.
|
||||||
|
/* Here the comment leader should be left intact. */ // And so should this one.
|
||||||
|
if (condition) // Remove the next comment leader! OK, I will.
|
||||||
|
action();
|
||||||
|
if (condition) // Remove the next comment leader! OK, I will.
|
||||||
|
action();
|
||||||
|
int i = 7 /* foo *// 3 // comment
|
||||||
|
;
|
||||||
|
int i = 7 /* foo *// 3 // comment
|
||||||
|
;
|
||||||
|
># Note that the last character of the ending comment leader (left angle bracket) is a comment leader itself. Make sure that this comment leader is not removed from the next line #< < On this line a new comment is opened which spans 2 lines. This comment should retain its comment leader.
|
||||||
|
># Note that the last character of the ending comment leader (left angle bracket) is a comment leader itself. Make sure that this comment leader is not removed from the next line #< < On this line a new comment is opened which spans 2 lines. This comment should retain its comment leader.
|
||||||
|
|
||||||
|
Some code!// Make sure backspacing does not remove this comment leader.
|
||||||
|
}
|
||||||
|
.
|
||||||
|
|
||||||
|
call assert_equal(getline(last_line + 1, '$'), getline(1, last_line))
|
||||||
|
close!
|
||||||
|
endfunc
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
" tests for listener_add() and listener_remove()
|
" tests for listener_add() and listener_remove()
|
||||||
|
|
||||||
func s:StoreList(l)
|
func s:StoreList(s, l)
|
||||||
|
let s:start = a:s
|
||||||
|
let s:text = getline(a:s)
|
||||||
let s:list = a:l
|
let s:list = a:l
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
@@ -16,9 +18,10 @@ endfunc
|
|||||||
func Test_listening()
|
func Test_listening()
|
||||||
new
|
new
|
||||||
call setline(1, ['one', 'two'])
|
call setline(1, ['one', 'two'])
|
||||||
let id = listener_add({l -> s:StoreList(l)})
|
let s:list = []
|
||||||
|
let id = listener_add({b, s, e, a, l -> s:StoreList(s, l)})
|
||||||
call setline(1, 'one one')
|
call setline(1, 'one one')
|
||||||
redraw
|
call listener_flush()
|
||||||
call assert_equal([{'lnum': 1, 'end': 2, 'col': 1, 'added': 0}], s:list)
|
call assert_equal([{'lnum': 1, 'end': 2, 'col': 1, 'added': 0}], s:list)
|
||||||
|
|
||||||
" Undo is also a change
|
" Undo is also a change
|
||||||
@@ -26,12 +29,14 @@ func Test_listening()
|
|||||||
call append(2, 'two two')
|
call append(2, 'two two')
|
||||||
undo
|
undo
|
||||||
redraw
|
redraw
|
||||||
call assert_equal([{'lnum': 3, 'end': 3, 'col': 1, 'added': 1},
|
" the two changes get merged
|
||||||
\ {'lnum': 3, 'end': 4, 'col': 1, 'added': -1}, ], s:list)
|
call assert_equal([{'lnum': 3, 'end': 4, 'col': 1, 'added': 0}], s:list)
|
||||||
1
|
1
|
||||||
|
|
||||||
" Two listeners, both get called.
|
" Two listeners, both get called. Also check column.
|
||||||
let id2 = listener_add({l -> s:AnotherStoreList(l)})
|
call setline(1, ['one one', 'two'])
|
||||||
|
call listener_flush()
|
||||||
|
let id2 = listener_add({b, s, e, a, l -> s:AnotherStoreList(l)})
|
||||||
let s:list = []
|
let s:list = []
|
||||||
let s:list2 = []
|
let s:list2 = []
|
||||||
exe "normal $asome\<Esc>"
|
exe "normal $asome\<Esc>"
|
||||||
@@ -39,7 +44,10 @@ func Test_listening()
|
|||||||
call assert_equal([{'lnum': 1, 'end': 2, 'col': 8, 'added': 0}], s:list)
|
call assert_equal([{'lnum': 1, 'end': 2, 'col': 8, 'added': 0}], s:list)
|
||||||
call assert_equal([{'lnum': 1, 'end': 2, 'col': 8, 'added': 0}], s:list2)
|
call assert_equal([{'lnum': 1, 'end': 2, 'col': 8, 'added': 0}], s:list2)
|
||||||
|
|
||||||
|
" removing listener works
|
||||||
call listener_remove(id2)
|
call listener_remove(id2)
|
||||||
|
call setline(1, ['one one', 'two'])
|
||||||
|
call listener_flush()
|
||||||
let s:list = []
|
let s:list = []
|
||||||
let s:list2 = []
|
let s:list2 = []
|
||||||
call setline(3, 'three')
|
call setline(3, 'three')
|
||||||
@@ -47,12 +55,68 @@ func Test_listening()
|
|||||||
call assert_equal([{'lnum': 3, 'end': 3, 'col': 1, 'added': 1}], s:list)
|
call assert_equal([{'lnum': 3, 'end': 3, 'col': 1, 'added': 1}], s:list)
|
||||||
call assert_equal([], s:list2)
|
call assert_equal([], s:list2)
|
||||||
|
|
||||||
|
" a change above a previous change without a line number change is reported
|
||||||
|
" together
|
||||||
|
call setline(1, ['one one', 'two'])
|
||||||
|
call listener_flush()
|
||||||
|
call append(2, 'two two')
|
||||||
|
call setline(1, 'something')
|
||||||
|
call listener_flush()
|
||||||
|
call assert_equal([{'lnum': 3, 'end': 3, 'col': 1, 'added': 1},
|
||||||
|
\ {'lnum': 1, 'end': 2, 'col': 1, 'added': 0}], s:list)
|
||||||
|
|
||||||
|
" an insert just above a previous change that was the last one gets merged
|
||||||
|
call setline(1, ['one one', 'two'])
|
||||||
|
call listener_flush()
|
||||||
|
let s:list = []
|
||||||
|
call setline(2, 'something')
|
||||||
|
call append(1, 'two two')
|
||||||
|
call assert_equal([], s:list)
|
||||||
|
call listener_flush()
|
||||||
|
call assert_equal([{'lnum': 2, 'end': 3, 'col': 1, 'added': 1}], s:list)
|
||||||
|
|
||||||
|
" an insert above a previous change causes a flush
|
||||||
|
call setline(1, ['one one', 'two'])
|
||||||
|
call listener_flush()
|
||||||
|
call setline(2, 'something')
|
||||||
|
call append(0, 'two two')
|
||||||
|
call assert_equal([{'lnum': 2, 'end': 3, 'col': 1, 'added': 0}], s:list)
|
||||||
|
call assert_equal('something', s:text)
|
||||||
|
call listener_flush()
|
||||||
|
call assert_equal([{'lnum': 1, 'end': 1, 'col': 1, 'added': 1}], s:list)
|
||||||
|
call assert_equal('two two', s:text)
|
||||||
|
|
||||||
|
" a delete at a previous change that was the last one gets merged
|
||||||
|
call setline(1, ['one one', 'two'])
|
||||||
|
call listener_flush()
|
||||||
|
let s:list = []
|
||||||
|
call setline(2, 'something')
|
||||||
|
2del
|
||||||
|
call assert_equal([], s:list)
|
||||||
|
call listener_flush()
|
||||||
|
call assert_equal([{'lnum': 2, 'end': 3, 'col': 1, 'added': -1}], s:list)
|
||||||
|
|
||||||
|
" a delete above a previous change causes a flush
|
||||||
|
call setline(1, ['one one', 'two'])
|
||||||
|
call listener_flush()
|
||||||
|
call setline(2, 'another')
|
||||||
|
1del
|
||||||
|
call assert_equal([{'lnum': 2, 'end': 3, 'col': 1, 'added': 0}], s:list)
|
||||||
|
call assert_equal(2, s:start)
|
||||||
|
call assert_equal('another', s:text)
|
||||||
|
call listener_flush()
|
||||||
|
call assert_equal([{'lnum': 1, 'end': 2, 'col': 1, 'added': -1}], s:list)
|
||||||
|
call assert_equal('another', s:text)
|
||||||
|
|
||||||
" the "o" command first adds an empty line and then changes it
|
" the "o" command first adds an empty line and then changes it
|
||||||
|
%del
|
||||||
|
call setline(1, ['one one', 'two'])
|
||||||
|
call listener_flush()
|
||||||
let s:list = []
|
let s:list = []
|
||||||
exe "normal Gofour\<Esc>"
|
exe "normal Gofour\<Esc>"
|
||||||
redraw
|
redraw
|
||||||
call assert_equal([{'lnum': 4, 'end': 4, 'col': 1, 'added': 1},
|
call assert_equal([{'lnum': 3, 'end': 3, 'col': 1, 'added': 1},
|
||||||
\ {'lnum': 4, 'end': 5, 'col': 1, 'added': 0}], s:list)
|
\ {'lnum': 3, 'end': 4, 'col': 1, 'added': 0}], s:list)
|
||||||
|
|
||||||
" Remove last listener
|
" Remove last listener
|
||||||
let s:list = []
|
let s:list = []
|
||||||
@@ -62,7 +126,7 @@ func Test_listening()
|
|||||||
call assert_equal([], s:list)
|
call assert_equal([], s:list)
|
||||||
|
|
||||||
" Trying to change the list fails
|
" Trying to change the list fails
|
||||||
let id = listener_add({l -> s:EvilStoreList(l)})
|
let id = listener_add({b, s, e, a, l -> s:EvilStoreList(l)})
|
||||||
let s:list3 = []
|
let s:list3 = []
|
||||||
call setline(1, 'asdfasdf')
|
call setline(1, 'asdfasdf')
|
||||||
redraw
|
redraw
|
||||||
@@ -72,9 +136,64 @@ func Test_listening()
|
|||||||
bwipe!
|
bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func s:StoreBufList(buf, l)
|
func s:StoreListArgs(buf, start, end, added, list)
|
||||||
|
let s:buf = a:buf
|
||||||
|
let s:start = a:start
|
||||||
|
let s:end = a:end
|
||||||
|
let s:added = a:added
|
||||||
|
let s:list = a:list
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_listener_args()
|
||||||
|
new
|
||||||
|
call setline(1, ['one', 'two'])
|
||||||
|
let s:list = []
|
||||||
|
let id = listener_add('s:StoreListArgs')
|
||||||
|
|
||||||
|
" just one change
|
||||||
|
call setline(1, 'one one')
|
||||||
|
call listener_flush()
|
||||||
|
call assert_equal(bufnr(''), s:buf)
|
||||||
|
call assert_equal(1, s:start)
|
||||||
|
call assert_equal(2, s:end)
|
||||||
|
call assert_equal(0, s:added)
|
||||||
|
call assert_equal([{'lnum': 1, 'end': 2, 'col': 1, 'added': 0}], s:list)
|
||||||
|
|
||||||
|
" two disconnected changes
|
||||||
|
call setline(1, ['one', 'two', 'three', 'four'])
|
||||||
|
call listener_flush()
|
||||||
|
call setline(1, 'one one')
|
||||||
|
call setline(3, 'three three')
|
||||||
|
call listener_flush()
|
||||||
|
call assert_equal(bufnr(''), s:buf)
|
||||||
|
call assert_equal(1, s:start)
|
||||||
|
call assert_equal(4, s:end)
|
||||||
|
call assert_equal(0, s:added)
|
||||||
|
call assert_equal([{'lnum': 1, 'end': 2, 'col': 1, 'added': 0},
|
||||||
|
\ {'lnum': 3, 'end': 4, 'col': 1, 'added': 0}], s:list)
|
||||||
|
|
||||||
|
" add and remove lines
|
||||||
|
call setline(1, ['one', 'two', 'three', 'four', 'five', 'six'])
|
||||||
|
call listener_flush()
|
||||||
|
call append(2, 'two two')
|
||||||
|
4del
|
||||||
|
call append(5, 'five five')
|
||||||
|
call listener_flush()
|
||||||
|
call assert_equal(bufnr(''), s:buf)
|
||||||
|
call assert_equal(3, s:start)
|
||||||
|
call assert_equal(6, s:end)
|
||||||
|
call assert_equal(1, s:added)
|
||||||
|
call assert_equal([{'lnum': 3, 'end': 3, 'col': 1, 'added': 1},
|
||||||
|
\ {'lnum': 4, 'end': 5, 'col': 1, 'added': -1},
|
||||||
|
\ {'lnum': 6, 'end': 6, 'col': 1, 'added': 1}], s:list)
|
||||||
|
|
||||||
|
call listener_remove(id)
|
||||||
|
bwipe!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func s:StoreBufList(buf, start, end, added, list)
|
||||||
let s:bufnr = a:buf
|
let s:bufnr = a:buf
|
||||||
let s:list = a:l
|
let s:list = a:list
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_listening_other_buf()
|
func Test_listening_other_buf()
|
||||||
@@ -82,7 +201,7 @@ func Test_listening_other_buf()
|
|||||||
call setline(1, ['one', 'two'])
|
call setline(1, ['one', 'two'])
|
||||||
let bufnr = bufnr('')
|
let bufnr = bufnr('')
|
||||||
normal ww
|
normal ww
|
||||||
let id = listener_add(function('s:StoreBufList', [bufnr]), bufnr)
|
let id = listener_add(function('s:StoreBufList'), bufnr)
|
||||||
let s:list = []
|
let s:list = []
|
||||||
call setbufline(bufnr, 1, 'hello')
|
call setbufline(bufnr, 1, 'hello')
|
||||||
redraw
|
redraw
|
||||||
|
|||||||
@@ -470,13 +470,19 @@ func Test_shortmess_F2()
|
|||||||
call assert_match('file2', execute('bn', ''))
|
call assert_match('file2', execute('bn', ''))
|
||||||
set shortmess+=F
|
set shortmess+=F
|
||||||
call assert_true(empty(execute('bn', '')))
|
call assert_true(empty(execute('bn', '')))
|
||||||
|
call assert_false(test_getvalue('need_fileinfo'))
|
||||||
call assert_true(empty(execute('bn', '')))
|
call assert_true(empty(execute('bn', '')))
|
||||||
|
call assert_false(test_getvalue('need_fileinfo'))
|
||||||
set hidden
|
set hidden
|
||||||
call assert_true(empty(execute('bn', '')))
|
call assert_true(empty(execute('bn', '')))
|
||||||
|
call assert_false(test_getvalue('need_fileinfo'))
|
||||||
call assert_true(empty(execute('bn', '')))
|
call assert_true(empty(execute('bn', '')))
|
||||||
|
call assert_false(test_getvalue('need_fileinfo'))
|
||||||
set nohidden
|
set nohidden
|
||||||
call assert_true(empty(execute('bn', '')))
|
call assert_true(empty(execute('bn', '')))
|
||||||
|
call assert_false(test_getvalue('need_fileinfo'))
|
||||||
call assert_true(empty(execute('bn', '')))
|
call assert_true(empty(execute('bn', '')))
|
||||||
|
call assert_false(test_getvalue('need_fileinfo'))
|
||||||
set shortmess&
|
set shortmess&
|
||||||
call assert_match('file1', execute('bn', ''))
|
call assert_match('file1', execute('bn', ''))
|
||||||
call assert_match('file2', execute('bn', ''))
|
call assert_match('file2', execute('bn', ''))
|
||||||
|
|||||||
@@ -638,6 +638,17 @@ func Test_nocatch_sub_failure_handling()
|
|||||||
call assert_equal(1, error_caught)
|
call assert_equal(1, error_caught)
|
||||||
call assert_equal(['1 aaa', '2 aaa', '3 aaa'], getline(1, 3))
|
call assert_equal(['1 aaa', '2 aaa', '3 aaa'], getline(1, 3))
|
||||||
|
|
||||||
|
" Same, but using "n" flag so that "sandbox" gets set
|
||||||
|
call setline(1, ['1 aaa', '2 aaa', '3 aaa'])
|
||||||
|
let error_caught = 0
|
||||||
|
try
|
||||||
|
%s/aaa/\=Foo()/gn
|
||||||
|
catch
|
||||||
|
let error_caught = 1
|
||||||
|
endtry
|
||||||
|
call assert_equal(1, error_caught)
|
||||||
|
call assert_equal(['1 aaa', '2 aaa', '3 aaa'], getline(1, 3))
|
||||||
|
|
||||||
bwipe!
|
bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ endfunc
|
|||||||
|
|
||||||
func SetupOneLine()
|
func SetupOneLine()
|
||||||
call setline(1, 'xonex xtwoxx')
|
call setline(1, 'xonex xtwoxx')
|
||||||
|
normal gg0
|
||||||
call AddPropTypes()
|
call AddPropTypes()
|
||||||
call prop_add(1, 2, {'length': 3, 'id': 11, 'type': 'one'})
|
call prop_add(1, 2, {'length': 3, 'id': 11, 'type': 'one'})
|
||||||
call prop_add(1, 8, {'length': 3, 'id': 12, 'type': 'two'})
|
call prop_add(1, 8, {'length': 3, 'id': 12, 'type': 'two'})
|
||||||
@@ -272,6 +273,65 @@ func Test_prop_replace()
|
|||||||
set bs&
|
set bs&
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_prop_open_line()
|
||||||
|
new
|
||||||
|
|
||||||
|
" open new line, props stay in top line
|
||||||
|
let expected = SetupOneLine() " 'xonex xtwoxx'
|
||||||
|
exe "normal o\<Esc>"
|
||||||
|
call assert_equal('xonex xtwoxx', getline(1))
|
||||||
|
call assert_equal('', getline(2))
|
||||||
|
call assert_equal(expected, prop_list(1))
|
||||||
|
call DeletePropTypes()
|
||||||
|
|
||||||
|
" move all props to next line
|
||||||
|
let expected = SetupOneLine() " 'xonex xtwoxx'
|
||||||
|
exe "normal 0i\<CR>\<Esc>"
|
||||||
|
call assert_equal('', getline(1))
|
||||||
|
call assert_equal('xonex xtwoxx', getline(2))
|
||||||
|
call assert_equal(expected, prop_list(2))
|
||||||
|
call DeletePropTypes()
|
||||||
|
|
||||||
|
" split just before prop, move all props to next line
|
||||||
|
let expected = SetupOneLine() " 'xonex xtwoxx'
|
||||||
|
exe "normal 0li\<CR>\<Esc>"
|
||||||
|
call assert_equal('x', getline(1))
|
||||||
|
call assert_equal('onex xtwoxx', getline(2))
|
||||||
|
let expected[0].col -= 1
|
||||||
|
let expected[1].col -= 1
|
||||||
|
call assert_equal(expected, prop_list(2))
|
||||||
|
call DeletePropTypes()
|
||||||
|
|
||||||
|
" split inside prop, split first prop
|
||||||
|
let expected = SetupOneLine() " 'xonex xtwoxx'
|
||||||
|
exe "normal 0lli\<CR>\<Esc>"
|
||||||
|
call assert_equal('xo', getline(1))
|
||||||
|
call assert_equal('nex xtwoxx', getline(2))
|
||||||
|
let exp_first = [deepcopy(expected[0])]
|
||||||
|
let exp_first[0].length = 1
|
||||||
|
call assert_equal(exp_first, prop_list(1))
|
||||||
|
let expected[0].col = 1
|
||||||
|
let expected[0].length = 2
|
||||||
|
let expected[1].col -= 2
|
||||||
|
call assert_equal(expected, prop_list(2))
|
||||||
|
call DeletePropTypes()
|
||||||
|
|
||||||
|
" split just after first prop, second prop move to next line
|
||||||
|
let expected = SetupOneLine() " 'xonex xtwoxx'
|
||||||
|
exe "normal 0fea\<CR>\<Esc>"
|
||||||
|
call assert_equal('xone', getline(1))
|
||||||
|
call assert_equal('x xtwoxx', getline(2))
|
||||||
|
let exp_first = expected[0:0]
|
||||||
|
call assert_equal(exp_first, prop_list(1))
|
||||||
|
let expected = expected[1:1]
|
||||||
|
let expected[0].col -= 4
|
||||||
|
call assert_equal(expected, prop_list(2))
|
||||||
|
call DeletePropTypes()
|
||||||
|
|
||||||
|
bwipe!
|
||||||
|
set bs&
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_prop_clear()
|
func Test_prop_clear()
|
||||||
new
|
new
|
||||||
call AddPropTypes()
|
call AddPropTypes()
|
||||||
@@ -553,7 +613,7 @@ func Test_prop_undo()
|
|||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" screenshot test with textprop highlighting
|
" screenshot test with textprop highlighting
|
||||||
funct Test_textprop_screenshots()
|
func Test_textprop_screenshot_various()
|
||||||
" The Vim running in the terminal needs to use utf-8.
|
" The Vim running in the terminal needs to use utf-8.
|
||||||
if !CanRunVimInTerminal() || g:orig_encoding != 'utf-8'
|
if !CanRunVimInTerminal() || g:orig_encoding != 'utf-8'
|
||||||
return
|
return
|
||||||
@@ -564,6 +624,10 @@ funct Test_textprop_screenshots()
|
|||||||
\ .. "'Numbér 123 änd thœn 4¾7.',"
|
\ .. "'Numbér 123 änd thœn 4¾7.',"
|
||||||
\ .. "'--aa--bb--cc--dd--',"
|
\ .. "'--aa--bb--cc--dd--',"
|
||||||
\ .. "'// comment with error in it',"
|
\ .. "'// comment with error in it',"
|
||||||
|
\ .. "'first line',"
|
||||||
|
\ .. "' second line ',"
|
||||||
|
\ .. "'third line',"
|
||||||
|
\ .. "' fourth line',"
|
||||||
\ .. "])",
|
\ .. "])",
|
||||||
\ "hi NumberProp ctermfg=blue",
|
\ "hi NumberProp ctermfg=blue",
|
||||||
\ "hi LongProp ctermbg=yellow",
|
\ "hi LongProp ctermbg=yellow",
|
||||||
@@ -585,18 +649,74 @@ funct Test_textprop_screenshots()
|
|||||||
\ "call prop_add(3, 15, {'length': 2, 'type': 'both'})",
|
\ "call prop_add(3, 15, {'length': 2, 'type': 'both'})",
|
||||||
\ "call prop_add(4, 12, {'length': 10, 'type': 'background'})",
|
\ "call prop_add(4, 12, {'length': 10, 'type': 'background'})",
|
||||||
\ "call prop_add(4, 17, {'length': 5, 'type': 'error'})",
|
\ "call prop_add(4, 17, {'length': 5, 'type': 'error'})",
|
||||||
\ "set number",
|
\ "call prop_add(5, 7, {'length': 4, 'type': 'long'})",
|
||||||
|
\ "call prop_add(6, 1, {'length': 8, 'type': 'long'})",
|
||||||
|
\ "call prop_add(8, 1, {'length': 1, 'type': 'long'})",
|
||||||
|
\ "call prop_add(8, 11, {'length': 4, 'type': 'long'})",
|
||||||
|
\ "set number cursorline",
|
||||||
\ "hi clear SpellBad",
|
\ "hi clear SpellBad",
|
||||||
\ "set spell",
|
\ "set spell",
|
||||||
\ "syn match Comment '//.*'",
|
\ "syn match Comment '//.*'",
|
||||||
\ "hi Comment ctermfg=green",
|
\ "hi Comment ctermfg=green",
|
||||||
\ "normal 3G0llix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>",
|
\ "normal 3G0llix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>",
|
||||||
\ "normal 3G0lli\<BS>\<Esc>",
|
\ "normal 3G0lli\<BS>\<Esc>",
|
||||||
|
\ "normal 6G0i\<BS>\<Esc>",
|
||||||
|
\ "normal 3J",
|
||||||
|
\ "normal 3G",
|
||||||
\], 'XtestProp')
|
\], 'XtestProp')
|
||||||
let buf = RunVimInTerminal('-S XtestProp', {'rows': 7})
|
let buf = RunVimInTerminal('-S XtestProp', {'rows': 8})
|
||||||
call VerifyScreenDump(buf, 'Test_textprop_01', {})
|
call VerifyScreenDump(buf, 'Test_textprop_01', {})
|
||||||
|
|
||||||
" clean up
|
" clean up
|
||||||
call StopVimInTerminal(buf)
|
call StopVimInTerminal(buf)
|
||||||
call delete('XtestProp')
|
call delete('XtestProp')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func RunTestVisualBlock(width, dump)
|
||||||
|
call writefile([
|
||||||
|
\ "call setline(1, ["
|
||||||
|
\ .. "'xxxxxxxxx 123 x',"
|
||||||
|
\ .. "'xxxxxxxx 123 x',"
|
||||||
|
\ .. "'xxxxxxx 123 x',"
|
||||||
|
\ .. "'xxxxxx 123 x',"
|
||||||
|
\ .. "'xxxxx 123 x',"
|
||||||
|
\ .. "'xxxx 123 xx',"
|
||||||
|
\ .. "'xxx 123 xxx',"
|
||||||
|
\ .. "'xx 123 xxxx',"
|
||||||
|
\ .. "'x 123 xxxxx',"
|
||||||
|
\ .. "' 123 xxxxxx',"
|
||||||
|
\ .. "])",
|
||||||
|
\ "hi SearchProp ctermbg=yellow",
|
||||||
|
\ "call prop_type_add('search', {'highlight': 'SearchProp'})",
|
||||||
|
\ "call prop_add(1, 11, {'length': 3, 'type': 'search'})",
|
||||||
|
\ "call prop_add(2, 10, {'length': 3, 'type': 'search'})",
|
||||||
|
\ "call prop_add(3, 9, {'length': 3, 'type': 'search'})",
|
||||||
|
\ "call prop_add(4, 8, {'length': 3, 'type': 'search'})",
|
||||||
|
\ "call prop_add(5, 7, {'length': 3, 'type': 'search'})",
|
||||||
|
\ "call prop_add(6, 6, {'length': 3, 'type': 'search'})",
|
||||||
|
\ "call prop_add(7, 5, {'length': 3, 'type': 'search'})",
|
||||||
|
\ "call prop_add(8, 4, {'length': 3, 'type': 'search'})",
|
||||||
|
\ "call prop_add(9, 3, {'length': 3, 'type': 'search'})",
|
||||||
|
\ "call prop_add(10, 2, {'length': 3, 'type': 'search'})",
|
||||||
|
\ "normal 1G6|\<C-V>" .. repeat('l', a:width - 1) .. "10jx",
|
||||||
|
\], 'XtestPropVis')
|
||||||
|
let buf = RunVimInTerminal('-S XtestPropVis', {'rows': 12})
|
||||||
|
call VerifyScreenDump(buf, 'Test_textprop_vis_' .. a:dump, {})
|
||||||
|
|
||||||
|
" clean up
|
||||||
|
call StopVimInTerminal(buf)
|
||||||
|
call delete('XtestPropVis')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" screenshot test with Visual block mode operations
|
||||||
|
func Test_textprop_screenshot_visual()
|
||||||
|
if !CanRunVimInTerminal()
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Delete two columns while text props are three chars wide.
|
||||||
|
call RunTestVisualBlock(2, '01')
|
||||||
|
|
||||||
|
" Same, but delete four columns
|
||||||
|
call RunTestVisualBlock(4, '02')
|
||||||
|
endfunc
|
||||||
|
|||||||
163
src/textprop.c
163
src/textprop.c
@@ -8,19 +8,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Text properties implementation.
|
* Text properties implementation. See ":help text-properties".
|
||||||
*
|
|
||||||
* Text properties are attached to the text. They move with the text when
|
|
||||||
* text is inserted/deleted.
|
|
||||||
*
|
|
||||||
* Text properties have a user specified ID number, which can be unique.
|
|
||||||
* Text properties have a type, which can be used to specify highlighting.
|
|
||||||
*
|
*
|
||||||
* TODO:
|
* TODO:
|
||||||
* - When using 'cursorline' attributes should be merged. (#3912)
|
|
||||||
* - Adjust text property column and length when text is inserted/deleted.
|
* - Adjust text property column and length when text is inserted/deleted.
|
||||||
* -> a :substitute with a multi-line match
|
* -> a :substitute with a multi-line match
|
||||||
* -> search for changed_bytes() from misc1.c
|
* -> search for changed_bytes() from misc1.c
|
||||||
|
* -> search for mark_col_adjust()
|
||||||
* - Perhaps we only need TP_FLAG_CONT_NEXT and can drop TP_FLAG_CONT_PREV?
|
* - Perhaps we only need TP_FLAG_CONT_NEXT and can drop TP_FLAG_CONT_PREV?
|
||||||
* - Add an arrray for global_proptypes, to quickly lookup a prop type by ID
|
* - Add an arrray for global_proptypes, to quickly lookup a prop type by ID
|
||||||
* - Add an arrray for b_proptypes, to quickly lookup a prop type by ID
|
* - Add an arrray for b_proptypes, to quickly lookup a prop type by ID
|
||||||
@@ -28,8 +22,6 @@
|
|||||||
* the index, like DB_MARKED?
|
* the index, like DB_MARKED?
|
||||||
* - Also test line2byte() with many lines, so that ml_updatechunk() is taken
|
* - Also test line2byte() with many lines, so that ml_updatechunk() is taken
|
||||||
* into account.
|
* into account.
|
||||||
* - Add mechanism to keep track of changed lines, so that plugin can update
|
|
||||||
* text properties in these.
|
|
||||||
* - Perhaps have a window-local option to disable highlighting from text
|
* - Perhaps have a window-local option to disable highlighting from text
|
||||||
* properties?
|
* properties?
|
||||||
*/
|
*/
|
||||||
@@ -965,7 +957,7 @@ clear_buf_prop_types(buf_T *buf)
|
|||||||
* shift by "bytes_added" (can be negative).
|
* shift by "bytes_added" (can be negative).
|
||||||
* Note that "col" is zero-based, while tp_col is one-based.
|
* Note that "col" is zero-based, while tp_col is one-based.
|
||||||
* Only for the current buffer.
|
* Only for the current buffer.
|
||||||
* Called is expected to check b_has_textprop and "bytes_added" being non-zero.
|
* Caller is expected to check b_has_textprop and "bytes_added" being non-zero.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
adjust_prop_columns(
|
adjust_prop_columns(
|
||||||
@@ -1002,15 +994,28 @@ adjust_prop_columns(
|
|||||||
? 2 : 1))
|
? 2 : 1))
|
||||||
: (tmp_prop.tp_col > col + 1))
|
: (tmp_prop.tp_col > col + 1))
|
||||||
{
|
{
|
||||||
tmp_prop.tp_col += bytes_added;
|
if (tmp_prop.tp_col + bytes_added < col + 1)
|
||||||
|
{
|
||||||
|
tmp_prop.tp_len += (tmp_prop.tp_col - 1 - col) + bytes_added;
|
||||||
|
tmp_prop.tp_col = col + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tmp_prop.tp_col += bytes_added;
|
||||||
dirty = TRUE;
|
dirty = TRUE;
|
||||||
|
if (tmp_prop.tp_len <= 0)
|
||||||
|
continue; // drop this text property
|
||||||
}
|
}
|
||||||
else if (tmp_prop.tp_len > 0
|
else if (tmp_prop.tp_len > 0
|
||||||
&& tmp_prop.tp_col + tmp_prop.tp_len > col
|
&& tmp_prop.tp_col + tmp_prop.tp_len > col
|
||||||
+ ((pt != NULL && (pt->pt_flags & PT_FLAG_INS_END_INCL))
|
+ ((pt != NULL && (pt->pt_flags & PT_FLAG_INS_END_INCL))
|
||||||
? 0 : 1))
|
? 0 : 1))
|
||||||
{
|
{
|
||||||
tmp_prop.tp_len += bytes_added;
|
int after = col - bytes_added
|
||||||
|
- (tmp_prop.tp_col - 1 + tmp_prop.tp_len);
|
||||||
|
if (after > 0)
|
||||||
|
tmp_prop.tp_len += bytes_added + after;
|
||||||
|
else
|
||||||
|
tmp_prop.tp_len += bytes_added;
|
||||||
dirty = TRUE;
|
dirty = TRUE;
|
||||||
if (tmp_prop.tp_len <= 0)
|
if (tmp_prop.tp_len <= 0)
|
||||||
continue; // drop this text property
|
continue; // drop this text property
|
||||||
@@ -1033,12 +1038,17 @@ adjust_prop_columns(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Adjust text properties for a line that was split in two.
|
* Adjust text properties for a line that was split in two.
|
||||||
* "lnum" is the newly inserted line. The text properties are now on the line
|
* "lnum_props" is the line that has the properties from before the split.
|
||||||
* below it. "kept" is the number of bytes kept in the first line, while
|
* "lnum_top" is the top line.
|
||||||
|
* "kept" is the number of bytes kept in the first line, while
|
||||||
* "deleted" is the number of bytes deleted.
|
* "deleted" is the number of bytes deleted.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
adjust_props_for_split(linenr_T lnum, int kept, int deleted)
|
adjust_props_for_split(
|
||||||
|
linenr_T lnum_props,
|
||||||
|
linenr_T lnum_top,
|
||||||
|
int kept,
|
||||||
|
int deleted)
|
||||||
{
|
{
|
||||||
char_u *props;
|
char_u *props;
|
||||||
int count;
|
int count;
|
||||||
@@ -1049,11 +1059,12 @@ adjust_props_for_split(linenr_T lnum, int kept, int deleted)
|
|||||||
|
|
||||||
if (!curbuf->b_has_textprop)
|
if (!curbuf->b_has_textprop)
|
||||||
return;
|
return;
|
||||||
count = get_text_props(curbuf, lnum + 1, &props, FALSE);
|
|
||||||
|
// Get the text properties from "lnum_props".
|
||||||
|
count = get_text_props(curbuf, lnum_props, &props, FALSE);
|
||||||
ga_init2(&prevprop, sizeof(textprop_T), 10);
|
ga_init2(&prevprop, sizeof(textprop_T), 10);
|
||||||
ga_init2(&nextprop, sizeof(textprop_T), 10);
|
ga_init2(&nextprop, sizeof(textprop_T), 10);
|
||||||
|
|
||||||
// Get the text properties, which are at "lnum + 1".
|
|
||||||
// Keep the relevant ones in the first line, reducing the length if needed.
|
// Keep the relevant ones in the first line, reducing the length if needed.
|
||||||
// Copy the ones that include the split to the second line.
|
// Copy the ones that include the split to the second line.
|
||||||
// Move the ones after the split to the second line.
|
// Move the ones after the split to the second line.
|
||||||
@@ -1074,7 +1085,9 @@ adjust_props_for_split(linenr_T lnum, int kept, int deleted)
|
|||||||
++prevprop.ga_len;
|
++prevprop.ga_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prop.tp_col + prop.tp_len >= skipped && ga_grow(&nextprop, 1) == OK)
|
// Only add the property to the next line if the length is bigger than
|
||||||
|
// zero.
|
||||||
|
if (prop.tp_col + prop.tp_len > skipped && ga_grow(&nextprop, 1) == OK)
|
||||||
{
|
{
|
||||||
p = ((textprop_T *)nextprop.ga_data) + nextprop.ga_len;
|
p = ((textprop_T *)nextprop.ga_data) + nextprop.ga_len;
|
||||||
*p = prop;
|
*p = prop;
|
||||||
@@ -1089,11 +1102,117 @@ adjust_props_for_split(linenr_T lnum, int kept, int deleted)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set_text_props(lnum, prevprop.ga_data, prevprop.ga_len * sizeof(textprop_T));
|
set_text_props(lnum_top, prevprop.ga_data,
|
||||||
|
prevprop.ga_len * sizeof(textprop_T));
|
||||||
ga_clear(&prevprop);
|
ga_clear(&prevprop);
|
||||||
|
set_text_props(lnum_top + 1, nextprop.ga_data,
|
||||||
set_text_props(lnum + 1, nextprop.ga_data, nextprop.ga_len * sizeof(textprop_T));
|
nextprop.ga_len * sizeof(textprop_T));
|
||||||
ga_clear(&nextprop);
|
ga_clear(&nextprop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Line "lnum" has been joined and will end up at column "col" in the new line.
|
||||||
|
* "removed" bytes have been removed from the start of the line, properties
|
||||||
|
* there are to be discarded.
|
||||||
|
* Move the adjusted text properties to an allocated string, store it in
|
||||||
|
* "prop_line" and adjust the columns.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
adjust_props_for_join(
|
||||||
|
linenr_T lnum,
|
||||||
|
textprop_T **prop_line,
|
||||||
|
int *prop_length,
|
||||||
|
long col,
|
||||||
|
int removed)
|
||||||
|
{
|
||||||
|
int proplen;
|
||||||
|
char_u *props;
|
||||||
|
int ri;
|
||||||
|
int wi = 0;
|
||||||
|
|
||||||
|
proplen = get_text_props(curbuf, lnum, &props, FALSE);
|
||||||
|
if (proplen > 0)
|
||||||
|
{
|
||||||
|
*prop_line = (textprop_T *)alloc(proplen * (int)sizeof(textprop_T));
|
||||||
|
if (*prop_line != NULL)
|
||||||
|
{
|
||||||
|
for (ri = 0; ri < proplen; ++ri)
|
||||||
|
{
|
||||||
|
textprop_T *cp = *prop_line + wi;
|
||||||
|
|
||||||
|
mch_memmove(cp, props + ri * sizeof(textprop_T),
|
||||||
|
sizeof(textprop_T));
|
||||||
|
if (cp->tp_col + cp->tp_len > removed)
|
||||||
|
{
|
||||||
|
if (cp->tp_col > removed)
|
||||||
|
cp->tp_col += col;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// property was partly deleted, make it shorter
|
||||||
|
cp->tp_len -= removed - cp->tp_col;
|
||||||
|
cp->tp_col = col;
|
||||||
|
}
|
||||||
|
++wi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*prop_length = wi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* After joining lines: concatenate the text and the properties of all joined
|
||||||
|
* lines into one line and replace the line.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
join_prop_lines(
|
||||||
|
linenr_T lnum,
|
||||||
|
char_u *newp,
|
||||||
|
textprop_T **prop_lines,
|
||||||
|
int *prop_lengths,
|
||||||
|
int count)
|
||||||
|
{
|
||||||
|
size_t proplen = 0;
|
||||||
|
size_t oldproplen;
|
||||||
|
char_u *props;
|
||||||
|
int i;
|
||||||
|
int len;
|
||||||
|
char_u *line;
|
||||||
|
size_t l;
|
||||||
|
|
||||||
|
for (i = 0; i < count - 1; ++i)
|
||||||
|
proplen += prop_lengths[i];
|
||||||
|
if (proplen == 0)
|
||||||
|
{
|
||||||
|
ml_replace(lnum, newp, FALSE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get existing properties of the joined line
|
||||||
|
oldproplen = get_text_props(curbuf, lnum, &props, FALSE);
|
||||||
|
|
||||||
|
len = (int)STRLEN(newp) + 1;
|
||||||
|
line = alloc(len + (oldproplen + proplen) * (int)sizeof(textprop_T));
|
||||||
|
if (line == NULL)
|
||||||
|
return;
|
||||||
|
mch_memmove(line, newp, len);
|
||||||
|
l = oldproplen * sizeof(textprop_T);
|
||||||
|
mch_memmove(line + len, props, l);
|
||||||
|
len += l;
|
||||||
|
|
||||||
|
for (i = 0; i < count - 1; ++i)
|
||||||
|
if (prop_lines[i] != NULL)
|
||||||
|
{
|
||||||
|
l = prop_lengths[i] * sizeof(textprop_T);
|
||||||
|
mch_memmove(line + len, prop_lines[i], l);
|
||||||
|
len += l;
|
||||||
|
vim_free(prop_lines[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ml_replace_len(lnum, line, len, TRUE, FALSE);
|
||||||
|
vim_free(newp);
|
||||||
|
vim_free(prop_lines);
|
||||||
|
vim_free(prop_lengths);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // FEAT_TEXT_PROP
|
#endif // FEAT_TEXT_PROP
|
||||||
|
|||||||
@@ -767,6 +767,36 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1345,
|
||||||
|
/**/
|
||||||
|
1344,
|
||||||
|
/**/
|
||||||
|
1343,
|
||||||
|
/**/
|
||||||
|
1342,
|
||||||
|
/**/
|
||||||
|
1341,
|
||||||
|
/**/
|
||||||
|
1340,
|
||||||
|
/**/
|
||||||
|
1339,
|
||||||
|
/**/
|
||||||
|
1338,
|
||||||
|
/**/
|
||||||
|
1337,
|
||||||
|
/**/
|
||||||
|
1336,
|
||||||
|
/**/
|
||||||
|
1335,
|
||||||
|
/**/
|
||||||
|
1334,
|
||||||
|
/**/
|
||||||
|
1333,
|
||||||
|
/**/
|
||||||
|
1332,
|
||||||
|
/**/
|
||||||
|
1331,
|
||||||
/**/
|
/**/
|
||||||
1330,
|
1330,
|
||||||
/**/
|
/**/
|
||||||
|
|||||||
Reference in New Issue
Block a user