mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-02 11:19:22 +02:00
Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ed3fd67cfc | |||
| 678963c2b8 | |||
| dcdeaaf150 | |||
| b3307b5e7e | |||
| 222cd20e26 | |||
| 0e5979a6d4 | |||
| 2f82ca7d79 | |||
| a5616b0136 | |||
| c3ffc9b8d3 | |||
| 0e6e179f55 | |||
| 942b4541a2 | |||
| d595a1910c | |||
| 491ac28d5f | |||
| 84a9308511 | |||
| 600323b4ef | |||
| bc5020aa4d | |||
| bfa4246768 | |||
| 6ba3ec1bac | |||
| 43dee181f5 | |||
| 52d3aaeea4 | |||
| 5ecdf96422 | |||
| cf915c85f7 | |||
| ffa9684150 | |||
| 83f4cbd973 | |||
| 79c6b51e40 | |||
| 493359eb3b | |||
| d7a137fb0d | |||
| 07ccf7ce7f | |||
| 1983401088 | |||
| 1c3c10492a | |||
| ae0f30b761 | |||
| 8903676d3d | |||
| 7580849df9 | |||
| f98b845dd1 | |||
| e950f9992b | |||
| e31e256ba1 | |||
| 04ee357319 | |||
| a30133de19 | |||
| e95b546b3e | |||
| d79a26219d | |||
| 680c99b2ef | |||
| ca851593a6 | |||
| 891e1fd894 | |||
| 6d41c78e35 | |||
| 703ff6133b | |||
| 2a9f2b5bac | |||
| 5838d3ff38 | |||
| adb8fbec4f | |||
| acb9effecc | |||
| 6b810d92a9 | |||
| c8523e2e6c | |||
| 3339d3dad9 | |||
| 1580f755c9 | |||
| 1149382d21 | |||
| f273245f64 | |||
| 9289901c59 | |||
| 33c5e9fa7a | |||
| e5fa11186f | |||
| 6b69e5c646 | |||
| 22c105640c |
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
+87
-6
@@ -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,10 @@ 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_setcallback({buf}, {expr}) none set prompt callback function
|
||||
prompt_setinterrupt({buf}, {text}) none set prompt interrupt function
|
||||
prompt_setprompt({buf}, {text}) none set prompt text
|
||||
pumvisible() Number whether popup menu is visible
|
||||
pyeval({expr}) any evaluate |Python| expression
|
||||
py3eval({expr}) any evaluate |python3| expression
|
||||
@@ -2302,7 +2308,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 +2563,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 +3520,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 +4682,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 +6507,52 @@ printf({fmt}, {expr1} ...) *printf()*
|
||||
arguments an error is given. Up to 18 arguments can be used.
|
||||
|
||||
|
||||
prompt_setcallback({buf}, {expr}) *prompt_setcallback()*
|
||||
Set prompt callback for buffer {buf} to {expr}. When {expr}
|
||||
is an empty string the callback is removed. 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
|
||||
|
||||
prompt_setinterrupt({buf}, {expr}) *prompt_setinterrupt()*
|
||||
Set a callback for buffer {buf} to {expr}. When {expr} is an
|
||||
empty string the callback is removed. This has only effect if
|
||||
{buf} has 'buftype' set to "prompt".
|
||||
|
||||
This callback will be invoked when pressing CTRL-C in Insert
|
||||
mode. Without setting a callback Vim will exit Insert mode,
|
||||
as in any buffer.
|
||||
|
||||
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: ')
|
||||
|
||||
|
||||
pumvisible() *pumvisible()*
|
||||
Returns non-zero when the popup menu is visible, zero
|
||||
otherwise. See |ins-completion-menu|.
|
||||
@@ -8496,7 +8574,9 @@ term_start({cmd}, {options}) *term_start()*
|
||||
instead of using 'termwinsize'
|
||||
"term_cols" horizontal size to use for the terminal,
|
||||
instead of using 'termwinsize'
|
||||
"vertical" split the window vertically
|
||||
"vertical" split the window vertically; note that
|
||||
other window position can be defined with
|
||||
command modifiers, such as |:belowright|.
|
||||
"curwin" use the current window, do not split the
|
||||
window; fails if the current buffer
|
||||
cannot be |abandon|ed
|
||||
@@ -9329,11 +9409,12 @@ vtp Compiled for vcon support |+vtp| (check vcon to find
|
||||
out if it works in the current console).
|
||||
wildignore Compiled with 'wildignore' option.
|
||||
wildmenu Compiled with 'wildmenu' option.
|
||||
win16 old version for MS-Windows 3.1 (always False)
|
||||
win32 Win32 version of Vim (MS-Windows 95 and later, 32 or
|
||||
64 bits)
|
||||
win32unix Win32 version of Vim, using Unix files (Cygwin)
|
||||
win64 Win64 version of Vim (MS-Windows 64 bit).
|
||||
win95 Win32 version for MS-Windows 95/98/ME.
|
||||
win95 Win32 version for MS-Windows 95/98/ME (always False)
|
||||
winaltkeys Compiled with 'winaltkeys' option.
|
||||
windows Compiled with support for more than one window.
|
||||
writebackup Compiled with 'writebackup' default on.
|
||||
|
||||
+11
-4
@@ -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.
|
||||
|
||||
@@ -38,6 +38,7 @@ If the result is "1" you have it.
|
||||
Stepping through code |termdebug-stepping|
|
||||
Inspecting variables |termdebug-variables|
|
||||
Other commands |termdebug-commands|
|
||||
Prompt mode |termdebug-prompt|
|
||||
Communication |termdebug-communication|
|
||||
Customizing |termdebug-customizing|
|
||||
|
||||
@@ -86,7 +87,8 @@ to the job. For example:
|
||||
'termwinkey' CTRL-W move focus to the next window
|
||||
'termwinkey' : enter an Ex command
|
||||
'termwinkey' 'termwinkey' send 'termwinkey' to the job in the terminal
|
||||
'termwinkey' . send a CTRL-W to the job in the terminal
|
||||
'termwinkey' . send 'termwinkey' to the job in the terminal
|
||||
'termwinkey' CTRL-\ send a CTRL-\ to the job in the terminal
|
||||
'termwinkey' N go to terminal Normal mode, see below
|
||||
'termwinkey' CTRL-N same as CTRL-W N
|
||||
'termwinkey' CTRL-C same as |t_CTRL-W_CTRL-C|
|
||||
@@ -376,6 +378,7 @@ Environment variables are used to pass information to the running job:
|
||||
COLUMNS number of columns in the terminal initially
|
||||
COLORS number of colors, 't_Co' (256*256*256 in the GUI)
|
||||
VIM_SERVERNAME v:servername
|
||||
VIM_TERMINAL v:version
|
||||
|
||||
|
||||
MS-Windows ~
|
||||
@@ -619,6 +622,10 @@ The Terminal debugging plugin can be used to debug a program with gdb and view
|
||||
the source code in a Vim window. Since this is completely contained inside
|
||||
Vim this also works remotely over an ssh connection.
|
||||
|
||||
When the |+terminal| feature is missing, the plugin will use the "prompt"
|
||||
buffer type, if possible. The running program will then use a newly opened
|
||||
terminal window. See |termdebug-prompt| below for details.
|
||||
|
||||
|
||||
Starting ~
|
||||
*termdebug-starting*
|
||||
@@ -798,6 +805,23 @@ Other commands ~
|
||||
isn't one
|
||||
|
||||
|
||||
Prompt mode ~
|
||||
*termdebug-prompt*
|
||||
When the |+terminal| feature is not supported and on MS-Windows, gdb will run
|
||||
in a buffer with 'buftype' set to "prompt". This works slightly differently:
|
||||
- The gdb window will be in Insert mode while typing commands. Go to Normal
|
||||
mode with <Esc>, then you can move around in the buffer, copy/paste, etc.
|
||||
Go back to editing the gdb command with any command that starts Insert mode,
|
||||
such as `a` or `i`.
|
||||
- The program being debugged will run in a separate window. On MS-Windows
|
||||
this is a new console window. On Unix, if the |+terminal| feature is
|
||||
available a Terminal window will be opened to run the debugged program in.
|
||||
|
||||
*termdebug_use_prompt*
|
||||
Prompt mode can be used even when the |+terminal| feature is present with: >
|
||||
let g:termdebug_use_prompt = 1
|
||||
|
||||
|
||||
Communication ~
|
||||
*termdebug-communication*
|
||||
There is another, hidden, buffer, which is used for Vim to communicate with
|
||||
@@ -835,6 +859,14 @@ When 'background' is "dark":
|
||||
hi debugBreakpoint term=reverse ctermbg=red guibg=red
|
||||
|
||||
|
||||
Shorcuts *termdebug_shortcuts*
|
||||
|
||||
You can define your own shortcuts (mappings) to control gdb, that can work in
|
||||
any window, using the TermDebugSendCommand() function. Example: >
|
||||
map ,w :call TermDebugSendCommand('where')<CR>
|
||||
The argument is the gdb command.
|
||||
|
||||
|
||||
Popup menu *termdebug_popup*
|
||||
|
||||
By default the Termdebug plugin sets 'mousemodel' to "popup_setpos" and adds
|
||||
|
||||
+45
-3
@@ -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)
|
||||
|
||||
+326
-47
@@ -1,27 +1,60 @@
|
||||
" Debugger plugin using gdb.
|
||||
"
|
||||
" WORK IN PROGRESS - much doesn't work yet
|
||||
"
|
||||
" Open two visible terminal windows:
|
||||
" 1. run a pty, as with ":term NONE"
|
||||
" 2. run gdb, passing the pty
|
||||
" The current window is used to view source code and follows gdb.
|
||||
"
|
||||
" A third terminal window is hidden, it is used for communication with gdb.
|
||||
"
|
||||
" The communication with gdb uses GDB/MI. See:
|
||||
" https://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI.html
|
||||
"
|
||||
" Author: Bram Moolenaar
|
||||
" Copyright: Vim license applies, see ":help license"
|
||||
" Last Update: 2018 Jun 3
|
||||
"
|
||||
" WORK IN PROGRESS - Only the basics work
|
||||
" Note: On MS-Windows you need a recent version of gdb. The one included with
|
||||
" MingW is too old (7.6.1).
|
||||
" I used version 7.12 from http://www.equation.com/servlet/equation.cmd?fa=gdb
|
||||
"
|
||||
" There are two ways to run gdb:
|
||||
" - In a terminal window; used if possible, does not work on MS-Windows
|
||||
" Not used when g:termdebug_use_prompt is set to 1.
|
||||
" - Using a "prompt" buffer; may use a terminal window for the program
|
||||
"
|
||||
" For both the current window is used to view source code and shows the
|
||||
" current statement from gdb.
|
||||
"
|
||||
" USING A TERMINAL WINDOW
|
||||
"
|
||||
" Opens two visible terminal windows:
|
||||
" 1. runs a pty for the debugged program, as with ":term NONE"
|
||||
" 2. runs gdb, passing the pty of the debugged program
|
||||
" A third terminal window is hidden, it is used for communication with gdb.
|
||||
"
|
||||
" USING A PROMPT BUFFER
|
||||
"
|
||||
" Opens a window with a prompt buffer to communicate with gdb.
|
||||
" Gdb is run as a job with callbacks for I/O.
|
||||
" On Unix another terminal window is opened to run the debugged program
|
||||
" On MS-Windows a separate console is opened to run the debugged program
|
||||
"
|
||||
" The communication with gdb uses GDB/MI. See:
|
||||
" https://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI.html
|
||||
|
||||
" In case this gets loaded twice.
|
||||
" In case this gets sourced twice.
|
||||
if exists(':Termdebug')
|
||||
finish
|
||||
endif
|
||||
|
||||
" Uncomment this line to write logging in "debuglog".
|
||||
" call ch_logfile('debuglog', 'w')
|
||||
" Need either the +terminal feature or +channel and the prompt buffer.
|
||||
" The terminal feature does not work with gdb on win32.
|
||||
if has('terminal') && !has('win32')
|
||||
let s:way = 'terminal'
|
||||
elseif has('channel') && exists('*prompt_setprompt')
|
||||
let s:way = 'prompt'
|
||||
else
|
||||
if has('terminal')
|
||||
let s:err = 'Cannot debug, missing prompt buffer support'
|
||||
else
|
||||
let s:err = 'Cannot debug, +channel feature is not supported'
|
||||
endif
|
||||
command -nargs=* -complete=file -bang Termdebug echoerr s:err
|
||||
command -nargs=+ -complete=file -bang TermdebugCommand echoerr s:err
|
||||
finish
|
||||
endif
|
||||
|
||||
" The command that starts debugging, e.g. ":Termdebug vim".
|
||||
" To end type "quit" in the gdb window.
|
||||
@@ -59,8 +92,12 @@ func s:StartDebug_internal(dict)
|
||||
echoerr 'Terminal debugger already running'
|
||||
return
|
||||
endif
|
||||
let s:ptywin = 0
|
||||
|
||||
let s:startwin = win_getid(winnr())
|
||||
" Uncomment this line to write logging in "debuglog".
|
||||
" call ch_logfile('debuglog', 'w')
|
||||
|
||||
let s:sourcewin = win_getid(winnr())
|
||||
let s:startsigncolumn = &signcolumn
|
||||
|
||||
let s:save_columns = 0
|
||||
@@ -69,15 +106,31 @@ func s:StartDebug_internal(dict)
|
||||
let s:save_columns = &columns
|
||||
let &columns = g:termdebug_wide
|
||||
endif
|
||||
let vertical = 1
|
||||
let s:vertical = 1
|
||||
else
|
||||
let vertical = 0
|
||||
let s:vertical = 0
|
||||
endif
|
||||
|
||||
" Open a terminal window without a job, to run the debugged program
|
||||
" Override using a terminal window by setting g:termdebug_use_prompt to 1.
|
||||
let use_prompt = exists('g:termdebug_use_prompt') && g:termdebug_use_prompt
|
||||
if has('terminal') && !has('win32') && !use_prompt
|
||||
let s:way = 'terminal'
|
||||
else
|
||||
let s:way = 'prompt'
|
||||
endif
|
||||
|
||||
if s:way == 'prompt'
|
||||
call s:StartDebug_prompt(a:dict)
|
||||
else
|
||||
call s:StartDebug_term(a:dict)
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func s:StartDebug_term(dict)
|
||||
" Open a terminal window without a job, to run the debugged program in.
|
||||
let s:ptybuf = term_start('NONE', {
|
||||
\ 'term_name': 'gdb program',
|
||||
\ 'vertical': vertical,
|
||||
\ 'term_name': 'debugged program',
|
||||
\ 'vertical': s:vertical,
|
||||
\ })
|
||||
if s:ptybuf == 0
|
||||
echoerr 'Failed to open the program terminal window'
|
||||
@@ -85,7 +138,7 @@ func s:StartDebug_internal(dict)
|
||||
endif
|
||||
let pty = job_info(term_getjob(s:ptybuf))['tty_out']
|
||||
let s:ptywin = win_getid(winnr())
|
||||
if vertical
|
||||
if s:vertical
|
||||
" Assuming the source code window will get a signcolumn, use two more
|
||||
" columns for that, thus one less for the terminal window.
|
||||
exe (&columns / 2 - 1) . "wincmd |"
|
||||
@@ -110,9 +163,9 @@ func s:StartDebug_internal(dict)
|
||||
let proc_args = get(a:dict, 'proc_args', [])
|
||||
|
||||
let cmd = [g:termdebugger, '-quiet', '-tty', pty] + gdb_args
|
||||
echomsg 'executing "' . join(cmd) . '"'
|
||||
call ch_log('executing "' . join(cmd) . '"')
|
||||
let s:gdbbuf = term_start(cmd, {
|
||||
\ 'exit_cb': function('s:EndDebug'),
|
||||
\ 'exit_cb': function('s:EndTermDebug'),
|
||||
\ 'term_finish': 'close',
|
||||
\ })
|
||||
if s:gdbbuf == 0
|
||||
@@ -166,11 +219,108 @@ func s:StartDebug_internal(dict)
|
||||
" exec-interrupt, since many commands don't work properly while the target is
|
||||
" running.
|
||||
call s:SendCommand('-gdb-set mi-async on')
|
||||
" Older gdb uses a different command.
|
||||
call s:SendCommand('-gdb-set target-async on')
|
||||
|
||||
" Disable pagination, it causes everything to stop at the gdb
|
||||
" "Type <return> to continue" prompt.
|
||||
call s:SendCommand('-gdb-set pagination off')
|
||||
call s:SendCommand('set pagination off')
|
||||
|
||||
call s:StartDebugCommon(a:dict)
|
||||
endfunc
|
||||
|
||||
func s:StartDebug_prompt(dict)
|
||||
" Open a window with a prompt buffer to run gdb in.
|
||||
if s:vertical
|
||||
vertical new
|
||||
else
|
||||
new
|
||||
endif
|
||||
let s:gdbwin = win_getid(winnr())
|
||||
let s:promptbuf = bufnr('')
|
||||
call prompt_setprompt(s:promptbuf, 'gdb> ')
|
||||
set buftype=prompt
|
||||
file gdb
|
||||
call prompt_setcallback(s:promptbuf, function('s:PromptCallback'))
|
||||
call prompt_setinterrupt(s:promptbuf, function('s:PromptInterrupt'))
|
||||
|
||||
if s:vertical
|
||||
" Assuming the source code window will get a signcolumn, use two more
|
||||
" columns for that, thus one less for the terminal window.
|
||||
exe (&columns / 2 - 1) . "wincmd |"
|
||||
endif
|
||||
|
||||
" Add -quiet to avoid the intro message causing a hit-enter prompt.
|
||||
let gdb_args = get(a:dict, 'gdb_args', [])
|
||||
let proc_args = get(a:dict, 'proc_args', [])
|
||||
|
||||
let cmd = [g:termdebugger, '-quiet', '--interpreter=mi2'] + gdb_args
|
||||
call ch_log('executing "' . join(cmd) . '"')
|
||||
|
||||
let s:gdbjob = job_start(cmd, {
|
||||
\ 'exit_cb': function('s:EndPromptDebug'),
|
||||
\ 'out_cb': function('s:GdbOutCallback'),
|
||||
\ })
|
||||
if job_status(s:gdbjob) != "run"
|
||||
echoerr 'Failed to start gdb'
|
||||
exe 'bwipe! ' . s:promptbuf
|
||||
return
|
||||
endif
|
||||
let s:gdb_channel = job_getchannel(s:gdbjob)
|
||||
|
||||
" Interpret commands while the target is running. This should usualy only
|
||||
" be exec-interrupt, since many commands don't work properly while the
|
||||
" target is running.
|
||||
call s:SendCommand('-gdb-set mi-async on')
|
||||
" Older gdb uses a different command.
|
||||
call s:SendCommand('-gdb-set target-async on')
|
||||
|
||||
let s:ptybuf = 0
|
||||
if has('win32')
|
||||
" MS-Windows: run in a new console window for maximum compatibility
|
||||
call s:SendCommand('set new-console on')
|
||||
elseif has('terminal')
|
||||
" Unix: Run the debugged program in a terminal window. Open it below the
|
||||
" gdb window.
|
||||
belowright let s:ptybuf = term_start('NONE', {
|
||||
\ 'term_name': 'debugged program',
|
||||
\ })
|
||||
if s:ptybuf == 0
|
||||
echoerr 'Failed to open the program terminal window'
|
||||
call job_stop(s:gdbjob)
|
||||
return
|
||||
endif
|
||||
let s:ptywin = win_getid(winnr())
|
||||
let pty = job_info(term_getjob(s:ptybuf))['tty_out']
|
||||
call s:SendCommand('tty ' . pty)
|
||||
|
||||
" Since GDB runs in a prompt window, the environment has not been set to
|
||||
" match a terminal window, need to do that now.
|
||||
call s:SendCommand('set env TERM = xterm-color')
|
||||
call s:SendCommand('set env ROWS = ' . winheight(s:ptywin))
|
||||
call s:SendCommand('set env LINES = ' . winheight(s:ptywin))
|
||||
call s:SendCommand('set env COLUMNS = ' . winwidth(s:ptywin))
|
||||
call s:SendCommand('set env COLORS = ' . &t_Co)
|
||||
call s:SendCommand('set env VIM_TERMINAL = ' . v:version)
|
||||
else
|
||||
" TODO: open a new terminal get get the tty name, pass on to gdb
|
||||
call s:SendCommand('show inferior-tty')
|
||||
endif
|
||||
call s:SendCommand('set print pretty on')
|
||||
call s:SendCommand('set breakpoint pending on')
|
||||
" Disable pagination, it causes everything to stop at the gdb
|
||||
call s:SendCommand('set pagination off')
|
||||
|
||||
" Set arguments to be run
|
||||
if len(proc_args)
|
||||
call s:SendCommand('set args ' . join(proc_args))
|
||||
endif
|
||||
|
||||
call s:StartDebugCommon(a:dict)
|
||||
startinsert
|
||||
endfunc
|
||||
|
||||
func s:StartDebugCommon(dict)
|
||||
" Sign used to highlight the line where the program has stopped.
|
||||
" There can be only one.
|
||||
sign define debugPC linehl=debugPC
|
||||
@@ -180,7 +330,7 @@ func s:StartDebug_internal(dict)
|
||||
sign define debugBreakpoint text=>> texthl=debugBreakpoint
|
||||
|
||||
" Install debugger commands in the text window.
|
||||
call win_gotoid(s:startwin)
|
||||
call win_gotoid(s:sourcewin)
|
||||
call s:InstallCommands()
|
||||
call win_gotoid(s:gdbwin)
|
||||
|
||||
@@ -202,27 +352,130 @@ func s:StartDebug_internal(dict)
|
||||
au BufUnload * call s:BufUnloaded()
|
||||
augroup END
|
||||
|
||||
" Run the command if the bang attribute was given
|
||||
" and got to the window
|
||||
" Run the command if the bang attribute was given and got to the debug
|
||||
" window.
|
||||
if get(a:dict, 'bang', 0)
|
||||
call s:SendCommand('-exec-run')
|
||||
call win_gotoid(s:ptywin)
|
||||
endif
|
||||
|
||||
endfunc
|
||||
|
||||
func s:EndDebug(job, status)
|
||||
exe 'bwipe! ' . s:ptybuf
|
||||
" Send a command to gdb. "cmd" is the string without line terminator.
|
||||
func s:SendCommand(cmd)
|
||||
call ch_log('sending to gdb: ' . a:cmd)
|
||||
if s:way == 'prompt'
|
||||
call ch_sendraw(s:gdb_channel, a:cmd . "\n")
|
||||
else
|
||||
call term_sendkeys(s:commbuf, a:cmd . "\r")
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" This is global so that a user can create their mappings with this.
|
||||
func TermDebugSendCommand(cmd)
|
||||
if s:way == 'prompt'
|
||||
call ch_sendraw(s:gdb_channel, a:cmd . "\n")
|
||||
else
|
||||
let do_continue = 0
|
||||
if !s:stopped
|
||||
let do_continue = 1
|
||||
call s:SendCommand('-exec-interrupt')
|
||||
sleep 10m
|
||||
endif
|
||||
call term_sendkeys(s:gdbbuf, a:cmd . "\r")
|
||||
if do_continue
|
||||
Continue
|
||||
endif
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" Function called when entering a line in the prompt buffer.
|
||||
func s:PromptCallback(text)
|
||||
call s:SendCommand(a:text)
|
||||
endfunc
|
||||
|
||||
" Function called when pressing CTRL-C in the prompt buffer.
|
||||
func s:PromptInterrupt()
|
||||
call ch_log('Interrupting gdb')
|
||||
call job_stop(s:gdbjob, 'int')
|
||||
endfunc
|
||||
|
||||
" Function called when gdb outputs text.
|
||||
func s:GdbOutCallback(channel, text)
|
||||
call ch_log('received from gdb: ' . a:text)
|
||||
|
||||
" Drop the gdb prompt, we have our own.
|
||||
" Drop status and echo'd commands.
|
||||
if a:text == '(gdb) ' || a:text == '^done' || a:text[0] == '&' || a:text[0] == '='
|
||||
return
|
||||
endif
|
||||
if a:text =~ '^^error,msg='
|
||||
let text = s:DecodeMessage(a:text[11:])
|
||||
if exists('s:evalexpr') && text =~ 'A syntax error in expression, near\|No symbol .* in current context'
|
||||
" Silently drop evaluation errors.
|
||||
unlet s:evalexpr
|
||||
return
|
||||
endif
|
||||
elseif a:text[0] == '~'
|
||||
let text = s:DecodeMessage(a:text[1:])
|
||||
else
|
||||
call s:CommOutput(a:channel, a:text)
|
||||
return
|
||||
endif
|
||||
|
||||
let curwinid = win_getid(winnr())
|
||||
call win_gotoid(s:gdbwin)
|
||||
|
||||
" Add the output above the current prompt.
|
||||
call append(line('$') - 1, text)
|
||||
set nomodified
|
||||
|
||||
call win_gotoid(curwinid)
|
||||
endfunc
|
||||
|
||||
" Decode a message from gdb. quotedText starts with a ", return the text up
|
||||
" to the next ", unescaping characters.
|
||||
func s:DecodeMessage(quotedText)
|
||||
if a:quotedText[0] != '"'
|
||||
echoerr 'DecodeMessage(): missing quote'
|
||||
return
|
||||
endif
|
||||
let result = ''
|
||||
let i = 1
|
||||
while a:quotedText[i] != '"' && i < len(a:quotedText)
|
||||
if a:quotedText[i] == '\'
|
||||
let i += 1
|
||||
if a:quotedText[i] == 'n'
|
||||
" drop \n
|
||||
let i += 1
|
||||
continue
|
||||
endif
|
||||
endif
|
||||
let result .= a:quotedText[i]
|
||||
let i += 1
|
||||
endwhile
|
||||
return result
|
||||
endfunc
|
||||
|
||||
func s:EndTermDebug(job, status)
|
||||
exe 'bwipe! ' . s:commbuf
|
||||
unlet s:gdbwin
|
||||
|
||||
call s:EndDebugCommon()
|
||||
endfunc
|
||||
|
||||
func s:EndDebugCommon()
|
||||
let curwinid = win_getid(winnr())
|
||||
|
||||
call win_gotoid(s:startwin)
|
||||
if exists('s:ptybuf') && s:ptybuf
|
||||
exe 'bwipe! ' . s:ptybuf
|
||||
endif
|
||||
|
||||
call win_gotoid(s:sourcewin)
|
||||
let &signcolumn = s:startsigncolumn
|
||||
call s:DeleteCommands()
|
||||
|
||||
call win_gotoid(curwinid)
|
||||
|
||||
if s:save_columns > 0
|
||||
let &columns = s:save_columns
|
||||
endif
|
||||
@@ -240,6 +493,19 @@ func s:EndDebug(job, status)
|
||||
au! TermDebug
|
||||
endfunc
|
||||
|
||||
func s:EndPromptDebug(job, status)
|
||||
let curwinid = win_getid(winnr())
|
||||
call win_gotoid(s:gdbwin)
|
||||
close
|
||||
if curwinid != s:gdbwin
|
||||
call win_gotoid(curwinid)
|
||||
endif
|
||||
|
||||
call s:EndDebugCommon()
|
||||
unlet s:gdbwin
|
||||
call ch_log("Returning from EndPromptDebug()")
|
||||
endfunc
|
||||
|
||||
" Handle a message received from gdb on the GDB/MI interface.
|
||||
func s:CommOutput(chan, msg)
|
||||
let msgs = split(a:msg, "\r")
|
||||
@@ -275,11 +541,18 @@ func s:InstallCommands()
|
||||
command -nargs=* Run call s:Run(<q-args>)
|
||||
command -nargs=* Arguments call s:SendCommand('-exec-arguments ' . <q-args>)
|
||||
command Stop call s:SendCommand('-exec-interrupt')
|
||||
command Continue call s:SendCommand('-exec-continue')
|
||||
|
||||
" using -exec-continue results in CTRL-C in gdb window not working
|
||||
if s:way == 'prompt'
|
||||
command Continue call s:SendCommand('continue')
|
||||
else
|
||||
command Continue call term_sendkeys(s:gdbbuf, "continue\r")
|
||||
endif
|
||||
|
||||
command -range -nargs=* Evaluate call s:Evaluate(<range>, <q-args>)
|
||||
command Gdb call win_gotoid(s:gdbwin)
|
||||
command Program call win_gotoid(s:ptywin)
|
||||
command Source call s:GotoStartwinOrCreateIt()
|
||||
command Source call s:GotoSourcewinOrCreateIt()
|
||||
command Winbar call s:InstallWinbar()
|
||||
|
||||
" TODO: can the K mapping be restored?
|
||||
@@ -375,7 +648,13 @@ func s:SetBreakpoint()
|
||||
let do_continue = 0
|
||||
if !s:stopped
|
||||
let do_continue = 1
|
||||
call s:SendCommand('-exec-interrupt')
|
||||
if s:way == 'prompt'
|
||||
" Need to send a signal to get the UI to listen. Strangely this is only
|
||||
" needed once.
|
||||
call job_stop(s:gdbjob, 'int')
|
||||
else
|
||||
call s:SendCommand('-exec-interrupt')
|
||||
endif
|
||||
sleep 10m
|
||||
endif
|
||||
call s:SendCommand('-break-insert --source '
|
||||
@@ -391,7 +670,7 @@ func s:ClearBreakpoint()
|
||||
let lnum = line('.')
|
||||
for [key, val] in items(s:breakpoints)
|
||||
if val['fname'] == fname && val['lnum'] == lnum
|
||||
call term_sendkeys(s:commbuf, '-break-delete ' . key . "\r")
|
||||
call s:SendCommand('-break-delete ' . key)
|
||||
" Assume this always wors, the reply is simply "^done".
|
||||
exe 'sign unplace ' . (s:break_id + key)
|
||||
unlet s:breakpoints[key]
|
||||
@@ -400,11 +679,6 @@ func s:ClearBreakpoint()
|
||||
endfor
|
||||
endfunc
|
||||
|
||||
" :Next, :Continue, etc - send a command to gdb
|
||||
func s:SendCommand(cmd)
|
||||
call term_sendkeys(s:commbuf, a:cmd . "\r")
|
||||
endfunc
|
||||
|
||||
func s:Run(args)
|
||||
if a:args != ''
|
||||
call s:SendCommand('-exec-arguments ' . a:args)
|
||||
@@ -466,7 +740,12 @@ endfunc
|
||||
" Show a balloon with information of the variable under the mouse pointer,
|
||||
" if there is any.
|
||||
func TermDebugBalloonExpr()
|
||||
if v:beval_winid != s:startwin
|
||||
if v:beval_winid != s:sourcewin
|
||||
return
|
||||
endif
|
||||
if !s:stopped
|
||||
" Only evaluate when stopped, otherwise setting a breakpoint using the
|
||||
" mouse triggers a balloon.
|
||||
return
|
||||
endif
|
||||
let s:evalFromBalloonExpr = 1
|
||||
@@ -487,10 +766,10 @@ func s:HandleError(msg)
|
||||
echoerr substitute(a:msg, '.*msg="\(.*\)"', '\1', '')
|
||||
endfunc
|
||||
|
||||
func s:GotoStartwinOrCreateIt()
|
||||
if !win_gotoid(s:startwin)
|
||||
func s:GotoSourcewinOrCreateIt()
|
||||
if !win_gotoid(s:sourcewin)
|
||||
new
|
||||
let s:startwin = win_getid(winnr())
|
||||
let s:sourcewin = win_getid(winnr())
|
||||
call s:InstallWinbar()
|
||||
endif
|
||||
endfunc
|
||||
@@ -506,7 +785,7 @@ func s:HandleCursor(msg)
|
||||
let s:stopped = 0
|
||||
endif
|
||||
|
||||
call s:GotoStartwinOrCreateIt()
|
||||
call s:GotoSourcewinOrCreateIt()
|
||||
|
||||
let fname = substitute(a:msg, '.*fullname="\([^"]*\)".*', '\1', '')
|
||||
if a:msg =~ '^\(\*stopped\|=thread-selected\)' && filereadable(fname)
|
||||
@@ -516,7 +795,7 @@ func s:HandleCursor(msg)
|
||||
if &modified
|
||||
" TODO: find existing window
|
||||
exe 'split ' . fnameescape(fname)
|
||||
let s:startwin = win_getid(winnr())
|
||||
let s:sourcewin = win_getid(winnr())
|
||||
call s:InstallWinbar()
|
||||
else
|
||||
exe 'edit ' . fnameescape(fname)
|
||||
|
||||
@@ -1255,7 +1255,7 @@
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>147</string>
|
||||
<string>149</string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
|
||||
@@ -2269,6 +2269,7 @@ test_arglist \
|
||||
test_popup \
|
||||
test_preview \
|
||||
test_profile \
|
||||
test_prompt_buffer \
|
||||
test_put \
|
||||
test_python2 \
|
||||
test_python3 \
|
||||
|
||||
+53
-30
@@ -38,7 +38,7 @@ static int buf_same_ino(buf_T *buf, stat_T *stp);
|
||||
static int otherfile_buf(buf_T *buf, char_u *ffname);
|
||||
#endif
|
||||
#ifdef FEAT_TITLE
|
||||
static int ti_change(char_u *str, char_u **last);
|
||||
static int value_changed(char_u *str, char_u **last);
|
||||
#endif
|
||||
static int append_arg_number(win_T *wp, char_u *buf, int buflen, int add_file);
|
||||
static void free_buffer(buf_T *);
|
||||
@@ -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);
|
||||
|
||||
@@ -3545,20 +3549,18 @@ col_print(
|
||||
}
|
||||
|
||||
#if defined(FEAT_TITLE) || defined(PROTO)
|
||||
/*
|
||||
* put file name in title bar of window and in icon title
|
||||
*/
|
||||
|
||||
static char_u *lasttitle = NULL;
|
||||
static char_u *lasticon = NULL;
|
||||
|
||||
/*
|
||||
* Put the file name in the title bar and icon of the window.
|
||||
*/
|
||||
void
|
||||
maketitle(void)
|
||||
{
|
||||
char_u *p;
|
||||
char_u *t_str = NULL;
|
||||
char_u *i_name;
|
||||
char_u *i_str = NULL;
|
||||
char_u *title_str = NULL;
|
||||
char_u *icon_str = NULL;
|
||||
int maxlen = 0;
|
||||
int len;
|
||||
int mustset;
|
||||
@@ -3578,7 +3580,7 @@ maketitle(void)
|
||||
|
||||
need_maketitle = FALSE;
|
||||
if (!p_title && !p_icon && lasttitle == NULL && lasticon == NULL)
|
||||
return;
|
||||
return; // nothing to do
|
||||
|
||||
if (p_title)
|
||||
{
|
||||
@@ -3589,7 +3591,7 @@ maketitle(void)
|
||||
maxlen = 10;
|
||||
}
|
||||
|
||||
t_str = buf;
|
||||
title_str = buf;
|
||||
if (*p_titlestring != NUL)
|
||||
{
|
||||
#ifdef FEAT_STL_OPT
|
||||
@@ -3602,7 +3604,7 @@ maketitle(void)
|
||||
use_sandbox = was_set_insecurely((char_u *)"titlestring", 0);
|
||||
# endif
|
||||
called_emsg = FALSE;
|
||||
build_stl_str_hl(curwin, t_str, sizeof(buf),
|
||||
build_stl_str_hl(curwin, title_str, sizeof(buf),
|
||||
p_titlestring, use_sandbox,
|
||||
0, maxlen, NULL, NULL);
|
||||
if (called_emsg)
|
||||
@@ -3612,7 +3614,7 @@ maketitle(void)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
t_str = p_titlestring;
|
||||
title_str = p_titlestring;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3720,11 +3722,11 @@ maketitle(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
mustset = ti_change(t_str, &lasttitle);
|
||||
mustset = value_changed(title_str, &lasttitle);
|
||||
|
||||
if (p_icon)
|
||||
{
|
||||
i_str = buf;
|
||||
icon_str = buf;
|
||||
if (*p_iconstring != NUL)
|
||||
{
|
||||
#ifdef FEAT_STL_OPT
|
||||
@@ -3737,7 +3739,7 @@ maketitle(void)
|
||||
use_sandbox = was_set_insecurely((char_u *)"iconstring", 0);
|
||||
# endif
|
||||
called_emsg = FALSE;
|
||||
build_stl_str_hl(curwin, i_str, sizeof(buf),
|
||||
build_stl_str_hl(curwin, icon_str, sizeof(buf),
|
||||
p_iconstring, use_sandbox,
|
||||
0, 0, NULL, NULL);
|
||||
if (called_emsg)
|
||||
@@ -3747,32 +3749,32 @@ maketitle(void)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
i_str = p_iconstring;
|
||||
icon_str = p_iconstring;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (buf_spname(curbuf) != NULL)
|
||||
i_name = buf_spname(curbuf);
|
||||
p = buf_spname(curbuf);
|
||||
else /* use file name only in icon */
|
||||
i_name = gettail(curbuf->b_ffname);
|
||||
*i_str = NUL;
|
||||
p = gettail(curbuf->b_ffname);
|
||||
*icon_str = NUL;
|
||||
/* Truncate name at 100 bytes. */
|
||||
len = (int)STRLEN(i_name);
|
||||
len = (int)STRLEN(p);
|
||||
if (len > 100)
|
||||
{
|
||||
len -= 100;
|
||||
#ifdef FEAT_MBYTE
|
||||
if (has_mbyte)
|
||||
len += (*mb_tail_off)(i_name, i_name + len) + 1;
|
||||
len += (*mb_tail_off)(p, p + len) + 1;
|
||||
#endif
|
||||
i_name += len;
|
||||
p += len;
|
||||
}
|
||||
STRCPY(i_str, i_name);
|
||||
trans_characters(i_str, IOSIZE);
|
||||
STRCPY(icon_str, p);
|
||||
trans_characters(icon_str, IOSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
mustset |= ti_change(i_str, &lasticon);
|
||||
mustset |= value_changed(icon_str, &lasticon);
|
||||
|
||||
if (mustset)
|
||||
resettitle();
|
||||
@@ -3781,20 +3783,25 @@ maketitle(void)
|
||||
/*
|
||||
* Used for title and icon: Check if "str" differs from "*last". Set "*last"
|
||||
* from "str" if it does.
|
||||
* Return TRUE when "*last" changed.
|
||||
* Return TRUE if resettitle() is to be called.
|
||||
*/
|
||||
static int
|
||||
ti_change(char_u *str, char_u **last)
|
||||
value_changed(char_u *str, char_u **last)
|
||||
{
|
||||
if ((str == NULL) != (*last == NULL)
|
||||
|| (str != NULL && *last != NULL && STRCMP(str, *last) != 0))
|
||||
{
|
||||
vim_free(*last);
|
||||
if (str == NULL)
|
||||
{
|
||||
*last = NULL;
|
||||
mch_restore_title(last == &lasttitle ? 1 : 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
*last = vim_strsave(str);
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -5643,6 +5650,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 +5668,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 +5678,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 +5746,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]");
|
||||
}
|
||||
|
||||
|
||||
+64
-2
@@ -5567,7 +5567,11 @@ job_check_ended(void)
|
||||
* Returns NULL when out of memory.
|
||||
*/
|
||||
job_T *
|
||||
job_start(typval_T *argvars, char **argv_arg, jobopt_T *opt_arg)
|
||||
job_start(
|
||||
typval_T *argvars,
|
||||
char **argv_arg,
|
||||
jobopt_T *opt_arg,
|
||||
int is_terminal UNUSED)
|
||||
{
|
||||
job_T *job;
|
||||
char_u *cmd = NULL;
|
||||
@@ -5721,7 +5725,7 @@ job_start(typval_T *argvars, char **argv_arg, jobopt_T *opt_arg)
|
||||
ch_log(NULL, "Starting job: %s", (char *)ga.ga_data);
|
||||
ga_clear(&ga);
|
||||
}
|
||||
mch_job_start(argv, job, &opt);
|
||||
mch_job_start(argv, job, &opt, is_terminal);
|
||||
#else
|
||||
ch_log(NULL, "Starting job: %s", (char *)cmd);
|
||||
mch_job_start((char *)cmd, job, &opt);
|
||||
@@ -5878,6 +5882,64 @@ 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 || *curbuf->b_prompt_callback == NUL)
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE when the interrupt callback was invoked.
|
||||
*/
|
||||
int
|
||||
invoke_prompt_interrupt(void)
|
||||
{
|
||||
typval_T rettv;
|
||||
int dummy;
|
||||
typval_T argv[1];
|
||||
|
||||
if (curbuf->b_prompt_interrupt == NULL
|
||||
|| *curbuf->b_prompt_interrupt == NUL)
|
||||
return FALSE;
|
||||
argv[0].v_type = VAR_UNKNOWN;
|
||||
|
||||
got_int = FALSE; // don't skip executing commands
|
||||
call_func(curbuf->b_prompt_interrupt,
|
||||
(int)STRLEN(curbuf->b_prompt_interrupt),
|
||||
&rettv, 0, argv, NULL, 0L, 0L, &dummy, TRUE,
|
||||
curbuf->b_prompt_int_partial, NULL);
|
||||
clear_tv(&rettv);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
# ifdef FEAT_GUI_MACVIM
|
||||
void
|
||||
job_cleanup_all(void)
|
||||
|
||||
+9
-6
@@ -1928,8 +1928,8 @@ vim_str2nr(
|
||||
while ('0' <= *ptr && *ptr <= '1')
|
||||
{
|
||||
/* avoid ubsan error for overflow */
|
||||
if (un < UVARNUM_MAX / 2)
|
||||
un = 2 * un + (unsigned long)(*ptr - '0');
|
||||
if (un <= UVARNUM_MAX / 2)
|
||||
un = 2 * un + (uvarnumber_T)(*ptr - '0');
|
||||
else
|
||||
un = UVARNUM_MAX;
|
||||
++ptr;
|
||||
@@ -1943,7 +1943,7 @@ vim_str2nr(
|
||||
while ('0' <= *ptr && *ptr <= '7')
|
||||
{
|
||||
/* avoid ubsan error for overflow */
|
||||
if (un < UVARNUM_MAX / 8)
|
||||
if (un <= UVARNUM_MAX / 8)
|
||||
un = 8 * un + (uvarnumber_T)(*ptr - '0');
|
||||
else
|
||||
un = UVARNUM_MAX;
|
||||
@@ -1960,7 +1960,7 @@ vim_str2nr(
|
||||
while (vim_isxdigit(*ptr))
|
||||
{
|
||||
/* avoid ubsan error for overflow */
|
||||
if (un < UVARNUM_MAX / 16)
|
||||
if (un <= UVARNUM_MAX / 16)
|
||||
un = 16 * un + (uvarnumber_T)hex2nr(*ptr);
|
||||
else
|
||||
un = UVARNUM_MAX;
|
||||
@@ -1974,9 +1974,12 @@ vim_str2nr(
|
||||
/* decimal */
|
||||
while (VIM_ISDIGIT(*ptr))
|
||||
{
|
||||
uvarnumber_T digit = (uvarnumber_T)(*ptr - '0');
|
||||
|
||||
/* avoid ubsan error for overflow */
|
||||
if (un < UVARNUM_MAX / 10)
|
||||
un = 10 * un + (uvarnumber_T)(*ptr - '0');
|
||||
if (un < UVARNUM_MAX / 10
|
||||
|| (un == UVARNUM_MAX / 10 && digit <= UVARNUM_MAX % 10))
|
||||
un = 10 * un + digit;
|
||||
else
|
||||
un = UVARNUM_MAX;
|
||||
++ptr;
|
||||
|
||||
@@ -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
|
||||
|
||||
+25
-2
@@ -1979,14 +1979,37 @@ do_digraph(int c)
|
||||
* If not found return NULL.
|
||||
*/
|
||||
char_u *
|
||||
get_digraph_for_char(val)
|
||||
int val;
|
||||
get_digraph_for_char(int val_arg)
|
||||
{
|
||||
int val = val_arg;
|
||||
int i;
|
||||
int use_defaults;
|
||||
digr_T *dp;
|
||||
static char_u r[3];
|
||||
|
||||
#if defined(FEAT_MBYTE) && defined(USE_UNICODE_DIGRAPHS)
|
||||
if (!enc_utf8)
|
||||
{
|
||||
char_u buf[6], *to;
|
||||
vimconv_T vc;
|
||||
|
||||
// convert the character from 'encoding' to Unicode
|
||||
i = mb_char2bytes(val, buf);
|
||||
vc.vc_type = CONV_NONE;
|
||||
if (convert_setup(&vc, p_enc, (char_u *)"utf-8") == OK)
|
||||
{
|
||||
vc.vc_fail = TRUE;
|
||||
to = string_convert(&vc, buf, &i);
|
||||
if (to != NULL)
|
||||
{
|
||||
val = utf_ptr2char(to);
|
||||
vim_free(to);
|
||||
}
|
||||
(void)convert_setup(&vc, NULL, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (use_defaults = 0; use_defaults <= 1; use_defaults++)
|
||||
{
|
||||
if (use_defaults == 0)
|
||||
|
||||
+154
-8
@@ -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. */
|
||||
@@ -994,6 +1016,19 @@ edit(
|
||||
goto doESCkey;
|
||||
}
|
||||
#endif
|
||||
#ifdef FEAT_JOB_CHANNEL
|
||||
if (c == Ctrl_C && bt_prompt(curbuf))
|
||||
{
|
||||
if (invoke_prompt_interrupt())
|
||||
{
|
||||
if (!bt_prompt(curbuf))
|
||||
// buffer changed to a non-prompt buffer, get out of
|
||||
// Insert mode
|
||||
goto doESCkey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UNIX
|
||||
do_intr:
|
||||
@@ -1151,6 +1186,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 = 'A';
|
||||
nomove = TRUE;
|
||||
count = 0;
|
||||
goto doESCkey;
|
||||
}
|
||||
#endif
|
||||
did_backspace = ins_bs(c, BACKSPACE_WORD, &inserted_space);
|
||||
auto_format(FALSE, TRUE);
|
||||
break;
|
||||
@@ -1382,6 +1429,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 */
|
||||
@@ -1668,7 +1726,12 @@ ins_redraw(
|
||||
#endif
|
||||
)
|
||||
{
|
||||
aco_save_T aco;
|
||||
|
||||
// save and restore curwin and curbuf, in case the autocmd changes them
|
||||
aucmd_prepbuf(&aco, curbuf);
|
||||
apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf);
|
||||
aucmd_restbuf(&aco);
|
||||
curbuf->b_last_changedtick = CHANGEDTICK(curbuf);
|
||||
}
|
||||
|
||||
@@ -1680,7 +1743,12 @@ ins_redraw(
|
||||
&& curbuf->b_last_changedtick_pum != CHANGEDTICK(curbuf)
|
||||
&& pum_visible())
|
||||
{
|
||||
aco_save_T aco;
|
||||
|
||||
// save and restore curwin and curbuf, in case the autocmd changes them
|
||||
aucmd_prepbuf(&aco, curbuf);
|
||||
apply_autocmds(EVENT_TEXTCHANGEDP, NULL, NULL, FALSE, curbuf);
|
||||
aucmd_restbuf(&aco);
|
||||
curbuf->b_last_changedtick_pum = CHANGEDTICK(curbuf);
|
||||
}
|
||||
#endif
|
||||
@@ -1817,6 +1885,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 = (int)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 = (int)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().
|
||||
*/
|
||||
@@ -4103,7 +4238,7 @@ expand_by_function(
|
||||
{
|
||||
list_T *matchlist = NULL;
|
||||
dict_T *matchdict = NULL;
|
||||
char_u *args[2];
|
||||
typval_T args[3];
|
||||
char_u *funcname;
|
||||
pos_T pos;
|
||||
win_T *curwin_save;
|
||||
@@ -4115,15 +4250,18 @@ expand_by_function(
|
||||
return;
|
||||
|
||||
/* Call 'completefunc' to obtain the list of matches. */
|
||||
args[0] = (char_u *)"0";
|
||||
args[1] = base;
|
||||
args[0].v_type = VAR_NUMBER;
|
||||
args[0].vval.v_number = 0;
|
||||
args[1].v_type = VAR_STRING;
|
||||
args[1].vval.v_string = base != NULL ? base : (char_u *)"";
|
||||
args[2].v_type = VAR_UNKNOWN;
|
||||
|
||||
pos = curwin->w_cursor;
|
||||
curwin_save = curwin;
|
||||
curbuf_save = curbuf;
|
||||
|
||||
/* Call a function, which returns a list or dict. */
|
||||
if (call_vim_function(funcname, 2, args, FALSE, FALSE, &rettv) == OK)
|
||||
if (call_vim_function(funcname, 2, args, &rettv, FALSE) == OK)
|
||||
{
|
||||
switch (rettv.v_type)
|
||||
{
|
||||
@@ -5430,7 +5568,7 @@ ins_complete(int c, int enable_pum)
|
||||
* Call user defined function 'completefunc' with "a:findstart"
|
||||
* set to 1 to obtain the length of text to use for completion.
|
||||
*/
|
||||
char_u *args[2];
|
||||
typval_T args[3];
|
||||
int col;
|
||||
char_u *funcname;
|
||||
pos_T pos;
|
||||
@@ -5450,8 +5588,11 @@ ins_complete(int c, int enable_pum)
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
args[0] = (char_u *)"1";
|
||||
args[1] = NULL;
|
||||
args[0].v_type = VAR_NUMBER;
|
||||
args[0].vval.v_number = 1;
|
||||
args[1].v_type = VAR_STRING;
|
||||
args[1].vval.v_string = (char_u *)"";
|
||||
args[2].v_type = VAR_UNKNOWN;
|
||||
pos = curwin->w_cursor;
|
||||
curwin_save = curwin;
|
||||
curbuf_save = curbuf;
|
||||
@@ -9370,7 +9511,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 +9561,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))
|
||||
|
||||
+18
-60
@@ -1011,63 +1011,22 @@ eval_expr(char_u *arg, char_u **nextcmd)
|
||||
|
||||
/*
|
||||
* Call some Vim script function and return the result in "*rettv".
|
||||
* Uses argv[argc] for the function arguments. Only Number and String
|
||||
* arguments are currently supported.
|
||||
* Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc]
|
||||
* should have type VAR_UNKNOWN.
|
||||
* Returns OK or FAIL.
|
||||
*/
|
||||
int
|
||||
call_vim_function(
|
||||
char_u *func,
|
||||
int argc,
|
||||
char_u **argv,
|
||||
int safe, /* use the sandbox */
|
||||
int str_arg_only, /* all arguments are strings */
|
||||
typval_T *rettv)
|
||||
typval_T *argv,
|
||||
typval_T *rettv,
|
||||
int safe) /* use the sandbox */
|
||||
{
|
||||
typval_T *argvars;
|
||||
varnumber_T n;
|
||||
int len;
|
||||
int i;
|
||||
int doesrange;
|
||||
void *save_funccalp = NULL;
|
||||
int ret;
|
||||
|
||||
argvars = (typval_T *)alloc((unsigned)((argc + 1) * sizeof(typval_T)));
|
||||
if (argvars == NULL)
|
||||
return FAIL;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
/* Pass a NULL or empty argument as an empty string */
|
||||
if (argv[i] == NULL || *argv[i] == NUL)
|
||||
{
|
||||
argvars[i].v_type = VAR_STRING;
|
||||
argvars[i].vval.v_string = (char_u *)"";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str_arg_only)
|
||||
len = 0;
|
||||
else
|
||||
{
|
||||
/* Recognize a number argument, the others must be strings. A dash
|
||||
* is a string too. */
|
||||
vim_str2nr(argv[i], NULL, &len, STR2NR_ALL, &n, NULL, 0);
|
||||
if (len == 1 && *argv[i] == '-')
|
||||
len = 0;
|
||||
}
|
||||
if (len != 0 && len == (int)STRLEN(argv[i]))
|
||||
{
|
||||
argvars[i].v_type = VAR_NUMBER;
|
||||
argvars[i].vval.v_number = n;
|
||||
}
|
||||
else
|
||||
{
|
||||
argvars[i].v_type = VAR_STRING;
|
||||
argvars[i].vval.v_string = argv[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (safe)
|
||||
{
|
||||
save_funccalp = save_funccal();
|
||||
@@ -1075,7 +1034,7 @@ call_vim_function(
|
||||
}
|
||||
|
||||
rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
|
||||
ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars, NULL,
|
||||
ret = call_func(func, (int)STRLEN(func), rettv, argc, argv, NULL,
|
||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
||||
&doesrange, TRUE, NULL, NULL);
|
||||
if (safe)
|
||||
@@ -1083,7 +1042,6 @@ call_vim_function(
|
||||
--sandbox;
|
||||
restore_funccal(save_funccalp);
|
||||
}
|
||||
vim_free(argvars);
|
||||
|
||||
if (ret == FAIL)
|
||||
clear_tv(rettv);
|
||||
@@ -1094,20 +1052,20 @@ call_vim_function(
|
||||
/*
|
||||
* Call Vim script function "func" and return the result as a number.
|
||||
* Returns -1 when calling the function fails.
|
||||
* Uses argv[argc] for the function arguments.
|
||||
* Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc] should
|
||||
* have type VAR_UNKNOWN.
|
||||
*/
|
||||
varnumber_T
|
||||
call_func_retnr(
|
||||
char_u *func,
|
||||
int argc,
|
||||
char_u **argv,
|
||||
typval_T *argv,
|
||||
int safe) /* use the sandbox */
|
||||
{
|
||||
typval_T rettv;
|
||||
varnumber_T retval;
|
||||
|
||||
/* All arguments are passed as strings, no conversion to number. */
|
||||
if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
|
||||
if (call_vim_function(func, argc, argv, &rettv, safe) == FAIL)
|
||||
return -1;
|
||||
|
||||
retval = get_tv_number_chk(&rettv, NULL);
|
||||
@@ -1122,20 +1080,20 @@ call_func_retnr(
|
||||
/*
|
||||
* Call Vim script function "func" and return the result as a string.
|
||||
* Returns NULL when calling the function fails.
|
||||
* Uses argv[argc] for the function arguments.
|
||||
* Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc] should
|
||||
* have type VAR_UNKNOWN.
|
||||
*/
|
||||
void *
|
||||
call_func_retstr(
|
||||
char_u *func,
|
||||
int argc,
|
||||
char_u **argv,
|
||||
typval_T *argv,
|
||||
int safe) /* use the sandbox */
|
||||
{
|
||||
typval_T rettv;
|
||||
char_u *retval;
|
||||
|
||||
/* All arguments are passed as strings, no conversion to number. */
|
||||
if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
|
||||
if (call_vim_function(func, argc, argv, &rettv, safe) == FAIL)
|
||||
return NULL;
|
||||
|
||||
retval = vim_strsave(get_tv_string(&rettv));
|
||||
@@ -1146,20 +1104,20 @@ call_func_retstr(
|
||||
|
||||
/*
|
||||
* Call Vim script function "func" and return the result as a List.
|
||||
* Uses argv[argc] for the function arguments.
|
||||
* Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc] should
|
||||
* have type VAR_UNKNOWN.
|
||||
* Returns NULL when there is something wrong.
|
||||
*/
|
||||
void *
|
||||
call_func_retlist(
|
||||
char_u *func,
|
||||
int argc,
|
||||
char_u **argv,
|
||||
typval_T *argv,
|
||||
int safe) /* use the sandbox */
|
||||
{
|
||||
typval_T rettv;
|
||||
|
||||
/* All arguments are passed as strings, no conversion to number. */
|
||||
if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
|
||||
if (call_vim_function(func, argc, argv, &rettv, safe) == FAIL)
|
||||
return NULL;
|
||||
|
||||
if (rettv.v_type != VAR_LIST)
|
||||
|
||||
+370
-180
@@ -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,11 @@ 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_setinterrupt(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 +490,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 +579,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 +753,11 @@ 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_setinterrupt", 2, 2, f_prompt_setinterrupt},
|
||||
{"prompt_setprompt", 2, 2, f_prompt_setprompt},
|
||||
#endif
|
||||
{"pumvisible", 0, 0, f_pumvisible},
|
||||
#ifdef FEAT_PYTHON3
|
||||
{"py3eval", 1, 1, f_py3eval},
|
||||
@@ -1183,66 +1197,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 +2820,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 +4492,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
|
||||
*/
|
||||
@@ -7061,7 +7275,7 @@ f_job_start(typval_T *argvars, typval_T *rettv)
|
||||
rettv->v_type = VAR_JOB;
|
||||
if (check_restricted() || check_secure())
|
||||
return;
|
||||
rettv->vval.v_job = job_start(argvars, NULL, NULL);
|
||||
rettv->vval.v_job = job_start(argvars, NULL, NULL, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -8398,6 +8612,86 @@ 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_setinterrupt({buffer}, {callback})" function
|
||||
*/
|
||||
static void
|
||||
f_prompt_setinterrupt(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_interrupt, buf->b_prompt_int_partial);
|
||||
if (partial == NULL)
|
||||
buf->b_prompt_interrupt = vim_strsave(callback);
|
||||
else
|
||||
/* pointer into the partial */
|
||||
buf->b_prompt_interrupt = callback;
|
||||
buf->b_prompt_int_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 +10482,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 +10499,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 +10659,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);
|
||||
@@ -10495,6 +10679,7 @@ set_qf_ll_list(
|
||||
static char *e_invact = N_("E927: Invalid action: '%s'");
|
||||
char_u *act;
|
||||
int action = 0;
|
||||
static int recursive = 0;
|
||||
#endif
|
||||
|
||||
rettv->vval.v_number = -1;
|
||||
@@ -10502,6 +10687,8 @@ set_qf_ll_list(
|
||||
#ifdef FEAT_QUICKFIX
|
||||
if (list_arg->v_type != VAR_LIST)
|
||||
EMSG(_(e_listreq));
|
||||
else if (recursive != 0)
|
||||
EMSG(_(e_au_recursive));
|
||||
else
|
||||
{
|
||||
list_T *l = list_arg->vval.v_list;
|
||||
@@ -10536,9 +10723,12 @@ set_qf_ll_list(
|
||||
}
|
||||
}
|
||||
|
||||
++recursive;
|
||||
if (l != NULL && action && valid_dict && set_errorlist(wp, l, action,
|
||||
(char_u *)(wp == NULL ? ":setqflist()" : ":setloclist()"), d) == OK)
|
||||
(char_u *)(wp == NULL ? ":setqflist()" : ":setloclist()"),
|
||||
d) == OK)
|
||||
rettv->vval.v_number = 0;
|
||||
--recursive;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+10
-3
@@ -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;
|
||||
|
||||
+17
-3
@@ -4063,8 +4063,16 @@ set_one_cmd_context(
|
||||
case CMD_unlet:
|
||||
while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
|
||||
arg = xp->xp_pattern + 1;
|
||||
|
||||
xp->xp_context = EXPAND_USER_VARS;
|
||||
xp->xp_pattern = arg;
|
||||
|
||||
if (*xp->xp_pattern == '$')
|
||||
{
|
||||
xp->xp_context = EXPAND_ENV_VARS;
|
||||
++xp->xp_pattern;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CMD_function:
|
||||
@@ -5334,7 +5342,9 @@ get_bad_opt(char_u *p, exarg_T *eap)
|
||||
eap->bad_char = BAD_DROP;
|
||||
else if (MB_BYTE2LEN(*p) == 1 && p[1] == NUL)
|
||||
eap->bad_char = *p;
|
||||
return FAIL;
|
||||
else
|
||||
return FAIL;
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -7357,7 +7367,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++;
|
||||
@@ -11309,7 +11320,10 @@ makeopens(
|
||||
* winminheight and winminwidth need to be set to avoid an error if the
|
||||
* user has set winheight or winwidth.
|
||||
*/
|
||||
if (put_line(fd, "set winminheight=1 winheight=1 winminwidth=1 winwidth=1") == FAIL)
|
||||
if (put_line(fd, "set winminheight=0") == FAIL
|
||||
|| put_line(fd, "set winheight=1") == FAIL
|
||||
|| put_line(fd, "set winminwidth=0") == FAIL
|
||||
|| put_line(fd, "set winwidth=1") == FAIL)
|
||||
return FAIL;
|
||||
if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
+14
-9
@@ -5280,7 +5280,7 @@ expand_shellcmd(
|
||||
|
||||
|
||||
# if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL)
|
||||
static void * call_user_expand_func(void *(*user_expand_func)(char_u *, int, char_u **, int), expand_T *xp, int *num_file, char_u ***file);
|
||||
static void * call_user_expand_func(void *(*user_expand_func)(char_u *, int, typval_T *, int), expand_T *xp, int *num_file, char_u ***file);
|
||||
|
||||
/*
|
||||
* Call "user_expand_func()" to invoke a user defined Vim script function and
|
||||
@@ -5288,15 +5288,15 @@ static void * call_user_expand_func(void *(*user_expand_func)(char_u *, int, cha
|
||||
*/
|
||||
static void *
|
||||
call_user_expand_func(
|
||||
void *(*user_expand_func)(char_u *, int, char_u **, int),
|
||||
void *(*user_expand_func)(char_u *, int, typval_T *, int),
|
||||
expand_T *xp,
|
||||
int *num_file,
|
||||
char_u ***file)
|
||||
{
|
||||
int keep = 0;
|
||||
char_u num[50];
|
||||
char_u *args[3];
|
||||
typval_T args[4];
|
||||
int save_current_SID = current_SID;
|
||||
char_u *pat = NULL;
|
||||
void *ret;
|
||||
struct cmdline_info save_ccline;
|
||||
|
||||
@@ -5311,10 +5311,15 @@ call_user_expand_func(
|
||||
ccline.cmdbuff[ccline.cmdlen] = 0;
|
||||
}
|
||||
|
||||
args[0] = vim_strnsave(xp->xp_pattern, xp->xp_pattern_len);
|
||||
args[1] = xp->xp_line;
|
||||
sprintf((char *)num, "%d", xp->xp_col);
|
||||
args[2] = num;
|
||||
pat = vim_strnsave(xp->xp_pattern, xp->xp_pattern_len);
|
||||
|
||||
args[0].v_type = VAR_STRING;
|
||||
args[0].vval.v_string = pat;
|
||||
args[1].v_type = VAR_STRING;
|
||||
args[1].vval.v_string = xp->xp_line;
|
||||
args[2].v_type = VAR_NUMBER;
|
||||
args[2].vval.v_number = xp->xp_col;
|
||||
args[3].v_type = VAR_UNKNOWN;
|
||||
|
||||
/* Save the cmdline, we don't know what the function may do. */
|
||||
save_ccline = ccline;
|
||||
@@ -5329,7 +5334,7 @@ call_user_expand_func(
|
||||
if (ccline.cmdbuff != NULL)
|
||||
ccline.cmdbuff[ccline.cmdlen] = keep;
|
||||
|
||||
vim_free(args[0]);
|
||||
vim_free(pat);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -2856,6 +2856,11 @@ vgetorpeek(int advance)
|
||||
/*
|
||||
* get a character: 3. from the user - get it
|
||||
*/
|
||||
if (typebuf.tb_len == 0)
|
||||
// timedout may have been set while waiting for a mapping
|
||||
// that has a <Nop> RHS.
|
||||
timedout = FALSE;
|
||||
|
||||
wait_tb_len = typebuf.tb_len;
|
||||
c = inchar(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_len,
|
||||
typebuf.tb_buflen - typebuf.tb_off - typebuf.tb_len - 1,
|
||||
|
||||
+9
-1
@@ -3372,8 +3372,9 @@ mch_print_start_line(int margin, int page_line)
|
||||
}
|
||||
|
||||
int
|
||||
mch_print_text_out(char_u *p, int len UNUSED)
|
||||
mch_print_text_out(char_u *textp, int len UNUSED)
|
||||
{
|
||||
char_u *p = textp;
|
||||
int need_break;
|
||||
char_u ch;
|
||||
char_u ch_buff[8];
|
||||
@@ -3508,8 +3509,15 @@ mch_print_text_out(char_u *p, int len UNUSED)
|
||||
|
||||
#ifdef FEAT_MBYTE
|
||||
if (prt_do_conv)
|
||||
{
|
||||
/* Convert from multi-byte to 8-bit encoding */
|
||||
tofree = p = string_convert(&prt_conv, p, &len);
|
||||
if (p == NULL)
|
||||
{
|
||||
p = (char_u *)"";
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (prt_out_mbyte)
|
||||
{
|
||||
|
||||
+13
-2
@@ -3836,9 +3836,20 @@ get_firstwin(TabPageObject *tabObject)
|
||||
else
|
||||
return firstwin;
|
||||
}
|
||||
|
||||
// Use the same order as in the WindowAttr() function.
|
||||
static char *WindowAttrs[] = {
|
||||
"buffer", "cursor", "height", "vars", "options", "number", "row", "col",
|
||||
"tabpage", "valid",
|
||||
"buffer",
|
||||
"cursor",
|
||||
"height",
|
||||
"row",
|
||||
"width",
|
||||
"col",
|
||||
"vars",
|
||||
"options",
|
||||
"number",
|
||||
"tabpage",
|
||||
"valid",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
+4
-5
@@ -4799,12 +4799,11 @@ iconv_end(void)
|
||||
# endif
|
||||
call_imactivatefunc(int active)
|
||||
{
|
||||
char_u *argv[1];
|
||||
typval_T argv[2];
|
||||
|
||||
if (active)
|
||||
argv[0] = (char_u *)"1";
|
||||
else
|
||||
argv[0] = (char_u *)"0";
|
||||
argv[0].v_type = VAR_NUMBER;
|
||||
argv[0].vval.v_number = active ? 1 : 0;
|
||||
argv[1].v_type = VAR_UNKNOWN;
|
||||
(void)call_func_retnr(p_imaf, 1, argv, FALSE);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
|
||||
+71
-4
@@ -2219,7 +2219,7 @@ op_colon(oparg_T *oap)
|
||||
op_function(oparg_T *oap UNUSED)
|
||||
{
|
||||
#ifdef FEAT_EVAL
|
||||
char_u *(argv[1]);
|
||||
typval_T argv[2];
|
||||
# ifdef FEAT_VIRTUALEDIT
|
||||
int save_virtual_op = virtual_op;
|
||||
# endif
|
||||
@@ -2235,12 +2235,14 @@ op_function(oparg_T *oap UNUSED)
|
||||
/* Exclude the end position. */
|
||||
decl(&curbuf->b_op_end);
|
||||
|
||||
argv[0].v_type = VAR_STRING;
|
||||
if (oap->block_mode)
|
||||
argv[0] = (char_u *)"block";
|
||||
argv[0].vval.v_string = (char_u *)"block";
|
||||
else if (oap->motion_type == MLINE)
|
||||
argv[0] = (char_u *)"line";
|
||||
argv[0].vval.v_string = (char_u *)"line";
|
||||
else
|
||||
argv[0] = (char_u *)"char";
|
||||
argv[0].vval.v_string = (char_u *)"char";
|
||||
argv[1].v_type = VAR_UNKNOWN;
|
||||
|
||||
# ifdef FEAT_VIRTUALEDIT
|
||||
/* Reset virtual_op so that 'virtualedit' can be changed in the
|
||||
@@ -4184,6 +4186,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 +6253,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 +7023,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 +7047,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 +7529,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 +8642,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 +8666,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 +9514,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 +9645,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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+35
-39
@@ -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
|
||||
@@ -3339,9 +3339,6 @@ static char_u *illegal_char(char_u *, int);
|
||||
#ifdef FEAT_CMDWIN
|
||||
static char_u *check_cedit(void);
|
||||
#endif
|
||||
#ifdef FEAT_TITLE
|
||||
static void did_set_title(int icon);
|
||||
#endif
|
||||
static char_u *option_expand(int opt_idx, char_u *val);
|
||||
static void didset_options(void);
|
||||
static void didset_options2(void);
|
||||
@@ -5478,27 +5475,14 @@ check_cedit(void)
|
||||
* the old value back.
|
||||
*/
|
||||
static void
|
||||
did_set_title(
|
||||
int icon) /* Did set icon instead of title */
|
||||
did_set_title(void)
|
||||
{
|
||||
if (starting != NO_SCREEN
|
||||
#ifdef FEAT_GUI
|
||||
&& !gui.starting
|
||||
#endif
|
||||
)
|
||||
{
|
||||
maketitle();
|
||||
if (icon)
|
||||
{
|
||||
if (!p_icon)
|
||||
mch_restore_title(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!p_title)
|
||||
mch_restore_title(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6153,7 +6137,7 @@ did_set_string_option(
|
||||
/* set when changing an option that only requires a redraw in the GUI */
|
||||
int redraw_gui_only = FALSE;
|
||||
#endif
|
||||
int ft_changed = FALSE;
|
||||
int value_changed = FALSE;
|
||||
#if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS)
|
||||
int did_swaptcap = FALSE;
|
||||
#endif
|
||||
@@ -7062,8 +7046,7 @@ did_set_string_option(
|
||||
else
|
||||
stl_syntax &= ~flagval;
|
||||
# endif
|
||||
did_set_title(varp == &p_iconstring);
|
||||
|
||||
did_set_title();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -7577,7 +7560,7 @@ did_set_string_option(
|
||||
if (!valid_filetype(*varp))
|
||||
errmsg = e_invarg;
|
||||
else
|
||||
ft_changed = STRCMP(oldval, *varp) != 0;
|
||||
value_changed = STRCMP(oldval, *varp) != 0;
|
||||
}
|
||||
|
||||
#ifdef FEAT_SYN_HL
|
||||
@@ -7585,6 +7568,8 @@ did_set_string_option(
|
||||
{
|
||||
if (!valid_filetype(*varp))
|
||||
errmsg = e_invarg;
|
||||
else
|
||||
value_changed = STRCMP(oldval, *varp) != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -7705,8 +7690,14 @@ did_set_string_option(
|
||||
/* When 'syntax' is set, load the syntax of that name */
|
||||
if (varp == &(curbuf->b_p_syn))
|
||||
{
|
||||
apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
|
||||
curbuf->b_fname, TRUE, curbuf);
|
||||
static int syn_recursive = 0;
|
||||
|
||||
++syn_recursive;
|
||||
// Only pass TRUE for "force" when the value changed or not used
|
||||
// recursively, to avoid endless recurrence.
|
||||
apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, curbuf->b_fname,
|
||||
value_changed || syn_recursive == 1, curbuf);
|
||||
--syn_recursive;
|
||||
}
|
||||
#endif
|
||||
else if (varp == &(curbuf->b_p_ft))
|
||||
@@ -7714,11 +7705,17 @@ did_set_string_option(
|
||||
/* 'filetype' is set, trigger the FileType autocommand.
|
||||
* Skip this when called from a modeline and the filetype was
|
||||
* already set to this value. */
|
||||
if (!(opt_flags & OPT_MODELINE) || ft_changed)
|
||||
if (!(opt_flags & OPT_MODELINE) || value_changed)
|
||||
{
|
||||
static int ft_recursive = 0;
|
||||
|
||||
++ft_recursive;
|
||||
did_filetype = TRUE;
|
||||
apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft,
|
||||
curbuf->b_fname, TRUE, curbuf);
|
||||
// Only pass TRUE for "force" when the value changed or not
|
||||
// used recursively, to avoid endless recurrence.
|
||||
apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname,
|
||||
value_changed || ft_recursive == 1, curbuf);
|
||||
--ft_recursive;
|
||||
/* Just in case the old "curbuf" is now invalid. */
|
||||
if (varp != &(curbuf->b_p_ft))
|
||||
varp = NULL;
|
||||
@@ -8569,14 +8566,9 @@ set_bool_option(
|
||||
|
||||
#ifdef FEAT_TITLE
|
||||
/* when 'title' changed, may need to change the title; same for 'icon' */
|
||||
else if ((int *)varp == &p_title)
|
||||
else if ((int *)varp == &p_title || (int *)varp == &p_icon)
|
||||
{
|
||||
did_set_title(FALSE);
|
||||
}
|
||||
|
||||
else if ((int *)varp == &p_icon)
|
||||
{
|
||||
did_set_title(TRUE);
|
||||
did_set_title();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -8967,6 +8959,7 @@ set_num_option(
|
||||
*/
|
||||
if (pp == &p_wh || pp == &p_hh)
|
||||
{
|
||||
// 'winheight' and 'helpheight'
|
||||
if (p_wh < 1)
|
||||
{
|
||||
errmsg = e_positive;
|
||||
@@ -8992,10 +8985,9 @@ set_num_option(
|
||||
win_setheight((int)p_hh);
|
||||
}
|
||||
}
|
||||
|
||||
/* 'winminheight' */
|
||||
else if (pp == &p_wmh)
|
||||
{
|
||||
// 'winminheight'
|
||||
if (p_wmh < 0)
|
||||
{
|
||||
errmsg = e_positive;
|
||||
@@ -9010,6 +9002,7 @@ set_num_option(
|
||||
}
|
||||
else if (pp == &p_wiw)
|
||||
{
|
||||
// 'winwidth'
|
||||
if (p_wiw < 1)
|
||||
{
|
||||
errmsg = e_positive;
|
||||
@@ -9025,10 +9018,9 @@ set_num_option(
|
||||
if (!ONE_WINDOW && curwin->w_width < p_wiw)
|
||||
win_setwidth((int)p_wiw);
|
||||
}
|
||||
|
||||
/* 'winminwidth' */
|
||||
else if (pp == &p_wmw)
|
||||
{
|
||||
// 'winminwidth'
|
||||
if (p_wmw < 0)
|
||||
{
|
||||
errmsg = e_positive;
|
||||
@@ -9039,7 +9031,7 @@ set_num_option(
|
||||
errmsg = e_winwidth;
|
||||
p_wmw = p_wiw;
|
||||
}
|
||||
win_setminheight();
|
||||
win_setminwidth();
|
||||
}
|
||||
|
||||
/* (re)set last window status line */
|
||||
@@ -12655,6 +12647,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;
|
||||
|
||||
+21
-2
@@ -63,8 +63,13 @@ clip_mch_request_selection(VimClipboard *cbd)
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSPasteboard *pb = [NSPasteboard generalPasteboard];
|
||||
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
|
||||
NSArray *supportedTypes = [NSArray arrayWithObjects:VimPboardType,
|
||||
NSPasteboardTypeString, nil];
|
||||
#else
|
||||
NSArray *supportedTypes = [NSArray arrayWithObjects:VimPboardType,
|
||||
NSStringPboardType, nil];
|
||||
#endif
|
||||
NSString *bestType = [pb availableTypeFromArray:supportedTypes];
|
||||
if (!bestType) goto releasepool;
|
||||
|
||||
@@ -76,7 +81,7 @@ clip_mch_request_selection(VimClipboard *cbd)
|
||||
/* This type should consist of an array with two objects:
|
||||
* 1. motion type (NSNumber)
|
||||
* 2. text (NSString)
|
||||
* If this is not the case we fall back on using NSStringPboardType.
|
||||
* If this is not the case we fall back on using NSPasteboardTypeString.
|
||||
*/
|
||||
id plist = [pb propertyListForType:VimPboardType];
|
||||
if ([plist isKindOfClass:[NSArray class]] && [plist count] == 2)
|
||||
@@ -92,10 +97,15 @@ clip_mch_request_selection(VimClipboard *cbd)
|
||||
|
||||
if (!string)
|
||||
{
|
||||
/* Use NSStringPboardType. The motion type is detected automatically.
|
||||
/* Use NSPasteboardTypeString. The motion type is detected automatically.
|
||||
*/
|
||||
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
|
||||
NSMutableString *mstring =
|
||||
[[pb stringForType:NSPasteboardTypeString] mutableCopy];
|
||||
#else
|
||||
NSMutableString *mstring =
|
||||
[[pb stringForType:NSStringPboardType] mutableCopy];
|
||||
#endif
|
||||
if (!mstring) goto releasepool;
|
||||
|
||||
/* Replace unrecognized end-of-line sequences with \x0a (line feed). */
|
||||
@@ -178,15 +188,24 @@ clip_mch_set_selection(VimClipboard *cbd)
|
||||
|
||||
/* See clip_mch_request_selection() for info on pasteboard types. */
|
||||
NSPasteboard *pb = [NSPasteboard generalPasteboard];
|
||||
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
|
||||
NSArray *supportedTypes = [NSArray arrayWithObjects:VimPboardType,
|
||||
NSPasteboardTypeString, nil];
|
||||
#else
|
||||
NSArray *supportedTypes = [NSArray arrayWithObjects:VimPboardType,
|
||||
NSStringPboardType, nil];
|
||||
#endif
|
||||
[pb declareTypes:supportedTypes owner:nil];
|
||||
|
||||
NSNumber *motion = [NSNumber numberWithInt:motion_type];
|
||||
NSArray *plist = [NSArray arrayWithObjects:motion, string, nil];
|
||||
[pb setPropertyList:plist forType:VimPboardType];
|
||||
|
||||
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
|
||||
[pb setString:string forType:NSPasteboardTypeString];
|
||||
#else
|
||||
[pb setString:string forType:NSStringPboardType];
|
||||
#endif
|
||||
|
||||
[string release];
|
||||
}
|
||||
|
||||
+30
-7
@@ -4165,7 +4165,11 @@ wait4pid(pid_t child, waitstatus *status)
|
||||
* Set the environment for a child process.
|
||||
*/
|
||||
static void
|
||||
set_child_environment(long rows, long columns, char *term)
|
||||
set_child_environment(
|
||||
long rows,
|
||||
long columns,
|
||||
char *term,
|
||||
int is_terminal UNUSED)
|
||||
{
|
||||
# ifdef HAVE_SETENV
|
||||
char envbuf[50];
|
||||
@@ -4175,6 +4179,9 @@ set_child_environment(long rows, long columns, char *term)
|
||||
static char envbuf_Lines[20];
|
||||
static char envbuf_Columns[20];
|
||||
static char envbuf_Colors[20];
|
||||
# ifdef FEAT_TERMINAL
|
||||
static char envbuf_Version[20];
|
||||
# endif
|
||||
# ifdef FEAT_CLIENTSERVER
|
||||
static char envbuf_Servername[60];
|
||||
# endif
|
||||
@@ -4195,6 +4202,13 @@ set_child_environment(long rows, long columns, char *term)
|
||||
setenv("COLUMNS", (char *)envbuf, 1);
|
||||
sprintf((char *)envbuf, "%ld", colors);
|
||||
setenv("COLORS", (char *)envbuf, 1);
|
||||
# ifdef FEAT_TERMINAL
|
||||
if (is_terminal)
|
||||
{
|
||||
sprintf((char *)envbuf, "%ld", (long)get_vim_var_nr(VV_VERSION));
|
||||
setenv("VIM_TERMINAL", (char *)envbuf, 1);
|
||||
}
|
||||
# endif
|
||||
# ifdef FEAT_CLIENTSERVER
|
||||
setenv("VIM_SERVERNAME", serverName == NULL ? "" : (char *)serverName, 1);
|
||||
# endif
|
||||
@@ -4215,6 +4229,14 @@ set_child_environment(long rows, long columns, char *term)
|
||||
putenv(envbuf_Columns);
|
||||
vim_snprintf(envbuf_Colors, sizeof(envbuf_Colors), "COLORS=%ld", colors);
|
||||
putenv(envbuf_Colors);
|
||||
# ifdef FEAT_TERMINAL
|
||||
if (is_terminal)
|
||||
{
|
||||
vim_snprintf(envbuf_Version, sizeof(envbuf_Version),
|
||||
"VIM_TERMINAL=%ld", (long)get_vim_var_nr(VV_VERSION));
|
||||
putenv(envbuf_Version);
|
||||
}
|
||||
# endif
|
||||
# ifdef FEAT_CLIENTSERVER
|
||||
vim_snprintf(envbuf_Servername, sizeof(envbuf_Servername),
|
||||
"VIM_SERVERNAME=%s", serverName == NULL ? "" : (char *)serverName);
|
||||
@@ -4224,9 +4246,9 @@ set_child_environment(long rows, long columns, char *term)
|
||||
}
|
||||
|
||||
static void
|
||||
set_default_child_environment(void)
|
||||
set_default_child_environment(int is_terminal)
|
||||
{
|
||||
set_child_environment(Rows, Columns, "dumb");
|
||||
set_child_environment(Rows, Columns, "dumb", is_terminal);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -4701,7 +4723,7 @@ mch_call_shell_fork(
|
||||
# endif
|
||||
}
|
||||
# endif
|
||||
set_default_child_environment();
|
||||
set_default_child_environment(FALSE);
|
||||
|
||||
/*
|
||||
* stderr is only redirected when using the GUI, so that a
|
||||
@@ -5383,7 +5405,7 @@ mch_call_shell(
|
||||
|
||||
#if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
|
||||
void
|
||||
mch_job_start(char **argv, job_T *job, jobopt_T *options)
|
||||
mch_job_start(char **argv, job_T *job, jobopt_T *options, int is_terminal)
|
||||
{
|
||||
pid_t pid;
|
||||
int fd_in[2] = {-1, -1}; /* for stdin */
|
||||
@@ -5531,11 +5553,12 @@ mch_job_start(char **argv, job_T *job, jobopt_T *options)
|
||||
set_child_environment(
|
||||
(long)options->jo_term_rows,
|
||||
(long)options->jo_term_cols,
|
||||
term);
|
||||
term,
|
||||
is_terminal);
|
||||
}
|
||||
else
|
||||
# endif
|
||||
set_default_child_environment();
|
||||
set_default_child_environment(is_terminal);
|
||||
|
||||
if (options->jo_env != NULL)
|
||||
{
|
||||
|
||||
+35
-6
@@ -5275,22 +5275,51 @@ win32_build_env(dict_T *env, garray_T *gap, int is_terminal)
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef FEAT_CLIENTSERVER
|
||||
if (is_terminal)
|
||||
# if defined(FEAT_CLIENTSERVER) || defined(FEAT_TERMINAL)
|
||||
{
|
||||
# ifdef FEAT_CLIENTSERVER
|
||||
char_u *servername = get_vim_var_str(VV_SEND_SERVER);
|
||||
size_t lval = STRLEN(servername);
|
||||
size_t n;
|
||||
size_t servername_len = STRLEN(servername);
|
||||
# endif
|
||||
# ifdef FEAT_TERMINAL
|
||||
char_u *version = get_vim_var_str(VV_VERSION);
|
||||
size_t version_len = STRLEN(version);
|
||||
# endif
|
||||
// size of "VIM_SERVERNAME=" and value,
|
||||
// plus "VIM_TERMINAL=" and value,
|
||||
// plus two terminating NULs
|
||||
size_t n = 0
|
||||
# ifdef FEAT_CLIENTSERVER
|
||||
+ 15 + servername_len
|
||||
# endif
|
||||
# ifdef FEAT_TERMINAL
|
||||
+ 13 + version_len + 2
|
||||
# endif
|
||||
;
|
||||
|
||||
if (ga_grow(gap, (int)(14 + lval + 2)) == OK)
|
||||
if (ga_grow(gap, (int)n) == OK)
|
||||
{
|
||||
# ifdef FEAT_CLIENTSERVER
|
||||
for (n = 0; n < 15; n++)
|
||||
*((WCHAR*)gap->ga_data + gap->ga_len++) =
|
||||
(WCHAR)"VIM_SERVERNAME="[n];
|
||||
for (n = 0; n < lval; n++)
|
||||
for (n = 0; n < servername_len; n++)
|
||||
*((WCHAR*)gap->ga_data + gap->ga_len++) =
|
||||
(WCHAR)servername[n];
|
||||
*((WCHAR*)gap->ga_data + gap->ga_len++) = L'\0';
|
||||
# endif
|
||||
# ifdef FEAT_TERMINAL
|
||||
if (is_terminal)
|
||||
{
|
||||
for (n = 0; n < 13; n++)
|
||||
*((WCHAR*)gap->ga_data + gap->ga_len++) =
|
||||
(WCHAR)"VIM_TERMINAL="[n];
|
||||
for (n = 0; n < version_len; n++)
|
||||
*((WCHAR*)gap->ga_data + gap->ga_len++) =
|
||||
(WCHAR)version[n];
|
||||
*((WCHAR*)gap->ga_data + gap->ga_len++) = L'\0';
|
||||
}
|
||||
# endif
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
+64
-11
@@ -29,6 +29,13 @@ static int pum_scrollbar; /* TRUE when scrollbar present */
|
||||
static int pum_row; /* top row of pum */
|
||||
static int pum_col; /* left column of pum */
|
||||
|
||||
static win_T *pum_window = NULL;
|
||||
static int pum_win_row;
|
||||
static int pum_win_height;
|
||||
static int pum_win_col;
|
||||
static int pum_win_wcol;
|
||||
static int pum_win_width;
|
||||
|
||||
static int pum_do_redraw = FALSE; /* do redraw anyway */
|
||||
|
||||
static int pum_set_selected(int n, int repeat);
|
||||
@@ -81,7 +88,6 @@ pum_display(
|
||||
{
|
||||
int def_width;
|
||||
int max_width;
|
||||
int row;
|
||||
int context_lines;
|
||||
int cursor_col;
|
||||
int above_row;
|
||||
@@ -103,7 +109,14 @@ pum_display(
|
||||
validate_cursor_col();
|
||||
pum_array = NULL;
|
||||
|
||||
row = curwin->w_wrow + W_WINROW(curwin);
|
||||
// Remember the essential parts of the window position and size, so we
|
||||
// can decide when to reposition the popup menu.
|
||||
pum_window = curwin;
|
||||
pum_win_row = curwin->w_wrow + W_WINROW(curwin);
|
||||
pum_win_height = curwin->w_height;
|
||||
pum_win_col = curwin->w_wincol;
|
||||
pum_win_wcol = curwin->w_wcol;
|
||||
pum_win_width = curwin->w_width;
|
||||
|
||||
#if defined(FEAT_QUICKFIX)
|
||||
FOR_ALL_WINDOWS(pvwin)
|
||||
@@ -128,12 +141,12 @@ pum_display(
|
||||
if (p_ph > 0 && pum_height > p_ph)
|
||||
pum_height = p_ph;
|
||||
|
||||
/* Put the pum below "row" if possible. If there are few lines decide
|
||||
/* Put the pum below "pum_win_row" if possible. If there are few lines decide
|
||||
* on where there is more room. */
|
||||
if (row + 2 >= below_row - pum_height
|
||||
&& row - above_row > (below_row - above_row) / 2)
|
||||
if (pum_win_row + 2 >= below_row - pum_height
|
||||
&& pum_win_row - above_row > (below_row - above_row) / 2)
|
||||
{
|
||||
/* pum above "row" */
|
||||
/* pum above "pum_win_row" */
|
||||
|
||||
/* Leave two lines of context if possible */
|
||||
if (curwin->w_wrow - curwin->w_cline_row >= 2)
|
||||
@@ -141,15 +154,15 @@ pum_display(
|
||||
else
|
||||
context_lines = curwin->w_wrow - curwin->w_cline_row;
|
||||
|
||||
if (row >= size + context_lines)
|
||||
if (pum_win_row >= size + context_lines)
|
||||
{
|
||||
pum_row = row - size - context_lines;
|
||||
pum_row = pum_win_row - size - context_lines;
|
||||
pum_height = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
pum_row = 0;
|
||||
pum_height = row - context_lines;
|
||||
pum_height = pum_win_row - context_lines;
|
||||
}
|
||||
if (p_ph > 0 && pum_height > p_ph)
|
||||
{
|
||||
@@ -159,7 +172,7 @@ pum_display(
|
||||
}
|
||||
else
|
||||
{
|
||||
/* pum below "row" */
|
||||
/* pum below "pum_win_row" */
|
||||
|
||||
/* Leave two lines of context if possible */
|
||||
if (curwin->w_cline_row
|
||||
@@ -169,7 +182,7 @@ pum_display(
|
||||
context_lines = curwin->w_cline_row
|
||||
+ curwin->w_cline_height - curwin->w_wrow;
|
||||
|
||||
pum_row = row + context_lines;
|
||||
pum_row = pum_win_row + context_lines;
|
||||
if (size > below_row - pum_row)
|
||||
pum_height = below_row - pum_row;
|
||||
else
|
||||
@@ -822,6 +835,43 @@ pum_visible(void)
|
||||
return !pum_do_redraw && pum_array != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reposition the popup menu to adjust for window layout changes.
|
||||
*/
|
||||
void
|
||||
pum_may_redraw(void)
|
||||
{
|
||||
pumitem_T *array = pum_array;
|
||||
int len = pum_size;
|
||||
int selected = pum_selected;
|
||||
|
||||
if (!pum_visible())
|
||||
return; // nothing to do
|
||||
|
||||
if (pum_window != curwin
|
||||
|| (pum_win_row == curwin->w_wrow + W_WINROW(curwin)
|
||||
&& pum_win_height == curwin->w_height
|
||||
&& pum_win_col == curwin->w_wincol
|
||||
&& pum_win_width == curwin->w_width))
|
||||
{
|
||||
// window position didn't change, redraw in the same position
|
||||
pum_redraw();
|
||||
}
|
||||
else
|
||||
{
|
||||
int wcol = curwin->w_wcol;
|
||||
|
||||
// Window layout changed, recompute the position.
|
||||
// Use the remembered w_wcol value, the cursor may have moved when a
|
||||
// completion was inserted, but we want the menu in the same position.
|
||||
pum_undisplay();
|
||||
curwin->w_wcol = pum_win_wcol;
|
||||
curwin->w_valid |= VALID_WCOL;
|
||||
pum_display(array, len, selected);
|
||||
curwin->w_wcol = wcol;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the height of the popup menu, the number of entries visible.
|
||||
* Only valid when pum_visible() returns TRUE!
|
||||
@@ -865,6 +915,9 @@ pum_position_at_mouse(int min_width)
|
||||
pum_width = Columns - pum_col;
|
||||
if (pum_width > pum_base_width + 1)
|
||||
pum_width = pum_base_width + 1;
|
||||
|
||||
// Do not redraw at cursor position.
|
||||
pum_window = NULL;
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -67,10 +67,12 @@ void job_set_options(job_T *job, jobopt_T *opt);
|
||||
void job_stop_on_exit(void);
|
||||
int has_pending_job(void);
|
||||
void job_check_ended(void);
|
||||
job_T *job_start(typval_T *argvars, char **argv_arg, jobopt_T *opt_arg);
|
||||
job_T *job_start(typval_T *argvars, char **argv_arg, jobopt_T *opt_arg, int is_terminal);
|
||||
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);
|
||||
int invoke_prompt_interrupt(void);
|
||||
void job_cleanup_all(void);
|
||||
/* vim: set ft=c : */
|
||||
|
||||
@@ -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);
|
||||
|
||||
+4
-4
@@ -19,10 +19,10 @@ varnumber_T eval_to_number(char_u *expr);
|
||||
list_T *eval_spell_expr(char_u *badword, char_u *expr);
|
||||
int get_spellword(list_T *list, char_u **pp);
|
||||
typval_T *eval_expr(char_u *arg, char_u **nextcmd);
|
||||
int call_vim_function(char_u *func, int argc, char_u **argv, int safe, int str_arg_only, typval_T *rettv);
|
||||
varnumber_T call_func_retnr(char_u *func, int argc, char_u **argv, int safe);
|
||||
void *call_func_retstr(char_u *func, int argc, char_u **argv, int safe);
|
||||
void *call_func_retlist(char_u *func, int argc, char_u **argv, int safe);
|
||||
int call_vim_function(char_u *func, int argc, typval_T *argv, typval_T *rettv, int safe);
|
||||
varnumber_T call_func_retnr(char_u *func, int argc, typval_T *argv, int safe);
|
||||
void *call_func_retstr(char_u *func, int argc, typval_T *argv, int safe);
|
||||
void *call_func_retlist(char_u *func, int argc, typval_T *argv, int safe);
|
||||
int eval_foldexpr(char_u *arg, int *cp);
|
||||
void ex_let(exarg_T *eap);
|
||||
void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *first);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -62,7 +62,7 @@ void mch_set_shellsize(void);
|
||||
void mch_new_shellsize(void);
|
||||
void may_send_sigint(int c, pid_t pid, pid_t wpid);
|
||||
int mch_call_shell(char_u *cmd, int options);
|
||||
void mch_job_start(char **argv, job_T *job, jobopt_T *options);
|
||||
void mch_job_start(char **argv, job_T *job, jobopt_T *options, int is_terminal);
|
||||
char *mch_job_status(job_T *job);
|
||||
job_T *mch_detect_ended_job(job_T *job_list);
|
||||
int mch_signal_job(job_T *job, char_u *how);
|
||||
|
||||
@@ -4,6 +4,7 @@ void pum_redraw(void);
|
||||
void pum_undisplay(void);
|
||||
void pum_clear(void);
|
||||
int pum_visible(void);
|
||||
void pum_may_redraw(void);
|
||||
int pum_get_height(void);
|
||||
int split_message(char_u *mesg, pumitem_T **array);
|
||||
void ui_remove_balloon(void);
|
||||
|
||||
@@ -25,7 +25,6 @@ void status_redraw_curbuf(void);
|
||||
void redraw_statuslines(void);
|
||||
void win_redraw_last_status(frame_T *frp);
|
||||
void win_redr_status_matches(expand_T *xp, int num_matches, char_u **matches, int match, int showtail);
|
||||
void win_redr_status(win_T *wp);
|
||||
int stl_connected(win_T *wp);
|
||||
int get_keymap_str(win_T *wp, char_u *fmt, char_u *buf, int len);
|
||||
void screen_putchar(int c, int row, int col, int attr);
|
||||
|
||||
@@ -54,6 +54,7 @@ void win_setheight_win(int height, win_T *win);
|
||||
void win_setwidth(int width);
|
||||
void win_setwidth_win(int width, win_T *wp);
|
||||
void win_setminheight(void);
|
||||
void win_setminwidth(void);
|
||||
void win_drag_status_line(win_T *dragwin, int offset);
|
||||
void win_drag_vsep_line(win_T *dragwin, int offset);
|
||||
void set_fraction(win_T *wp);
|
||||
|
||||
@@ -6272,8 +6272,16 @@ ex_cbuffer(exarg_T *eap)
|
||||
if (res >= 0)
|
||||
qf_list_changed(qi, qi->qf_curlist);
|
||||
if (au_name != NULL)
|
||||
{
|
||||
buf_T *curbuf_old = curbuf;
|
||||
|
||||
apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
|
||||
curbuf->b_fname, TRUE, curbuf);
|
||||
if (curbuf != curbuf_old)
|
||||
// Autocommands changed buffer, don't jump now, "qi" may
|
||||
// be invalid.
|
||||
res = 0;
|
||||
}
|
||||
if (res > 0 && (eap->cmdidx == CMD_cbuffer ||
|
||||
eap->cmdidx == CMD_lbuffer))
|
||||
qf_jump(qi, 0, 0, eap->forceit); /* display first error */
|
||||
|
||||
+45
-29
@@ -125,6 +125,7 @@ static int redrawing_for_callback = 0;
|
||||
static schar_T *current_ScreenLine;
|
||||
|
||||
static void win_update(win_T *wp);
|
||||
static void win_redr_status(win_T *wp, int ignore_pum);
|
||||
static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T hl);
|
||||
#ifdef FEAT_FOLDING
|
||||
static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T lnum, int row);
|
||||
@@ -170,7 +171,7 @@ static void redraw_win_toolbar(win_T *wp);
|
||||
static void win_redr_custom(win_T *wp, int draw_ruler);
|
||||
#endif
|
||||
#ifdef FEAT_CMDL_INFO
|
||||
static void win_redr_ruler(win_T *wp, int always);
|
||||
static void win_redr_ruler(win_T *wp, int always, int ignore_pum);
|
||||
#endif
|
||||
|
||||
/* Ugly global: overrule attribute used by screen_char() */
|
||||
@@ -476,6 +477,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;
|
||||
}
|
||||
@@ -774,7 +779,7 @@ update_screen(int type_arg)
|
||||
if (wp->w_redr_status)
|
||||
{
|
||||
cursor_off();
|
||||
win_redr_status(wp);
|
||||
win_redr_status(wp, TRUE); // any popup menu will be redrawn below
|
||||
}
|
||||
}
|
||||
#if defined(FEAT_SEARCH_EXTRA)
|
||||
@@ -782,8 +787,7 @@ update_screen(int type_arg)
|
||||
#endif
|
||||
#ifdef FEAT_INS_EXPAND
|
||||
/* May need to redraw the popup menu. */
|
||||
if (pum_visible())
|
||||
pum_redraw();
|
||||
pum_may_redraw();
|
||||
#endif
|
||||
|
||||
/* Reset b_mod_set flags. Going through all windows is probably faster
|
||||
@@ -1030,7 +1034,7 @@ update_debug_sign(buf_T *buf, linenr_T lnum)
|
||||
if (wp->w_redr_type != 0)
|
||||
win_update(wp);
|
||||
if (wp->w_redr_status)
|
||||
win_redr_status(wp);
|
||||
win_redr_status(wp, FALSE);
|
||||
}
|
||||
|
||||
update_finish();
|
||||
@@ -1074,7 +1078,7 @@ updateWindow(win_T *wp)
|
||||
|| *p_stl != NUL || *wp->w_p_stl != NUL
|
||||
# endif
|
||||
)
|
||||
win_redr_status(wp);
|
||||
win_redr_status(wp, FALSE);
|
||||
|
||||
update_finish();
|
||||
}
|
||||
@@ -6551,7 +6555,7 @@ redraw_statuslines(void)
|
||||
|
||||
FOR_ALL_WINDOWS(wp)
|
||||
if (wp->w_redr_status)
|
||||
win_redr_status(wp);
|
||||
win_redr_status(wp, FALSE);
|
||||
if (redraw_tabline)
|
||||
draw_tabline();
|
||||
}
|
||||
@@ -6880,9 +6884,11 @@ win_redr_status_matches(
|
||||
* Redraw the status line of window wp.
|
||||
*
|
||||
* If inversion is possible we use it. Else '=' characters are used.
|
||||
* If "ignore_pum" is TRUE, also redraw statusline when the popup menu is
|
||||
* displayed.
|
||||
*/
|
||||
void
|
||||
win_redr_status(win_T *wp)
|
||||
static void
|
||||
win_redr_status(win_T *wp, int ignore_pum)
|
||||
{
|
||||
int row;
|
||||
char_u *p;
|
||||
@@ -6906,9 +6912,9 @@ win_redr_status(win_T *wp)
|
||||
}
|
||||
else if (!redrawing()
|
||||
#ifdef FEAT_INS_EXPAND
|
||||
/* don't update status line when popup menu is visible and may be
|
||||
* drawn over it */
|
||||
|| pum_visible()
|
||||
// don't update status line when popup menu is visible and may be
|
||||
// drawn over it, unless it will be redrawn later
|
||||
|| (!ignore_pum && pum_visible())
|
||||
#endif
|
||||
)
|
||||
{
|
||||
@@ -7015,7 +7021,7 @@ win_redr_status(win_T *wp)
|
||||
- 1 + wp->w_wincol), attr);
|
||||
|
||||
#ifdef FEAT_CMDL_INFO
|
||||
win_redr_ruler(wp, TRUE);
|
||||
win_redr_ruler(wp, TRUE, ignore_pum);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -9839,6 +9845,7 @@ screen_ins_lines(
|
||||
int j;
|
||||
unsigned temp;
|
||||
int cursor_row;
|
||||
int cursor_col = 0;
|
||||
int type;
|
||||
int result_empty;
|
||||
int can_ce = can_clear(T_CE);
|
||||
@@ -9935,6 +9942,9 @@ screen_ins_lines(
|
||||
gui_dont_update_cursor(row + off <= gui.cursor_row);
|
||||
#endif
|
||||
|
||||
if (wp != NULL && wp->w_wincol != 0 && *T_CSV != NUL && *T_CCS == NUL)
|
||||
cursor_col = wp->w_wincol;
|
||||
|
||||
if (*T_CCS != NUL) /* cursor relative to region */
|
||||
cursor_row = row;
|
||||
else
|
||||
@@ -9981,7 +9991,7 @@ screen_ins_lines(
|
||||
}
|
||||
|
||||
screen_stop_highlight();
|
||||
windgoto(cursor_row, 0);
|
||||
windgoto(cursor_row, cursor_col);
|
||||
if (clear_attr != 0)
|
||||
screen_start_highlight(clear_attr);
|
||||
|
||||
@@ -10000,7 +10010,7 @@ screen_ins_lines(
|
||||
if (type == USE_T_AL)
|
||||
{
|
||||
if (i && cursor_row != 0)
|
||||
windgoto(cursor_row, 0);
|
||||
windgoto(cursor_row, cursor_col);
|
||||
out_str(T_AL);
|
||||
}
|
||||
else /* type == USE_T_SR */
|
||||
@@ -10017,7 +10027,7 @@ screen_ins_lines(
|
||||
{
|
||||
for (i = 0; i < line_count; ++i)
|
||||
{
|
||||
windgoto(off + i, 0);
|
||||
windgoto(off + i, cursor_col);
|
||||
out_str(T_CE);
|
||||
screen_start(); /* don't know where cursor is now */
|
||||
}
|
||||
@@ -10053,6 +10063,7 @@ screen_del_lines(
|
||||
int i;
|
||||
unsigned temp;
|
||||
int cursor_row;
|
||||
int cursor_col = 0;
|
||||
int cursor_end;
|
||||
int result_empty; /* result is empty until end of region */
|
||||
int can_delete; /* deleting line codes can be used */
|
||||
@@ -10152,6 +10163,9 @@ screen_del_lines(
|
||||
&& gui.cursor_row < end + off);
|
||||
#endif
|
||||
|
||||
if (wp != NULL && wp->w_wincol != 0 && *T_CSV != NUL && *T_CCS == NUL)
|
||||
cursor_col = wp->w_wincol;
|
||||
|
||||
if (*T_CCS != NUL) /* cursor relative to region */
|
||||
{
|
||||
cursor_row = row;
|
||||
@@ -10214,13 +10228,13 @@ screen_del_lines(
|
||||
redraw_block(row, end, wp);
|
||||
else if (type == USE_T_CD) /* delete the lines */
|
||||
{
|
||||
windgoto(cursor_row, 0);
|
||||
windgoto(cursor_row, cursor_col);
|
||||
out_str(T_CD);
|
||||
screen_start(); /* don't know where cursor is now */
|
||||
}
|
||||
else if (type == USE_T_CDL)
|
||||
{
|
||||
windgoto(cursor_row, 0);
|
||||
windgoto(cursor_row, cursor_col);
|
||||
term_delete_lines(line_count);
|
||||
screen_start(); /* don't know where cursor is now */
|
||||
}
|
||||
@@ -10231,7 +10245,7 @@ screen_del_lines(
|
||||
*/
|
||||
else if (type == USE_NL)
|
||||
{
|
||||
windgoto(cursor_end - 1, 0);
|
||||
windgoto(cursor_end - 1, cursor_col);
|
||||
for (i = line_count; --i >= 0; )
|
||||
out_char('\n'); /* cursor will remain on same line */
|
||||
}
|
||||
@@ -10241,12 +10255,12 @@ screen_del_lines(
|
||||
{
|
||||
if (type == USE_T_DL)
|
||||
{
|
||||
windgoto(cursor_row, 0);
|
||||
windgoto(cursor_row, cursor_col);
|
||||
out_str(T_DL); /* delete a line */
|
||||
}
|
||||
else /* type == USE_T_CE */
|
||||
{
|
||||
windgoto(cursor_row + i, 0);
|
||||
windgoto(cursor_row + i, cursor_col);
|
||||
out_str(T_CE); /* erase a line */
|
||||
}
|
||||
screen_start(); /* don't know where cursor is now */
|
||||
@@ -10261,7 +10275,7 @@ screen_del_lines(
|
||||
{
|
||||
for (i = line_count; i > 0; --i)
|
||||
{
|
||||
windgoto(cursor_end - i, 0);
|
||||
windgoto(cursor_end - i, cursor_col);
|
||||
out_str(T_CE); /* erase a line */
|
||||
screen_start(); /* don't know where cursor is now */
|
||||
}
|
||||
@@ -10298,7 +10312,7 @@ showmode(void)
|
||||
|
||||
do_mode = ((p_smd && msg_silent == 0)
|
||||
&& ((State & INSERT)
|
||||
|| restart_edit
|
||||
|| restart_edit != NUL
|
||||
|| VIsual_active));
|
||||
if (do_mode || reg_recording != 0)
|
||||
{
|
||||
@@ -10406,7 +10420,7 @@ showmode(void)
|
||||
#endif
|
||||
MSG_PUTS_ATTR(_(" INSERT"), attr);
|
||||
}
|
||||
else if (restart_edit == 'I')
|
||||
else if (restart_edit == 'I' || restart_edit == 'A')
|
||||
MSG_PUTS_ATTR(_(" (insert)"), attr);
|
||||
else if (restart_edit == 'R')
|
||||
MSG_PUTS_ATTR(_(" (replace)"), attr);
|
||||
@@ -10490,7 +10504,7 @@ showmode(void)
|
||||
/* If the last window has no status line, the ruler is after the mode
|
||||
* message and must be redrawn */
|
||||
if (redrawing() && lastwin->w_status_height == 0)
|
||||
win_redr_ruler(lastwin, TRUE);
|
||||
win_redr_ruler(lastwin, TRUE, FALSE);
|
||||
#endif
|
||||
redraw_cmdline = FALSE;
|
||||
clear_cmdline = FALSE;
|
||||
@@ -10909,6 +10923,7 @@ redraw_win_toolbar(win_T *wp)
|
||||
(int)wp->w_width, FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Show current status info in ruler and various other places
|
||||
* If always is FALSE, only show ruler if position has changed.
|
||||
@@ -10934,7 +10949,7 @@ showruler(int always)
|
||||
else
|
||||
#endif
|
||||
#ifdef FEAT_CMDL_INFO
|
||||
win_redr_ruler(curwin, always);
|
||||
win_redr_ruler(curwin, always, FALSE);
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_TITLE
|
||||
@@ -10953,7 +10968,7 @@ showruler(int always)
|
||||
|
||||
#ifdef FEAT_CMDL_INFO
|
||||
static void
|
||||
win_redr_ruler(win_T *wp, int always)
|
||||
win_redr_ruler(win_T *wp, int always, int ignore_pum)
|
||||
{
|
||||
#define RULER_BUF_LEN 70
|
||||
char_u buffer[RULER_BUF_LEN];
|
||||
@@ -10986,8 +11001,9 @@ win_redr_ruler(win_T *wp, int always)
|
||||
if (wp == lastwin && lastwin->w_status_height == 0)
|
||||
if (edit_submode != NULL)
|
||||
return;
|
||||
/* Don't draw the ruler when the popup menu is visible, it may overlap. */
|
||||
if (pum_visible())
|
||||
// Don't draw the ruler when the popup menu is visible, it may overlap.
|
||||
// Except when the popup menu will be redrawn anyway.
|
||||
if (!ignore_pum && pum_visible())
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -2362,6 +2362,15 @@ 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()
|
||||
char_u *b_prompt_interrupt; // set by prompt_setinterrupt()
|
||||
partial_T *b_prompt_int_partial; // set by prompt_setinterrupt()
|
||||
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
|
||||
|
||||
+22
-6
@@ -2112,7 +2112,11 @@ terminal_loop(int blocking)
|
||||
in_terminal_loop = curbuf->b_term;
|
||||
|
||||
if (*curwin->w_p_twk != NUL)
|
||||
{
|
||||
termwinkey = string_to_key(curwin->w_p_twk, TRUE);
|
||||
if (termwinkey == Ctrl_W)
|
||||
termwinkey = 0;
|
||||
}
|
||||
position_cursor(curwin, &curbuf->b_term->tl_cursor_pos);
|
||||
may_set_cursor_props(curbuf->b_term);
|
||||
|
||||
@@ -2208,12 +2212,13 @@ terminal_loop(int blocking)
|
||||
/* "CTRL-W CTRL-C" or 'termwinkey' CTRL-C: end the job */
|
||||
mch_signal_job(curbuf->b_term->tl_job, (char_u *)"kill");
|
||||
}
|
||||
else if (termwinkey == 0 && c == '.')
|
||||
else if (c == '.')
|
||||
{
|
||||
/* "CTRL-W .": send CTRL-W to the job */
|
||||
c = Ctrl_W;
|
||||
/* "'termwinkey' .": send 'termwinkey' to the job */
|
||||
c = termwinkey == 0 ? Ctrl_W : termwinkey;
|
||||
}
|
||||
else if (termwinkey == 0 && c == Ctrl_BSL)
|
||||
else if (c == Ctrl_BSL)
|
||||
{
|
||||
/* "CTRL-W CTRL-\": send CTRL-\ to the job */
|
||||
c = Ctrl_BSL;
|
||||
@@ -5099,8 +5104,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5763,7 +5779,7 @@ term_and_job_init(
|
||||
#endif
|
||||
|
||||
/* This may change a string in "argvar". */
|
||||
term->tl_job = job_start(argvar, argv, opt);
|
||||
term->tl_job = job_start(argvar, argv, opt, TRUE);
|
||||
if (term->tl_job != NULL)
|
||||
++term->tl_job->jv_refcount;
|
||||
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -124,7 +124,10 @@ func RunTheTest(test)
|
||||
exe 'call ' . a:test
|
||||
else
|
||||
try
|
||||
let s:test = a:test
|
||||
au VimLeavePre * call EarlyExit(s:test)
|
||||
exe 'call ' . a:test
|
||||
au! VimLeavePre
|
||||
catch /^\cskipped/
|
||||
call add(s:messages, ' Skipped')
|
||||
call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', ''))
|
||||
@@ -174,6 +177,15 @@ func AfterTheTest()
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func EarlyExit(test)
|
||||
" It's OK for the test we use to test the quit detection.
|
||||
if a:test != 'Test_zz_quit_detected()'
|
||||
call add(v:errors, 'Test caused Vim to exit: ' . a:test)
|
||||
endif
|
||||
|
||||
call FinishTesting()
|
||||
endfunc
|
||||
|
||||
" This function can be called by a test if it wants to abort testing.
|
||||
func FinishTesting()
|
||||
call AfterTheTest()
|
||||
|
||||
+19
-14
@@ -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
|
||||
|
||||
@@ -443,7 +443,7 @@ vim.current.window:Window:True
|
||||
vim.current.tabpage:TabPage:True
|
||||
current:__dir__,__members__,buffer,line,range,tabpage,window
|
||||
buffer:__dir__,__members__,append,mark,name,number,options,range,valid,vars
|
||||
window:__dir__,__members__,buffer,col,cursor,height,number,options,row,tabpage,valid,vars
|
||||
window:__dir__,__members__,buffer,col,cursor,height,number,options,row,tabpage,valid,vars,width
|
||||
tabpage:__dir__,__members__,number,valid,vars,window,windows
|
||||
range:__dir__,__members__,append,end,start
|
||||
dictionary:__dir__,__members__,get,has_key,items,keys,locked,pop,popitem,scope,update,values
|
||||
|
||||
@@ -443,7 +443,7 @@ vim.current.window:Window:True
|
||||
vim.current.tabpage:TabPage:True
|
||||
current:__dir__,buffer,line,range,tabpage,window
|
||||
buffer:__dir__,append,mark,name,number,options,range,valid,vars
|
||||
window:__dir__,buffer,col,cursor,height,number,options,row,tabpage,valid,vars
|
||||
window:__dir__,buffer,col,cursor,height,number,options,row,tabpage,valid,vars,width
|
||||
tabpage:__dir__,number,valid,vars,window,windows
|
||||
range:__dir__,append,end,start
|
||||
dictionary:__dir__,get,has_key,items,keys,locked,pop,popitem,scope,update,values
|
||||
|
||||
@@ -198,3 +198,9 @@ func Test_user_is_happy()
|
||||
smile
|
||||
sleep 300m
|
||||
endfunc
|
||||
|
||||
" Must be last.
|
||||
func Test_zz_quit_detected()
|
||||
" Verify that if a test function ends Vim the test script detects this.
|
||||
quit
|
||||
endfunc
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -465,4 +465,16 @@ func Test_show_digraph()
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
func Test_show_digraph_cp1251()
|
||||
if !has('multi_byte')
|
||||
return
|
||||
endif
|
||||
new
|
||||
set encoding=cp1251
|
||||
call Put_Dig("='")
|
||||
call assert_equal("\n<\xfa> <|z> <M-z> 250, Hex fa, Oct 372, Digr ='", execute('ascii'))
|
||||
set encoding=utf-8
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -63,12 +63,27 @@ func Test_with_syntax()
|
||||
endfunc
|
||||
|
||||
func Test_fname_with_spaces()
|
||||
if has('postscript')
|
||||
split t\ e\ s\ t.txt
|
||||
call setline(1, ['just', 'some', 'text'])
|
||||
hardcopy > %.ps
|
||||
call assert_true(filereadable('t e s t.txt.ps'))
|
||||
call delete('t e s t.txt.ps')
|
||||
bwipe!
|
||||
if !has('postscript')
|
||||
return
|
||||
endif
|
||||
split t\ e\ s\ t.txt
|
||||
call setline(1, ['just', 'some', 'text'])
|
||||
hardcopy > %.ps
|
||||
call assert_true(filereadable('t e s t.txt.ps'))
|
||||
call delete('t e s t.txt.ps')
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
func Test_illegal_byte()
|
||||
if !has('postscript') || &enc != 'utf-8'
|
||||
return
|
||||
endif
|
||||
new
|
||||
" conversion of 0xff will fail, this used to cause a crash
|
||||
call setline(1, "\xff")
|
||||
hardcopy >Xpstest
|
||||
|
||||
bwipe!
|
||||
call delete('Xpstest')
|
||||
endfunc
|
||||
|
||||
|
||||
@@ -117,6 +117,31 @@ func Test_omni_dash()
|
||||
set omnifunc=
|
||||
endfunc
|
||||
|
||||
func Test_completefunc_args()
|
||||
let s:args = []
|
||||
func! CompleteFunc(findstart, base)
|
||||
let s:args += [[a:findstart, empty(a:base)]]
|
||||
endfunc
|
||||
new
|
||||
|
||||
set completefunc=CompleteFunc
|
||||
call feedkeys("i\<C-X>\<C-U>\<Esc>", 'x')
|
||||
call assert_equal([1, 1], s:args[0])
|
||||
call assert_equal(0, s:args[1][0])
|
||||
set completefunc=
|
||||
|
||||
let s:args = []
|
||||
set omnifunc=CompleteFunc
|
||||
call feedkeys("i\<C-X>\<C-O>\<Esc>", 'x')
|
||||
call assert_equal([1, 1], s:args[0])
|
||||
call assert_equal(0, s:args[1][0])
|
||||
set omnifunc=
|
||||
|
||||
bwipe!
|
||||
unlet s:args
|
||||
delfunc CompleteFunc
|
||||
endfunc
|
||||
|
||||
function! s:CompleteDone_CompleteFuncDict( findstart, base )
|
||||
if a:findstart
|
||||
return 0
|
||||
|
||||
@@ -106,13 +106,22 @@ endfunc
|
||||
|
||||
func Test_mksession_winheight()
|
||||
new
|
||||
set winheight=10 winminheight=2
|
||||
set winheight=10
|
||||
set winminheight=2
|
||||
mksession! Xtest_mks.out
|
||||
source Xtest_mks.out
|
||||
|
||||
call delete('Xtest_mks.out')
|
||||
endfunc
|
||||
|
||||
func Test_mksession_large_winheight()
|
||||
set winheight=999
|
||||
mksession! Xtest_mks_winheight.out
|
||||
set winheight&
|
||||
source Xtest_mks_winheight.out
|
||||
call delete('Xtest_mks_winheight.out')
|
||||
endfunc
|
||||
|
||||
func Test_mksession_arglist()
|
||||
argdel *
|
||||
next file1 file2 file3 file4
|
||||
|
||||
@@ -1,10 +1,38 @@
|
||||
" Tests for complicated + argument to :edit command
|
||||
function Test_edit()
|
||||
call writefile(["foo|bar"], "Xfile1")
|
||||
call writefile(["foo/bar"], "Xfile2")
|
||||
call writefile(["foo|bar"], "Xfile1")
|
||||
call writefile(["foo/bar"], "Xfile2")
|
||||
edit +1|s/|/PIPE/|w Xfile1| e Xfile2|1 | s/\//SLASH/|w
|
||||
call assert_equal(["fooPIPEbar"], readfile("Xfile1"))
|
||||
call assert_equal(["fooSLASHbar"], readfile("Xfile2"))
|
||||
call delete('Xfile1')
|
||||
call delete('Xfile2')
|
||||
endfunction
|
||||
|
||||
func Test_edit_bad()
|
||||
if !has('multi_byte')
|
||||
finish
|
||||
endif
|
||||
|
||||
" Test loading a utf8 file with bad utf8 sequences.
|
||||
call writefile(["[\xff][\xc0][\xe2\x89\xf0][\xc2\xc2]"], "Xfile")
|
||||
new
|
||||
|
||||
" Without ++bad=..., the default behavior is like ++bad=?
|
||||
e! ++enc=utf8 Xfile
|
||||
call assert_equal('[?][?][???][??]', getline(1))
|
||||
|
||||
e! ++enc=utf8 ++bad=_ Xfile
|
||||
call assert_equal('[_][_][___][__]', getline(1))
|
||||
|
||||
e! ++enc=utf8 ++bad=drop Xfile
|
||||
call assert_equal('[][][][]', getline(1))
|
||||
|
||||
e! ++enc=utf8 ++bad=keep Xfile
|
||||
call assert_equal("[\xff][\xc0][\xe2\x89\xf0][\xc2\xc2]", getline(1))
|
||||
|
||||
call assert_fails('e! ++enc=utf8 ++bad=foo Xfile', 'E474:')
|
||||
|
||||
bw!
|
||||
call delete('Xfile')
|
||||
endfunc
|
||||
|
||||
+25
-25
@@ -6,7 +6,7 @@ source screendump.vim
|
||||
let g:months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
|
||||
let g:setting = ''
|
||||
|
||||
func! ListMonths()
|
||||
func ListMonths()
|
||||
if g:setting != ''
|
||||
exe ":set" g:setting
|
||||
endif
|
||||
@@ -19,7 +19,7 @@ func! ListMonths()
|
||||
return ''
|
||||
endfunc
|
||||
|
||||
func! Test_popup_complete2()
|
||||
func Test_popup_complete2()
|
||||
" Although the popupmenu is not visible, this does not mean completion mode
|
||||
" has ended. After pressing <f5> to complete the currently typed char, Vim
|
||||
" still stays in the first state of the completion (:h ins-completion-menu),
|
||||
@@ -34,9 +34,9 @@ func! Test_popup_complete2()
|
||||
call assert_equal(["Dece", "", "December2015"], getline(1,3))
|
||||
%d
|
||||
bw!
|
||||
endfu
|
||||
endfunc
|
||||
|
||||
func! Test_popup_complete()
|
||||
func Test_popup_complete()
|
||||
new
|
||||
inoremap <f5> <c-r>=ListMonths()<cr>
|
||||
|
||||
@@ -215,10 +215,10 @@ func! Test_popup_complete()
|
||||
call feedkeys("aM\<f5>\<enter>\<esc>", 'tx')
|
||||
call assert_equal(["March", "M", "March"], getline(1,4))
|
||||
%d
|
||||
endfu
|
||||
endfunc
|
||||
|
||||
|
||||
func! Test_popup_completion_insertmode()
|
||||
func Test_popup_completion_insertmode()
|
||||
new
|
||||
inoremap <F5> <C-R>=ListMonths()<CR>
|
||||
|
||||
@@ -248,15 +248,15 @@ func! Test_popup_completion_insertmode()
|
||||
endfunc
|
||||
|
||||
func Test_noinsert_complete()
|
||||
function! s:complTest1() abort
|
||||
func! s:complTest1() abort
|
||||
call complete(1, ['source', 'soundfold'])
|
||||
return ''
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function! s:complTest2() abort
|
||||
func! s:complTest2() abort
|
||||
call complete(1, ['source', 'soundfold'])
|
||||
return ''
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
new
|
||||
set completeopt+=noinsert
|
||||
@@ -277,9 +277,9 @@ func Test_noinsert_complete()
|
||||
endfunc
|
||||
|
||||
func Test_compl_vim_cmds_after_register_expr()
|
||||
function! s:test_func()
|
||||
func! s:test_func()
|
||||
return 'autocmd '
|
||||
endfunction
|
||||
endfunc
|
||||
augroup AAAAA_Group
|
||||
au!
|
||||
augroup END
|
||||
@@ -326,7 +326,7 @@ func DummyCompleteTwo(findstart, base)
|
||||
else
|
||||
return ['twodef', 'twoDEF']
|
||||
endif
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" Test that nothing happens if the 'completefunc' opens
|
||||
" a new window (no completion, no crash)
|
||||
@@ -403,7 +403,7 @@ func Test_omnifunc_with_check()
|
||||
q!
|
||||
endfunc
|
||||
|
||||
function UndoComplete()
|
||||
func UndoComplete()
|
||||
call complete(1, ['January', 'February', 'March',
|
||||
\ 'April', 'May', 'June', 'July', 'August', 'September',
|
||||
\ 'October', 'November', 'December'])
|
||||
@@ -440,7 +440,7 @@ func Test_complete_no_undo()
|
||||
q!
|
||||
endfunc
|
||||
|
||||
function! DummyCompleteFive(findstart, base)
|
||||
func DummyCompleteFive(findstart, base)
|
||||
if a:findstart
|
||||
return 0
|
||||
else
|
||||
@@ -485,7 +485,7 @@ func Test_completion_ctrl_e_without_autowrap()
|
||||
q!
|
||||
endfunc
|
||||
|
||||
function! DummyCompleteSix()
|
||||
func DummyCompleteSix()
|
||||
call complete(1, ['Hello', 'World'])
|
||||
return ''
|
||||
endfunction
|
||||
@@ -573,7 +573,7 @@ func Test_completion_comment_formatting()
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
fun MessCompleteMonths()
|
||||
func MessCompleteMonths()
|
||||
for m in split("Jan Feb Mar Apr May Jun Jul Aug Sep")
|
||||
call complete_add(m)
|
||||
if complete_check()
|
||||
@@ -581,14 +581,14 @@ fun MessCompleteMonths()
|
||||
endif
|
||||
endfor
|
||||
return []
|
||||
endfun
|
||||
endfunc
|
||||
|
||||
fun MessCompleteMore()
|
||||
func MessCompleteMore()
|
||||
call complete(1, split("Oct Nov Dec"))
|
||||
return []
|
||||
endfun
|
||||
endfunc
|
||||
|
||||
fun MessComplete(findstart, base)
|
||||
func MessComplete(findstart, base)
|
||||
if a:findstart
|
||||
let line = getline('.')
|
||||
let start = col('.') - 1
|
||||
@@ -601,7 +601,7 @@ fun MessComplete(findstart, base)
|
||||
call MessCompleteMore()
|
||||
return []
|
||||
endif
|
||||
endf
|
||||
endfunc
|
||||
|
||||
func Test_complete_func_mess()
|
||||
" Calling complete() after complete_add() in 'completefunc' is wrong, but it
|
||||
@@ -831,7 +831,7 @@ func Test_popup_complete_backwards_ctrl_p()
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
fun! Test_complete_o_tab()
|
||||
func Test_complete_o_tab()
|
||||
let s:o_char_pressed = 0
|
||||
|
||||
fun! s:act_on_text_changed()
|
||||
@@ -839,7 +839,7 @@ fun! Test_complete_o_tab()
|
||||
let s:o_char_pressed = 0
|
||||
call feedkeys("\<c-x>\<c-n>", 'i')
|
||||
endif
|
||||
endf
|
||||
endfunc
|
||||
|
||||
set completeopt=menu,noselect
|
||||
new
|
||||
@@ -858,7 +858,7 @@ fun! Test_complete_o_tab()
|
||||
bwipe!
|
||||
set completeopt&
|
||||
delfunc s:act_on_text_changed
|
||||
endf
|
||||
endfunc
|
||||
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -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
|
||||
@@ -3350,3 +3350,15 @@ func Test_qftitle()
|
||||
call assert_equal('Errors', w:quickfix_title)
|
||||
cclose
|
||||
endfunc
|
||||
|
||||
func Test_lbuffer_with_bwipe()
|
||||
new
|
||||
new
|
||||
augroup nasty
|
||||
au * * bwipe
|
||||
augroup END
|
||||
lbuffer
|
||||
augroup nasty
|
||||
au!
|
||||
augroup END
|
||||
endfunc
|
||||
|
||||
@@ -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
|
||||
@@ -481,18 +482,25 @@ func Test_terminal_servername()
|
||||
if !has('clientserver')
|
||||
return
|
||||
endif
|
||||
call s:test_environment("VIM_SERVERNAME", v:servername)
|
||||
endfunc
|
||||
|
||||
func Test_terminal_version()
|
||||
call s:test_environment("VIM_TERMINAL", string(v:version))
|
||||
endfunc
|
||||
|
||||
func s:test_environment(name, value)
|
||||
let buf = Run_shell_in_terminal({})
|
||||
" Wait for the shell to display a prompt
|
||||
call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))})
|
||||
if has('win32')
|
||||
call term_sendkeys(buf, "echo %VIM_SERVERNAME%\r")
|
||||
call term_sendkeys(buf, "echo %" . a:name . "%\r")
|
||||
else
|
||||
call term_sendkeys(buf, "echo $VIM_SERVERNAME\r")
|
||||
call term_sendkeys(buf, "echo $" . a:name . "\r")
|
||||
endif
|
||||
call term_wait(buf)
|
||||
call Stop_shell_in_terminal(buf)
|
||||
call WaitFor('getline(2) == v:servername')
|
||||
call assert_equal(v:servername, getline(2))
|
||||
call WaitForAssert({-> assert_equal(a:value, getline(2))})
|
||||
|
||||
exe buf . 'bwipe'
|
||||
unlet buf
|
||||
@@ -585,6 +593,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -45,3 +45,13 @@ func Test_unlet_env()
|
||||
|
||||
unlet $MUST_NOT_BE_AN_ERROR
|
||||
endfunc
|
||||
|
||||
func Test_unlet_complete()
|
||||
let g:FOOBAR = 1
|
||||
call feedkeys(":unlet g:FOO\t\n", 'tx')
|
||||
call assert_true(!exists('g:FOOBAR'))
|
||||
|
||||
let $FOOBAR = 1
|
||||
call feedkeys(":unlet $FOO\t\n", 'tx')
|
||||
call assert_true(!exists('$FOOBAR') || empty($FOOBAR))
|
||||
endfunc
|
||||
|
||||
+100
@@ -776,6 +776,106 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
72,
|
||||
/**/
|
||||
71,
|
||||
/**/
|
||||
70,
|
||||
/**/
|
||||
69,
|
||||
/**/
|
||||
68,
|
||||
/**/
|
||||
67,
|
||||
/**/
|
||||
66,
|
||||
/**/
|
||||
65,
|
||||
/**/
|
||||
64,
|
||||
/**/
|
||||
63,
|
||||
/**/
|
||||
62,
|
||||
/**/
|
||||
61,
|
||||
/**/
|
||||
60,
|
||||
/**/
|
||||
59,
|
||||
/**/
|
||||
58,
|
||||
/**/
|
||||
57,
|
||||
/**/
|
||||
56,
|
||||
/**/
|
||||
55,
|
||||
/**/
|
||||
54,
|
||||
/**/
|
||||
53,
|
||||
/**/
|
||||
52,
|
||||
/**/
|
||||
51,
|
||||
/**/
|
||||
50,
|
||||
/**/
|
||||
49,
|
||||
/**/
|
||||
48,
|
||||
/**/
|
||||
47,
|
||||
/**/
|
||||
46,
|
||||
/**/
|
||||
45,
|
||||
/**/
|
||||
44,
|
||||
/**/
|
||||
43,
|
||||
/**/
|
||||
42,
|
||||
/**/
|
||||
41,
|
||||
/**/
|
||||
40,
|
||||
/**/
|
||||
39,
|
||||
/**/
|
||||
38,
|
||||
/**/
|
||||
37,
|
||||
/**/
|
||||
36,
|
||||
/**/
|
||||
35,
|
||||
/**/
|
||||
34,
|
||||
/**/
|
||||
33,
|
||||
/**/
|
||||
32,
|
||||
/**/
|
||||
31,
|
||||
/**/
|
||||
30,
|
||||
/**/
|
||||
29,
|
||||
/**/
|
||||
28,
|
||||
/**/
|
||||
27,
|
||||
/**/
|
||||
26,
|
||||
/**/
|
||||
25,
|
||||
/**/
|
||||
24,
|
||||
/**/
|
||||
23,
|
||||
/**/
|
||||
22,
|
||||
/**/
|
||||
|
||||
+96
-8
@@ -2108,6 +2108,50 @@ win_equal_rec(
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FEAT_JOB_CHANNEL
|
||||
static void
|
||||
leaving_window(win_T *win)
|
||||
{
|
||||
// Only matters for a prompt window.
|
||||
if (!bt_prompt(win->w_buffer))
|
||||
return;
|
||||
|
||||
// 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;
|
||||
if (restart_edit != 0 && mode_displayed)
|
||||
clear_cmdline = TRUE; /* unshow mode later */
|
||||
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 and restart Insert
|
||||
// mode when entering the window again.
|
||||
if (State & INSERT)
|
||||
{
|
||||
stop_insert_mode = TRUE;
|
||||
if (win->w_buffer->b_prompt_insert == NUL)
|
||||
win->w_buffer->b_prompt_insert = 'A';
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
entering_window(win_T *win)
|
||||
{
|
||||
// Only matters for a prompt window.
|
||||
if (!bt_prompt(win->w_buffer))
|
||||
return;
|
||||
|
||||
// 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 (win->w_buffer->b_prompt_insert != NUL)
|
||||
stop_insert_mode = FALSE;
|
||||
|
||||
// When entering the prompt window restart Insert mode if we were in Insert
|
||||
// mode when we left it.
|
||||
restart_edit = win->w_buffer->b_prompt_insert;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Close all windows for buffer "buf".
|
||||
*/
|
||||
@@ -2236,6 +2280,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 +2348,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 +3704,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 +3880,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 +4379,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 +4455,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)
|
||||
@@ -5373,23 +5437,21 @@ frame_setwidth(frame_T *curfrp, int width)
|
||||
}
|
||||
|
||||
/*
|
||||
* Check 'winminheight' for a valid value.
|
||||
* Check 'winminheight' for a valid value and reduce it if needed.
|
||||
*/
|
||||
void
|
||||
win_setminheight(void)
|
||||
{
|
||||
int room;
|
||||
int needed;
|
||||
int first = TRUE;
|
||||
win_T *wp;
|
||||
|
||||
/* loop until there is a 'winminheight' that is possible */
|
||||
// loop until there is a 'winminheight' that is possible
|
||||
while (p_wmh > 0)
|
||||
{
|
||||
/* TODO: handle vertical splits */
|
||||
room = -p_wh;
|
||||
FOR_ALL_WINDOWS(wp)
|
||||
room += VISIBLE_HEIGHT(wp) - p_wmh;
|
||||
if (room >= 0)
|
||||
room = Rows - p_ch;
|
||||
needed = frame_minheight(topframe, NULL);
|
||||
if (room >= needed)
|
||||
break;
|
||||
--p_wmh;
|
||||
if (first)
|
||||
@@ -5400,6 +5462,32 @@ win_setminheight(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check 'winminwidth' for a valid value and reduce it if needed.
|
||||
*/
|
||||
void
|
||||
win_setminwidth(void)
|
||||
{
|
||||
int room;
|
||||
int needed;
|
||||
int first = TRUE;
|
||||
|
||||
// loop until there is a 'winminheight' that is possible
|
||||
while (p_wmw > 0)
|
||||
{
|
||||
room = Columns;
|
||||
needed = frame_minwidth(topframe, NULL);
|
||||
if (room >= needed)
|
||||
break;
|
||||
--p_wmw;
|
||||
if (first)
|
||||
{
|
||||
EMSG(_(e_noroom));
|
||||
first = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(FEAT_MOUSE) || defined(PROTO)
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user