Merge remote-tracking branch 'origin/master' into lambda

This commit is contained in:
James McCoy 2017-02-22 17:07:47 -05:00
commit bc76ce2c4f
No known key found for this signature in database
GPG Key ID: DFE691AE331BA3DB
58 changed files with 2507 additions and 2152 deletions

View File

@ -1,4 +1,4 @@
[![Neovim](https://raw.githubusercontent.com/neovim/neovim.github.io/master/logos/neovim-logo.png)](https://neovim.io)
[![Neovim](https://raw.githubusercontent.com/neovim/neovim.github.io/master/logos/neovim-logo-600x173.png)](https://neovim.io)
[Wiki](https://github.com/neovim/neovim/wiki) |
[Documentation](https://neovim.io/doc) |
@ -18,14 +18,28 @@ Neovim is a project that seeks to aggressively refactor Vim in order to:
- Simplify maintenance and encourage [contributions](CONTRIBUTING.md)
- Split the work between multiple developers
- Enable advanced [external UIs] without modifications to the core
- Improve extensibility with a new [plugin architecture](https://github.com/neovim/neovim/wiki/Plugin-UI-architecture)
- Enable [advanced UIs] without modifications to the core
- Maximize [extensibility](https://github.com/neovim/neovim/wiki/Plugin-UI-architecture)
For more details, see
[the wiki](https://github.com/neovim/neovim/wiki/Introduction)!
See [the wiki](https://github.com/neovim/neovim/wiki/Introduction) and [Roadmap]
for more information.
[![Throughput Graph](https://graphs.waffle.io/neovim/neovim/throughput.svg)](https://waffle.io/neovim/neovim/metrics)
Install from source
-------------------
make CMAKE_BUILD_TYPE=RelWithDebInfo
sudo make install
See [the wiki](https://github.com/neovim/neovim/wiki/Building-Neovim) for details.
Install from package
--------------------
Packages are in [Homebrew], [Debian], [Ubuntu], [Fedora], [Arch Linux], and
[more](https://github.com/neovim/neovim/wiki/Installing-Neovim).
What's been done so far
-----------------------
@ -34,24 +48,13 @@ What's been done so far
- Asynchronous [job control](https://github.com/neovim/neovim/pull/2247)
- [Shared data (shada)](https://github.com/neovim/neovim/pull/2506) among multiple editor instances
- [XDG base directories](https://github.com/neovim/neovim/pull/3470) support
- [libuv](https://github.com/libuv/libuv/)-based platform/OS/"mch" layer
- [libuv](https://github.com/libuv/libuv/)-based platform/OS layer
- [Pushdown automaton](https://github.com/neovim/neovim/pull/3413) input model
- 1000s of new tests
- Legacy tests converted to Lua tests
See [`:help nvim-features`][nvim-features] for a comprehensive list.
What's being worked on now
--------------------------
See the [Roadmap].
How do I get it?
----------------
There is a Debian package, homebrew formula, PKGBUILD for Arch Linux, RPM, and
more. See [the wiki](https://github.com/neovim/neovim/wiki/Installing-Neovim)!
License
-------
@ -81,6 +84,11 @@ See `LICENSE` for details.
[license-commit]: https://github.com/neovim/neovim/commit/b17d9691a24099c9210289f16afb1a498a89d803
[nvim-features]: https://neovim.io/doc/user/vim_diff.html#nvim-features
[Roadmap]: https://neovim.io/roadmap/
[external UIs]: https://github.com/neovim/neovim/wiki/Related-projects#gui-projects
[advanced UIs]: https://github.com/neovim/neovim/wiki/Related-projects#gui-projects
[Homebrew]: https://github.com/neovim/homebrew-neovim#installation
[Debian]: https://packages.debian.org/testing/neovim
[Ubuntu]: http://packages.ubuntu.com/search?keywords=neovim
[Fedora]: https://admin.fedoraproject.org/pkgdb/package/rpms/neovim
[Arch Linux]: https://www.archlinux.org/packages/?q=neovim
<!-- vim: set tw=80: -->

View File

@ -5,6 +5,9 @@ configuration:
install: []
build_script:
- call .ci\build.bat
cache:
- C:\msys64\var\cache\pacman\pkg -> .ci\build.bat
- .deps -> third-party/CMakeLists.txt
artifacts:
- path: build/Neovim.zip
- path: build/bin/nvim.exe

View File

@ -370,9 +370,6 @@ CTRL-G U don't break undo with next left/right cursor *i_CTRL-G_U*
within same the line)
-----------------------------------------------------------------------
Note: If the cursor keys take you out of Insert mode, check the 'noesckeys'
option.
The CTRL-O command sometimes has a side effect: If the cursor was beyond the
end of the line, it will be put on the last character in the line. In
mappings it's often better to use <Esc> (first put an "x" in the text, <Esc>

View File

@ -2209,18 +2209,6 @@ A jump table for the options with a short description can be found at |Q_op|.
Scanf-like description of the format for the lines in the error file
(see |errorformat|).
*'esckeys'* *'ek'* *'noesckeys'* *'noek'*
'esckeys' 'ek' boolean (Vim default: on, Vi default: off)
global
Function keys that start with an <Esc> are recognized in Insert
mode. When this option is off, the cursor and function keys cannot be
used in Insert mode if they start with an <Esc>. The advantage of
this is that the single <Esc> is recognized immediately, instead of
after one second. Instead of resetting this option, you might want to
try changing the values for 'timeoutlen' and 'ttimeoutlen'. Note that
when 'esckeys' is off, you can still map anything, but the cursor keys
won't work by default.
*'eventignore'* *'ei'*
'eventignore' 'ei' string (default "")
global

View File

@ -49,7 +49,8 @@ Note: The `--upgrade` flag ensures you have the latest version even if
PYTHON PROVIDER CONFIGURATION ~
*g:python_host_prog*
*g:python3_host_prog*
Program to use for evaluating Python code. Setting this makes startup faster. >
Program to use for evaluating Python code. Setting this makes startup faster.
Also useful for working with virtualenvs. >
let g:python_host_prog = '/path/to/python'
let g:python3_host_prog = '/path/to/python3'
<
@ -61,6 +62,23 @@ To disable Python 2 support: >
To disable Python 3 support: >
let g:loaded_python3_provider = 1
PYTHON VIRTUALENVS ~
If you plan to use per-project virtualenvs often, you should assign
a virtualenv for Neovim and hard-code the interpreter path via
|g:python_host_prog| (or |g:python3_host_prog|) so that the "neovim" python
package is not required for each Environment. Example using pyenv: >
pyenv install 3.4.4
pyenv virtualenv 3.4.4 py3neovim
pyenv activate py3neovim
pip install neovim
pyenv which python # Note the path
The last command reports the interpreter path. Add it to your init.vim: >
let g:python3_host_prog = '/full/path/to/py3neovim/bin/python'
More information:
https://github.com/zchee/deoplete-jedi/wiki/Setting-up-Python-for-Neovim
==============================================================================
Ruby integration *provider-ruby*
@ -80,7 +98,6 @@ RUBY PROVIDER CONFIGURATION ~
To disable Ruby support: >
let g:loaded_ruby_provider = 1
==============================================================================
Clipboard integration *provider-clipboard* *clipboard*
@ -93,7 +110,7 @@ are found in your `$PATH`.
- xclip
- xsel (newer alternative to xclip)
- pbcopy/pbpaste (Mac OS X)
- pbcopy/pbpaste (macOS)
- lemonade (for SSH) https://github.com/pocke/lemonade
- doitclient (for SSH) http://www.chiark.greenend.org.uk/~sgtatham/doit/

View File

@ -678,7 +678,6 @@ Short explanation of each option: *option-list*
'errorbells' 'eb' ring the bell for error messages
'errorfile' 'ef' name of the errorfile for the QuickFix mode
'errorformat' 'efm' description of the lines in the error file
'esckeys' 'ek' recognize function keys in Insert mode
'eventignore' 'ei' autocommand events that are ignored
'expandtab' 'et' use spaces when <Tab> is inserted
'exrc' 'ex' read .nvimrc and .exrc in the current directory

View File

@ -70,9 +70,7 @@ for a next character to arrive. If it does not arrive within one second a
single <Esc> is assumed. On very slow systems this may fail, causing cursor
keys not to work sometimes. If you discover this problem reset the 'timeout'
option. Vim will wait for the next character to arrive after an <Esc>. If
you want to enter a single <Esc> you must type it twice. Resetting the
'esckeys' option avoids this problem in Insert mode, but you lose the
possibility to use cursor and function keys in Insert mode.
you want to enter a single <Esc> you must type it twice.
Some terminals have confusing codes for the cursor keys. The televideo 925 is
such a terminal. It sends a CTRL-H for cursor-left. This would make it

View File

@ -238,6 +238,8 @@ newly allocated memory all over the place) and fail on types which cannot be
coerced to strings. See |id()| for more details, currently it uses
`printf("%p", {expr})` internally.
|c_CTRL-R| pasting a non-special register into |cmdline| omits the last <CR>.
==============================================================================
5. Missing legacy features *nvim-features-missing*
*if_lua* *if_perl* *if_mzscheme* *if_tcl*
@ -298,6 +300,7 @@ Other options:
'antialias'
'cpoptions' ("g", "w", "H", "*", "-", "j", and all POSIX flags were removed)
'encoding' ("utf-8" is always used)
'esckeys'
'guioptions' "t" flag was removed
*'guipty'* (Nvim uses pipes and PTYs consistently on all platforms.)
*'imactivatefunc'* *'imaf'*

View File

@ -524,8 +524,6 @@ endif
call <SID>Header("terminal")
call append("$", "esckeys\trecognize keys that start with <Esc> in Insert mode")
call <SID>BinOptionG("ek", &ek)
call append("$", "scrolljump\tminimal number of lines to scroll at a time")
call append("$", " \tset sj=" . &sj)
if has("gui") || has("msdos") || has("win32")

View File

@ -66,7 +66,7 @@ for i, cmd in ipairs(defs) do
defsfile:write(string.format([[
[%s] = {
.cmd_name = (char_u *) "%s",
.cmd_func = &%s,
.cmd_func = (ex_func_T)&%s,
.cmd_argt = %uL,
.cmd_addr_type = %i
}]], enumname, cmd.command, cmd.func, cmd.flags, cmd.addr_type))

View File

@ -299,25 +299,6 @@ if(WIN32)
install(DIRECTORY ${PROJECT_BINARY_DIR}/windows_runtime_deps/
DESTINATION ${CMAKE_INSTALL_BINDIR})
foreach(BIN win32yank.exe)
unset(BIN_PATH CACHE)
find_program(BIN_PATH ${BIN})
if(NOT BIN_PATH)
message(FATAL_ERROR "Unable to find external dependency ${BIN}")
endif()
add_custom_target(external_${BIN}
COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps
COMMAND ${CMAKE_COMMAND}
"-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}"
-DBINARY="${BIN_PATH}"
-DDST=${PROJECT_BINARY_DIR}/windows_runtime_deps
-P ${PROJECT_SOURCE_DIR}/cmake/WindowsDllCopy.cmake
COMMAND ${CMAKE_COMMAND} -E copy ${BIN_PATH} ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMENT "${BIN_PATH}")
add_dependencies(nvim_runtime_deps "external_${BIN}")
endforeach()
add_custom_target(nvim_dll_deps DEPENDS nvim
COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps
COMMAND ${CMAKE_COMMAND}
@ -326,6 +307,34 @@ if(WIN32)
-DDST=${PROJECT_BINARY_DIR}/windows_runtime_deps
-P ${PROJECT_SOURCE_DIR}/cmake/WindowsDllCopy.cmake)
add_dependencies(nvim_runtime_deps nvim_dll_deps)
add_custom_target(external_blobs
COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps/platforms
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/ca-bundle.crt" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/curl.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/diff.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/tee.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/tidy.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/win32yank.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/D3Dcompiler_47.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libEGL.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libgcc_s_dw2-1.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libGLESV2.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libstdc++-6.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libwinpthread-1.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/nvim-qt.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Core.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Gui.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Network.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Svg.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Widgets.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/platforms/qwindows.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/platforms/
)
add_dependencies(nvim_runtime_deps external_blobs)
endif()
if(CLANG_ASAN_UBSAN)

View File

@ -1373,17 +1373,17 @@ void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left,
/// skipwhite: skip over ' ' and '\t'.
///
/// @param q
/// @param[in] q String to skip in.
///
/// @return Pointer to character after the skipped whitespace.
char_u* skipwhite(char_u *q)
char_u *skipwhite(const char_u *q)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
char_u *p = q;
const char_u *p = q;
while (ascii_iswhite(*p)) {
// skip to next non-white
p++;
}
return p;
return (char_u *)p;
}
/// skip over digits

View File

@ -1859,8 +1859,9 @@ static bool check_compl_option(bool dict_opt)
: (*curbuf->b_p_tsr == NUL && *p_tsr == NUL)) {
ctrl_x_mode = 0;
edit_submode = NULL;
msg_attr(dict_opt ? (char_u *)_("'dictionary' option is empty")
: (char_u *)_("'thesaurus' option is empty"), hl_attr(HLF_E));
msg_attr((dict_opt
? _("'dictionary' option is empty")
: _("'thesaurus' option is empty")), hl_attr(HLF_E));
if (emsg_silent == 0) {
vim_beep(BO_COMPL);
setcursor();
@ -4801,9 +4802,9 @@ static int ins_complete(int c, bool enable_pum)
if (!shortmess(SHM_COMPLETIONMENU)) {
if (edit_submode_extra != NULL) {
if (!p_smd) {
msg_attr(edit_submode_extra,
edit_submode_highl < HLF_COUNT
? hl_attr(edit_submode_highl) : 0);
msg_attr((const char *)edit_submode_extra,
(edit_submode_highl < HLF_COUNT
? hl_attr(edit_submode_highl) : 0));
}
} else {
msg_clr_cmdline(); // necessary for "noshowmode"

File diff suppressed because it is too large Load Diff

View File

@ -1474,12 +1474,12 @@ void append_redir(char *const buf, const size_t buflen,
void print_line_no_prefix(linenr_T lnum, int use_number, int list)
{
char_u numbuf[30];
char numbuf[30];
if (curwin->w_p_nu || use_number) {
vim_snprintf((char *)numbuf, sizeof(numbuf),
"%*ld ", number_width(curwin), (long)lnum);
msg_puts_attr(numbuf, hl_attr(HLF_N)); /* Highlight line nrs */
vim_snprintf(numbuf, sizeof(numbuf), "%*" PRIdLINENR " ",
number_width(curwin), lnum);
msg_puts_attr(numbuf, hl_attr(HLF_N)); // Highlight line nrs.
}
msg_prt_line(ml_get(lnum), list);
}
@ -5720,33 +5720,33 @@ void ex_sign(exarg_T *eap)
*/
static void sign_list_defined(sign_T *sp)
{
char_u *p;
smsg("sign %s", sp->sn_name);
if (sp->sn_icon != NULL) {
MSG_PUTS(" icon=");
msg_puts(" icon=");
msg_outtrans(sp->sn_icon);
MSG_PUTS(_(" (not supported)"));
msg_puts(_(" (not supported)"));
}
if (sp->sn_text != NULL) {
MSG_PUTS(" text=");
msg_puts(" text=");
msg_outtrans(sp->sn_text);
}
if (sp->sn_line_hl > 0) {
MSG_PUTS(" linehl=");
p = get_highlight_name(NULL, sp->sn_line_hl - 1);
if (p == NULL)
MSG_PUTS("NONE");
else
msg_puts(" linehl=");
const char *const p = get_highlight_name(NULL, sp->sn_line_hl - 1);
if (p == NULL) {
msg_puts("NONE");
} else {
msg_puts(p);
}
}
if (sp->sn_text_hl > 0) {
MSG_PUTS(" texthl=");
p = get_highlight_name(NULL, sp->sn_text_hl - 1);
if (p == NULL)
MSG_PUTS("NONE");
else
msg_puts(" texthl=");
const char *const p = get_highlight_name(NULL, sp->sn_text_hl - 1);
if (p == NULL) {
msg_puts("NONE");
} else {
msg_puts(p);
}
}
}

View File

@ -2250,7 +2250,7 @@ void ex_compiler(exarg_T *eap)
// plugin will then skip the settings. Afterwards set
// "b:current_compiler" and restore "current_compiler".
// Explicitly prepend "g:" to make it work in a function.
old_cur_comp = get_var_value((char_u *)"g:current_compiler");
old_cur_comp = get_var_value("g:current_compiler");
if (old_cur_comp != NULL) {
old_cur_comp = vim_strsave(old_cur_comp);
}
@ -2268,7 +2268,7 @@ void ex_compiler(exarg_T *eap)
do_cmdline_cmd(":delcommand CompilerSet");
// Set "b:current_compiler" from "current_compiler".
p = get_var_value((char_u *)"g:current_compiler");
p = get_var_value("g:current_compiler");
if (p != NULL) {
set_internal_string_var((char_u *)"b:current_compiler", p);
}

View File

@ -583,10 +583,10 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline,
++no_wait_return;
verbose_enter_scroll();
smsg(_("line %" PRId64 ": %s"),
(int64_t)sourcing_lnum, cmdline_copy);
if (msg_silent == 0)
msg_puts((char_u *)"\n"); /* don't overwrite this */
smsg(_("line %" PRIdLINENR ": %s"), sourcing_lnum, cmdline_copy);
if (msg_silent == 0) {
msg_puts("\n"); // don't overwrite this either
}
verbose_leave_scroll();
--no_wait_return;
@ -1815,9 +1815,9 @@ static char_u * do_one_cmd(char_u **cmdlinep,
errormsg = (char_u *)_("E493: Backwards range given");
goto doend;
}
if (ask_yesno((char_u *)
_("Backwards range given, OK to swap"), FALSE) != 'y')
if (ask_yesno(_("Backwards range given, OK to swap"), false) != 'y') {
goto doend;
}
}
lnum = ea.line1;
ea.line1 = ea.line2;
@ -2582,27 +2582,29 @@ int modifier_len(char_u *cmd)
* Return 2 if there is an exact match.
* Return 3 if there is an ambiguous match.
*/
int cmd_exists(char_u *name)
int cmd_exists(const char *const name)
{
exarg_T ea;
int full = FALSE;
int i;
int j;
char_u *p;
/* Check command modifiers. */
for (i = 0; i < (int)ARRAY_SIZE(cmdmods); ++i) {
for (j = 0; name[j] != NUL; ++j)
if (name[j] != cmdmods[i].name[j])
// Check command modifiers.
for (int i = 0; i < (int)ARRAY_SIZE(cmdmods); i++) {
int j;
for (j = 0; name[j] != NUL; j++) {
if (name[j] != (char)cmdmods[i].name[j]) {
break;
if (name[j] == NUL && j >= cmdmods[i].minlen)
}
}
if (name[j] == NUL && j >= cmdmods[i].minlen) {
return cmdmods[i].name[j] == NUL ? 2 : 1;
}
}
/* Check built-in commands and user defined commands.
* For ":2match" and ":3match" we need to skip the number. */
ea.cmd = (*name == '2' || *name == '3') ? name + 1 : name;
ea.cmd = (char_u *)((*name == '2' || *name == '3') ? name + 1 : name);
ea.cmdidx = (cmdidx_T)0;
int full = false;
p = find_command(&ea, &full);
if (p == NULL)
return 3;
@ -3940,8 +3942,6 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp)
* Don't do this for:
* - replacement that already has been escaped: "##"
* - shell commands (may have to use quotes instead).
* - non-unix systems when there is a single argument (spaces don't
* separate arguments then).
*/
if (!eap->usefilter
&& !escaped
@ -3952,9 +3952,7 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp)
&& eap->cmdidx != CMD_lgrep
&& eap->cmdidx != CMD_grepadd
&& eap->cmdidx != CMD_lgrepadd
#ifndef UNIX
&& !(eap->argt & NOSPC)
#endif
) {
char_u *l;
#ifdef BACKSLASH_IN_FILENAME
@ -4016,28 +4014,6 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp)
}
}
// Replace any other wildcards, remove backslashes.
#ifdef UNIX
/*
* Only for Unix we check for more than one file name.
* For other systems spaces are considered to be part
* of the file name.
* Only check here if there is no wildcard, otherwise
* ExpandOne() will check for errors. This allows
* ":e `ls ve*.c`" on Unix.
*/
if (!has_wildcards)
for (p = eap->arg; *p; ++p) {
/* skip escaped characters */
if (p[1] && (*p == '\\' || *p == Ctrl_V))
++p;
else if (ascii_iswhite(*p)) {
*errormsgp = (char_u *)_("E172: Only one file name allowed");
return FAIL;
}
}
#endif
/*
* Halve the number of backslashes (this is Vi compatible).
* For Unix, when wildcards are expanded, this is
@ -8246,9 +8222,9 @@ eval_vars (
char_u *resultbuf = NULL;
size_t resultlen;
buf_T *buf;
int valid = VALID_HEAD + VALID_PATH; /* assume valid result */
int skip_mod = FALSE;
char_u strbuf[30];
int valid = VALID_HEAD | VALID_PATH; // Assume valid result.
int skip_mod = false;
char strbuf[30];
*errormsg = NULL;
if (escaped != NULL)
@ -8380,8 +8356,8 @@ eval_vars (
"E496: no autocommand buffer number to substitute for \"<abuf>\"");
return NULL;
}
sprintf((char *)strbuf, "%d", autocmd_bufnr);
result = strbuf;
snprintf(strbuf, sizeof(strbuf), "%d", autocmd_bufnr);
result = (char_u *)strbuf;
break;
case SPEC_AMATCH: /* match name for autocommand */
@ -8406,8 +8382,8 @@ eval_vars (
*errormsg = (char_u *)_("E842: no line number to use for \"<slnum>\"");
return NULL;
}
sprintf((char *)strbuf, "%" PRId64, (int64_t)sourcing_lnum);
result = strbuf;
snprintf(strbuf, sizeof(strbuf), "%" PRIdLINENR, sourcing_lnum);
result = (char_u *)strbuf;
break;
default:
// should not happen

View File

@ -482,7 +482,7 @@ static int throw_exception(void *value, int type, char_u *cmdname)
msg_scroll = TRUE; /* always scroll up, don't overwrite */
smsg(_("Exception thrown: %s"), excp->value);
msg_puts((char_u *)"\n"); /* don't overwrite this either */
msg_puts("\n"); // don't overwrite this either
if (debug_break_level > 0 || *p_vfile == NUL)
cmdline_row = msg_row;
@ -532,15 +532,17 @@ static void discard_exception(except_T *excp, int was_finished)
smsg(was_finished ? _("Exception finished: %s")
: _("Exception discarded: %s"),
excp->value);
msg_puts((char_u *)"\n"); /* don't overwrite this either */
if (debug_break_level > 0 || *p_vfile == NUL)
msg_puts("\n"); // don't overwrite this either
if (debug_break_level > 0 || *p_vfile == NUL) {
cmdline_row = msg_row;
--no_wait_return;
if (debug_break_level > 0)
}
no_wait_return--;
if (debug_break_level > 0) {
msg_silent = save_msg_silent;
else
} else {
verbose_leave();
STRCPY(IObuff, saved_IObuff);
}
xstrlcpy((char *)IObuff, (const char *)saved_IObuff, IOSIZE);
xfree(saved_IObuff);
}
if (excp->type != ET_INTERRUPT)
@ -595,7 +597,7 @@ static void catch_exception(except_T *excp)
msg_scroll = TRUE; /* always scroll up, don't overwrite */
smsg(_("Exception caught: %s"), excp->value);
msg_puts((char_u *)"\n"); /* don't overwrite this either */
msg_puts("\n"); // don't overwrite this either
if (debug_break_level > 0 || *p_vfile == NUL)
cmdline_row = msg_row;
@ -714,7 +716,7 @@ static void report_pending(int action, int pending, void *value)
++no_wait_return;
msg_scroll = TRUE; /* always scroll up, don't overwrite */
smsg(mesg, s);
msg_puts((char_u *)"\n"); /* don't overwrite this either */
msg_puts("\n"); // don't overwrite this either
cmdline_row = msg_row;
--no_wait_return;
if (debug_break_level > 0)

View File

@ -1879,7 +1879,7 @@ getexmodeline (
vcol = indent;
while (indent >= 8) {
ga_append(&line_ga, TAB);
msg_puts((char_u *)" ");
msg_puts(" ");
indent -= 8;
}
while (indent-- > 0) {
@ -2608,7 +2608,7 @@ static void redrawcmdprompt(void)
if (ccline.cmdfirstc != NUL)
msg_putchar(ccline.cmdfirstc);
if (ccline.cmdprompt != NULL) {
msg_puts_attr(ccline.cmdprompt, ccline.cmdattr);
msg_puts_attr((const char *)ccline.cmdprompt, ccline.cmdattr);
ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns;
/* do the reverse of set_cmdspos() */
if (ccline.cmdfirstc != NUL)
@ -3317,7 +3317,7 @@ static int showmatches(expand_T *xp, int wildmenu)
msg_outtrans_attr(files_found[k], hl_attr(HLF_D));
p = files_found[k] + STRLEN(files_found[k]) + 1;
msg_advance(maxlen + 1);
msg_puts(p);
msg_puts((const char *)p);
msg_advance(maxlen + 3);
msg_puts_long_attr(p + 2, hl_attr(HLF_D));
break;
@ -3759,6 +3759,8 @@ static void cleanup_help_tags(int num_file, char_u **file)
}
}
typedef char_u *(*ExpandFunc)(expand_T *, int);
/*
* Do the expansion based on xp->xp_context and "pat".
*/
@ -3898,39 +3900,38 @@ ExpandFromContext (
else {
static struct expgen {
int context;
char_u *((*func)(expand_T *, int));
ExpandFunc func;
int ic;
int escaped;
} tab[] =
{
{EXPAND_COMMANDS, get_command_name, FALSE, TRUE},
{EXPAND_BEHAVE, get_behave_arg, TRUE, TRUE},
{EXPAND_HISTORY, get_history_arg, TRUE, TRUE},
{EXPAND_USER_COMMANDS, get_user_commands, FALSE, TRUE},
{EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, FALSE, TRUE},
{EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, FALSE, TRUE},
{EXPAND_USER_NARGS, get_user_cmd_nargs, FALSE, TRUE},
{EXPAND_USER_COMPLETE, get_user_cmd_complete, FALSE, TRUE},
{EXPAND_USER_VARS, get_user_var_name, FALSE, TRUE},
{EXPAND_FUNCTIONS, get_function_name, FALSE, TRUE},
{EXPAND_USER_FUNC, get_user_func_name, FALSE, TRUE},
{EXPAND_EXPRESSION, get_expr_name, FALSE, TRUE},
{EXPAND_MENUS, get_menu_name, FALSE, TRUE},
{EXPAND_MENUNAMES, get_menu_names, FALSE, TRUE},
{EXPAND_SYNTAX, get_syntax_name, TRUE, TRUE},
{EXPAND_SYNTIME, get_syntime_arg, TRUE, TRUE},
{EXPAND_HIGHLIGHT, get_highlight_name, TRUE, TRUE},
{EXPAND_EVENTS, get_event_name, TRUE, TRUE},
{EXPAND_AUGROUP, get_augroup_name, TRUE, TRUE},
{EXPAND_CSCOPE, get_cscope_name, TRUE, TRUE},
{EXPAND_SIGN, get_sign_name, TRUE, TRUE},
{EXPAND_PROFILE, get_profile_name, TRUE, TRUE},
} tab[] = {
{ EXPAND_COMMANDS, get_command_name, false, true },
{ EXPAND_BEHAVE, get_behave_arg, true, true },
{ EXPAND_HISTORY, get_history_arg, true, true },
{ EXPAND_USER_COMMANDS, get_user_commands, false, true },
{ EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, false, true },
{ EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, false, true },
{ EXPAND_USER_NARGS, get_user_cmd_nargs, false, true },
{ EXPAND_USER_COMPLETE, get_user_cmd_complete, false, true },
{ EXPAND_USER_VARS, get_user_var_name, false, true },
{ EXPAND_FUNCTIONS, get_function_name, false, true },
{ EXPAND_USER_FUNC, get_user_func_name, false, true },
{ EXPAND_EXPRESSION, get_expr_name, false, true },
{ EXPAND_MENUS, get_menu_name, false, true },
{ EXPAND_MENUNAMES, get_menu_names, false, true },
{ EXPAND_SYNTAX, get_syntax_name, true, true },
{ EXPAND_SYNTIME, get_syntime_arg, true, true },
{ EXPAND_HIGHLIGHT, (ExpandFunc)get_highlight_name, true, true },
{ EXPAND_EVENTS, get_event_name, true, true },
{ EXPAND_AUGROUP, get_augroup_name, true, true },
{ EXPAND_CSCOPE, get_cscope_name, true, true },
{ EXPAND_SIGN, get_sign_name, true, true },
{ EXPAND_PROFILE, get_profile_name, true, true },
#ifdef HAVE_WORKING_LIBINTL
{EXPAND_LANGUAGE, get_lang_arg, TRUE, FALSE},
{EXPAND_LOCALES, get_locales, TRUE, FALSE},
{ EXPAND_LANGUAGE, get_lang_arg, true, false },
{ EXPAND_LOCALES, get_locales, true, false },
#endif
{EXPAND_ENV_VARS, get_env_name, TRUE, TRUE},
{EXPAND_USER, get_users, TRUE, FALSE},
{ EXPAND_ENV_VARS, get_env_name, true, true },
{ EXPAND_USER, get_users, true, false },
};
int i;

View File

@ -1593,7 +1593,7 @@ void conv_to_pvim(void)
// Assume the screen has been messed up: clear it and redraw.
redraw_later(CLEAR);
MSG_ATTR(farsi_text_1, hl_attr(HLF_S));
MSG_ATTR((const char *)farsi_text_1, hl_attr(HLF_S));
}
/// Convert the Farsi VIM into Farsi 3342 standard.
@ -1614,7 +1614,7 @@ void conv_to_pstd(void)
// Assume the screen has been messed up: clear it and redraw.
redraw_later(CLEAR);
MSG_ATTR(farsi_text_2, hl_attr(HLF_S));
msg_attr((const char *)farsi_text_2, hl_attr(HLF_S));
}
/// left-right swap the characters in buf[len].

View File

@ -636,9 +636,8 @@ char_u *vim_findfile(void *search_ctx_arg)
if (p_verbose >= 5) {
verbose_enter_scroll();
smsg("Already Searched: %s (%s)",
stackp->ffs_fix_path, stackp->ffs_wc_path);
/* don't overwrite this either */
msg_puts((char_u *)"\n");
stackp->ffs_fix_path, stackp->ffs_wc_path);
msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
#endif
@ -650,8 +649,7 @@ char_u *vim_findfile(void *search_ctx_arg)
verbose_enter_scroll();
smsg("Searching: %s (%s)",
stackp->ffs_fix_path, stackp->ffs_wc_path);
/* don't overwrite this either */
msg_puts((char_u *)"\n");
msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
#endif
@ -809,10 +807,8 @@ char_u *vim_findfile(void *search_ctx_arg)
) == FAIL) {
if (p_verbose >= 5) {
verbose_enter_scroll();
smsg("Already: %s",
file_path);
/* don't overwrite this either */
msg_puts((char_u *)"\n");
smsg("Already: %s", file_path);
msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
continue;
@ -837,8 +833,7 @@ char_u *vim_findfile(void *search_ctx_arg)
if (p_verbose >= 5) {
verbose_enter_scroll();
smsg("HIT: %s", file_path);
/* don't overwrite this either */
msg_puts((char_u *)"\n");
msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
#endif
@ -999,10 +994,8 @@ static ff_visited_list_hdr_T *ff_get_visited_list(char_u *filename, ff_visited_l
#ifdef FF_VERBOSE
if (p_verbose >= 5) {
verbose_enter_scroll();
smsg("ff_get_visited_list: FOUND list for %s",
filename);
/* don't overwrite this either */
msg_puts((char_u *)"\n");
smsg("ff_get_visited_list: FOUND list for %s", filename);
msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
#endif
@ -1016,8 +1009,7 @@ static ff_visited_list_hdr_T *ff_get_visited_list(char_u *filename, ff_visited_l
if (p_verbose >= 5) {
verbose_enter_scroll();
smsg("ff_get_visited_list: new list for %s", filename);
/* don't overwrite this either */
msg_puts((char_u *)"\n");
msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
#endif

View File

@ -3895,15 +3895,15 @@ static int check_mtime(buf_T *buf, FileInfo *file_info)
if (buf->b_mtime_read != 0
&& time_differs(file_info->stat.st_mtim.tv_sec,
buf->b_mtime_read)) {
msg_scroll = TRUE; /* don't overwrite messages here */
msg_silent = 0; /* must give this prompt */
/* don't use emsg() here, don't want to flush the buffers */
MSG_ATTR(_("WARNING: The file has been changed since reading it!!!"),
hl_attr(HLF_E));
if (ask_yesno((char_u *)_("Do you really want to write to it"),
TRUE) == 'n')
msg_scroll = true; // Don't overwrite messages here.
msg_silent = 0; // Must give this prompt.
// Don't use emsg() here, don't want to flush the buffers.
msg_attr(_("WARNING: The file has been changed since reading it!!!"),
hl_attr(HLF_E));
if (ask_yesno(_("Do you really want to write to it"), true) == 'n') {
return FAIL;
msg_scroll = FALSE; /* always overwrite the file message now */
}
msg_scroll = false; // Always overwrite the file message now.
}
return OK;
}
@ -4778,8 +4778,8 @@ check_timestamps (
--no_wait_return;
need_check_timestamps = FALSE;
if (need_wait_return && didit == 2) {
/* make sure msg isn't overwritten */
msg_puts((char_u *)"\n");
// make sure msg isn't overwritten
msg_puts("\n");
ui_flush();
}
}
@ -5006,10 +5006,9 @@ buf_check_timestamp (
} else {
if (!autocmd_busy) {
msg_start();
msg_puts_attr((char_u *) tbuf, hl_attr(HLF_E) + MSG_HIST);
msg_puts_attr(tbuf, hl_attr(HLF_E) + MSG_HIST);
if (*mesg2 != NUL) {
msg_puts_attr((char_u *)mesg2,
hl_attr(HLF_W) + MSG_HIST);
msg_puts_attr(mesg2, hl_attr(HLF_W) + MSG_HIST);
}
msg_clr_eos();
(void)msg_end();
@ -5385,13 +5384,9 @@ char_u *vim_tempname(void)
static AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */
/*
* augroups stores a list of autocmd group names.
*/
static garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
// use get_deleted_augroup() to get this
static char_u *deleted_augroup = NULL;
/// List of autocmd group names
static garray_T augroups = { 0, 0, sizeof(char_u *), 10, NULL };
#define AUGROUP_NAME(i) (((char **)augroups.ga_data)[i])
/*
* The ID of the current group. Group 0 is the default one.
@ -5406,10 +5401,14 @@ static event_T last_event;
static int last_group;
static int autocmd_blocked = 0; /* block all autocmds */
static char_u *get_deleted_augroup(void)
// use get_deleted_augroup() to get this
static const char *deleted_augroup = NULL;
static inline const char *get_deleted_augroup(void)
FUNC_ATTR_ALWAYS_INLINE
{
if (deleted_augroup == NULL) {
deleted_augroup = (char_u *)_("--Deleted--");
deleted_augroup = _("--Deleted--");
}
return deleted_augroup;
}
@ -5438,7 +5437,7 @@ static void show_autocmd(AutoPat *ap, event_T event)
} else {
msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T));
}
msg_puts((char_u *)" ");
msg_puts(" ");
}
msg_puts_attr(event_nr2name(event), hl_attr(HLF_T));
last_event = event;
@ -5567,7 +5566,7 @@ void aubuflocal_remove(buf_T *buf)
if (p_verbose >= 6) {
verbose_enter();
smsg(_("auto-removing autocommand: %s <buffer=%d>"),
event_nr2name(event), buf->b_fnum);
event_nr2name(event), buf->b_fnum);
verbose_leave();
}
}
@ -5590,9 +5589,10 @@ static int au_new_group(char_u *name)
ga_grow(&augroups, 1);
}
AUGROUP_NAME(i) = vim_strsave(name);
if (i == augroups.ga_len)
++augroups.ga_len;
AUGROUP_NAME(i) = xstrdup((char *)name);
if (i == augroups.ga_len) {
augroups.ga_len++;
}
}
return i;
@ -5626,7 +5626,7 @@ static void au_del_group(char_u *name)
}
xfree(AUGROUP_NAME(i));
if (in_use) {
AUGROUP_NAME(i) = get_deleted_augroup();
AUGROUP_NAME(i) = (char *)get_deleted_augroup();
} else {
AUGROUP_NAME(i) = NULL;
}
@ -5680,7 +5680,7 @@ void do_augroup(char_u *arg, int del_group)
for (int i = 0; i < augroups.ga_len; ++i) {
if (AUGROUP_NAME(i) != NULL) {
msg_puts(AUGROUP_NAME(i));
msg_puts((char_u *)" ");
msg_puts(" ");
}
}
msg_clr_eos();
@ -5691,23 +5691,19 @@ void do_augroup(char_u *arg, int del_group)
#if defined(EXITFREE)
void free_all_autocmds(void)
{
int i;
char_u *s;
for (current_augroup = -1; current_augroup < augroups.ga_len;
current_augroup++) {
do_autocmd((char_u *)"", true);
}
for (i = 0; i < augroups.ga_len; i++) {
s = ((char_u **)(augroups.ga_data))[i];
if (s != get_deleted_augroup()) {
xfree(s);
}
for (int i = 0; i < augroups.ga_len; i++) {
char *const s = ((char **)(augroups.ga_data))[i];
if ((const char *)s != get_deleted_augroup()) {
xfree(s);
}
}
ga_clear(&augroups);
}
#endif
/*
@ -5715,13 +5711,13 @@ void free_all_autocmds(void)
* Return NUM_EVENTS if the event name was not found.
* Return a pointer to the next event name in "end".
*/
static event_T event_name2nr(char_u *start, char_u **end)
static event_T event_name2nr(const char_u *start, char_u **end)
{
char_u *p;
const char_u *p;
int i;
int len;
// the event name ends with end of line, '|', a blank or a comma */
// the event name ends with end of line, '|', a blank or a comma
for (p = start; *p && !ascii_iswhite(*p) && *p != ',' && *p != '|'; p++) {
}
for (i = 0; event_names[i].name != NULL; i++) {
@ -5730,25 +5726,32 @@ static event_T event_name2nr(char_u *start, char_u **end)
break;
}
}
if (*p == ',')
++p;
*end = p;
if (event_names[i].name == NULL)
if (*p == ',') {
p++;
}
*end = (char_u *)p;
if (event_names[i].name == NULL) {
return NUM_EVENTS;
}
return event_names[i].event;
}
/*
* Return the name for event "event".
*/
static char_u *event_nr2name(event_T event)
/// Return the name for event
///
/// @param[in] event Event to return name for.
///
/// @return Event name, static string. Returns "Unknown" for unknown events.
static const char *event_nr2name(event_T event)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_CONST
{
int i;
for (i = 0; event_names[i].name != NULL; ++i)
if (event_names[i].event == event)
return (char_u *)event_names[i].name;
return (char_u *)"Unknown";
for (i = 0; event_names[i].name != NULL; i++) {
if (event_names[i].event == event) {
return event_names[i].name;
}
}
return "Unknown";
}
/*
@ -7013,7 +7016,6 @@ auto_next_pat (
{
AutoPat *ap;
AutoCmd *cp;
char_u *name;
char *s;
xfree(sourcing_name);
@ -7032,11 +7034,13 @@ auto_next_pat (
? match_file_pat(NULL, &ap->reg_prog, apc->fname, apc->sfname,
apc->tail, ap->allow_dirs)
: ap->buflocal_nr == apc->arg_bufnr) {
name = event_nr2name(apc->event);
const char *const name = event_nr2name(apc->event);
s = _("%s Auto commands for \"%s\"");
sourcing_name = xmalloc(STRLEN(s) + STRLEN(name) + ap->patlen + 1);
sprintf((char *)sourcing_name, s,
(char *)name, (char *)ap->pat);
const size_t sourcing_name_len = (STRLEN(s) + strlen(name) + ap->patlen
+ 1);
sourcing_name = xmalloc(sourcing_name_len);
snprintf((char *)sourcing_name, sourcing_name_len, s, name,
(char *)ap->pat);
if (p_verbose >= 8) {
verbose_enter();
smsg(_("Executing %s"), sourcing_name);
@ -7102,7 +7106,7 @@ char_u *getnextac(int c, void *cookie, int indent)
if (p_verbose >= 9) {
verbose_enter_scroll();
smsg(_("autocommand %s"), ac->cmd);
msg_puts((char_u *)"\n"); /* don't overwrite this either */
msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
retval = vim_strsave(ac->cmd);
@ -7168,15 +7172,17 @@ bool has_autocmd(event_T event, char_u *sfname, buf_T *buf)
*/
char_u *get_augroup_name(expand_T *xp, int idx)
{
if (idx == augroups.ga_len) /* add "END" add the end */
if (idx == augroups.ga_len) { // add "END" add the end
return (char_u *)"END";
if (idx >= augroups.ga_len) /* end of list */
}
if (idx >= augroups.ga_len) { // end of list
return NULL;
}
if (AUGROUP_NAME(idx) == NULL || AUGROUP_NAME(idx) == get_deleted_augroup()) {
// skip deleted entries
return (char_u *)"";
}
return AUGROUP_NAME(idx); // return a name
return (char_u *)AUGROUP_NAME(idx);
}
static int include_groups = FALSE;
@ -7238,18 +7244,22 @@ char_u *get_event_name(expand_T *xp, int idx)
|| AUGROUP_NAME(idx) == get_deleted_augroup()) {
return (char_u *)""; // skip deleted entries
}
return AUGROUP_NAME(idx); // return a name
return (char_u *)AUGROUP_NAME(idx);
}
return (char_u *)event_names[idx - augroups.ga_len].name;
}
/// Return true if autocmd "event" is supported.
bool autocmd_supported(char_u *event)
/// Check whether given autocommand is supported
///
/// @param[in] event Event to check.
///
/// @return True if it is, false otherwise.
bool autocmd_supported(const char *const event)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
char_u *p;
return event_name2nr(event, &p) != NUM_EVENTS;
return event_name2nr((const char_u *)event, &p) != NUM_EVENTS;
}
/// Return true if an autocommand is defined for a group, event and
@ -7264,26 +7274,24 @@ bool autocmd_supported(char_u *event)
/// exists("#Event#pat")
///
/// @param arg autocommand string
bool au_exists(const char_u *arg) FUNC_ATTR_WARN_UNUSED_RESULT
bool au_exists(const char *const arg) FUNC_ATTR_WARN_UNUSED_RESULT
{
char_u *arg_save;
char_u *pattern = NULL;
char_u *event_name;
char_u *p;
event_T event;
AutoPat *ap;
buf_T *buflocal_buf = NULL;
int group;
bool retval = false;
/* Make a copy so that we can change the '#' chars to a NUL. */
arg_save = vim_strsave(arg);
p = vim_strchr(arg_save, '#');
if (p != NULL)
// Make a copy so that we can change the '#' chars to a NUL.
char *const arg_save = xstrdup(arg);
char *p = strchr(arg_save, '#');
if (p != NULL) {
*p++ = NUL;
}
/* First, look for an autocmd group name */
group = au_find_group(arg_save);
// First, look for an autocmd group name.
group = au_find_group((char_u *)arg_save);
char *event_name;
if (group == AUGROUP_ERROR) {
/* Didn't match a group name, assume the first argument is an event. */
group = AUGROUP_ALL;
@ -7295,17 +7303,18 @@ bool au_exists(const char_u *arg) FUNC_ATTR_WARN_UNUSED_RESULT
goto theend;
}
/* Must be "Group#Event" or "Group#Event#pat". */
// Must be "Group#Event" or "Group#Event#pat".
event_name = p;
p = vim_strchr(event_name, '#');
if (p != NULL)
*p++ = NUL; /* "Group#Event#pat" */
p = strchr(event_name, '#');
if (p != NULL) {
*p++ = NUL; // "Group#Event#pat"
}
}
pattern = p; /* "pattern" is NULL when there is no pattern */
char *pattern = p; // "pattern" is NULL when there is no pattern.
/* find the index (enum) for the event name */
event = event_name2nr(event_name, &p);
// Find the index (enum) for the event name.
event = event_name2nr((char_u *)event_name, (char_u **)&p);
/* return FALSE if the event name is not recognized */
if (event == NUM_EVENTS)
@ -7331,7 +7340,7 @@ bool au_exists(const char_u *arg) FUNC_ATTR_WARN_UNUSED_RESULT
&& (group == AUGROUP_ALL || ap->group == group)
&& (pattern == NULL
|| (buflocal_buf == NULL
? fnamecmp(ap->pat, pattern) == 0
? fnamecmp(ap->pat, (char_u *)pattern) == 0
: ap->buflocal_nr == buflocal_buf->b_fnum))) {
retval = true;
break;

View File

@ -1913,17 +1913,13 @@ static int vgetorpeek(int advance)
if ((mp == NULL || max_mlen >= mp_match_len)
&& keylen != KEYLEN_PART_MAP) {
/*
* When no matching mapping found or found a
* non-matching mapping that matches at least what the
* matching mapping matched:
* Check if we have a terminal code, when:
* mapping is allowed,
* keys have not been mapped,
* and not an ESC sequence, not in insert mode or
* p_ek is on,
* and when not timed out,
*/
// When no matching mapping found or found a non-matching mapping
// that matches at least what the matching mapping matched:
// Check if we have a terminal code, when:
// mapping is allowed,
// keys have not been mapped,
// and not an ESC sequence, not in insert mode,
// and when not timed out.
if ((no_mapping == 0 || allow_keys != 0)
&& (typebuf.tb_maplen == 0
|| (p_remap && typebuf.tb_noremap[
@ -3165,11 +3161,11 @@ map_clear_int (
}
}
/*
* Return characters to represent the map mode in an allocated string.
* Returns NULL when out of memory.
*/
char_u *map_mode_to_chars(int mode)
/// Return characters to represent the map mode in an allocated string
///
/// @return [allocated] NUL-terminated string with characters.
char *map_mode_to_chars(int mode)
FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET
{
garray_T mapmode;
@ -3202,7 +3198,7 @@ char_u *map_mode_to_chars(int mode)
}
ga_append(&mapmode, NUL);
return (char_u *)mapmode.ga_data;
return (char *)mapmode.ga_data;
}
static void
@ -3211,8 +3207,7 @@ showmap (
int local /* TRUE for buffer-local map */
)
{
int len = 1;
char_u *mapchars;
size_t len = 1;
if (msg_didout || msg_silent != 0) {
msg_putchar('\n');
@ -3220,29 +3215,30 @@ showmap (
return;
}
mapchars = map_mode_to_chars(mp->m_mode);
if (mapchars != NULL) {
{
char *const mapchars = map_mode_to_chars(mp->m_mode);
msg_puts(mapchars);
len = (int)STRLEN(mapchars);
len = strlen(mapchars);
xfree(mapchars);
}
while (++len <= 3)
msg_putchar(' ');
/* Display the LHS. Get length of what we write. */
len = msg_outtrans_special(mp->m_keys, TRUE);
// Display the LHS. Get length of what we write.
len = (size_t)msg_outtrans_special(mp->m_keys, true);
do {
msg_putchar(' '); /* padd with blanks */
++len;
} while (len < 12);
if (mp->m_noremap == REMAP_NONE)
msg_puts_attr((char_u *)"*", hl_attr(HLF_8));
else if (mp->m_noremap == REMAP_SCRIPT)
msg_puts_attr((char_u *)"&", hl_attr(HLF_8));
else
if (mp->m_noremap == REMAP_NONE) {
msg_puts_attr("*", hl_attr(HLF_8));
} else if (mp->m_noremap == REMAP_SCRIPT) {
msg_puts_attr("&", hl_attr(HLF_8));
} else {
msg_putchar(' ');
}
if (local)
msg_putchar('@');
@ -3251,11 +3247,11 @@ showmap (
/* Use FALSE below if we only want things like <Up> to show up as such on
* the rhs, and not M-x etc, TRUE gets both -- webb */
if (*mp->m_str == NUL)
msg_puts_attr((char_u *)"<Nop>", hl_attr(HLF_8));
else {
/* Remove escaping of CSI, because "m_str" is in a format to be used
* as typeahead. */
if (*mp->m_str == NUL) {
msg_puts_attr("<Nop>", hl_attr(HLF_8));
} else {
// Remove escaping of CSI, because "m_str" is in a format to be used
// as typeahead.
char_u *s = vim_strsave(mp->m_str);
vim_unescape_csi(s);
msg_outtrans_special(s, FALSE);

View File

@ -882,8 +882,13 @@ EXTERN int swap_exists_did_quit INIT(= FALSE);
EXTERN char_u IObuff[IOSIZE]; ///< Buffer for sprintf, I/O, etc.
EXTERN char_u NameBuff[MAXPATHL]; ///< Buffer for expanding file names
EXTERN char_u msg_buf[MSG_BUF_LEN]; ///< Small buffer for messages
EXTERN char os_buf[MAX(MAXPATHL, IOSIZE)]; ///< Buffer for the os/ layer
EXTERN char os_buf[ ///< Buffer for the os/ layer
#if MAXPATHL > IOSIZE
MAXPATHL
#else
IOSIZE
#endif
];
/* When non-zero, postpone redrawing. */
EXTERN int RedrawingDisabled INIT(= 0);

View File

@ -82,22 +82,42 @@ void hash_clear_all(hashtab_T *ht, unsigned int off)
/// used for that key.
/// WARNING: Returned pointer becomes invalid as soon as the hash table
/// is changed in any way.
hashitem_T* hash_find(hashtab_T *ht, char_u *key)
hashitem_T *hash_find(hashtab_T *ht, const char_u *key)
{
return hash_lookup(ht, key, hash_hash(key));
return hash_lookup(ht, (const char *)key, STRLEN(key), hash_hash(key));
}
/// Like hash_find, but key is not NUL-terminated
///
/// @param[in] ht Hashtab to look in.
/// @param[in] key Key of the looked-for item. Must not be NULL.
/// @param[in] len Key length.
///
/// @return Pointer to the hash item corresponding to the given key.
/// If not found, then return pointer to the empty item that would be
/// used for that key.
///
/// @warning Returned pointer becomes invalid as soon as the hash table
/// is changed in any way.
hashitem_T *hash_find_len(hashtab_T *ht, const char *key, const size_t len)
{
return hash_lookup(ht, key, len, hash_hash_len(key, len));
}
/// Like hash_find(), but caller computes "hash".
///
/// @param key The key of the looked-for item. Must not be NULL.
/// @param hash The precomputed hash for the key.
/// @param[in] key The key of the looked-for item. Must not be NULL.
/// @param[in] key_len Key length.
/// @param[in] hash The precomputed hash for the key.
///
/// @return Pointer to the hashitem corresponding to the given key.
/// If not found, then return pointer to the empty item that would be
/// used for that key.
/// WARNING: Returned pointer becomes invalid as soon as the hash table
/// is changed in any way.
hashitem_T* hash_lookup(hashtab_T *ht, char_u *key, hash_T hash)
hashitem_T *hash_lookup(hashtab_T *const ht,
const char *const key, const size_t key_len,
const hash_T hash)
{
#ifdef HT_DEBUG
hash_count_lookup++;
@ -117,7 +137,9 @@ hashitem_T* hash_lookup(hashtab_T *ht, char_u *key, hash_T hash)
hashitem_T *freeitem = NULL;
if (hi->hi_key == HI_KEY_REMOVED) {
freeitem = hi;
} else if ((hi->hi_hash == hash) && (STRCMP(hi->hi_key, key) == 0)) {
} else if ((hi->hi_hash == hash)
&& (STRNCMP(hi->hi_key, key, key_len) == 0)
&& hi->hi_key[key_len] == NUL) {
return hi;
}
@ -142,7 +164,8 @@ hashitem_T* hash_lookup(hashtab_T *ht, char_u *key, hash_T hash)
if ((hi->hi_hash == hash)
&& (hi->hi_key != HI_KEY_REMOVED)
&& (STRCMP(hi->hi_key, key) == 0)) {
&& (STRNCMP(hi->hi_key, key, key_len) == 0)
&& hi->hi_key[key_len] == NUL) {
return hi;
}
@ -179,7 +202,7 @@ void hash_debug_results(void)
int hash_add(hashtab_T *ht, char_u *key)
{
hash_T hash = hash_hash(key);
hashitem_T *hi = hash_lookup(ht, key, hash);
hashitem_T *hi = hash_lookup(ht, (const char *)key, STRLEN(key), hash);
if (!HASHITEM_EMPTY(hi)) {
EMSG2(_(e_intern2), "hash_add()");
return FAIL;
@ -359,13 +382,16 @@ static void hash_may_resize(hashtab_T *ht, size_t minitems)
ht->ht_filled = ht->ht_used;
}
#define HASH_CYCLE_BODY(hash, p) \
hash = hash * 101 + *p++
/// Get the hash number for a key.
///
/// If you think you know a better hash function: Compile with HT_DEBUG set and
/// run a script that uses hashtables a lot. Vim will then print statistics
/// when exiting. Try that with the current hash algorithm and yours. The
/// lower the percentage the better.
hash_T hash_hash(char_u *key)
hash_T hash_hash(const char_u *key)
{
hash_T hash = *key;
@ -375,14 +401,43 @@ hash_T hash_hash(char_u *key)
// A simplistic algorithm that appears to do very well.
// Suggested by George Reilly.
char_u *p = key + 1;
const uint8_t *p = key + 1;
while (*p != NUL) {
hash = hash * 101 + *p++;
HASH_CYCLE_BODY(hash, p);
}
return hash;
}
/// Get the hash number for a key that is not a NUL-terminated string
///
/// @warning Function does not check whether key contains NUL. But you will not
/// be able to get hash entry in this case.
///
/// @param[in] key Key.
/// @param[in] len Key length.
///
/// @return Key hash.
hash_T hash_hash_len(const char *key, const size_t len)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
if (len == 0) {
return 0;
}
hash_T hash = *(uint8_t *)key;
const uint8_t *end = (uint8_t *)key + len;
const uint8_t *p = (const uint8_t *)key + 1;
while (p < end) {
HASH_CYCLE_BODY(hash, p);
}
return hash;
}
#undef HASH_CYCLE_BODY
/// Function to get HI_KEY_REMOVED value
///
/// Used for testing because luajit ffi does not allow getting addresses of

View File

@ -2008,8 +2008,9 @@ static int cs_reset(exarg_T *eap)
xfree(pplist);
xfree(fllist);
if (p_csverbose)
MSG_ATTR(_("All cscope databases reset"), hl_attr(HLF_R) | MSG_HIST);
if (p_csverbose) {
msg_attr(_("All cscope databases reset"), hl_attr(HLF_R) | MSG_HIST);
}
return CSCOPE_SUCCESS;
} /* cs_reset */

View File

@ -843,10 +843,10 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len,
// If "mapleader" or "maplocalleader" isn't set use a backslash.
if (end - src >= 7 && STRNICMP(src, "<Leader>", 8) == 0) {
len = 8;
p = get_var_value((char_u *)"g:mapleader");
p = get_var_value("g:mapleader");
} else if (end - src >= 12 && STRNICMP(src, "<LocalLeader>", 13) == 0) {
len = 13;
p = get_var_value((char_u *)"g:maplocalleader");
p = get_var_value("g:maplocalleader");
} else {
len = 0;
p = NULL;

View File

@ -1410,8 +1410,8 @@ recover_names (
for (int i = 0; i < num_files; ++i) {
/* print the swap file name */
msg_outnum((long)++file_count);
MSG_PUTS(". ");
msg_puts(path_tail(files[i]));
msg_puts(". ");
msg_puts((const char *)path_tail(files[i]));
msg_putchar('\n');
(void)swapfile_info(files[i]);
}

View File

@ -755,10 +755,11 @@ static void show_menus_recursive(vimmenu_T *menu, int modes, int depth)
else
msg_putchar(' ');
MSG_PUTS(" ");
if (*menu->strings[bit] == NUL)
msg_puts_attr((char_u *)"<Nop>", hl_attr(HLF_8));
else
msg_outtrans_special(menu->strings[bit], FALSE);
if (*menu->strings[bit] == NUL) {
msg_puts_attr("<Nop>", hl_attr(HLF_8));
} else {
msg_outtrans_special(menu->strings[bit], false);
}
}
} else {
if (menu == NULL) {

File diff suppressed because it is too large Load Diff

View File

@ -3,8 +3,9 @@
#include <stdbool.h>
#include <stdarg.h>
#include "nvim/eval_defs.h" // for typval_T
#include "nvim/ex_cmds_defs.h" // for exarg_T
#include <stddef.h>
#include "nvim/types.h"
/*
* Types of dialogs passed to do_dialog().
@ -29,7 +30,7 @@
#define MSG(s) msg((char_u *)(s))
/// Show message highlighted according to the attr
#define MSG_ATTR(s, attr) msg_attr((char_u *)(s), (attr))
#define MSG_ATTR(s, attr) msg_attr((const char *)(s), (attr))
/// Display error message
///
@ -49,13 +50,13 @@
#define EMSGU(s, n) emsgf((const char *) (s), (uint64_t)(n))
/// Display message at the recorded position
#define MSG_PUTS(s) msg_puts((char_u *)(s))
#define MSG_PUTS(s) msg_puts((const char *)(s))
/// Display message at the recorded position, highlighted
#define MSG_PUTS_ATTR(s, a) msg_puts_attr((char_u *)(s), (a))
#define MSG_PUTS_ATTR(s, a) msg_puts_attr((const char *)(s), (a))
/// Like #MSG_PUTS, but highlight like title
#define MSG_PUTS_TITLE(s) msg_puts_title((char_u *)(s))
#define MSG_PUTS_TITLE(s) msg_puts_title((const char *)(s))
/// Like #MSG_PUTS, but if middle part of too long messages it will be replaced
#define MSG_PUTS_LONG(s) msg_puts_long_attr((char_u *)(s), 0)

View File

@ -2223,7 +2223,7 @@ change_warning (
*
* return the 'y' or 'n'
*/
int ask_yesno(char_u *str, int direct)
int ask_yesno(const char *str, bool direct)
{
int r = ' ';
int save_State = State;
@ -2545,7 +2545,7 @@ void vim_beep(unsigned val)
* function give the user a hint where the beep comes from. */
if (vim_strchr(p_debug, 'e') != NULL) {
msg_source(hl_attr(HLF_W));
msg_attr((char_u *)_("Beep!"), hl_attr(HLF_W));
msg_attr(_("Beep!"), hl_attr(HLF_W));
}
}
}

View File

@ -617,7 +617,7 @@ static void normal_redraw_mode_message(NormalState *s)
update_screen(0);
// now reset it, otherwise it's put in the history again
keep_msg = kmsg;
msg_attr(kmsg, keep_msg_attr);
msg_attr((const char *)kmsg, keep_msg_attr);
xfree(kmsg);
}
setcursor();
@ -1276,7 +1276,7 @@ static void normal_redraw(NormalState *s)
// msg_attr_keep() will set keep_msg to NULL, must free the string here.
// Don't reset keep_msg, msg_attr_keep() uses it to check for duplicates.
char *p = (char *)keep_msg;
msg_attr((uint8_t *)p, keep_msg_attr);
msg_attr(p, keep_msg_attr);
xfree(p);
}

View File

@ -1260,7 +1260,7 @@ int get_spec_reg(
/// Paste a yank register into the command line.
/// Only for non-special registers.
/// Used by CTRL-R command in command-line mode
/// Used by CTRL-R in command-line mode.
/// insert_reg() can't be used here, because special characters from the
/// register contents will be interpreted as commands.
///
@ -1278,9 +1278,8 @@ bool cmdline_paste_reg(int regname, bool literally, bool remcr)
for (size_t i = 0; i < reg->y_size; i++) {
cmdline_paste_str(reg->y_array[i], literally);
// Insert ^M between lines and after last line if type is kMTLineWise.
// Don't do this when "remcr" is true.
if ((reg->y_type == kMTLineWise || i < reg->y_size - 1) && !remcr) {
// Insert ^M between lines, unless `remcr` is true.
if (i < reg->y_size - 1 && !remcr) {
cmdline_paste_str((char_u *)"\r", literally);
}

View File

@ -2569,12 +2569,11 @@ did_set_string_option (
init_highlight(FALSE, FALSE);
if (dark != (*p_bg == 'd')
&& get_var_value((char_u *)"g:colors_name") != NULL) {
/* The color scheme must have set 'background' back to another
* value, that's not what we want here. Disable the color
* scheme and set the colors again. */
do_unlet((char_u *)"g:colors_name", TRUE);
if (dark != (*p_bg == 'd') && get_var_value("g:colors_name") != NULL) {
// The color scheme must have set 'background' back to another
// value, that's not what we want here. Disable the color
// scheme and set the colors again.
do_unlet((char_u *)"g:colors_name", true);
free_string_option(p_bg);
p_bg = vim_strsave((char_u *)(dark ? "dark" : "light"));
check_string_option(&p_bg);
@ -3886,7 +3885,7 @@ set_bool_option (
"W17: Arabic requires UTF-8, do ':set encoding=utf-8'");
msg_source(hl_attr(HLF_W));
MSG_ATTR(_(w_arabic), hl_attr(HLF_W));
msg_attr(_(w_arabic), hl_attr(HLF_W));
set_vim_var_string(VV_WARNINGMSG, _(w_arabic), -1);
}

View File

@ -411,7 +411,6 @@ EXTERN char_u *p_efm; // 'errorformat'
EXTERN char_u *p_gefm; // 'grepformat'
EXTERN char_u *p_gp; // 'grepprg'
EXTERN char_u *p_ei; // 'eventignore'
EXTERN int p_ek; // 'esckeys'
EXTERN int p_exrc; // 'exrc'
EXTERN char_u *p_fencs; // 'fileencodings'
EXTERN char_u *p_ffs; // 'fileformats'

View File

@ -710,13 +710,6 @@ return {
varname='p_efm',
defaults={if_true={vi=macros('DFLT_EFM')}}
},
{
full_name='esckeys', abbreviation='ek',
type='bool', scope={'global'},
vim=true,
varname='p_ek',
defaults={if_true={vi=false, vim=true}}
},
{
full_name='eventignore', abbreviation='ei',
type='string', list='onecomma', scope={'global'},

View File

@ -2,6 +2,8 @@
#define NVIM_POS_H
typedef long linenr_T; // line number type
/// Format used to print values which have linenr_T type
#define PRIdLINENR "ld"
/// Column number type
typedef int colnr_T;

View File

@ -2068,21 +2068,20 @@ void qf_list(exarg_T *eap)
if (qfp->qf_lnum == 0) {
IObuff[0] = NUL;
} else if (qfp->qf_col == 0) {
vim_snprintf((char *)IObuff, IOSIZE, ":%" PRId64,
(int64_t)qfp->qf_lnum);
vim_snprintf((char *)IObuff, IOSIZE, ":%" PRIdLINENR, qfp->qf_lnum);
} else {
vim_snprintf((char *)IObuff, IOSIZE, ":%" PRId64 " col %d",
(int64_t)qfp->qf_lnum, qfp->qf_col);
vim_snprintf((char *)IObuff, IOSIZE, ":%" PRIdLINENR " col %d",
qfp->qf_lnum, qfp->qf_col);
}
vim_snprintf((char *)IObuff + STRLEN(IObuff), IOSIZE, "%s:",
(char *)qf_types(qfp->qf_type, qfp->qf_nr));
msg_puts_attr(IObuff, hl_attr(HLF_N));
msg_puts_attr((const char *)IObuff, hl_attr(HLF_N));
if (qfp->qf_pattern != NULL) {
qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE);
STRCAT(IObuff, ":");
msg_puts(IObuff);
xstrlcat((char *)IObuff, ":", IOSIZE);
msg_puts((const char *)IObuff);
}
msg_puts((char_u *)" ");
msg_puts(" ");
/* Remove newlines and leading whitespace from the text. For an
* unrecognized line keep the indent, the compiler may mark a word

View File

@ -6719,17 +6719,19 @@ int showmode(void)
if (edit_submode_pre != NULL)
length -= vim_strsize(edit_submode_pre);
if (length - vim_strsize(edit_submode) > 0) {
if (edit_submode_pre != NULL)
msg_puts_attr(edit_submode_pre, attr);
msg_puts_attr(edit_submode, attr);
if (edit_submode_pre != NULL) {
msg_puts_attr((const char *)edit_submode_pre, attr);
}
msg_puts_attr((const char *)edit_submode, attr);
}
if (edit_submode_extra != NULL) {
MSG_PUTS_ATTR(" ", attr); /* add a space in between */
if ((int)edit_submode_highl < (int)HLF_COUNT)
MSG_PUTS_ATTR(" ", attr); // Add a space in between.
if ((int)edit_submode_highl < (int)HLF_COUNT) {
sub_attr = hl_attr(edit_submode_highl);
else
} else {
sub_attr = attr;
msg_puts_attr(edit_submode_extra, sub_attr);
}
msg_puts_attr((const char *)edit_submode_extra, sub_attr);
}
}
} else {

View File

@ -4656,12 +4656,12 @@ static void show_pat_in_path(char_u *line, int type, int did_show, int action, F
*(p + 1) = NUL;
}
if (action == ACTION_SHOW_ALL) {
sprintf((char *)IObuff, "%3ld: ", count); /* show match nr */
msg_puts(IObuff);
sprintf((char *)IObuff, "%4ld", *lnum); /* show line nr */
/* Highlight line numbers */
msg_puts_attr(IObuff, hl_attr(HLF_N));
MSG_PUTS(" ");
snprintf((char *)IObuff, IOSIZE, "%3ld: ", count); // Show match nr.
msg_puts((const char *)IObuff);
snprintf((char *)IObuff, IOSIZE, "%4ld", *lnum); // Show line nr.
// Highlight line numbers.
msg_puts_attr((const char *)IObuff, hl_attr(HLF_N));
msg_puts(" ");
}
msg_prt_line(line, FALSE);
ui_flush(); /* show one line at a time */

View File

@ -3094,10 +3094,11 @@ count_common_word (
}
hash = hash_hash(p);
hi = hash_lookup(&lp->sl_wordcount, p, hash);
const size_t p_len = STRLEN(p);
hi = hash_lookup(&lp->sl_wordcount, (const char *)p, p_len, hash);
if (HASHITEM_EMPTY(hi)) {
wc = xmalloc(sizeof(wordcount_T) + STRLEN(p));
STRCPY(wc->wc_word, p);
wc = xmalloc(sizeof(wordcount_T) + p_len);
memcpy(wc->wc_word, p, p_len + 1);
wc->wc_count = count;
hash_add_item(&lp->sl_wordcount, hi, wc->wc_word, hash);
} else {
@ -5513,7 +5514,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
}
hash = hash_hash(dw);
hi = hash_lookup(&ht, dw, hash);
hi = hash_lookup(&ht, (const char *)dw, STRLEN(dw), hash);
if (!HASHITEM_EMPTY(hi)) {
if (p_verbose > 0)
smsg(_("Duplicate word in %s line %d: %s"),
@ -6343,7 +6344,7 @@ static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int
if (spin->si_verbose) {
msg_start();
msg_puts((char_u *)_(msg_compressing));
msg_puts(_(msg_compressing));
msg_clr_eos();
msg_didout = FALSE;
msg_col = 0;
@ -6519,7 +6520,8 @@ node_compress (
// Try to find an identical child.
hash = hash_hash(child->wn_u1.hashkey);
hi = hash_lookup(ht, child->wn_u1.hashkey, hash);
hi = hash_lookup(ht, (const char *)child->wn_u1.hashkey,
STRLEN(child->wn_u1.hashkey), hash);
if (!HASHITEM_EMPTY(hi)) {
// There are children we encountered before with a hash value
// identical to the current child. Now check if there is one
@ -8515,7 +8517,7 @@ void spell_suggest(int count)
vim_snprintf((char *)IObuff, IOSIZE, ":ot \"%.*s\" egnahC",
sug.su_badlen, sug.su_badptr);
}
msg_puts(IObuff);
msg_puts((const char *)IObuff);
msg_clr_eos();
msg_putchar('\n');
@ -8531,18 +8533,19 @@ void spell_suggest(int count)
sug.su_badptr + stp->st_orglen,
sug.su_badlen - stp->st_orglen + 1);
vim_snprintf((char *)IObuff, IOSIZE, "%2d", i + 1);
if (cmdmsg_rl)
if (cmdmsg_rl) {
rl_mirror(IObuff);
msg_puts(IObuff);
}
msg_puts((const char *)IObuff);
vim_snprintf((char *)IObuff, IOSIZE, " \"%s\"", wcopy);
msg_puts(IObuff);
msg_puts((const char *)IObuff);
// The word may replace more than "su_badlen".
if (sug.su_badlen < stp->st_orglen) {
vim_snprintf((char *)IObuff, IOSIZE, _(" < \"%.*s\""),
stp->st_orglen, sug.su_badptr);
msg_puts(IObuff);
stp->st_orglen, sug.su_badptr);
msg_puts((const char *)IObuff);
}
if (p_verbose > 0) {
@ -8558,7 +8561,7 @@ void spell_suggest(int count)
// Mirror the numbers, but keep the leading space.
rl_mirror(IObuff + 1);
msg_advance(30);
msg_puts(IObuff);
msg_puts((const char *)IObuff);
}
msg_putchar('\n');
}
@ -11182,11 +11185,13 @@ add_sound_suggest (
// the words that have a better score than before. Use a hashtable to
// remember the words that have been done.
hash = hash_hash(goodword);
hi = hash_lookup(&slang->sl_sounddone, goodword, hash);
const size_t goodword_len = STRLEN(goodword);
hi = hash_lookup(&slang->sl_sounddone, (const char *)goodword, goodword_len,
hash);
if (HASHITEM_EMPTY(hi)) {
sft = xmalloc(sizeof(sftword_T) + STRLEN(goodword));
sft = xmalloc(sizeof(sftword_T) + goodword_len);
sft->sft_score = score;
STRCPY(sft->sft_word, goodword);
memcpy(sft->sft_word, goodword, goodword_len + 1);
hash_add_item(&slang->sl_sounddone, hi, sft->sft_word, hash);
} else {
sft = HI2SFT(hi);
@ -11453,10 +11458,10 @@ static void set_map_str(slang_T *lp, char_u *map)
mb_char2bytes(headc, b + cl + 1);
b[cl + 1 + headcl] = NUL;
hash = hash_hash(b);
hi = hash_lookup(&lp->sl_map_hash, b, hash);
if (HASHITEM_EMPTY(hi))
hi = hash_lookup(&lp->sl_map_hash, (const char *)b, STRLEN(b), hash);
if (HASHITEM_EMPTY(hi)) {
hash_add_item(&lp->sl_map_hash, hi, b, hash);
else {
} else {
// This should have been checked when generating the .spl
// file.
EMSG(_("E783: duplicate char in MAP entry"));
@ -11661,9 +11666,10 @@ static void add_banned(suginfo_T *su, char_u *word)
hashitem_T *hi;
hash = hash_hash(word);
hi = hash_lookup(&su->su_banned, word, hash);
const size_t word_len = STRLEN(word);
hi = hash_lookup(&su->su_banned, (const char *)word, word_len, hash);
if (HASHITEM_EMPTY(hi)) {
s = vim_strsave(word);
s = xmemdupz(word, word_len);
hash_add_item(&su->su_banned, hi, s, hash);
}
}
@ -12995,19 +13001,17 @@ pop:
// ":spellinfo"
void ex_spellinfo(exarg_T *eap)
{
langp_T *lp;
char_u *p;
if (no_spell_checking(curwin))
if (no_spell_checking(curwin)) {
return;
}
msg_start();
for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len && !got_int; ++lpi) {
lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
msg_puts((char_u *)"file: ");
msg_puts(lp->lp_slang->sl_fname);
for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len && !got_int; lpi++) {
langp_T *const lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
msg_puts("file: ");
msg_puts((const char *)lp->lp_slang->sl_fname);
msg_putchar('\n');
p = lp->lp_slang->sl_info;
const char *const p = (const char *)lp->lp_slang->sl_info;
if (p != NULL) {
msg_puts(p);
msg_putchar('\n');

View File

@ -1,7 +1,11 @@
#include <inttypes.h>
#include <stdarg.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include "nvim/assert.h"
#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/strings.h"
@ -541,3 +545,847 @@ char_u *concat_str(const char_u *restrict str1, const char_u *restrict str2)
return dest;
}
static const char *const e_printf =
N_("E766: Insufficient arguments for printf()");
/// Get number argument from idxp entry in tvs
///
/// Will give an error message for VimL entry with invalid type or for
/// insufficient entries.
///
/// @param[in] tvs List of VimL values. List is terminated by VAR_UNKNOWN
/// value.
/// @param[in,out] idxp Index in a list. Will be incremented. Indexing starts
/// at 1.
///
/// @return Number value or 0 in case of error.
static varnumber_T tv_nr(typval_T *tvs, int *idxp)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
int idx = *idxp - 1;
varnumber_T n = 0;
if (tvs[idx].v_type == VAR_UNKNOWN) {
EMSG(_(e_printf));
} else {
(*idxp)++;
int err = false;
n = (varnumber_T)get_tv_number_chk(&tvs[idx], &err);
if (err) {
n = 0;
}
}
return n;
}
/// Get string argument from idxp entry in tvs
///
/// Will give an error message for VimL entry with invalid type or for
/// insufficient entries.
///
/// @param[in] tvs List of VimL values. List is terminated by VAR_UNKNOWN
/// value.
/// @param[in,out] idxp Index in a list. Will be incremented.
///
/// @return String value or NULL in case of error.
static char *tv_str(typval_T *tvs, int *idxp)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
int idx = *idxp - 1;
char *s = NULL;
if (tvs[idx].v_type == VAR_UNKNOWN) {
EMSG(_(e_printf));
} else {
(*idxp)++;
s = (char *)get_tv_string_chk(&tvs[idx]);
}
return s;
}
/// Get pointer argument from the next entry in tvs
///
/// Will give an error message for VimL entry with invalid type or for
/// insufficient entries.
///
/// @param[in] tvs List of typval_T values.
/// @param[in,out] idxp Pointer to the index of the current value.
///
/// @return Pointer stored in typval_T or NULL.
static const void *tv_ptr(const typval_T *const tvs, int *const idxp)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
#define OFF(attr) offsetof(union typval_vval_union, attr)
STATIC_ASSERT(
OFF(v_string) == OFF(v_list)
&& OFF(v_string) == OFF(v_dict)
&& OFF(v_string) == OFF(v_partial)
&& sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_list)
&& sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_dict)
&& sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_partial),
"Strings, dictionaries, lists and partials are expected to be pointers, "
"so that all three of them can be accessed via v_string");
#undef OFF
const int idx = *idxp - 1;
if (tvs[idx].v_type == VAR_UNKNOWN) {
EMSG(_(e_printf));
return NULL;
} else {
(*idxp)++;
return tvs[idx].vval.v_string;
}
}
/// Get float argument from idxp entry in tvs
///
/// Will give an error message for VimL entry with invalid type or for
/// insufficient entries.
///
/// @param[in] tvs List of VimL values. List is terminated by VAR_UNKNOWN
/// value.
/// @param[in,out] idxp Index in a list. Will be incremented.
///
/// @return Floating-point value or zero in case of error.
static float_T tv_float(typval_T *const tvs, int *const idxp)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
int idx = *idxp - 1;
float_T f = 0;
if (tvs[idx].v_type == VAR_UNKNOWN) {
EMSG(_(e_printf));
} else {
(*idxp)++;
if (tvs[idx].v_type == VAR_FLOAT) {
f = tvs[idx].vval.v_float;
} else if (tvs[idx].v_type == VAR_NUMBER) {
f = tvs[idx].vval.v_number;
} else {
EMSG(_("E807: Expected Float argument for printf()"));
}
}
return f;
}
// This code was included to provide a portable vsnprintf() and snprintf().
// Some systems may provide their own, but we always use this one for
// consistency.
//
// This code is based on snprintf.c - a portable implementation of snprintf
// by Mark Martinec <mark.martinec@ijs.si>, Version 2.2, 2000-10-06.
// Included with permission. It was heavily modified to fit in Vim.
// The original code, including useful comments, can be found here:
//
// http://www.ijs.si/software/snprintf/
//
// This snprintf() only supports the following conversion specifiers:
// s, c, b, B, d, u, o, x, X, p (and synonyms: i, D, U, O - see below)
// with flags: '-', '+', ' ', '0' and '#'.
// An asterisk is supported for field width as well as precision.
//
// Limited support for floating point was added: 'f', 'e', 'E', 'g', 'G'.
//
// Length modifiers 'h' (short int), 'l' (long int) and "ll" (long long int) are
// supported.
//
// The locale is not used, the string is used as a byte string. This is only
// relevant for double-byte encodings where the second byte may be '%'.
//
// It is permitted for "str_m" to be zero, and it is permitted to specify NULL
// pointer for resulting string argument if "str_m" is zero (as per ISO C99).
//
// The return value is the number of characters which would be generated
// for the given input, excluding the trailing NUL. If this value
// is greater or equal to "str_m", not all characters from the result
// have been stored in str, output bytes beyond the ("str_m"-1) -th character
// are discarded. If "str_m" is greater than zero it is guaranteed
// the resulting string will be NUL-terminated.
// vim_vsnprintf() can be invoked with either "va_list" or a list of
// "typval_T". When the latter is not used it must be NULL.
/// Append a formatted value to the string
///
/// @see vim_vsnprintf().
int vim_snprintf_add(char *str, size_t str_m, char *fmt, ...)
{
const size_t len = strlen(str);
size_t space;
if (str_m <= len) {
space = 0;
} else {
space = str_m - len;
}
va_list ap;
va_start(ap, fmt);
const int str_l = vim_vsnprintf(str + len, space, fmt, ap, NULL);
va_end(ap);
return str_l;
}
/// Write formatted value to the string
///
/// @param[out] str String to write to.
/// @param[in] str_m String length.
/// @param[in] fmt String format.
///
/// @return Number of bytes excluding NUL byte that would be written to the
/// string if str_m was greater or equal to the return value.
int vim_snprintf(char *str, size_t str_m, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
const int str_l = vim_vsnprintf(str, str_m, fmt, ap, NULL);
va_end(ap);
return str_l;
}
/// Write formatted value to the string
///
/// @param[out] str String to write to.
/// @param[in] str_m String length.
/// @param[in] fmt String format.
/// @param[in] ap Values that should be formatted. Ignored if tvs is not NULL.
/// @param[in] tvs Values that should be formatted, for printf() VimL
/// function. Must be NULL in other cases.
///
/// @return Number of bytes excluding NUL byte that would be written to the
/// string if str_m was greater or equal to the return value.
int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,
typval_T *const tvs)
{
size_t str_l = 0;
bool str_avail = str_l < str_m;
const char *p = fmt;
int arg_idx = 1;
if (!p) {
p = "";
}
while (*p) {
if (*p != '%') {
// copy up to the next '%' or NUL without any changes
size_t n = (size_t)(xstrchrnul(p + 1, '%') - p);
if (str_avail) {
size_t avail = str_m - str_l;
memmove(str + str_l, p, MIN(n, avail));
str_avail = n < avail;
}
p += n;
assert(n <= SIZE_MAX - str_l);
str_l += n;
} else {
size_t min_field_width = 0, precision = 0;
int zero_padding = 0, precision_specified = 0, justify_left = 0;
int alternate_form = 0, force_sign = 0;
// if both ' ' and '+' flags appear, ' ' flag should be ignored
int space_for_positive = 1;
// allowed values: \0, h, l, 2 (for ll), z, L
char length_modifier = '\0';
// temporary buffer for simple numeric->string conversion
# define TMP_LEN 350 // 1e308 seems reasonable as the maximum printable
char tmp[TMP_LEN];
// string address in case of string argument
const char *str_arg = NULL;
// natural field width of arg without padding and sign
size_t str_arg_l;
// unsigned char argument value (only defined for c conversion);
// standard explicitly states the char argument for the c
// conversion is unsigned
unsigned char uchar_arg;
// number of zeros to be inserted for numeric conversions as
// required by the precision or minimal field width
size_t number_of_zeros_to_pad = 0;
// index into tmp where zero padding is to be inserted
size_t zero_padding_insertion_ind = 0;
// current conversion specifier character
char fmt_spec = '\0';
p++; // skip '%'
// parse flags
while (true) {
switch (*p) {
case '0': zero_padding = 1; p++; continue;
case '-': justify_left = 1; p++; continue;
// if both '0' and '-' flags appear, '0' should be ignored
case '+': force_sign = 1; space_for_positive = 0; p++; continue;
case ' ': force_sign = 1; p++; continue;
// if both ' ' and '+' flags appear, ' ' should be ignored
case '#': alternate_form = 1; p++; continue;
case '\'': p++; continue;
default: break;
}
break;
}
// parse field width
if (*p == '*') {
p++;
const int j = tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int);
if (j >= 0) {
min_field_width = (size_t)j;
} else {
min_field_width = (size_t)-j;
justify_left = 1;
}
} else if (ascii_isdigit((int)(*p))) {
// size_t could be wider than unsigned int; make sure we treat
// argument like common implementations do
unsigned int uj = (unsigned)(*p++ - '0');
while (ascii_isdigit((int)(*p))) {
uj = 10 * uj + (unsigned int)(*p++ - '0');
}
min_field_width = uj;
}
// parse precision
if (*p == '.') {
p++;
precision_specified = 1;
if (*p == '*') {
const int j = tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int);
p++;
if (j >= 0) {
precision = (size_t)j;
} else {
precision_specified = 0;
precision = 0;
}
} else if (ascii_isdigit((int)(*p))) {
// size_t could be wider than unsigned int; make sure we
// treat argument like common implementations do
unsigned int uj = (unsigned)(*p++ - '0');
while (ascii_isdigit((int)(*p))) {
uj = 10 * uj + (unsigned int)(*p++ - '0');
}
precision = uj;
}
}
// parse 'h', 'l', 'll' and 'z' length modifiers
if (*p == 'h' || *p == 'l' || *p == 'z') {
length_modifier = *p;
p++;
if (length_modifier == 'l' && *p == 'l') { // ll, encoded as 2
length_modifier = '2';
p++;
}
}
fmt_spec = *p;
// common synonyms
switch (fmt_spec) {
case 'i': fmt_spec = 'd'; break;
case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
case 'F': fmt_spec = 'f'; break;
default: break;
}
// get parameter value, do initial processing
switch (fmt_spec) {
// '%' and 'c' behave similar to 's' regarding flags and field widths
case '%': case 'c': case 's': case 'S':
str_arg_l = 1;
switch (fmt_spec) {
case '%':
str_arg = p;
break;
case 'c': {
const int j = tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int);
// standard demands unsigned char
uchar_arg = (unsigned char)j;
str_arg = (char *)&uchar_arg;
break;
}
case 's':
case 'S':
str_arg = tvs ? tv_str(tvs, &arg_idx) : va_arg(ap, char *);
if (!str_arg) {
str_arg = "[NULL]";
str_arg_l = 6;
} else if (!precision_specified) {
// make sure not to address string beyond the specified
// precision
str_arg_l = strlen(str_arg);
} else if (precision == 0) {
// truncate string if necessary as requested by precision
str_arg_l = 0;
} else {
// memchr on HP does not like n > 2^31
// TODO(elmart): check if this still holds / is relevant
str_arg_l = (size_t)((char *)xmemscan(str_arg,
NUL,
MIN(precision,
0x7fffffff))
- str_arg);
}
if (fmt_spec == 'S') {
if (min_field_width != 0) {
min_field_width += (strlen(str_arg)
- mb_string2cells((char_u *)str_arg));
}
if (precision) {
const char *p1 = str_arg;
for (size_t i = 0; i < precision && *p1; i++) {
p1 += mb_ptr2len((const char_u *)p1);
}
str_arg_l = precision = (size_t)(p1 - str_arg);
}
}
break;
default:
break;
}
break;
case 'd':
case 'u':
case 'b': case 'B':
case 'o':
case 'x': case 'X':
case 'p': {
// u, b, B, o, x, X and p conversion specifiers imply
// the value is unsigned; d implies a signed value
// 0 if numeric argument is zero (or if pointer is NULL for 'p'),
// +1 if greater than zero (or non NULL for 'p'),
// -1 if negative (unsigned argument is never negative)
int arg_sign = 0;
intmax_t arg = 0;
uintmax_t uarg = 0;
// only defined for p conversion
const void *ptr_arg = NULL;
if (fmt_spec == 'p') {
length_modifier = '\0';
ptr_arg = tvs ? tv_ptr(tvs, &arg_idx) : va_arg(ap, void *);
if (ptr_arg) {
arg_sign = 1;
}
} else if (fmt_spec == 'd') {
// signed
switch (length_modifier) {
case '\0':
case 'h': {
// char and short arguments are passed as int
arg = (tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int));
break;
}
case 'l': {
arg = (tvs ? (long)tv_nr(tvs, &arg_idx) : va_arg(ap, long));
break;
}
case '2': {
arg = (
tvs
? (long long)tv_nr(tvs, &arg_idx) // NOLINT (runtime/int)
: va_arg(ap, long long)); // NOLINT (runtime/int)
break;
}
case 'z': {
arg = (tvs
? (ptrdiff_t)tv_nr(tvs, &arg_idx)
: va_arg(ap, ptrdiff_t));
break;
}
}
if (arg > 0) {
arg_sign = 1;
} else if (arg < 0) {
arg_sign = -1;
}
} else {
// unsigned
switch (length_modifier) {
case '\0':
case 'h': {
uarg = (tvs
? (unsigned)tv_nr(tvs, &arg_idx)
: va_arg(ap, unsigned));
break;
}
case 'l': {
uarg = (tvs
? (unsigned long)tv_nr(tvs, &arg_idx)
: va_arg(ap, unsigned long));
break;
}
case '2': {
uarg = (uintmax_t)(unsigned long long)( // NOLINT (runtime/int)
tvs
? ((unsigned long long) // NOLINT (runtime/int)
tv_nr(tvs, &arg_idx))
: va_arg(ap, unsigned long long)); // NOLINT (runtime/int)
break;
}
case 'z': {
uarg = (tvs
? (size_t)tv_nr(tvs, &arg_idx)
: va_arg(ap, size_t));
break;
}
}
arg_sign = (uarg != 0);
}
str_arg = tmp;
str_arg_l = 0;
// For d, i, u, o, x, and X conversions, if precision is specified,
// '0' flag should be ignored. This is so with Solaris 2.6, Digital
// UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl.
if (precision_specified) {
zero_padding = 0;
}
if (fmt_spec == 'd') {
if (force_sign && arg_sign >= 0) {
tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
}
// leave negative numbers for snprintf to handle, to
// avoid handling tricky cases like (short int)-32768
} else if (alternate_form) {
if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X'
|| fmt_spec == 'b' || fmt_spec == 'B')) {
tmp[str_arg_l++] = '0';
tmp[str_arg_l++] = fmt_spec;
}
// alternate form should have no effect for p * conversion, but ...
}
zero_padding_insertion_ind = str_arg_l;
if (!precision_specified) {
precision = 1; // default precision is 1
}
if (precision == 0 && arg_sign == 0) {
// when zero value is formatted with an explicit precision 0,
// resulting formatted string is empty (d, i, u, b, B, o, x, X, p)
} else {
switch (fmt_spec) {
case 'p': { // pointer
str_arg_l += (size_t)snprintf(tmp + str_arg_l,
sizeof(tmp) - str_arg_l,
"%p", ptr_arg);
break;
}
case 'd': { // signed
str_arg_l += (size_t)snprintf(tmp + str_arg_l,
sizeof(tmp) - str_arg_l,
"%" PRIdMAX, arg);
break;
}
case 'b': case 'B': { // binary
size_t bits = 0;
for (bits = sizeof(uintmax_t) * 8; bits > 0; bits--) {
if ((uarg >> (bits - 1)) & 0x1) {
break;
}
}
while (bits > 0) {
tmp[str_arg_l++] = ((uarg >> --bits) & 0x1) ? '1' : '0';
}
break;
}
default: { // unsigned
// construct a simple format string for snprintf
char f[] = "%" PRIuMAX;
f[sizeof("%" PRIuMAX) - 1 - 1] = fmt_spec;
assert(PRIuMAX[sizeof(PRIuMAX) - 1 - 1] == 'u');
str_arg_l += (size_t)snprintf(tmp + str_arg_l,
sizeof(tmp) - str_arg_l,
f, uarg);
break;
}
assert(str_arg_l < sizeof(tmp));
}
// include the optional minus sign and possible "0x" in the region
// before the zero padding insertion point
if (zero_padding_insertion_ind < str_arg_l
&& tmp[zero_padding_insertion_ind] == '-') {
zero_padding_insertion_ind++;
}
if (zero_padding_insertion_ind + 1 < str_arg_l
&& tmp[zero_padding_insertion_ind] == '0'
&& (tmp[zero_padding_insertion_ind + 1] == 'x'
|| tmp[zero_padding_insertion_ind + 1] == 'X'
|| tmp[zero_padding_insertion_ind + 1] == 'b'
|| tmp[zero_padding_insertion_ind + 1] == 'B')) {
zero_padding_insertion_ind += 2;
}
}
{
size_t num_of_digits = str_arg_l - zero_padding_insertion_ind;
if (alternate_form && fmt_spec == 'o'
// unless zero is already the first character
&& !(zero_padding_insertion_ind < str_arg_l
&& tmp[zero_padding_insertion_ind] == '0')) {
// assure leading zero for alternate-form octal numbers
if (!precision_specified
|| precision < num_of_digits + 1) {
// precision is increased to force the first character to be
// zero, except if a zero value is formatted with an explicit
// precision of zero
precision = num_of_digits + 1;
}
}
// zero padding to specified precision?
if (num_of_digits < precision) {
number_of_zeros_to_pad = precision - num_of_digits;
}
}
// zero padding to specified minimal field width?
if (!justify_left && zero_padding) {
const int n = (int)(min_field_width - (str_arg_l
+ number_of_zeros_to_pad));
if (n > 0) {
number_of_zeros_to_pad += (size_t)n;
}
}
break;
}
case 'f':
case 'e':
case 'E':
case 'g':
case 'G':
{
// floating point
char format[40];
int remove_trailing_zeroes = false;
double f = tvs ? tv_float(tvs, &arg_idx) : va_arg(ap, double);
double abs_f = f < 0 ? -f : f;
if (fmt_spec == 'g' || fmt_spec == 'G') {
// can't use %g directly, cause it prints "1.0" as "1"
if ((abs_f >= 0.001 && abs_f < 10000000.0) || abs_f == 0.0) {
fmt_spec = 'f';
} else {
fmt_spec = fmt_spec == 'g' ? 'e' : 'E';
}
remove_trailing_zeroes = true;
}
if (fmt_spec == 'f' && abs_f > 1.0e307) {
// avoid a buffer overflow
memmove(tmp, "inf", sizeof("inf"));
str_arg_l = sizeof("inf") - 1;
} else {
format[0] = '%';
int l = 1;
if (precision_specified) {
size_t max_prec = TMP_LEN - 10;
// make sure we don't get more digits than we have room for
if (fmt_spec == 'f' && abs_f > 1.0) {
max_prec -= (size_t)log10(abs_f);
}
if (precision > max_prec) {
precision = max_prec;
}
l += snprintf(format + 1, sizeof(format) - 1, ".%d",
(int)precision);
}
format[l] = fmt_spec;
format[l + 1] = NUL;
assert(l + 1 < (int)sizeof(format));
str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f);
assert(str_arg_l < sizeof(tmp));
if (remove_trailing_zeroes) {
int i;
char *tp;
// using %g or %G: remove superfluous zeroes
if (fmt_spec == 'f') {
tp = tmp + str_arg_l - 1;
} else {
tp = (char *)vim_strchr((char_u *)tmp,
fmt_spec == 'e' ? 'e' : 'E');
if (tp) {
// remove superfluous '+' and leading zeroes from exponent
if (tp[1] == '+') {
// change "1.0e+07" to "1.0e07"
STRMOVE(tp + 1, tp + 2);
str_arg_l--;
}
i = (tp[1] == '-') ? 2 : 1;
while (tp[i] == '0') {
// change "1.0e07" to "1.0e7"
STRMOVE(tp + i, tp + i + 1);
str_arg_l--;
}
tp--;
}
}
if (tp != NULL && !precision_specified) {
// remove trailing zeroes, but keep the one just after a dot
while (tp > tmp + 2 && *tp == '0' && tp[-1] != '.') {
STRMOVE(tp, tp + 1);
tp--;
str_arg_l--;
}
}
} else {
// Be consistent: some printf("%e") use 1.0e+12 and some
// 1.0e+012; remove one zero in the last case.
char *tp = (char *)vim_strchr((char_u *)tmp,
fmt_spec == 'e' ? 'e' : 'E');
if (tp && (tp[1] == '+' || tp[1] == '-') && tp[2] == '0'
&& ascii_isdigit(tp[3]) && ascii_isdigit(tp[4])) {
STRMOVE(tp + 2, tp + 3);
str_arg_l--;
}
}
}
str_arg = tmp;
break;
}
default:
// unrecognized conversion specifier, keep format string as-is
zero_padding = 0; // turn zero padding off for non-numeric conversion
justify_left = 1;
min_field_width = 0; // reset flags
// discard the unrecognized conversion, just keep
// the unrecognized conversion character
str_arg = p;
str_arg_l = 0;
if (*p) {
str_arg_l++; // include invalid conversion specifier
}
// unchanged if not at end-of-string
break;
}
if (*p) {
p++; // step over the just processed conversion specifier
}
// insert padding to the left as requested by min_field_width;
// this does not include the zero padding in case of numerical conversions
if (!justify_left) {
assert(str_arg_l <= SIZE_MAX - number_of_zeros_to_pad);
if (min_field_width > str_arg_l + number_of_zeros_to_pad) {
// left padding with blank or zero
size_t pn = min_field_width - (str_arg_l + number_of_zeros_to_pad);
if (str_avail) {
size_t avail = str_m - str_l;
memset(str + str_l, zero_padding ? '0' : ' ', MIN(pn, avail));
str_avail = pn < avail;
}
assert(pn <= SIZE_MAX - str_l);
str_l += pn;
}
}
// zero padding as requested by the precision or by the minimal
// field width for numeric conversions required?
if (number_of_zeros_to_pad == 0) {
// will not copy first part of numeric right now,
// force it to be copied later in its entirety
zero_padding_insertion_ind = 0;
} else {
// insert first part of numerics (sign or '0x') before zero padding
if (zero_padding_insertion_ind > 0) {
size_t zn = zero_padding_insertion_ind;
if (str_avail) {
size_t avail = str_m - str_l;
memmove(str + str_l, str_arg, MIN(zn, avail));
str_avail = zn < avail;
}
assert(zn <= SIZE_MAX - str_l);
str_l += zn;
}
// insert zero padding as requested by precision or min field width
if (number_of_zeros_to_pad > 0) {
size_t zn = number_of_zeros_to_pad;
if (str_avail) {
size_t avail = str_m - str_l;
memset(str + str_l, '0', MIN(zn, avail));
str_avail = zn < avail;
}
assert(zn <= SIZE_MAX - str_l);
str_l += zn;
}
}
// insert formatted string
// (or as-is conversion specifier for unknown conversions)
if (str_arg_l > zero_padding_insertion_ind) {
size_t sn = str_arg_l - zero_padding_insertion_ind;
if (str_avail) {
size_t avail = str_m - str_l;
memmove(str + str_l,
str_arg + zero_padding_insertion_ind,
MIN(sn, avail));
str_avail = sn < avail;
}
assert(sn <= SIZE_MAX - str_l);
str_l += sn;
}
// insert right padding
if (justify_left) {
assert(str_arg_l <= SIZE_MAX - number_of_zeros_to_pad);
if (min_field_width > str_arg_l + number_of_zeros_to_pad) {
// right blank padding to the field width
size_t pn = min_field_width - (str_arg_l + number_of_zeros_to_pad);
if (str_avail) {
size_t avail = str_m - str_l;
memset(str + str_l, ' ', MIN(pn, avail));
str_avail = pn < avail;
}
assert(pn <= SIZE_MAX - str_l);
str_l += pn;
}
}
}
}
if (str_m > 0) {
// make sure the string is nul-terminated even at the expense of
// overwriting the last character (shouldn't happen, but just in case)
str[str_l <= str_m - 1 ? str_l : str_m - 1] = '\0';
}
if (tvs && tvs[arg_idx - 1].v_type != VAR_UNKNOWN) {
EMSG(_("E767: Too many arguments to printf()"));
}
// return the number of characters formatted (excluding trailing nul
// character); that is, the number of characters that would have been
// written to the buffer if it were large enough.
return (int)str_l;
}

View File

@ -1,7 +1,12 @@
#ifndef NVIM_STRINGS_H
#define NVIM_STRINGS_H
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include "nvim/types.h"
#include "nvim/eval_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "strings.h.generated.h"

View File

@ -3576,22 +3576,24 @@ syn_list_one (
}
syn_list_flags(namelist1, spp->sp_flags, attr);
if (spp->sp_cont_list != NULL)
put_id_list((char_u *)"contains", spp->sp_cont_list, attr);
if (spp->sp_cont_list != NULL) {
put_id_list("contains", spp->sp_cont_list, attr);
}
if (spp->sp_syn.cont_in_list != NULL)
put_id_list((char_u *)"containedin",
spp->sp_syn.cont_in_list, attr);
if (spp->sp_syn.cont_in_list != NULL) {
put_id_list("containedin", spp->sp_syn.cont_in_list, attr);
}
if (spp->sp_next_list != NULL) {
put_id_list((char_u *)"nextgroup", spp->sp_next_list, attr);
put_id_list("nextgroup", spp->sp_next_list, attr);
syn_list_flags(namelist2, spp->sp_flags, attr);
}
if (spp->sp_flags & (HL_SYNC_HERE|HL_SYNC_THERE)) {
if (spp->sp_flags & HL_SYNC_HERE)
msg_puts_attr((char_u *)"grouphere", attr);
else
msg_puts_attr((char_u *)"groupthere", attr);
if (spp->sp_flags & HL_SYNC_HERE) {
msg_puts_attr("grouphere", attr);
} else {
msg_puts_attr("groupthere", attr);
}
msg_putchar(' ');
if (spp->sp_sync_idx >= 0)
msg_outtrans(HL_TABLE()[SYN_ITEMS(curwin->w_s)
@ -3605,7 +3607,7 @@ syn_list_one (
/* list the link, if there is one */
if (HL_TABLE()[id - 1].sg_link && (did_header || link_only) && !got_int) {
(void)syn_list_header(did_header, 999, id);
msg_puts_attr((char_u *)"links to", attr);
msg_puts_attr("links to", attr);
msg_putchar(' ');
msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name);
}
@ -3617,7 +3619,7 @@ static void syn_list_flags(struct name_list *nlist, int flags, int attr)
for (i = 0; nlist[i].flag != 0; ++i)
if (flags & nlist[i].flag) {
msg_puts_attr((char_u *)nlist[i].name, attr);
msg_puts_attr(nlist[i].name, attr);
msg_putchar(' ');
}
}
@ -3640,15 +3642,16 @@ static void syn_list_cluster(int id)
msg_advance(endcol);
if (SYN_CLSTR(curwin->w_s)[id].scl_list != NULL) {
put_id_list((char_u *)"cluster", SYN_CLSTR(curwin->w_s)[id].scl_list,
hl_attr(HLF_D));
put_id_list("cluster", SYN_CLSTR(curwin->w_s)[id].scl_list, hl_attr(HLF_D));
} else {
msg_puts_attr((char_u *)"cluster", hl_attr(HLF_D));
msg_puts((char_u *)"=NONE");
msg_puts_attr("cluster", hl_attr(HLF_D));
msg_puts("=NONE");
}
}
static void put_id_list(char_u *name, short *list, int attr)
static void put_id_list(const char *name,
short *list, // NOLINT(runtime/int)
int attr)
{
short *p;
@ -3656,14 +3659,15 @@ static void put_id_list(char_u *name, short *list, int attr)
msg_putchar('=');
for (p = list; *p; ++p) {
if (*p >= SYNID_ALLBUT && *p < SYNID_TOP) {
if (p[1])
MSG_PUTS("ALLBUT");
else
MSG_PUTS("ALL");
if (p[1]) {
msg_puts("ALLBUT");
} else {
msg_puts("ALL");
}
} else if (*p >= SYNID_TOP && *p < SYNID_CONTAINED) {
MSG_PUTS("TOP");
msg_puts("TOP");
} else if (*p >= SYNID_CONTAINED && *p < SYNID_CLUSTER) {
MSG_PUTS("CONTAINED");
msg_puts("CONTAINED");
} else if (*p >= SYNID_CLUSTER) {
short scl_id = *p - SYNID_CLUSTER;
@ -3688,7 +3692,7 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr)
/* May have to write "matchgroup=group" */
if (last_matchgroup != spp->sp_syn_match_id) {
last_matchgroup = spp->sp_syn_match_id;
msg_puts_attr((char_u *)"matchgroup", attr);
msg_puts_attr("matchgroup", attr);
msg_putchar('=');
if (last_matchgroup == 0)
msg_outtrans((char_u *)"NONE");
@ -3697,8 +3701,8 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr)
msg_putchar(' ');
}
/* output the name of the pattern and an '=' or ' ' */
msg_puts_attr((char_u *)s, attr);
// Output the name of the pattern and an '=' or ' '.
msg_puts_attr(s, attr);
msg_putchar(c);
/* output the pattern, in between a char that is not in the pattern */
@ -3718,9 +3722,10 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr)
if (!(spp->sp_off_flags & (mask + (mask << SPO_COUNT)))) {
continue;
}
if (!first)
msg_putchar(','); /* separate with commas */
msg_puts((char_u *)spo_name_tab[i]);
if (!first) {
msg_putchar(','); // Separate with commas.
}
msg_puts(spo_name_tab[i]);
n = spp->sp_offsets[i];
if (i != SPO_LC_OFF) {
if (spp->sp_off_flags & mask)
@ -3792,32 +3797,31 @@ syn_list_keywords (
}
did_header = TRUE;
if (prev_contained != (kp->flags & HL_CONTAINED)) {
msg_puts_attr((char_u *)"contained", attr);
msg_puts_attr("contained", attr);
msg_putchar(' ');
prev_contained = (kp->flags & HL_CONTAINED);
}
if (kp->k_syn.cont_in_list != prev_cont_in_list) {
put_id_list((char_u *)"containedin",
kp->k_syn.cont_in_list, attr);
put_id_list("containedin", kp->k_syn.cont_in_list, attr);
msg_putchar(' ');
prev_cont_in_list = kp->k_syn.cont_in_list;
}
if (kp->next_list != prev_next_list) {
put_id_list((char_u *)"nextgroup", kp->next_list, attr);
put_id_list("nextgroup", kp->next_list, attr);
msg_putchar(' ');
prev_next_list = kp->next_list;
if (kp->flags & HL_SKIPNL) {
msg_puts_attr((char_u *)"skipnl", attr);
msg_puts_attr("skipnl", attr);
msg_putchar(' ');
prev_skipnl = (kp->flags & HL_SKIPNL);
}
if (kp->flags & HL_SKIPWHITE) {
msg_puts_attr((char_u *)"skipwhite", attr);
msg_puts_attr("skipwhite", attr);
msg_putchar(' ');
prev_skipwhite = (kp->flags & HL_SKIPWHITE);
}
if (kp->flags & HL_SKIPEMPTY) {
msg_puts_attr((char_u *)"skipempty", attr);
msg_puts_attr("skipempty", attr);
msg_putchar(' ');
prev_skipempty = (kp->flags & HL_SKIPEMPTY);
}
@ -3929,7 +3933,8 @@ static void add_keyword(char_u *name,
hash_T hash = hash_hash(kp->keyword);
hashtab_T *ht = (curwin->w_s->b_syn_ic) ? &curwin->w_s->b_keywtab_ic
: &curwin->w_s->b_keywtab;
hashitem_T *hi = hash_lookup(ht, kp->keyword, hash);
hashitem_T *hi = hash_lookup(ht, (const char *)kp->keyword,
STRLEN(kp->keyword), hash);
// even though it looks like only the kp->keyword member is
// being used here, vim uses some pointer trickery to get the orignal
@ -5516,19 +5521,21 @@ void ex_ownsyntax(exarg_T *eap)
clear_string_option(&curwin->w_s->b_syn_isk);
}
/* save value of b:current_syntax */
old_value = get_var_value((char_u *)"b:current_syntax");
if (old_value != NULL)
// Save value of b:current_syntax.
old_value = get_var_value("b:current_syntax");
if (old_value != NULL) {
old_value = vim_strsave(old_value);
}
/* Apply the "syntax" autocommand event, this finds and loads the syntax
* file. */
apply_autocmds(EVENT_SYNTAX, eap->arg, curbuf->b_fname, TRUE, curbuf);
/* move value of b:current_syntax to w:current_syntax */
new_value = get_var_value((char_u *)"b:current_syntax");
if (new_value != NULL)
// Move value of b:current_syntax to w:current_syntax.
new_value = get_var_value("b:current_syntax");
if (new_value != NULL) {
set_internal_string_var((char_u *)"w:current_syntax", new_value);
}
/* restore value of b:current_syntax */
if (old_value == NULL)
@ -5988,7 +5995,7 @@ init_highlight (
* Try finding the color scheme file. Used when a color file was loaded
* and 'background' or 't_Co' is changed.
*/
char_u *p = get_var_value((char_u *)"g:colors_name");
char_u *p = get_var_value("g:colors_name");
if (p != NULL) {
// Value of g:colors_name could be freed in load_colors() and make
// p invalid, so copy it.
@ -6042,7 +6049,7 @@ init_highlight (
/*
* If syntax highlighting is enabled load the highlighting for it.
*/
if (get_var_value((char_u *)"g:syntax_on") != NULL) {
if (get_var_value("g:syntax_on") != NULL) {
static int recursive = 0;
if (recursive >= 5) {
@ -6871,8 +6878,8 @@ static void highlight_list_one(int id)
if (sgp->sg_link && !got_int) {
(void)syn_list_header(didh, 9999, id);
didh = TRUE;
msg_puts_attr((char_u *)"links to", hl_attr(HLF_D));
didh = true;
msg_puts_attr("links to", hl_attr(HLF_D));
msg_putchar(' ');
msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name);
}
@ -7057,7 +7064,7 @@ syn_list_header (
/* Show "xxx" with the attributes. */
if (!did_header) {
msg_puts_attr((char_u *)"xxx", syn_id2attr(id));
msg_puts_attr("xxx", syn_id2attr(id));
msg_putchar(' ');
}
@ -7517,7 +7524,7 @@ static void highlight_list(void)
static void highlight_list_two(int cnt, int attr)
{
msg_puts_attr((char_u *)&("N \bI \b! \b"[cnt / 11]), attr);
msg_puts_attr(&("N \bI \b! \b"[cnt / 11]), attr);
msg_clr_eos();
ui_flush();
os_delay(cnt == 99 ? 40L : (long)cnt * 50L, false);
@ -7528,22 +7535,25 @@ static void highlight_list_two(int cnt, int attr)
* Function given to ExpandGeneric() to obtain the list of group names.
* Also used for synIDattr() function.
*/
char_u *get_highlight_name(expand_T *xp, int idx)
const char *get_highlight_name(expand_T *const xp, const int idx)
FUNC_ATTR_WARN_UNUSED_RESULT
{
//TODO: 'xp' is unused
if (idx == highlight_ga.ga_len && include_none != 0)
return (char_u *)"none";
if (idx == highlight_ga.ga_len + include_none && include_default != 0)
return (char_u *)"default";
if (idx == highlight_ga.ga_len + include_none + include_default
&& include_link != 0)
return (char_u *)"link";
if (idx == highlight_ga.ga_len + include_none + include_default + 1
&& include_link != 0)
return (char_u *)"clear";
if (idx < 0 || idx >= highlight_ga.ga_len)
// TODO(justinmk): 'xp' is unused
if (idx == highlight_ga.ga_len && include_none != 0) {
return "none";
} else if (idx == highlight_ga.ga_len + include_none
&& include_default != 0) {
return "default";
} else if (idx == highlight_ga.ga_len + include_none + include_default
&& include_link != 0) {
return "link";
} else if (idx == highlight_ga.ga_len + include_none + include_default + 1
&& include_link != 0) {
return "clear";
} else if (idx < 0 || idx >= highlight_ga.ga_len) {
return NULL;
return HL_TABLE()[idx].sg_name;
}
return (const char *)HL_TABLE()[idx].sg_name;
}
color_name_table_T color_name_table[] = {

View File

@ -540,10 +540,11 @@ do_tag (
}
vim_snprintf((char *)IObuff + 1, IOSIZE - 1, "%2d %s ", i + 1,
mt_names[matches[i][0] & MT_MASK]);
msg_puts(IObuff);
if (tagp.tagkind != NULL)
msg_puts((const char *)IObuff);
if (tagp.tagkind != NULL) {
msg_outtrans_len(tagp.tagkind,
(int)(tagp.tagkind_end - tagp.tagkind));
(int)(tagp.tagkind_end - tagp.tagkind));
}
msg_advance(13);
msg_outtrans_len_attr(tagp.tagname,
(int)(tagp.tagname_end - tagp.tagname),
@ -595,7 +596,7 @@ do_tag (
}
p = msg_outtrans_one(p, attr);
if (*p == TAB) {
msg_puts_attr((char_u *)" ", attr);
msg_puts_attr(" ", attr);
break;
}
if (*p == ':')
@ -858,13 +859,15 @@ do_tag (
STRCAT(IObuff, _(" Using tag with different case!"));
if ((num_matches > prev_num_matches || new_tag)
&& num_matches > 1) {
if (ic)
msg_attr(IObuff, hl_attr(HLF_W));
else
if (ic) {
msg_attr((const char *)IObuff, hl_attr(HLF_W));
} else {
msg(IObuff);
msg_scroll = TRUE; /* don't overwrite this message */
} else
}
msg_scroll = true; // Don't overwrite this message.
} else {
give_warning(IObuff, ic);
}
if (ic && !msg_scrolled && msg_silent == 0) {
ui_flush();
os_delay(1000L, true);

View File

@ -1014,7 +1014,7 @@ static const char *tui_tk_ti_getstr(const char *name, const char *value,
} else if (strcmp(name, "key_dc") == 0) {
ILOG("libtermkey:kdch1=%s", value);
// Vim: "If <BS> and <DEL> are now the same, redefine <DEL>."
if (stty_erase != NULL && strcmp(stty_erase, value) == 0) {
if (stty_erase != NULL && value != NULL && strcmp(stty_erase, value) == 0) {
return stty_erase[0] == DEL ? (char *)CTRL_H_STR : (char *)DEL_STR;
}
}

View File

@ -2512,13 +2512,14 @@ void ex_undolist(exarg_T *eap)
sort_strings((char_u **)ga.ga_data, ga.ga_len);
msg_start();
msg_puts_attr((char_u *)_("number changes when saved"),
hl_attr(HLF_T));
for (int i = 0; i < ga.ga_len && !got_int; ++i) {
msg_puts_attr(_("number changes when saved"),
hl_attr(HLF_T));
for (int i = 0; i < ga.ga_len && !got_int; i++) {
msg_putchar('\n');
if (got_int)
if (got_int) {
break;
msg_puts(((char_u **)ga.ga_data)[i]);
}
msg_puts(((const char **)ga.ga_data)[i]);
}
msg_end();

View File

@ -2572,7 +2572,7 @@ static void list_features(void)
int idx = (i / ncol) + (i % ncol) * nrow;
if (idx < nfeat) {
int last_col = (i + 1) % ncol == 0;
msg_puts((char_u *)features[idx]);
msg_puts(features[idx]);
if (last_col) {
if (msg_col > 0) {
msg_putchar('\n');

View File

@ -0,0 +1,34 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, insert, funcs, eq, feed =
helpers.clear, helpers.insert, helpers.funcs, helpers.eq, helpers.feed
describe('cmdline CTRL-R', function()
before_each(clear)
it('pasting non-special register inserts <CR> *between* lines', function()
insert([[
line1abc
line2somemoretext
]])
-- Yank 2 lines linewise, then paste to cmdline.
feed([[<C-\><C-N>gg0yj:<C-R>0]])
-- <CR> inserted between lines, NOT after the final line.
eq('line1abc\rline2somemoretext', funcs.getcmdline())
-- Yank 2 lines characterwise, then paste to cmdline.
feed([[<C-\><C-N>gg05lyvj:<C-R>0]])
-- <CR> inserted between lines, NOT after the final line.
eq('abc\rline2', funcs.getcmdline())
-- Yank 1 line linewise, then paste to cmdline.
feed([[<C-\><C-N>ggyy:<C-R>0]])
-- No <CR> inserted.
eq('line1abc', funcs.getcmdline())
end)
it('pasting special register inserts <CR>, <NL>', function()
feed([[:<C-R>="foo\nbar\rbaz"<CR>]])
eq('foo\nbar\rbaz', funcs.getcmdline())
end)
end)

View File

@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
local clear = helpers.clear
local funcs = helpers.funcs
local iswin = helpers.iswin
describe('has()', function()
before_each(clear)
@ -49,4 +50,11 @@ describe('has()', function()
eq(1, funcs.has("nvim-00.001.05"))
end)
it('"unnamedplus"', function()
if (not iswin()) and funcs.has("clipboard") == 1 then
eq(1, funcs.has("unnamedplus"))
else
eq(0, funcs.has("unnamedplus"))
end
end)
end)

View File

@ -0,0 +1,22 @@
local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
local clear = helpers.clear
local meths = helpers.meths
local redir_exec = helpers.redir_exec
before_each(clear)
describe(':let command', function()
it('correctly lists variables with curly-braces', function()
meths.set_var('v', {0})
eq('\nv [0]', redir_exec('let {"v"}'))
end)
it('correctly lists variables with subscript', function()
meths.set_var('v', {0})
eq('\nv[0] #0', redir_exec('let v[0]'))
eq('\ng:["v"][0] #0', redir_exec('let g:["v"][0]'))
eq('\n{"g:"}["v"][0] #0', redir_exec('let {"g:"}["v"][0]'))
end)
end)

View File

@ -222,7 +222,6 @@ describe('argument list commands', function()
execute('argedit a')
eq({'a', 'b'}, eval('argv()'))
eq('a', eval('expand("%:t")'))
assert_fails('argedit a b', 'E172:')
execute('argedit c')
eq({'a', 'c', 'b'}, eval('argv()'))
execute('0argedit x')
@ -232,6 +231,9 @@ describe('argument list commands', function()
execute('argedit! y')
eq({'x', 'y', 'a', 'c', 'b'}, eval('argv()'))
execute('%argd')
-- Nvim allows unescaped spaces in filename on all platforms. #6010
execute('argedit a b')
eq({'a b'}, eval('argv()'))
end)
it('test for :argdelete command', function()

View File

@ -120,9 +120,19 @@ set(LUV_SHA256 86a199403856018cd8e5529c8527450c83664a3d36f52d5253cbe909ea6c5a06)
set(GPERF_URL http://ftp.gnu.org/pub/gnu/gperf/gperf-3.0.4.tar.gz)
set(GPERF_SHA256 767112a204407e62dbc3106647cf839ed544f3cf5d0f0523aaa2508623aad63e)
# 7za.exe cat.exe curl.exe ca-bundle.crt diff.exe tee.exe tidy.exe xxd.exe
set(WINTOOLS_URL https://github.com/neovim/deps/raw/5d23093c66d63a8777244ed84de727c26d3f7b79/opt/win32tools.zip)
set(WINTOOLS_SHA256 40c7d1fbed47d8b1cf3b3cada6bfe0e0df06d99beb48775b4db27972d3ceafc1)
set(WINGUI_URL https://github.com/equalsraf/neovim-qt/releases/download/v0.2.4/neovim-qt.zip)
set(WINGUI_SHA256 95bbc852b69b12d0ef962a8410522010b453ba70f36ea379c548558d16abc2e6)
set(WIN32YANK_URL https://github.com/equalsraf/win32yank/releases/download/v0.0.2/win32yank.zip)
set(WIN32YANK_SHA256 78869bf68565607cda1b6a3d549e2487d59d6f0f16f9b003e123c0086f90309d)
set(WINPTY_URL https://github.com/rprichard/winpty/releases/download/0.4.2/winpty-0.4.2-msvc2015.zip)
set(WINPTY_SHA256 b465f2584ff394b3fe27c01aa1dcfc679583c1ee951d0e83de3f859d8b8305b8)
if(USE_BUNDLED_UNIBILIUM)
include(BuildUnibilium)
endif()
@ -170,8 +180,33 @@ endif()
include(GetBinaryDeps)
if(WIN32)
GetBinaryDep(TARGET wintools
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory . ${DEPS_INSTALL_DIR}/bin)
GetBinaryDep(TARGET win32yank
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy win32yank.exe ${DEPS_INSTALL_DIR}/bin)
GetBinaryDep(TARGET wingui
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory bin ${DEPS_INSTALL_DIR}/bin
COMMAND ${CMAKE_COMMAND} -E copy_directory share/nvim-qt/runtime ${DEPS_INSTALL_DIR}/share/nvim/runtime)
include(TargetArch)
if("${TARGET_ARCH}" STREQUAL "X86_64")
set(TARGET_ARCH x64)
elseif(TARGET_ARCH STREQUAL "X86")
set(TARGET_ARCH ia32)
endif()
GetBinaryDep(TARGET winpty
INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_INSTALL_DIR}/bin
COMMAND ${CMAKE_COMMAND} -DFROM_GLOB=${DEPS_BUILD_DIR}/src/winpty/${TARGET_ARCH}/bin/*
-DTO=${DEPS_INSTALL_DIR}/bin/
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CopyFilesGlob.cmake
COMMAND ${CMAKE_COMMAND} -DFROM_GLOB=${DEPS_BUILD_DIR}/src/winpty/include/*
-DTO=${DEPS_INSTALL_DIR}/include/
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CopyFilesGlob.cmake
COMMAND ${CMAKE_COMMAND} -DFROM_GLOB=${DEPS_BUILD_DIR}/src/winpty/${TARGET_ARCH}/lib/*
-DTO=${DEPS_INSTALL_DIR}/lib/
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CopyFilesGlob.cmake)
endif()
add_custom_target(clean-shared-libraries

View File

@ -75,16 +75,16 @@ elseif(WIN32 AND MSVC)
message(FATAL_ERROR "Python2 is required to build libuv on windows, use -DPYTHON_EXECUTABLE to set a python interpreter")
endif()
string(FIND ${CMAKE_GENERATOR} Win64 VS_WIN64)
if(VS_WIN64 EQUAL -1)
set(VS_ARCH x86)
else()
set(VS_ARCH x64)
include(TargetArch)
if("${TARGET_ARCH}" STREQUAL "X86_64")
set(TARGET_ARCH x64)
elseif(TARGET_ARCH STREQUAL "X86")
set(TARGET_ARCH x86)
endif()
string(TOLOWER ${CMAKE_BUILD_TYPE} LOWERCASE_BUILD_TYPE)
set(UV_OUTPUT_DIR ${DEPS_BUILD_DIR}/src/libuv/${CMAKE_BUILD_TYPE})
BuildLibUv(
BUILD_COMMAND set PYTHON=${PYTHON_EXECUTABLE} COMMAND ${DEPS_BUILD_DIR}/src/libuv/vcbuild.bat shared ${LOWERCASE_BUILD_TYPE} ${VS_ARCH}
BUILD_COMMAND set PYTHON=${PYTHON_EXECUTABLE} COMMAND ${DEPS_BUILD_DIR}/src/libuv/vcbuild.bat shared ${LOWERCASE_BUILD_TYPE} ${TARGET_ARCH}
INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_INSTALL_DIR}/lib
COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_INSTALL_DIR}/bin
COMMAND ${CMAKE_COMMAND} -E copy ${UV_OUTPUT_DIR}/libuv.lib ${DEPS_INSTALL_DIR}/lib

View File

@ -21,7 +21,7 @@ function(GetBinaryDep)
set(URL ${${URL_VARNAME}})
set(HASH ${${HASH_VARNAME}})
if(NOT URL OR NOT HASH )
message(FATAL_ERROR "${URL_VARNAME} and ${HASH_VARNAME} must be set")
message(FATAL_ERROR "${URL_VARNAME} and ${HASH_VARNAME} must be set")
endif()
ExternalProject_Add(${_gettool_TARGET}
@ -41,6 +41,6 @@ function(GetBinaryDep)
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_INSTALL_DIR}/bin
COMMAND "${_gettool_INSTALL_COMMAND}")
COMMAND "${_gettool_INSTALL_COMMAND}")
list(APPEND THIRD_PARTY_DEPS ${__gettool_TARGET})
endfunction()

23
third-party/cmake/TargetArch.cmake vendored Normal file
View File

@ -0,0 +1,23 @@
# Sets TARGET_ARCH to a normalized name (X86 or X86_64).
# See https://github.com/axr/solar-cmake/blob/master/TargetArch.cmake
include(CheckSymbolExists)
# X86
check_symbol_exists("_M_IX86" "" T_M_IX86)
check_symbol_exists("__i386__" "" T_I386)
if(T_M_IX86 OR T_I386)
set(TARGET_ARCH "X86")
return()
endif()
# X86_64
check_symbol_exists("_M_AMD64" "" T_M_AMD64)
check_symbol_exists("__x86_64__" "" T_X86_64)
check_symbol_exists("__amd64__" "" T_AMD64)
if(T_M_AMD64 OR T_X86_64 OR T_AMD64)
set(TARGET_ARCH "X86_64")
return()
endif()
message(FATAL_ERROR "Unknown target architecture")