Compare commits

...

24 Commits

Author SHA1 Message Date
Kazuki Sakamoto 04ee357319 MacVim Snapshot 148
Binary targets macOS 10.8+

- Vim patch 8.1.0039

Script interfaces have compatibility with these versions

- Lua 5.3
- Perl 5.18
- Python2 2.7
- Python3 3.6
- Ruby 2.5
2018-06-07 21:57:29 -07:00
Kazuki Sakamoto a30133de19 Use XCODEFLAGS in order to set MACOSX_DEPLOYMENT_TARGET 2018-06-07 21:56:35 -07:00
Kazuki Sakamoto e95b546b3e Merge remote-tracking branch 'vim/master' 2018-06-07 21:26:10 -07:00
Bram Moolenaar d79a26219d patch 8.1.0039: cannot easily delete lines in another buffer
Problem:    Cannot easily delete lines in another buffer.
Solution:   Add deletebufline().
2018-06-07 18:17:46 +02:00
Bram Moolenaar 680c99b2ef patch 8.1.0038: popup test causes Vim to exit
Problem:    Popup test causes Vim to exit.
Solution:   Disable the broken part of the test for now.
2018-06-07 15:18:41 +02:00
Bram Moolenaar ca851593a6 patch 8.1.0037: cannot easily append lines to another buffer
Problem:    Cannot easily append lines to another buffer.
Solution:   Add appendbufline().
2018-06-06 21:04:07 +02:00
Bram Moolenaar 891e1fd894 patch 8.1.0036: not restoring Insert mode if leaving prompt buffer with mouse
Problem:    Not restoring Insert mode if leaving a prompt buffer by using a
            mouse click.
Solution:   Set b_prompt_insert appropriately. Also correct cursor position
            when moving cursor to last line.
2018-06-06 18:02:39 +02:00
Bram Moolenaar 6d41c78e35 patch 8.1.0035: not easy to switch between prompt buffer and other windows
Problem:    Not easy to switch between prompt buffer and other windows.
Solution:   Accept CTRL-W commands in Insert mode.  Start and stop Insert mode
            as one would expect.
2018-06-06 09:11:12 +02:00
Kazuki Sakamoto 703ff6133b Merge remote-tracking branch 'vim/master' 2018-06-05 21:53:59 -07:00
Kazuki Sakamoto 2a9f2b5bac Merge pull request #689 from ichizok/fix/redraw_after_callback
Fix: redraw_after_callback should force flush
2018-06-05 21:39:55 -07:00
ichizok 5838d3ff38 Fix: redraw_after_callback should force flush 2018-06-05 17:27:04 +09:00
Bram Moolenaar adb8fbec4f patch 8.1.0034: cursor not restored with ":edit #"
Problem:    Cursor not restored with ":edit #".
Solution:   Don't assume autocommands moved the cursor when it was moved to
            the first non-blank.
2018-06-04 20:34:23 +02:00
Bram Moolenaar acb9effecc patch 8.1.0033: keys to stop Vim in terminal are wrong
Problem:    Keys to stop Vim in terminal are wrong. (Marius Gedminas)
Solution:   Move ":" to before CTRL-U.
2018-06-04 19:11:11 +02:00
Bram Moolenaar 6b810d92a9 patch 8.1.0032: BS in prompt buffer starts new line
Problem:    BS in prompt buffer starts new line.
Solution:   Do not allows BS over the prompt.  Make term_sendkeys() handle
            special keys. Add a test.
