mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge remote-tracking branch 'origin/master' into lambda
This commit is contained in:
commit
bc76ce2c4f
44
README.md
44
README.md
@ -1,4 +1,4 @@
|
||||
[](https://neovim.io)
|
||||
[](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.
|
||||
|
||||
[](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: -->
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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/
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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'*
|
||||
|
@ -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")
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
1356
src/nvim/eval.c
1356
src/nvim/eval.c
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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].
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
1229
src/nvim/message.c
1229
src/nvim/message.c
File diff suppressed because it is too large
Load Diff
@ -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)
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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'
|
||||
|
@ -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'},
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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 */
|
||||
|
@ -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');
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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[] = {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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');
|
||||
|
34
test/functional/cmdline/ctrl_r_spec.lua
Normal file
34
test/functional/cmdline/ctrl_r_spec.lua
Normal 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)
|
||||
|
@ -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)
|
||||
|
22
test/functional/eval/let_spec.lua
Normal file
22
test/functional/eval/let_spec.lua
Normal 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)
|
@ -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()
|
||||
|
35
third-party/CMakeLists.txt
vendored
35
third-party/CMakeLists.txt
vendored
@ -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
|
||||
|
12
third-party/cmake/BuildLibuv.cmake
vendored
12
third-party/cmake/BuildLibuv.cmake
vendored
@ -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
|
||||
|
4
third-party/cmake/GetBinaryDeps.cmake
vendored
4
third-party/cmake/GetBinaryDeps.cmake
vendored
@ -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
23
third-party/cmake/TargetArch.cmake
vendored
Normal 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")
|
Loading…
Reference in New Issue
Block a user