2018-06-04 17:28:44 +02:00
Bram Moolenaar c8523e2e6c patch 8.1.0031: terminal test aucmd_on_close if flaky
Problem:    Terminal test aucmd_on_close if flaky.
Solution:   Wait a bit longer.
2018-06-03 18:22:02 +02:00
Bram Moolenaar 3339d3dad9 patch 8.1.0030: stoping Vim running in a terminal may not work
Problem:    Stoping Vim running in a terminal may not work.
Solution:   Instead of sending <Esc> send CTRL-O.
2018-06-03 17:10:40 +02:00
Bram Moolenaar 1580f755c9 patch 8.1.0029: terminal test fails on MS-Windows when "wc" exists
Problem:    Terminal test fails on MS-Windows when "wc" exists.
Solution:   Skip test with redirection on MS-Windows.
2018-06-03 15:26:36 +02:00
Bram Moolenaar 1149382d21 patch 8.1.0028: prompt buffer test fails on MS-Windows
Problem:    Prompt buffer test fails on MS-Windows.
Solution:   Disable the test for now. Remove stray assert.
2018-06-03 15:08:09 +02:00
Bram Moolenaar f273245f64 patch 8.1.0027: difficult to make a plugin that feeds a line to a job
Problem:    Difficult to make a plugin that feeds a line to a job.
Solution:   Add the nitial code for the "prompt" buftype.
2018-06-03 14:47:35 +02:00
Kazuki Sakamoto 9289901c59 Merge remote-tracking branch 'vim/master' 2018-05-28 22:36:00 -07:00
Bram Moolenaar 33c5e9fa7a patch 8.1.0026: terminal test fails with very tall terminal
Problem:    Terminal test fails with very tall terminal. (Tom)
Solution:   Fix the terminal window size in the test.
2018-05-26 18:58:51 +02:00
Bram Moolenaar e5fa11186f patch 8.1.0025: no test for the undofile() function
Problem:    No test for the undofile() function.
Solution:   Add test. (Dominique Pelle, closes #2958)
2018-05-26 18:46:30 +02:00
Bram Moolenaar 6b69e5c646 patch 8.1.0024: % command not testded on #ifdef and comment
Problem:    % command not testded on #ifdef and comment.
Solution:   Add tests. (Dominique Pelle, closes #2956)
2018-05-26 18:39:32 +02:00
Bram Moolenaar 22c105640c patch 8.1.0023: gcc 8.1 warns for use of strncpy()
Problem:    gcc 8.1 warns for use of strncpy(). (John Marriott)
Solution:   Use mch_memmove() instead of STRNCPY().
2018-05-26 17:35:27 +02:00
36 changed files with 1221 additions and 257 deletions
+1
View File
@@ -11,6 +11,7 @@ compiler:
env:
- MACOSX_DEPLOYMENT_TARGET=10.8
XCODEFLAGS="MACOSX_DEPLOYMENT_TARGET=10.8"
VERSIONER_PERL_VERSION=5.18
VERSIONER_PYTHON_VERSION=2.7
vi_cv_path_python=/usr/bin/python
+39
View File
@@ -22,6 +22,7 @@ The Netbeans interface also uses a channel. |netbeans|
9. Starting a job without a channel |job-start-nochannel|
10. Job options |job-options|
11. Controlling a job |job-control|
12. Using a prompt buffer |prompt-buffer|
{Vi does not have any of these features}
{only when compiled with the |+channel| feature for channel stuff}
@@ -770,5 +771,43 @@ signals. E.g. to force a job to stop, "kill it": >
For more options see |job_stop()|.
==============================================================================
12. Using a prompt buffer *prompt-buffer*
If you want to type input for the job in a Vim window you have a few options:
- Use a normal buffer and handle all possible commands yourself.
This will be complicated, since there are so many possible commands.
- Use a terminal window. This works well if what you type goes directly to
the job and the job output is directly displayed in the window.
See |terminal-window|.
- Use a prompt window. This works well when entering a line for the job in Vim
while displaying (possibly filtered) output from the job.
A prompt buffer is created by setting 'buftype' to "prompt". You would
normally only do that in a newly created buffer.
The user can edit and enter one line of text at the very last line of the
buffer. When pressing Enter in the prompt line the callback set with
|prompt_setcallback()| is invoked. It would normally send the line to a job.
Another callback would receive the output from the job and display it in the
buffer, below the prompt (and above the next prompt).
Only the text in the last line, after the prompt, is editable. The rest of the
buffer is not modifiable with Normal mode commands. It can be modified by
calling functions, such as |append()|. Using other commands may mess up the
buffer.
After setting 'buftype' to "prompt" Vim does not automatically start Insert
mode, use `:startinsert` if you want to enter Insert mode, so that the user
can start typing a line.
The text of the prompt can be set with the |prompt_setprompt()| function.
The user can go to Normal mode and navigate through the buffer. This can be
useful see older output or copy text.
Any command that starts Insert mode, such as "a", "i", "A" and "I", will move
the cursor to the last line, after the prompt.
vim:tw=78:ts=8:ft=help:norl:
+71 -4
View File
@@ -2110,6 +2110,8 @@ cursor({lnum}, {col} [, {off}])
cursor({list}) Number move cursor to position in {list}
deepcopy({expr} [, {noref}]) any make a full copy of {expr}
delete({fname} [, {flags}]) Number delete the file or directory {fname}
deletebufline({expr}, {first}[, {last}])
Number delete lines from buffer {expr}
did_filetype() Number |TRUE| if FileType autocmd event used
diff_filler({lnum}) Number diff filler lines about {lnum}
diff_hlID({lnum}, {col}) Number diff highlighting at {lnum}/{col}
@@ -2294,6 +2296,9 @@ perleval({expr}) any evaluate |Perl| expression
pow({x}, {y}) Float {x} to the power of {y}
prevnonblank({lnum}) Number line nr of non-blank line <= {lnum}
printf({fmt}, {expr1}...) String format text
prompt_addtext({buf}, {expr}) none add text to a prompt buffer
prompt_setprompt({buf}, {text}) none set prompt text
prompt_setcallback({buf}, {expr}) none set prompt callback function
pumvisible() Number whether popup menu is visible
pyeval({expr}) any evaluate |Python| expression
py3eval({expr}) any evaluate |python3| expression
@@ -2302,7 +2307,7 @@ range({expr} [, {max} [, {stride}]])
List items from {expr} to {max}
readfile({fname} [, {binary} [, {max}]])
List get list of lines from file {fname}
reg_executing() Number get the executing register name
reg_executing() String get the executing register name
reg_recording() String get the recording register name
reltime([{start} [, {end}]]) List get time value
reltimefloat({time}) Float turn the time value into a Float
@@ -2557,6 +2562,21 @@ append({lnum}, {expr}) *append()*
0 for success. Example: >
:let failed = append(line('$'), "# THE END")
:let failed = append(0, ["Chapter 1", "the beginning"])
appendbufline({expr}, {lnum}, {text}) *appendbufline()*
Like |append()| but append the text in buffer {expr}.
For the use of {expr}, see |bufname()|.
{lnum} is used like with |append()|. Note that using |line()|
would use the current buffer, not the one appending to.
Use "$" to append at the end of the buffer.
On success 0 is returned, on failure 1 is returned.
If {expr} is not a valid buffer or {lnum} is not valid, an
error message is given. Example: >
:let failed = appendbufline(13, 0, "# THE START")
<
*argc()*
argc() The result is the number of files in the argument list of the
@@ -3499,8 +3519,19 @@ delete({fname} [, {flags}]) *delete()*
successful and -1 when the deletion failed or partly failed.
Use |remove()| to delete an item from a |List|.
To delete a line from the buffer use |:delete|. Use |:exe|
when the line number is in a variable.
To delete a line from the buffer use |:delete| or
|deletebufline()|.
deletebufline({expr}, {first}[, {last}]) *deletebufline()*
Delete lines {first} to {last} (inclusive) from buffer {expr}.
If {last} is omitted then delete line {first} only.
On success 0 is returned, on failure 1 is returned.
For the use of {expr}, see |bufname()| above.
{first} and {last} are used like with |setline()|. Note that
when using |line()| this refers to the current buffer. Use "$"
to refer to the last line in buffer {expr}.
*did_filetype()*
did_filetype() Returns |TRUE| when autocommands are being executed and the
@@ -4650,7 +4681,7 @@ getline({lnum} [, {end}])
from the current buffer. Example: >
getline(1)
< When {lnum} is a String that doesn't start with a
digit, line() is called to translate the String into a Number.
digit, |line()| is called to translate the String into a Number.
To get the line under the cursor: >
getline(".")
< When {lnum} is smaller than 1 or bigger than the number of
@@ -6475,6 +6506,42 @@ printf({fmt}, {expr1} ...) *printf()*
arguments an error is given. Up to 18 arguments can be used.
prompt_setprompt({buf}, {text}) *prompt_setprompt()*
Set prompt for buffer {buf} to {text}. You most likely want
{text} to end in a space.
The result is only visible if {buf} has 'buftype' set to
"prompt". Example: >
call prompt_setprompt(bufnr(''), 'command: ')
prompt_setcallback({buf}, {expr}) *prompt_setcallback()*
Set prompt callback for buffer {buf} to {expr}. This has only
effect if {buf} has 'buftype' set to "prompt".
The callback is invoked when pressing Enter. The current
buffer will always be the prompt buffer. A new line for a
prompt is added before invoking the callback, thus the prompt
for which the callback was invoked will be in the last but one
line.
If the callback wants to add text to the buffer, it must
insert it above the last line, since that is where the current
prompt is. This can also be done asynchronously.
The callback is invoked with one argument, which is the text
that was entered at the prompt. This can be an empty string
if the user only typed Enter.
Example: >
call prompt_setcallback(bufnr(''), function('s:TextEntered'))
func s:TextEntered(text)
if a:text == 'exit' || a:text == 'quit'
stopinsert
close
else
call append(line('$') - 1, 'Entered: "' . a:text . '"')
" Reset 'modified' to allow the buffer to be closed.
set nomodified
endif
endfunc
pumvisible() *pumvisible()*
Returns non-zero when the popup menu is visible, zero
otherwise. See |ins-completion-menu|.
+11 -4
View File
@@ -1407,6 +1407,9 @@ A jump table for the options with a short description can be found at |Q_op|.
manually)
terminal buffer for a |terminal| (you are not supposed to set
this manually)
prompt buffer where only the last line can be edited, meant
to be used by a plugin, see |prompt-buffer|
{only when compiled with the |+channel| feature}
This option is used together with 'bufhidden' and 'swapfile' to
specify special kinds of buffers. See |special-buffers|.
@@ -4387,7 +4390,8 @@ A jump table for the options with a short description can be found at |Q_op|.
'imactivatefunc' 'imaf' string (default "")
global
{not in Vi}
{only available when compiled with |+mbyte|}
{only available when compiled with the |+multi_byte|
feature}
This option specifies a function that will be called to
activate or deactivate the Input Method.
It is not used in the GUI.
@@ -4439,7 +4443,8 @@ A jump table for the options with a short description can be found at |Q_op|.
'imcmdline' 'imc' boolean (default off)
global
{not in Vi}
{only available when compiled with |+mbyte|}
{only available when compiled with the |+multi_byte|
feature}
When set the Input Method is always on when starting to edit a command
line, unless entering a search pattern (see 'imsearch' for that).
Setting this option is useful when your input method allows entering
@@ -4450,7 +4455,8 @@ A jump table for the options with a short description can be found at |Q_op|.
'imdisable' 'imd' boolean (default off, on for some systems (SGI))
global
{not in Vi}
{only available when compiled with |+mbyte|}
{only available when compiled with the |+multi_byte|
feature}
When set the Input Method is never used. This is useful to disable
the IM when it doesn't work properly.
Currently this option is on by default for SGI/IRIX. This may change
@@ -4503,7 +4509,8 @@ A jump table for the options with a short description can be found at |Q_op|.
'imstatusfunc' 'imsf' string (default "")
global
{not in Vi}
{only available when compiled with |+mbyte|}
{only available when compiled with the |+multi_byte|
feature}
This option specifies a function that is called to obtain the status
of Input Method. It must return a positive number when IME is active.
It is not used in the GUI.
+45 -3
View File
@@ -38,6 +38,10 @@ browser use: https://github.com/vim/vim/issues/1234
*known-bugs*
-------------------- Known bugs and current work -----------------------
Prompt buffer:
- Add a command line history.
- delay next prompt until plugin gives OK?
Terminal emulator window:
- Win32: Termdebug doesn't work, because gdb does not support mi2 on a tty.
This plugin: https://github.com/cpiger/NeoDebug runs gdb as a job,
@@ -71,9 +75,15 @@ Crash when mixing matchadd and substitute()? (Max Christian Pohle, 2018 May
On Win32 when not in the console and t_Co >= 256, allow using 'tgc'.
(Nobuhiro Takasaki, #2833) Also check t_Co.
balloon_show() does not work properly in the terminal. (Ben Jackson, 2017 Dec
20, #2481)
Also see #2352, want better control over balloon, perhaps set the position.
Patch to fix arguments of :edit. (Dominique Pelle, 2018 May 28 #2966)
Ptch to update html syntax. (Jorge Maldonado Ventura, #2974)
Patch to fix that restoring window doesn't work when 'winheight' is large.
(Darrell Nash, 2018 May 30, #2971) Doesn't work? Issue #2970
Patch to add completion to :unlet for environment vars. (Jason Franklin, 2018
May 30) Last update.
Errors found with random data:
heap-buffer-overflow in alist_add (#2472)
@@ -81,6 +91,22 @@ Errors found with random data:
More warnings from static analysis:
https://lgtm.com/projects/g/vim/vim/alerts/?mode=list
Patch to make "is" and "as" work bettter. (Jason Franklin, 2018 May 19)
Patch to add tests for user and language completion. (Dominique Pelle, 2018
Jun 2, #2978)
Using ":file" in quickfix window during an autocommand doesn't work.
(Jason Franklin, 2018 May 23) Allow for using it when there is no argument.
Pull request #2967: Allow white space in sign text. (Ben Jackson)
Patch for xterm and vt320 builtin termcap. (Kouichi Iwamoto, 2018 May 31,
#2973)
Patch to add more testing for :cd command. (Dominique Pelle, 2018 May 30,
#2972)
Script generated by :mksession does not work well if there are windows with
modified buffers
change "silent only" into "silent only!"
@@ -88,16 +114,27 @@ modified buffers
skip "badd fname" if "fname" is already in the buffer list
remove remark about unloading buffers from documentation
Patch to make :help work for tags with a ?. (Hirohito Higashi, 2018 May 28)
Compiler warnings (geeknik, 2017 Oct 26):
- signed integer overflow in do_sub() (#2249)
- signed integer overflow in get_address() (#2248)
- signed integer overflow in getdecchrs() (#2254)
- undefined left shift in get_string_tv() (#2250)
Patch for more quickfix refactoring. (Yegappan Lakshmanan, #2950)
Tests failing for "make testgui" with GTK:
- Test_setbufvar_options()
- Test_exit_callback_interval()
Make balloon_show() work outside of 'balloonexpr'? Users expect it to work:
#2948. (related to #1512?)
On Win32 it stops showing, because showState is already ShS_SHOWING.
balloon_show() does not work properly in the terminal. (Ben Jackson, 2017 Dec
20, #2481)
Also see #2352, want better control over balloon, perhaps set the position.
Try out background make plugin:
https://github.com/AndrewVos/vim-make-background
or asyncmake:
@@ -112,6 +149,8 @@ used for git temp files.
Cursor in wrong position when line wraps. (#2540)
Patch for Lua support. (Kazunobu Kuriyama, 2018 May 26)
Add an option similar to 'lazyredraw' to skip redrawing while executing a
script or function.
@@ -141,6 +180,9 @@ How to test that it works well for all Vim users?
Alternative manpager.vim. (Enno, 2018 Jan 5, #2529)
Patch to use NGETTEXT() in many more places. (Sergey Alyoshin, 2018 May 25)
Updated ptach May 27.
Does setting 'cursorline' cause syntax highlighting to slow down? Perhaps is
mess up the cache? (Mike Lee Williams, 2018 Jan 27, #2539)
Also: 'foldtext' is evaluated too often. (Daniel Hahler, #2773)
+1 -1
View File
@@ -1255,7 +1255,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>147</string>
<string>148</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
+1
View File
@@ -2269,6 +2269,7 @@ test_arglist \
test_popup \
test_preview \
test_profile \
test_prompt_buffer \
test_put \
test_python2 \
test_python3 \
+22 -2
View File
@@ -855,6 +855,10 @@ free_buffer(buf_T *buf)
#ifdef FEAT_TERMINAL
free_terminal(buf);
#endif
#ifdef FEAT_JOB_CHANNEL
vim_free(buf->b_prompt_text);
free_callback(buf->b_prompt_callback, buf->b_prompt_partial);
#endif
buf_hashtab_remove(buf);
@@ -5643,6 +5647,15 @@ bt_help(buf_T *buf)
return buf != NULL && buf->b_help;
}
/*
* Return TRUE if "buf" is a prompt buffer.
*/
int
bt_prompt(buf_T *buf)
{
return buf != NULL && buf->b_p_bt[0] == 'p';
}
/*
* Return TRUE if "buf" is a "nofile", "acwrite" or "terminal" buffer.
* This means the buffer name is not a file name.
@@ -5652,7 +5665,8 @@ bt_nofile(buf_T *buf)
{
return buf != NULL && ((buf->b_p_bt[0] == 'n' && buf->b_p_bt[2] == 'f')
|| buf->b_p_bt[0] == 'a'
|| buf->b_p_bt[0] == 't');
|| buf->b_p_bt[0] == 't'
|| buf->b_p_bt[0] == 'p');
}
/*
@@ -5661,7 +5675,9 @@ bt_nofile(buf_T *buf)
int
bt_dontwrite(buf_T *buf)
{
return buf != NULL && (buf->b_p_bt[0] == 'n' || buf->b_p_bt[0] == 't');
return buf != NULL && (buf->b_p_bt[0] == 'n'
|| buf->b_p_bt[0] == 't'
|| buf->b_p_bt[0] == 'p');
}
int
@@ -5727,6 +5743,10 @@ buf_spname(buf_T *buf)
#endif
if (buf->b_fname != NULL)
return buf->b_fname;
#ifdef FEAT_JOB_CHANNEL
if (bt_prompt(buf))
return (char_u *)_("[Prompt]");
#endif
return (char_u *)_("[Scratch]");
}
+34
View File
@@ -5878,6 +5878,40 @@ job_stop(job_T *job, typval_T *argvars, char *type)
return 1;
}
void
invoke_prompt_callback(void)
{
typval_T rettv;
int dummy;
typval_T argv[2];
char_u *text;
char_u *prompt;
linenr_T lnum = curbuf->b_ml.ml_line_count;
// Add a new line for the prompt before invoking the callback, so that
// text can always be inserted above the last line.
ml_append(lnum, (char_u *)"", 0, FALSE);
curwin->w_cursor.lnum = lnum + 1;
curwin->w_cursor.col = 0;
if (curbuf->b_prompt_callback == NULL)
return;
text = ml_get(lnum);
prompt = prompt_text();
if (STRLEN(text) >= STRLEN(prompt))
text += STRLEN(prompt);
argv[0].v_type = VAR_STRING;
argv[0].vval.v_string = vim_strsave(text);
argv[1].v_type = VAR_UNKNOWN;
call_func(curbuf->b_prompt_callback,
(int)STRLEN(curbuf->b_prompt_callback),
&rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE,
curbuf->b_prompt_partial, NULL);
clear_tv(&argv[0]);
clear_tv(&rettv);
}
# ifdef FEAT_GUI_MACVIM
void
job_cleanup_all(void)
+7
View File
@@ -2141,6 +2141,13 @@ nv_diffgetput(int put, long count)
exarg_T ea;
char_u buf[30];
#ifdef FEAT_JOB_CHANNEL
if (bt_prompt(curbuf))
{
vim_beep(BO_OPER);
return;
}
#endif
if (count == 0)
ea.arg = (char_u *)"";
else
+118 -1
View File
@@ -203,6 +203,9 @@ static unsigned quote_meta(char_u *dest, char_u *str, int len);
static void ins_redraw(int ready);
static void ins_ctrl_v(void);
#ifdef FEAT_JOB_CHANNEL
static void init_prompt(int cmdchar_todo);
#endif
static void undisplay_dollar(void);
static void insert_special(int, int, int);
static void internal_format(int textwidth, int second_indent, int flags, int format_only, int c);
@@ -351,6 +354,9 @@ edit(
int inserted_space = FALSE; /* just inserted a space */
int replaceState = REPLACE;
int nomove = FALSE; /* don't move cursor on return */
#ifdef FEAT_JOB_CHANNEL
int cmdchar_todo = cmdchar;
#endif
/* Remember whether editing was restarted after CTRL-O. */
did_restart_edit = restart_edit;
@@ -707,6 +713,14 @@ edit(
foldCheckClose();
#endif
#ifdef FEAT_JOB_CHANNEL
if (bt_prompt(curbuf))
{
init_prompt(cmdchar_todo);
cmdchar_todo = NUL;
}
#endif
/*
* If we inserted a character at the last position of the last line in
* the window, scroll the window one line up. This avoids an extra
@@ -797,6 +811,14 @@ edit(
do
{
c = safe_vgetc();
if (stop_insert_mode)
{
// Insert mode ended, possibly from a callback.
count = 0;
nomove = TRUE;
goto doESCkey;
}
} while (c == K_IGNORE || c == K_NOP);
/* Don't want K_CURSORHOLD for the second key, e.g., after CTRL-V. */
@@ -1151,6 +1173,18 @@ doESCkey:
break;
case Ctrl_W: /* delete word before the cursor */
#ifdef FEAT_JOB_CHANNEL
if (bt_prompt(curbuf) && (mod_mask & MOD_MASK_SHIFT) == 0)
{
// In a prompt window CTRL-W is used for window commands.
// Use Shift-CTRL-W to delete a word.
stuffcharReadbuff(Ctrl_W);
restart_edit = 'i';
nomove = TRUE;
count = 0;
goto doESCkey;
}
#endif
did_backspace = ins_bs(c, BACKSPACE_WORD, &inserted_space);
auto_format(FALSE, TRUE);
break;
@@ -1382,6 +1416,17 @@ doESCkey:
cmdwin_result = CAR;
goto doESCkey;
}
#endif
#ifdef FEAT_JOB_CHANNEL
if (bt_prompt(curbuf))
{
invoke_prompt_callback();
if (!bt_prompt(curbuf))
// buffer changed to a non-prompt buffer, get out of
// Insert mode
goto doESCkey;
break;
}
#endif
if (ins_eol(c) == FAIL && !p_im)
goto doESCkey; /* out of memory */
@@ -1817,6 +1862,73 @@ edit_putchar(int c, int highlight)
}
}
#if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
/*
* Return the effective prompt for the current buffer.
*/
char_u *
prompt_text(void)
{
if (curbuf->b_prompt_text == NULL)
return (char_u *)"% ";
return curbuf->b_prompt_text;
}
/*
* Prepare for prompt mode: Make sure the last line has the prompt text.
* Move the cursor to this line.
*/
static void
init_prompt(int cmdchar_todo)
{
char_u *prompt = prompt_text();
char_u *text;
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
text = ml_get_curline();
if (STRNCMP(text, prompt, STRLEN(prompt)) != 0)
{
// prompt is missing, insert it or append a line with it
if (*text == NUL)
ml_replace(curbuf->b_ml.ml_line_count, prompt, TRUE);
else
ml_append(curbuf->b_ml.ml_line_count, prompt, 0, FALSE);
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
coladvance((colnr_T)MAXCOL);
changed_bytes(curbuf->b_ml.ml_line_count, 0);
}
// Insert always starts after the prompt, allow editing text after it.
if (Insstart_orig.lnum != curwin->w_cursor.lnum
|| Insstart_orig.col != (int)STRLEN(prompt))
{
Insstart.lnum = curwin->w_cursor.lnum;
Insstart.col = STRLEN(prompt);
Insstart_orig = Insstart;
Insstart_textlen = Insstart.col;
Insstart_blank_vcol = MAXCOL;
arrow_used = FALSE;
}
if (cmdchar_todo == 'A')
coladvance((colnr_T)MAXCOL);
if (cmdchar_todo == 'I' || curwin->w_cursor.col <= (int)STRLEN(prompt))
curwin->w_cursor.col = STRLEN(prompt);
/* Make sure the cursor is in a valid position. */
check_cursor();
}
/*
* Return TRUE if the cursor is in the editable position of the prompt line.
*/
int
prompt_curpos_editable()
{
return curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count
&& curwin->w_cursor.col >= (int)STRLEN(prompt_text());
}
#endif
/*
* Undo the previous edit_putchar().
*/
@@ -9370,7 +9482,7 @@ ins_bs(
/* If deleted before the insertion point, adjust it */
if (curwin->w_cursor.lnum == Insstart_orig.lnum
&& curwin->w_cursor.col < Insstart_orig.col)
&& curwin->w_cursor.col < Insstart_orig.col)
Insstart_orig.col = curwin->w_cursor.col;
/* vi behaviour: the cursor moves backward but the character that
@@ -9420,6 +9532,11 @@ ins_mouse(int c)
* previous one to stop insert there properly. */
curwin = old_curwin;
curbuf = curwin->w_buffer;
#ifdef FEAT_JOB_CHANNEL
if (bt_prompt(curbuf))
// Restart Insert mode when re-entering the prompt buffer.
curbuf->b_prompt_insert = 'A';
#endif
}
start_arrow(curwin == old_curwin ? &tpos : NULL);
if (curwin != new_curwin && win_valid(new_curwin))
+331 -178
View File
@@ -40,6 +40,7 @@ static void f_acos(typval_T *argvars, typval_T *rettv);
static void f_add(typval_T *argvars, typval_T *rettv);
static void f_and(typval_T *argvars, typval_T *rettv);
static void f_append(typval_T *argvars, typval_T *rettv);
static void f_appendbufline(typval_T *argvars, typval_T *rettv);
static void f_argc(typval_T *argvars, typval_T *rettv);
static void f_argidx(typval_T *argvars, typval_T *rettv);
static void f_arglistid(typval_T *argvars, typval_T *rettv);
@@ -124,6 +125,7 @@ static void f_cscope_connection(typval_T *argvars, typval_T *rettv);
static void f_cursor(typval_T *argsvars, typval_T *rettv);
static void f_deepcopy(typval_T *argvars, typval_T *rettv);
static void f_delete(typval_T *argvars, typval_T *rettv);
static void f_deletebufline(typval_T *argvars, typval_T *rettv);
static void f_did_filetype(typval_T *argvars, typval_T *rettv);
static void f_diff_filler(typval_T *argvars, typval_T *rettv);
static void f_diff_hlID(typval_T *argvars, typval_T *rettv);
@@ -294,6 +296,10 @@ static void f_pow(typval_T *argvars, typval_T *rettv);
#endif
static void f_prevnonblank(typval_T *argvars, typval_T *rettv);
static void f_printf(typval_T *argvars, typval_T *rettv);
#ifdef FEAT_JOB_CHANNEL
static void f_prompt_setcallback(typval_T *argvars, typval_T *rettv);
static void f_prompt_setprompt(typval_T *argvars, typval_T *rettv);
#endif
static void f_pumvisible(typval_T *argvars, typval_T *rettv);
#ifdef FEAT_PYTHON3
static void f_py3eval(typval_T *argvars, typval_T *rettv);
@@ -483,6 +489,7 @@ static struct fst
{"add", 2, 2, f_add},
{"and", 2, 2, f_and},
{"append", 2, 2, f_append},
{"appendbufline", 3, 3, f_appendbufline},
{"argc", 0, 0, f_argc},
{"argidx", 0, 0, f_argidx},
{"arglistid", 0, 2, f_arglistid},
@@ -571,6 +578,7 @@ static struct fst
{"cursor", 1, 3, f_cursor},
{"deepcopy", 1, 2, f_deepcopy},
{"delete", 1, 2, f_delete},
{"deletebufline", 2, 3, f_deletebufline},
{"did_filetype", 0, 0, f_did_filetype},
{"diff_filler", 1, 1, f_diff_filler},
{"diff_hlID", 2, 2, f_diff_hlID},
@@ -744,6 +752,10 @@ static struct fst
#endif
{"prevnonblank", 1, 1, f_prevnonblank},
{"printf", 1, 19, f_printf},
#ifdef FEAT_JOB_CHANNEL
{"prompt_setcallback", 2, 2, f_prompt_setcallback},
{"prompt_setprompt", 2, 2, f_prompt_setprompt},
#endif
{"pumvisible", 0, 0, f_pumvisible},
#ifdef FEAT_PYTHON3
{"py3eval", 1, 1, f_py3eval},
@@ -1183,66 +1195,195 @@ f_and(typval_T *argvars, typval_T *rettv)
& get_tv_number_chk(&argvars[1], NULL);
}
/*
* Get the lnum from the first argument.
* Also accepts "$", then "buf" is used.
* Returns 0 on error.
*/
static linenr_T
get_tv_lnum_buf(typval_T *argvars, buf_T *buf)
{
if (argvars[0].v_type == VAR_STRING
&& argvars[0].vval.v_string != NULL
&& argvars[0].vval.v_string[0] == '$'
&& buf != NULL)
return buf->b_ml.ml_line_count;
return (linenr_T)get_tv_number_chk(&argvars[0], NULL);
}
/*
* If there is a window for "curbuf", make it the current window.
*/
static void
find_win_for_curbuf(void)
{
wininfo_T *wip;
for (wip = curbuf->b_wininfo; wip != NULL; wip = wip->wi_next)
{
if (wip->wi_win != NULL)
{
curwin = wip->wi_win;
break;
}
}
}
/*
* Set line or list of lines in buffer "buf".
*/
static void
set_buffer_lines(
buf_T *buf,
linenr_T lnum_arg,
int append,
typval_T *lines,
typval_T *rettv)
{
linenr_T lnum = lnum_arg + (append ? 1 : 0);
char_u *line = NULL;
list_T *l = NULL;
listitem_T *li = NULL;
long added = 0;
linenr_T append_lnum;
buf_T *curbuf_save = NULL;
win_T *curwin_save = NULL;
int is_curbuf = buf == curbuf;
/* When using the current buffer ml_mfp will be set if needed. Useful when
* setline() is used on startup. For other buffers the buffer must be
* loaded. */
if (buf == NULL || (!is_curbuf && buf->b_ml.ml_mfp == NULL) || lnum < 1)
{
rettv->vval.v_number = 1; /* FAIL */
return;
}
if (!is_curbuf)
{
curbuf_save = curbuf;
curwin_save = curwin;
curbuf = buf;
find_win_for_curbuf();
}
if (append)
// appendbufline() uses the line number below which we insert
append_lnum = lnum - 1;
else
// setbufline() uses the line number above which we insert, we only
// append if it's below the last line
append_lnum = curbuf->b_ml.ml_line_count;
if (lines->v_type == VAR_LIST)
{
l = lines->vval.v_list;
li = l->lv_first;
}
else
line = get_tv_string_chk(lines);
/* default result is zero == OK */
for (;;)
{
if (l != NULL)
{
/* list argument, get next string */
if (li == NULL)
break;
line = get_tv_string_chk(&li->li_tv);
li = li->li_next;
}
rettv->vval.v_number = 1; /* FAIL */
if (line == NULL || lnum > curbuf->b_ml.ml_line_count + 1)
break;
/* When coming here from Insert mode, sync undo, so that this can be
* undone separately from what was previously inserted. */
if (u_sync_once == 2)
{
u_sync_once = 1; /* notify that u_sync() was called */
u_sync(TRUE);
}
if (!append && lnum <= curbuf->b_ml.ml_line_count)
{
/* existing line, replace it */
if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK)
{
changed_bytes(lnum, 0);
if (is_curbuf && lnum == curwin->w_cursor.lnum)
check_cursor_col();
rettv->vval.v_number = 0; /* OK */
}
}
else if (added > 0 || u_save(lnum - 1, lnum) == OK)
{
/* append the line */
++added;
if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK)
rettv->vval.v_number = 0; /* OK */
}
if (l == NULL) /* only one string argument */
break;
++lnum;
}
if (added > 0)
{
win_T *wp;
tabpage_T *tp;
appended_lines_mark(append_lnum, added);
FOR_ALL_TAB_WINDOWS(tp, wp)
if (wp->w_buffer == buf && wp->w_cursor.lnum > append_lnum)
wp->w_cursor.lnum += added;
check_cursor_col();
#ifdef FEAT_JOB_CHANNEL
if (bt_prompt(curbuf) && (State & INSERT))
// show the line with the prompt
update_topline();
#endif
}
if (!is_curbuf)
{
curbuf = curbuf_save;
curwin = curwin_save;
}
}
/*
* "append(lnum, string/list)" function
*/
static void
f_append(typval_T *argvars, typval_T *rettv)
{
long lnum;
char_u *line;
list_T *l = NULL;
listitem_T *li = NULL;
typval_T *tv;
long added = 0;
linenr_T lnum = get_tv_lnum(&argvars[0]);
/* When coming here from Insert mode, sync undo, so that this can be
* undone separately from what was previously inserted. */
if (u_sync_once == 2)
{
u_sync_once = 1; /* notify that u_sync() was called */
u_sync(TRUE);
}
set_buffer_lines(curbuf, lnum, TRUE, &argvars[1], rettv);
}
lnum = get_tv_lnum(argvars);
if (lnum >= 0
&& lnum <= curbuf->b_ml.ml_line_count
&& u_save(lnum, lnum + 1) == OK)
{
if (argvars[1].v_type == VAR_LIST)
{
l = argvars[1].vval.v_list;
if (l == NULL)
return;
li = l->lv_first;
}
for (;;)
{
if (l == NULL)
tv = &argvars[1]; /* append a string */
else if (li == NULL)
break; /* end of list */
else
tv = &li->li_tv; /* append item from list */
line = get_tv_string_chk(tv);
if (line == NULL) /* type error */
{
rettv->vval.v_number = 1; /* Failed */
break;
}
ml_append(lnum + added, line, (colnr_T)0, FALSE);
++added;
if (l == NULL)
break;
li = li->li_next;
}
/*
* "appendbufline(buf, lnum, string/list)" function
*/
static void
f_appendbufline(typval_T *argvars, typval_T *rettv)
{
linenr_T lnum;
buf_T *buf;
appended_lines_mark(lnum, added);
if (curwin->w_cursor.lnum > lnum)
curwin->w_cursor.lnum += added;
}
buf = get_buf_tv(&argvars[0], FALSE);
if (buf == NULL)
rettv->vval.v_number = 1; /* FAIL */
else
rettv->vval.v_number = 1; /* Failed */
{
lnum = get_tv_lnum_buf(&argvars[1], buf);
set_buffer_lines(buf, lnum, TRUE, &argvars[2], rettv);
}
}
/*
@@ -2677,6 +2818,93 @@ f_delete(typval_T *argvars, typval_T *rettv)
EMSG2(_(e_invexpr2), flags);
}
/*
* "deletebufline()" function
*/
static void
f_deletebufline(argvars, rettv)
typval_T *argvars;
typval_T *rettv;
{
buf_T *buf;
linenr_T first, last;
linenr_T lnum;
long count;
int is_curbuf;
buf_T *curbuf_save = NULL;
win_T *curwin_save = NULL;
tabpage_T *tp;
win_T *wp;
buf = get_buf_tv(&argvars[0], FALSE);
if (buf == NULL)
{
rettv->vval.v_number = 1; /* FAIL */
return;
}
is_curbuf = buf == curbuf;
first = get_tv_lnum_buf(&argvars[1], buf);
if (argvars[2].v_type != VAR_UNKNOWN)
last = get_tv_lnum_buf(&argvars[2], buf);
else
last = first;
if (buf->b_ml.ml_mfp == NULL || first < 1
|| first > buf->b_ml.ml_line_count || last < first)
{
rettv->vval.v_number = 1; /* FAIL */
return;
}
if (!is_curbuf)
{
curbuf_save = curbuf;
curwin_save = curwin;
curbuf = buf;
find_win_for_curbuf();
}
if (last > curbuf->b_ml.ml_line_count)
last = curbuf->b_ml.ml_line_count;
count = last - first + 1;
// When coming here from Insert mode, sync undo, so that this can be
// undone separately from what was previously inserted.
if (u_sync_once == 2)
{
u_sync_once = 1; // notify that u_sync() was called
u_sync(TRUE);
}
if (u_save(first - 1, last + 1) == FAIL)
{
rettv->vval.v_number = 1; /* FAIL */
return;
}
for (lnum = first; lnum <= last; ++lnum)
ml_delete(first, TRUE);
FOR_ALL_TAB_WINDOWS(tp, wp)
if (wp->w_buffer == buf)
{
if (wp->w_cursor.lnum > last)
wp->w_cursor.lnum -= count;
else if (wp->w_cursor.lnum> first)
wp->w_cursor.lnum = first;
if (wp->w_cursor.lnum > wp->w_buffer->b_ml.ml_line_count)
wp->w_cursor.lnum = wp->w_buffer->b_ml.ml_line_count;
}
check_cursor_col();
deleted_lines_mark(first, count);
if (!is_curbuf)
{
curbuf = curbuf_save;
curwin = curwin_save;
}
}
/*
* "did_filetype()" function
*/
@@ -4262,22 +4490,6 @@ get_buffer_lines(
}
}
/*
* Get the lnum from the first argument.
* Also accepts "$", then "buf" is used.
* Returns 0 on error.
*/
static linenr_T
get_tv_lnum_buf(typval_T *argvars, buf_T *buf)
{
if (argvars[0].v_type == VAR_STRING
&& argvars[0].vval.v_string != NULL
&& argvars[0].vval.v_string[0] == '$'
&& buf != NULL)
return buf->b_ml.ml_line_count;
return (linenr_T)get_tv_number_chk(&argvars[0], NULL);
}
/*
* "getbufline()" function
*/
@@ -8398,6 +8610,57 @@ f_printf(typval_T *argvars, typval_T *rettv)
did_emsg |= saved_did_emsg;
}
#ifdef FEAT_JOB_CHANNEL
/*
* "prompt_setcallback({buffer}, {callback})" function
*/
static void
f_prompt_setcallback(typval_T *argvars, typval_T *rettv UNUSED)
{
buf_T *buf;
char_u *callback;
partial_T *partial;
if (check_secure())
return;
buf = get_buf_tv(&argvars[0], FALSE);
if (buf == NULL)
return;
callback = get_callback(&argvars[1], &partial);
if (callback == NULL)
return;
free_callback(buf->b_prompt_callback, buf->b_prompt_partial);
if (partial == NULL)
buf->b_prompt_callback = vim_strsave(callback);
else
/* pointer into the partial */
buf->b_prompt_callback = callback;
buf->b_prompt_partial = partial;
}
/*
* "prompt_setprompt({buffer}, {text})" function
*/
static void
f_prompt_setprompt(typval_T *argvars, typval_T *rettv UNUSED)
{
buf_T *buf;
char_u *text;
if (check_secure())
return;
buf = get_buf_tv(&argvars[0], FALSE);
if (buf == NULL)
return;
text = get_tv_string(&argvars[1]);
vim_free(buf->b_prompt_text);
buf->b_prompt_text = vim_strsave(text);
}
#endif
/*
* "pumvisible()" function
*/
@@ -10188,115 +10451,6 @@ f_serverlist(typval_T *argvars UNUSED, typval_T *rettv)
rettv->vval.v_string = r;
}
/*
* Set line or list of lines in buffer "buf".
*/
static void
set_buffer_lines(buf_T *buf, linenr_T lnum, typval_T *lines, typval_T *rettv)
{
char_u *line = NULL;
list_T *l = NULL;
listitem_T *li = NULL;
long added = 0;
linenr_T lcount;
buf_T *curbuf_save = NULL;
win_T *curwin_save = NULL;
int is_curbuf = buf == curbuf;
/* When using the current buffer ml_mfp will be set if needed. Useful when
* setline() is used on startup. For other buffers the buffer must be
* loaded. */
if (buf == NULL || (!is_curbuf && buf->b_ml.ml_mfp == NULL) || lnum < 1)
{
rettv->vval.v_number = 1; /* FAIL */
return;
}
if (!is_curbuf)
{
wininfo_T *wip;
curbuf_save = curbuf;
curwin_save = curwin;
curbuf = buf;
for (wip = buf->b_wininfo; wip != NULL; wip = wip->wi_next)
{
if (wip->wi_win != NULL)
{
curwin = wip->wi_win;
break;
}
}
}
lcount = curbuf->b_ml.ml_line_count;
if (lines->v_type == VAR_LIST)
{
l = lines->vval.v_list;
li = l->lv_first;
}
else
line = get_tv_string_chk(lines);
/* default result is zero == OK */
for (;;)
{
if (l != NULL)
{
/* list argument, get next string */
if (li == NULL)
break;
line = get_tv_string_chk(&li->li_tv);
li = li->li_next;
}
rettv->vval.v_number = 1; /* FAIL */
if (line == NULL || lnum > curbuf->b_ml.ml_line_count + 1)
break;
/* When coming here from Insert mode, sync undo, so that this can be
* undone separately from what was previously inserted. */
if (u_sync_once == 2)
{
u_sync_once = 1; /* notify that u_sync() was called */
u_sync(TRUE);
}
if (lnum <= curbuf->b_ml.ml_line_count)
{
/* existing line, replace it */
if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK)
{
changed_bytes(lnum, 0);
if (is_curbuf && lnum == curwin->w_cursor.lnum)
check_cursor_col();
rettv->vval.v_number = 0; /* OK */
}
}
else if (added > 0 || u_save(lnum - 1, lnum) == OK)
{
/* lnum is one past the last line, append the line */
++added;
if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK)
rettv->vval.v_number = 0; /* OK */
}
if (l == NULL) /* only one string argument */
break;
++lnum;
}
if (added > 0)
appended_lines_mark(lcount, added);
if (!is_curbuf)
{
curbuf = curbuf_save;
curwin = curwin_save;
}
}
/*
* "setbufline()" function
*/
@@ -10314,8 +10468,7 @@ f_setbufline(argvars, rettv)
else
{
lnum = get_tv_lnum_buf(&argvars[1], buf);
set_buffer_lines(buf, lnum, &argvars[2], rettv);
set_buffer_lines(buf, lnum, FALSE, &argvars[2], rettv);
}
}
@@ -10475,7 +10628,7 @@ f_setline(typval_T *argvars, typval_T *rettv)
{
linenr_T lnum = get_tv_lnum(&argvars[0]);
set_buffer_lines(curbuf, lnum, &argvars[1], rettv);
set_buffer_lines(curbuf, lnum, FALSE, &argvars[1], rettv);
}
static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T *action_arg, typval_T *what_arg, typval_T *rettv);
+10 -3
View File
@@ -4193,11 +4193,18 @@ do_ecmd(
check_arg_idx(curwin);
/* If autocommands change the cursor position or topline, we should
* keep it. Also when it moves within a line. */
* keep it. Also when it moves within a line. But not when it moves
* to the first non-blank. */
if (!EQUAL_POS(curwin->w_cursor, orig_pos))
{
newlnum = curwin->w_cursor.lnum;
newcol = curwin->w_cursor.col;
char_u *text = ml_get_curline();
if (curwin->w_cursor.lnum != orig_pos.lnum
|| curwin->w_cursor.col != (int)(skipwhite(text) - text))
{
newlnum = curwin->w_cursor.lnum;
newcol = curwin->w_cursor.col;
}
}
if (curwin->w_topline == topline)
topline = 0;
+2 -1
View File
@@ -7357,7 +7357,8 @@ ex_close(exarg_T *eap)
{
if (eap->addr_count == 0)
ex_win_close(eap->forceit, curwin, NULL);
else {
else
{
FOR_ALL_WINDOWS(win)
{
winnr++;
+1 -1
View File
@@ -344,7 +344,7 @@ ml_open(buf_T *buf)
b0p->b0_magic_int = (int)B0_MAGIC_INT;
b0p->b0_magic_short = (short)B0_MAGIC_SHORT;
b0p->b0_magic_char = B0_MAGIC_CHAR;
STRNCPY(b0p->b0_version, "VIM ", 4);
mch_memmove(b0p->b0_version, "VIM ", 4);
STRNCPY(b0p->b0_version + 4, Version, 6);
long_to_char((long)mfp->mf_page_size, b0p->b0_page_size);
+65
View File
@@ -4184,6 +4184,11 @@ nv_help(cmdarg_T *cap)
static void
nv_addsub(cmdarg_T *cap)
{
#ifdef FEAT_JOB_CHANNEL
if (bt_prompt(curbuf) && !prompt_curpos_editable())
clearopbeep(cap->oap);
else
#endif
if (!VIsual_active && cap->oap->op_type == OP_NOP)
{
prep_redo_cmd(cap);
@@ -6246,6 +6251,17 @@ nv_down(cmdarg_T *cap)
if (cmdwin_type != 0 && cap->cmdchar == CAR)
cmdwin_result = CAR;
else
#endif
#ifdef FEAT_JOB_CHANNEL
/* In a prompt buffer a <CR> in the last line invokes the callback. */
if (bt_prompt(curbuf) && cap->cmdchar == CAR
&& curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
{
invoke_prompt_callback();
if (restart_edit == 0)
restart_edit = 'a';
}
else
#endif
{
cap->oap->motion_type = MLINE;
@@ -7005,6 +7021,13 @@ nv_kundo(cmdarg_T *cap)
{
if (!checkclearopq(cap->oap))
{
#ifdef FEAT_JOB_CHANNEL
if (bt_prompt(curbuf))
{
clearopbeep(cap->oap);
return;
}
#endif
u_undo((int)cap->count1);
curwin->w_set_curswant = TRUE;
}
@@ -7022,6 +7045,13 @@ nv_replace(cmdarg_T *cap)
if (checkclearop(cap->oap))
return;
#ifdef FEAT_JOB_CHANNEL
if (bt_prompt(curbuf) && !prompt_curpos_editable())
{
clearopbeep(cap->oap);
return;
}
#endif
/* get another character */
if (cap->nchar == Ctrl_V)
@@ -7497,6 +7527,13 @@ nv_subst(cmdarg_T *cap)
/* When showing output of term_dumpdiff() swap the top and botom. */
if (term_swap_diff() == OK)
return;
#endif
#ifdef FEAT_JOB_CHANNEL
if (bt_prompt(curbuf) && !prompt_curpos_editable())
{
clearopbeep(cap->oap);
return;
}
#endif
if (VIsual_active) /* "vs" and "vS" are the same as "vc" */
{
@@ -8603,7 +8640,16 @@ nv_Undo(cmdarg_T *cap)
nv_tilde(cmdarg_T *cap)
{
if (!p_to && !VIsual_active && cap->oap->op_type != OP_TILDE)
{
#ifdef FEAT_JOB_CHANNEL
if (bt_prompt(curbuf) && !prompt_curpos_editable())
{
clearopbeep(cap->oap);
return;
}
#endif
n_swapchar(cap);
}
else
nv_operator(cap);
}
@@ -8618,6 +8664,13 @@ nv_operator(cmdarg_T *cap)
int op_type;
op_type = get_op_type(cap->cmdchar, cap->nchar);
#ifdef FEAT_JOB_CHANNEL
if (bt_prompt(curbuf) && op_is_change(op_type) && !prompt_curpos_editable())
{
clearopbeep(cap->oap);
return;
}
#endif
if (op_type == cap->oap->op_type) /* double operator works on lines */
nv_lineop(cap);
@@ -9459,6 +9512,12 @@ nv_put(cmdarg_T *cap)
#endif
clearopbeep(cap->oap);
}
#ifdef FEAT_JOB_CHANNEL
else if (bt_prompt(curbuf) && !prompt_curpos_editable())
{
clearopbeep(cap->oap);
}
#endif
else
{
dir = (cap->cmdchar == 'P'
@@ -9584,6 +9643,12 @@ nv_open(cmdarg_T *cap)
#endif
if (VIsual_active) /* switch start and end of visual */
v_swap_corners(cap->cmdchar);
#ifdef FEAT_JOB_CHANNEL
else if (bt_prompt(curbuf))
{
clearopbeep(cap->oap);
}
#endif
else
n_opencmd(cap);
}
+45 -32
View File
@@ -126,43 +126,47 @@ static int fmt_check_par(linenr_T, int *, char_u **, int do_comments);
static int fmt_check_par(linenr_T);
#endif
// Flags for third item in "opchars".
#define OPF_LINES 1 // operator always works on lines
#define OPF_CHANGE 2 // operator changes text
/*
* The names of operators.
* IMPORTANT: Index must correspond with defines in vim.h!!!
* The third field indicates whether the operator always works on lines.
* The third field holds OPF_ flags.
*/
static char opchars[][3] =
{
{NUL, NUL, FALSE}, /* OP_NOP */
{'d', NUL, FALSE}, /* OP_DELETE */
{'y', NUL, FALSE}, /* OP_YANK */
{'c', NUL, FALSE}, /* OP_CHANGE */
{'<', NUL, TRUE}, /* OP_LSHIFT */
{'>', NUL, TRUE}, /* OP_RSHIFT */
{'!', NUL, TRUE}, /* OP_FILTER */
{'g', '~', FALSE}, /* OP_TILDE */
{'=', NUL, TRUE}, /* OP_INDENT */
{'g', 'q', TRUE}, /* OP_FORMAT */
{':', NUL, TRUE}, /* OP_COLON */
{'g', 'U', FALSE}, /* OP_UPPER */
{'g', 'u', FALSE}, /* OP_LOWER */
{'J', NUL, TRUE}, /* DO_JOIN */
{'g', 'J', TRUE}, /* DO_JOIN_NS */
{'g', '?', FALSE}, /* OP_ROT13 */
{'r', NUL, FALSE}, /* OP_REPLACE */
{'I', NUL, FALSE}, /* OP_INSERT */
{'A', NUL, FALSE}, /* OP_APPEND */
{'z', 'f', TRUE}, /* OP_FOLD */
{'z', 'o', TRUE}, /* OP_FOLDOPEN */
{'z', 'O', TRUE}, /* OP_FOLDOPENREC */
{'z', 'c', TRUE}, /* OP_FOLDCLOSE */
{'z', 'C', TRUE}, /* OP_FOLDCLOSEREC */
{'z', 'd', TRUE}, /* OP_FOLDDEL */
{'z', 'D', TRUE}, /* OP_FOLDDELREC */
{'g', 'w', TRUE}, /* OP_FORMAT2 */
{'g', '@', FALSE}, /* OP_FUNCTION */
{Ctrl_A, NUL, FALSE}, /* OP_NR_ADD */
{Ctrl_X, NUL, FALSE}, /* OP_NR_SUB */
{NUL, NUL, 0}, // OP_NOP
{'d', NUL, OPF_CHANGE}, // OP_DELETE
{'y', NUL, 0}, // OP_YANK
{'c', NUL, OPF_CHANGE}, // OP_CHANGE
{'<', NUL, OPF_LINES | OPF_CHANGE}, // OP_LSHIFT
{'>', NUL, OPF_LINES | OPF_CHANGE}, // OP_RSHIFT
{'!', NUL, OPF_LINES | OPF_CHANGE}, // OP_FILTER
{'g', '~', OPF_CHANGE}, // OP_TILDE
{'=', NUL, OPF_LINES | OPF_CHANGE}, // OP_INDENT
{'g', 'q', OPF_LINES | OPF_CHANGE}, // OP_FORMAT
{':', NUL, OPF_LINES}, // OP_COLON
{'g', 'U', OPF_CHANGE}, // OP_UPPER
{'g', 'u', OPF_CHANGE}, // OP_LOWER
{'J', NUL, OPF_LINES | OPF_CHANGE}, // DO_JOIN
{'g', 'J', OPF_LINES | OPF_CHANGE}, // DO_JOIN_NS
{'g', '?', OPF_CHANGE}, // OP_ROT13
{'r', NUL, OPF_CHANGE}, // OP_REPLACE
{'I', NUL, OPF_CHANGE}, // OP_INSERT
{'A', NUL, OPF_CHANGE}, // OP_APPEND
{'z', 'f', OPF_LINES}, // OP_FOLD
{'z', 'o', OPF_LINES}, // OP_FOLDOPEN
{'z', 'O', OPF_LINES}, // OP_FOLDOPENREC
{'z', 'c', OPF_LINES}, // OP_FOLDCLOSE
{'z', 'C', OPF_LINES}, // OP_FOLDCLOSEREC
{'z', 'd', OPF_LINES}, // OP_FOLDDEL
{'z', 'D', OPF_LINES}, // OP_FOLDDELREC
{'g', 'w', OPF_LINES | OPF_CHANGE}, // OP_FORMAT2
{'g', '@', OPF_CHANGE}, // OP_FUNCTION
{Ctrl_A, NUL, OPF_CHANGE}, // OP_NR_ADD
{Ctrl_X, NUL, OPF_CHANGE}, // OP_NR_SUB
};
/*
@@ -201,7 +205,16 @@ get_op_type(int char1, int char2)
int
op_on_lines(int op)
{
return opchars[op][2];
return opchars[op][2] & OPF_LINES;
}
/*
* Return TRUE if operator "op" changes text.
*/
int
op_is_change(int op)
{
return opchars[op][2] & OPF_CHANGE;
}
/*
+5 -1
View File
@@ -3312,7 +3312,7 @@ static char *(p_bsdir_values[]) = {"current", "last", "buffer", NULL};
static char *(p_scbopt_values[]) = {"ver", "hor", "jump", NULL};
static char *(p_debug_values[]) = {"msg", "throw", "beep", NULL};
static char *(p_ead_values[]) = {"both", "ver", "hor", NULL};
static char *(p_buftype_values[]) = {"nofile", "nowrite", "quickfix", "help", "terminal", "acwrite", NULL};
static char *(p_buftype_values[]) = {"nofile", "nowrite", "quickfix", "help", "terminal", "acwrite", "prompt", NULL};
static char *(p_bufhidden_values[]) = {"hide", "unload", "delete", "wipe", NULL};
static char *(p_bs_values[]) = {"indent", "eol", "start", NULL};
#ifdef FEAT_FOLDING
@@ -12655,6 +12655,10 @@ check_opt_wim(void)
can_bs(
int what) /* BS_INDENT, BS_EOL or BS_START */
{
#ifdef FEAT_JOB_CHANNEL
if (what == BS_START && bt_prompt(curbuf))
return FALSE;
#endif
switch (*p_bs)
{
case '2': return TRUE;
+1
View File
@@ -59,6 +59,7 @@ void write_viminfo_bufferlist(FILE *fp);
int bt_quickfix(buf_T *buf);
int bt_terminal(buf_T *buf);
int bt_help(buf_T *buf);
int bt_prompt(buf_T *buf);
int bt_nofile(buf_T *buf);
int bt_dontwrite(buf_T *buf);
int bt_dontwrite_msg(buf_T *buf);
+1
View File
@@ -72,5 +72,6 @@ char *job_status(job_T *job);
void job_info(job_T *job, dict_T *dict);
void job_info_all(list_T *l);
int job_stop(job_T *job, typval_T *argvars, char *type);
void invoke_prompt_callback(void);
void job_cleanup_all(void);
/* vim: set ft=c : */
+2
View File
@@ -1,6 +1,8 @@
/* edit.c */
int edit(int cmdchar, int startln, long count);
void edit_putchar(int c, int highlight);
char_u *prompt_text(void);
int prompt_curpos_editable(void);
void edit_unputchar(void);
void display_dollar(colnr_T col);
void change_indent(int type, int amount, int round, int replaced, int call_changed_bytes);
+1
View File
@@ -1,6 +1,7 @@
/* ops.c */
int get_op_type(int char1, int char2);
int op_on_lines(int op);
int op_is_change(int op);
int get_op_char(int optype);
int get_extra_op_char(int optype);
void op_shift(oparg_T *oap, int curs_top, int amount);
+4
View File
@@ -476,6 +476,10 @@ redraw_after_callback(int call_update_screen)
else
#endif
out_flush();
#ifdef FEAT_GUI_MACVIM
if (gui.in_use)
gui_macvim_force_flush();
#endif
--redrawing_for_callback;
}
+7
View File
@@ -2362,6 +2362,13 @@ struct file_buffer
int b_shortname; /* this file has an 8.3 file name */
#ifdef FEAT_JOB_CHANNEL
char_u *b_prompt_text; // set by prompt_setprompt()
char_u *b_prompt_callback; // set by prompt_setcallback()
partial_T *b_prompt_partial; // set by prompt_setcallback()
int b_prompt_insert; // value for restart_edit when entering
// a prompt buffer window.
#endif
#ifdef FEAT_MZSCHEME
void *b_mzscheme_ref; /* The MzScheme reference to this buffer */
#endif
+13 -2
View File
@@ -5099,8 +5099,19 @@ f_term_sendkeys(typval_T *argvars, typval_T *rettv)
while (*msg != NUL)
{
send_keys_to_term(term, PTR2CHAR(msg), FALSE);
msg += MB_CPTR2LEN(msg);
int c;
if (*msg == K_SPECIAL && msg[1] != NUL && msg[2] != NUL)
{
c = TO_SPECIAL(msg[1], msg[2]);
msg += 3;
}
else
{
c = PTR2CHAR(msg);
msg += MB_CPTR2LEN(msg);
}
send_keys_to_term(term, c, FALSE);
}
}
+1
View File
@@ -147,6 +147,7 @@ NEW_TESTS = test_arabic.res \
test_perl.res \
test_plus_arg_edit.res \
test_preview.res \
test_prompt_buffer.res \
test_profile.res \
test_python2.res \
test_python3.res \
+19 -14
View File
@@ -5,19 +5,18 @@ if exists('*CanRunVimInTerminal')
finish
endif
" Need to be able to run terminal Vim with 256 colors. On MS-Windows the
" console only has 16 colors and the GUI can't run in a terminal.
if !has('terminal') || has('win32')
func CanRunVimInTerminal()
return 0
endfunc
" For most tests we need to be able to run terminal Vim with 256 colors. On
" MS-Windows the console only has 16 colors and the GUI can't run in a
" terminal.
func CanRunVimInTerminal()
return has('terminal') && !has('win32')
endfunc
" Skip the rest if there is no terminal feature at all.
if !has('terminal')
finish
endif
func CanRunVimInTerminal()
return 1
endfunc
source shared.vim
" Run Vim with "arguments" in a new terminal window.
@@ -54,6 +53,7 @@ func RunVimInTerminal(arguments, options)
let cols = get(a:options, 'cols', 75)
let cmd = GetVimCommandClean()
" Add -v to have gvim run in the terminal (if possible)
let cmd .= ' -v ' . a:arguments
let buf = term_start(cmd, {'curwin': 1, 'term_rows': rows, 'term_cols': cols})
@@ -64,11 +64,12 @@ func RunVimInTerminal(arguments, options)
let cols = term_getsize(buf)[1]
endif
" Wait for "All" or "Top" of the ruler in the status line to be shown. This
" can be quite slow (e.g. when using valgrind).
" Wait for "All" or "Top" of the ruler to be shown in the last line or in
" the status line of the last window. This can be quite slow (e.g. when
" using valgrind).
" If it fails then show the terminal contents for debugging.
try
call WaitFor({-> len(term_getline(buf, rows)) >= cols - 1})
call WaitFor({-> len(term_getline(buf, rows)) >= cols - 1 || len(term_getline(buf, rows - 1)) >= cols - 1})
catch /timed out after/
let lines = map(range(1, rows), {key, val -> term_getline(buf, val)})
call assert_report('RunVimInTerminal() failed, screen contents: ' . join(lines, "<NL>"))
@@ -80,7 +81,11 @@ endfunc
" Stop a Vim running in terminal buffer "buf".
func StopVimInTerminal(buf)
call assert_equal("running", term_getstatus(a:buf))
call term_sendkeys(a:buf, "\<Esc>\<Esc>:qa!\<cr>")
" CTRL-O : works both in Normal mode and Insert mode to start a command line.
" In Command-line it's inserted, the CTRL-U removes it again.
call term_sendkeys(a:buf, "\<C-O>:\<C-U>qa!\<cr>")
call WaitForAssert({-> assert_equal("finished", term_getstatus(a:buf))})
only!
endfunc
+48 -1
View File
@@ -1,4 +1,4 @@
" Tests for setbufline() and getbufline()
" Tests for setbufline(), getbufline(), appendbufline(), deletebufline()
source shared.vim
@@ -65,3 +65,50 @@ func Test_setline_startup()
call delete('Xscript')
call delete('Xtest')
endfunc
func Test_appendbufline()
new
let b = bufnr('%')
hide
call assert_equal(0, appendbufline(b, 0, ['foo', 'bar']))
call assert_equal(['foo'], getbufline(b, 1))
call assert_equal(['bar'], getbufline(b, 2))
call assert_equal(['foo', 'bar'], getbufline(b, 1, 2))
exe "bd!" b
call assert_equal([], getbufline(b, 1, 2))
split Xtest
call setline(1, ['a', 'b', 'c'])
let b = bufnr('%')
wincmd w
call assert_equal(1, appendbufline(b, 4, ['x']))
call assert_equal(1, appendbufline(1234, 1, ['x']))
call assert_equal(0, appendbufline(b, 3, ['d', 'e']))
call assert_equal(['c'], getbufline(b, 3))
call assert_equal(['d'], getbufline(b, 4))
call assert_equal(['e'], getbufline(b, 5))
call assert_equal([], getbufline(b, 6))
exe "bwipe! " . b
endfunc
func Test_deletebufline()
new
let b = bufnr('%')
call setline(1, ['aaa', 'bbb', 'ccc'])
hide
call assert_equal(0, deletebufline(b, 2))
call assert_equal(['aaa', 'ccc'], getbufline(b, 1, 2))
call assert_equal(0, deletebufline(b, 2, 8))
call assert_equal(['aaa'], getbufline(b, 1, 2))
exe "bd!" b
call assert_equal(1, deletebufline(b, 1))
split Xtest
call setline(1, ['a', 'b', 'c'])
let b = bufnr('%')
wincmd w
call assert_equal(1, deletebufline(b, 4))
call assert_equal(0, deletebufline(b, 1))
call assert_equal(['b', 'c'], getbufline(b, 1, 2))
exe "bwipe! " . b
endfunc
+15 -1
View File
@@ -527,7 +527,7 @@ func! Test_edit_CTRL_I()
" Tab in completion mode
let path=expand("%:p:h")
new
call setline(1, [path."/", ''])
call setline(1, [path. "/", ''])
call feedkeys("Arunt\<c-x>\<c-f>\<tab>\<cr>\<esc>", 'tnix')
call assert_match('runtest\.vim', getline(1))
%d
@@ -1387,3 +1387,17 @@ func Test_edit_quit()
only
endfunc
func Test_edit_alt()
" Keeping the cursor line didn't happen when the first line has indent.
new
call setline(1, [' one', 'two', 'three'])
w XAltFile
$
call assert_equal(3, line('.'))
e Xother
e #
call assert_equal(3, line('.'))
bwipe XAltFile
call delete('XAltFile')
endfunc
+62
View File
@@ -309,3 +309,65 @@ func Test_gd_local_block()
\ ]
call XTest_goto_decl('1gd', lines, 11, 11)
endfunc
func Test_motion_if_elif_else_endif()
new
a
/* Test pressing % on #if, #else #elsif and #endif,
* with nested #if
*/
#if FOO
/* ... */
# if BAR
/* ... */
# endif
#elif BAR
/* ... */
#else
/* ... */
#endif
.
/#if FOO
norm %
call assert_equal([9, 1], getpos('.')[1:2])
norm %
call assert_equal([11, 1], getpos('.')[1:2])
norm %
call assert_equal([13, 1], getpos('.')[1:2])
norm %
call assert_equal([4, 1], getpos('.')[1:2])
/# if BAR
norm $%
call assert_equal([8, 1], getpos('.')[1:2])
norm $%
call assert_equal([6, 1], getpos('.')[1:2])
bw!
endfunc
func Test_motion_c_comment()
new
a
/*
* Test pressing % on beginning/end
* of C comments.
*/
/* Another comment */
.
norm gg0%
call assert_equal([4, 3], getpos('.')[1:2])
norm %
call assert_equal([1, 1], getpos('.')[1:2])
norm gg0l%
call assert_equal([4, 3], getpos('.')[1:2])
norm h%
call assert_equal([1, 1], getpos('.')[1:2])
norm G^
norm %
call assert_equal([5, 21], getpos('.')[1:2])
norm %
call assert_equal([5, 1], getpos('.')[1:2])
bw!
endfunc
+4
View File
@@ -247,6 +247,10 @@ func! Test_popup_completion_insertmode()
iunmap <F5>
endfunc
" TODO: Fix what breaks after this line.
" - Do not use "q!", it may exit Vim if there is an error
finish
func Test_noinsert_complete()
function! s:complTest1() abort
call complete(1, ['source', 'soundfold'])
+103
View File
@@ -0,0 +1,103 @@
" Tests for setting 'buftype' to "prompt"
if !has('channel')
finish
endif
source shared.vim
source screendump.vim
func CanTestPromptBuffer()
" We need to use a terminal window to be able to feed keys without leaving
" Insert mode.
if !has('terminal')
return 0
endif
if has('win32')
" TODO: make the tests work on MS-Windows
return 0
endif
return 1
endfunc
func WriteScript(name)
call writefile([
\ 'func TextEntered(text)',
\ ' if a:text == "exit"',
\ ' stopinsert',
\ ' close',
\ ' else',
\ ' " Add the output above the current prompt.',
\ ' call append(line("$") - 1, "Command: \"" . a:text . "\"")',
\ ' " Reset &modified to allow the buffer to be closed.',
\ ' set nomodified',
\ ' call timer_start(20, {id -> TimerFunc(a:text)})',
\ ' endif',
\ 'endfunc',
\ '',
\ 'func TimerFunc(text)',
\ ' " Add the output above the current prompt.',
\ ' call append(line("$") - 1, "Result: \"" . a:text . "\"")',
\ ' " Reset &modified to allow the buffer to be closed.',
\ ' set nomodified',
\ 'endfunc',
\ '',
\ 'call setline(1, "other buffer")',
\ 'set nomodified',
\ 'new',
\ 'set buftype=prompt',
\ 'call prompt_setcallback(bufnr(""), function("TextEntered"))',
\ 'startinsert',
\ ], a:name)
endfunc
func Test_prompt_basic()
if !CanTestPromptBuffer()
return
endif
let scriptName = 'XpromptscriptBasic'
call WriteScript(scriptName)
let buf = RunVimInTerminal('-S ' . scriptName, {})
call WaitForAssert({-> assert_equal('%', term_getline(buf, 1))})
call term_sendkeys(buf, "hello\<CR>")
call WaitForAssert({-> assert_equal('% hello', term_getline(buf, 1))})
call WaitForAssert({-> assert_equal('Command: "hello"', term_getline(buf, 2))})
call WaitForAssert({-> assert_equal('Result: "hello"', term_getline(buf, 3))})
call term_sendkeys(buf, "exit\<CR>")
call WaitForAssert({-> assert_equal('other buffer', term_getline(buf, 1))})
call StopVimInTerminal(buf)
call delete(scriptName)
endfunc
func Test_prompt_editing()
if !CanTestPromptBuffer()
return
endif
let scriptName = 'XpromptscriptEditing'
call WriteScript(scriptName)
let buf = RunVimInTerminal('-S ' . scriptName, {})
call WaitForAssert({-> assert_equal('%', term_getline(buf, 1))})
let bs = "\<BS>"
call term_sendkeys(buf, "hello" . bs . bs)
call WaitForAssert({-> assert_equal('% hel', term_getline(buf, 1))})
let left = "\<Left>"
call term_sendkeys(buf, left . left . left . bs . '-')
call WaitForAssert({-> assert_equal('% -hel', term_getline(buf, 1))})
let end = "\<End>"
call term_sendkeys(buf, end . "x")
call WaitForAssert({-> assert_equal('% -helx', term_getline(buf, 1))})
call term_sendkeys(buf, "\<C-U>exit\<CR>")
call WaitForAssert({-> assert_equal('other buffer', term_getline(buf, 1))})
call StopVimInTerminal(buf)
call delete(scriptName)
endfunc
+7 -2
View File
@@ -270,7 +270,7 @@ func Test_terminal_scroll()
endfunc
func Test_terminal_scrollback()
let buf = Run_shell_in_terminal({})
let buf = Run_shell_in_terminal({'term_rows': 15})
set termwinscroll=100
call writefile(range(150), 'Xtext')
if has('win32')
@@ -384,7 +384,8 @@ endfunc
func s:get_sleep_cmd()
if s:python != ''
let cmd = s:python . " test_short_sleep.py"
let waittime = 500
" 500 was not enough for Travis
let waittime = 900
else
echo 'This will take five seconds...'
let waittime = 2000
@@ -585,6 +586,10 @@ func Test_terminal_write_stdin()
if !executable('wc')
throw 'skipped: wc command not available'
endif
if has('win32')
" TODO: enable once writing to stdin works on MS-Windows
return
endif
new
call setline(1, ['one', 'two', 'three'])
%term wc
+38 -6
View File
@@ -85,7 +85,7 @@ endfunc
func FillBuffer()
for i in range(1,13)
put=i
" Set 'undolevels' to split undo.
" Set 'undolevels' to split undo.
exe "setg ul=" . &g:ul
endfor
endfunc
@@ -193,19 +193,19 @@ func Test_undolist()
new
set ul=100
let a=execute('undolist')
let a = execute('undolist')
call assert_equal("\nNothing to undo", a)
" 1 leaf (2 changes).
call feedkeys('achange1', 'xt')
call feedkeys('achange2', 'xt')
let a=execute('undolist')
let a = execute('undolist')
call assert_match("^\nnumber changes when *saved\n *2 *2 .*$", a)
" 2 leaves.
call feedkeys('u', 'xt')
call feedkeys('achange3\<Esc>', 'xt')
let a=execute('undolist')
let a = execute('undolist')
call assert_match("^\nnumber changes when *saved\n *2 *2 *.*\n *3 *2 .*$", a)
close!
endfunc
@@ -339,7 +339,7 @@ endfunc
" Also test this in an empty buffer.
func Test_cmd_in_reg_undo()
enew!
let @a="Ox\<Esc>jAy\<Esc>kdd"
let @a = "Ox\<Esc>jAy\<Esc>kdd"
edit +/^$ test_undo.vim
normal @au
call assert_equal(0, &modified)
@@ -348,7 +348,7 @@ func Test_cmd_in_reg_undo()
normal @au
call assert_equal(0, &modified)
only!
let @a=''
let @a = ''
endfunc
" This used to cause an illegal memory access
@@ -410,3 +410,35 @@ func Test_redo_empty_line()
exe "norm."
bwipe!
endfunc
funct Test_undofile()
" Test undofile() without setting 'undodir'.
if has('persistent_undo')
call assert_equal(fnamemodify('.Xundofoo.un~', ':p'), undofile('Xundofoo'))
else
call assert_equal('', undofile('Xundofoo'))
endif
call assert_equal('', undofile(''))
" Test undofile() with 'undodir' set to to an existing directory.
call mkdir('Xundodir')
set undodir=Xundodir
let cwd = getcwd()
if has('win32')
" Replace windows drive such as C:... into C%...
let cwd = substitute(cwd, '^\([A-Z]\):', '\1%', 'g')
endif
let cwd = substitute(cwd . '/Xundofoo', '/', '%', 'g')
if has('persistent_undo')
call assert_equal('Xundodir/' . cwd, undofile('Xundofoo'))
else
call assert_equal('', undofile('Xundofoo'))
endif
call assert_equal('', undofile(''))
call delete('Xundodir', 'd')
" Test undofile() with 'undodir' set to a non-existing directory.
call assert_equal('', undofile('Xundofoo'))
set undodir&
endfunc
+34
View File
@@ -776,6 +776,40 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
39,
/**/
38,
/**/
37,
/**/
36,
/**/
35,
/**/
34,
/**/
33,
/**/
32,
/**/
31,
/**/
30,
/**/
29,
/**/
28,
/**/
27,
/**/
26,
/**/
25,
/**/
24,
/**/
23,
/**/
22,
/**/
+52
View File
@@ -2108,6 +2108,38 @@ win_equal_rec(
}
}
#ifdef FEAT_JOB_CHANNEL
static void
leaving_window(win_T *win)
{
// When leaving a prompt window stop Insert mode and perhaps restart
// it when entering that window again.
win->w_buffer->b_prompt_insert = restart_edit;
restart_edit = NUL;
// When leaving the window (or closing the window) was done from a
// callback we need to break out of the Insert mode loop.
if (State & INSERT)
{
stop_insert_mode = TRUE;
if (bt_prompt(win->w_buffer) && win->w_buffer->b_prompt_insert == NUL)
win->w_buffer->b_prompt_insert = 'A';
}
}
static void
entering_window(win_T *win)
{
// When switching to a prompt buffer that was in Insert mode, don't stop
// Insert mode, it may have been set in leaving_window().
if (bt_prompt(win->w_buffer) && win->w_buffer->b_prompt_insert != NUL)
stop_insert_mode = FALSE;
// When entering the prompt window may restart Insert mode.
restart_edit = win->w_buffer->b_prompt_insert;
}
#endif
/*
* Close all windows for buffer "buf".
*/
@@ -2236,6 +2268,9 @@ close_last_window_tabpage(
if (h != tabline_height())
shell_new_rows();
}
#ifdef FEAT_JOB_CHANNEL
entering_window(curwin);
#endif
/* Since goto_tabpage_tp above did not trigger *Enter autocommands, do
* that now. */
apply_autocmds(EVENT_TABCLOSED, NULL, NULL, FALSE, curbuf);
@@ -2301,6 +2336,9 @@ win_close(win_T *win, int free_buf)
if (win == curwin)
{
#ifdef FEAT_JOB_CHANNEL
leaving_window(curwin);
#endif
/*
* Guess which window is going to be the new current window.
* This may change because of the autocommands (sigh).
@@ -3654,6 +3692,9 @@ win_new_tabpage(int after)
* scrollbars. Have to update them anyway. */
gui_may_update_scrollbars();
#endif
#ifdef FEAT_JOB_CHANNEL
entering_window(curwin);
#endif
redraw_all_later(CLEAR);
apply_autocmds(EVENT_WINNEW, NULL, NULL, FALSE, curbuf);
@@ -3827,6 +3868,9 @@ leave_tabpage(
{
tabpage_T *tp = curtab;
#ifdef FEAT_JOB_CHANNEL
leaving_window(curwin);
#endif
reset_VIsual_and_resel(); /* stop Visual mode */
if (trigger_leave_autocmds)
{
@@ -4323,6 +4367,11 @@ win_enter_ext(
if (wp == curwin && !curwin_invalid) /* nothing to do */
return;
#ifdef FEAT_JOB_CHANNEL
if (!curwin_invalid)
leaving_window(curwin);
#endif
if (!curwin_invalid && trigger_leave_autocmds)
{
/*
@@ -4394,6 +4443,9 @@ win_enter_ext(
shorten_fnames(TRUE);
}
#ifdef FEAT_JOB_CHANNEL
entering_window(curwin);
#endif
if (trigger_new_autocmds)
apply_autocmds(EVENT_WINNEW, NULL, NULL, FALSE, curbuf);
if (trigger_enter_autocmds)