mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge #5119 from ZyX-I/split-eval
This commit is contained in:
commit
c60e409471
@ -181,11 +181,6 @@ vim.eval(str) *python-eval*
|
||||
# string.atoi() to convert to
|
||||
# a number.
|
||||
|
||||
:py tagList = vim.eval('taglist("eval_expr")')
|
||||
< The latter will return a python list of python dicts, for instance:
|
||||
[{'cmd': '/^eval_expr(arg, nextcmd)$/', 'static': 0, 'name':
|
||||
'eval_expr', 'kind': 'f', 'filename': './src/eval.c'}]
|
||||
|
||||
vim.bindeval(str) *python-bindeval*
|
||||
Like |python-eval|, but returns special objects described in
|
||||
|python-bindeval-objects|. These python objects let you modify (|List|
|
||||
|
66
scripts/check-includes.py
Executable file
66
scripts/check-includes.py
Executable file
@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
|
||||
from subprocess import Popen, PIPE
|
||||
from argparse import ArgumentParser
|
||||
|
||||
|
||||
GENERATED_INCLUDE_RE = re.compile(
|
||||
r'^\s*#\s*include\s*"([/a-z_0-9.]+\.generated\.h)"(\s+//.*)?$')
|
||||
|
||||
|
||||
def main(argv):
|
||||
argparser = ArgumentParser()
|
||||
argparser.add_argument('--generated-includes-dir', action='append',
|
||||
help='Directory where generated includes are located.')
|
||||
argparser.add_argument('--file', type=open, help='File to check.')
|
||||
argparser.add_argument('iwyu_args', nargs='*',
|
||||
help='IWYU arguments, must go after --.')
|
||||
args = argparser.parse_args(argv)
|
||||
|
||||
with args.file:
|
||||
include_dirs = []
|
||||
|
||||
iwyu = Popen(['include-what-you-use', '-xc'] + args.iwyu_args + ['/dev/stdin'],
|
||||
stdin=PIPE, stdout=PIPE, stderr=PIPE)
|
||||
|
||||
for line in args.file:
|
||||
match = GENERATED_INCLUDE_RE.match(line)
|
||||
if match:
|
||||
for d in args.generated_includes_dir:
|
||||
try:
|
||||
f = open(os.path.join(d, match.group(1)))
|
||||
except IOError:
|
||||
continue
|
||||
else:
|
||||
with f:
|
||||
for generated_line in f:
|
||||
iwyu.stdin.write(generated_line)
|
||||
break
|
||||
else:
|
||||
raise IOError('Failed to find {0}'.format(match.group(1)))
|
||||
else:
|
||||
iwyu.stdin.write(line)
|
||||
|
||||
iwyu.stdin.close()
|
||||
|
||||
out = iwyu.stdout.read()
|
||||
err = iwyu.stderr.read()
|
||||
|
||||
ret = iwyu.wait()
|
||||
|
||||
if ret != 2:
|
||||
print('IWYU failed with exit code {0}:'.format(ret))
|
||||
print('{0} stdout {0}'.format('=' * ((80 - len(' stdout ')) // 2)))
|
||||
print(out)
|
||||
print('{0} stderr {0}'.format('=' * ((80 - len(' stderr ')) // 2)))
|
||||
print(err)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main(sys.argv[1:]))
|
@ -1,3 +1,3 @@
|
||||
# multiqueue.h pointer arithmetic is not accepted by asan
|
||||
fun:multiqueue_node_data
|
||||
fun:dictwatcher_node_data
|
||||
fun:tv_dict_watcher_node_data
|
||||
|
@ -2268,11 +2268,14 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
|
||||
# //!< Header comment
|
||||
# or they begin with multiple slashes followed by a space:
|
||||
# //////// Header comment
|
||||
# or they are Vim {{{ fold markers
|
||||
match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or
|
||||
Search(r'^/$', line[commentend:]) or
|
||||
Search(r'^!< ', line[commentend:]) or
|
||||
Search(r'^/< ', line[commentend:]) or
|
||||
Search(r'^/+ ', line[commentend:]))
|
||||
Search(r'^/+ ', line[commentend:]) or
|
||||
Search(r'^(?:\{{3}|\}{3})\d*(?: |$)',
|
||||
line[commentend:]))
|
||||
if not match:
|
||||
error(filename, linenum, 'whitespace/comments', 4,
|
||||
'Should have a space between // and comment')
|
||||
@ -3575,7 +3578,7 @@ def main():
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
# vim: ts=4 sts=4 sw=4
|
||||
# vim: ts=4 sts=4 sw=4 foldmarker=▶,▲
|
||||
|
||||
# Ignore "too complex" warnings when using pymode.
|
||||
# pylama:ignore=C901
|
||||
|
@ -22,7 +22,6 @@ set(GENERATED_API_DISPATCH ${GENERATED_DIR}/api/private/dispatch_wrappers.genera
|
||||
set(GENERATED_FUNCS_METADATA ${GENERATED_DIR}/api/private/funcs_metadata.generated.h)
|
||||
set(GENERATED_EX_CMDS_ENUM ${GENERATED_INCLUDES_DIR}/ex_cmds_enum.generated.h)
|
||||
set(GENERATED_EX_CMDS_DEFS ${GENERATED_DIR}/ex_cmds_defs.generated.h)
|
||||
set(GENERATED_FUNCS_HASH_INPUT ${GENERATED_DIR}/funcs.generated.h.gperf)
|
||||
set(GENERATED_FUNCS ${GENERATED_DIR}/funcs.generated.h)
|
||||
set(GENERATED_EVENTS_ENUM ${GENERATED_INCLUDES_DIR}/auevents_enum.generated.h)
|
||||
set(GENERATED_EVENTS_NAMES_MAP ${GENERATED_DIR}/auevents_name_map.generated.h)
|
||||
@ -31,10 +30,6 @@ set(EX_CMDS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genex_cmds.lua)
|
||||
set(FUNCS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/geneval.lua)
|
||||
set(EVENTS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gen_events.lua)
|
||||
set(OPTIONS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genoptions.lua)
|
||||
set(EVENTS_LIST_FILE ${PROJECT_SOURCE_DIR}/src/nvim/auevents.lua)
|
||||
set(EX_CMDS_DEFS_FILE ${PROJECT_SOURCE_DIR}/src/nvim/ex_cmds.lua)
|
||||
set(EVAL_DEFS_FILE ${PROJECT_SOURCE_DIR}/src/nvim/eval.lua)
|
||||
set(OPTIONS_LIST_FILE ${PROJECT_SOURCE_DIR}/src/nvim/options.lua)
|
||||
set(UNICODE_TABLES_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genunicodetables.lua)
|
||||
set(UNICODE_DIR ${PROJECT_SOURCE_DIR}/unicode)
|
||||
file(GLOB UNICODE_FILES ${UNICODE_DIR}/*.txt)
|
||||
@ -112,7 +107,7 @@ set(CONV_SOURCES
|
||||
window.c)
|
||||
|
||||
foreach(sfile ${CONV_SOURCES})
|
||||
if(NOT EXISTS "${PROJECT_SOURCE_DIR}/src/nvim/${sfile}")
|
||||
if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/${sfile}")
|
||||
message(FATAL_ERROR "${sfile} doesn't exist (it was added to CONV_SOURCES)")
|
||||
endif()
|
||||
endforeach()
|
||||
@ -167,11 +162,11 @@ endfunction()
|
||||
# NVIM_GENERATED_SOURCES: generated source files
|
||||
# These lists must be mutually exclusive.
|
||||
foreach(sfile ${NVIM_SOURCES}
|
||||
"${PROJECT_SOURCE_DIR}/src/nvim/regexp_nfa.c"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/regexp_nfa.c"
|
||||
${GENERATED_API_DISPATCH})
|
||||
get_filename_component(full_d ${sfile} PATH)
|
||||
file(RELATIVE_PATH d "${PROJECT_SOURCE_DIR}/src/nvim" "${full_d}")
|
||||
if(${d} MATCHES "^([.][.]|auto/)")
|
||||
file(RELATIVE_PATH d "${CMAKE_CURRENT_LIST_DIR}" "${full_d}")
|
||||
if(${d} MATCHES "^[.][.]|auto/")
|
||||
file(RELATIVE_PATH d "${GENERATED_DIR}" "${full_d}")
|
||||
endif()
|
||||
get_filename_component(f ${sfile} NAME)
|
||||
@ -239,8 +234,8 @@ list(APPEND NVIM_GENERATED_SOURCES
|
||||
|
||||
add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS}
|
||||
COMMAND ${LUA_PRG} ${EX_CMDS_GENERATOR}
|
||||
${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_INCLUDES_DIR} ${GENERATED_DIR}
|
||||
DEPENDS ${EX_CMDS_GENERATOR} ${EX_CMDS_DEFS_FILE}
|
||||
${CMAKE_CURRENT_LIST_DIR} ${GENERATED_INCLUDES_DIR} ${GENERATED_DIR}
|
||||
DEPENDS ${EX_CMDS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/ex_cmds.lua
|
||||
)
|
||||
|
||||
if(NOT GPERF_PRG)
|
||||
@ -248,24 +243,24 @@ if(NOT GPERF_PRG)
|
||||
endif()
|
||||
add_custom_command(OUTPUT ${GENERATED_FUNCS} ${FUNCS_DATA}
|
||||
COMMAND ${LUA_PRG} ${FUNCS_GENERATOR}
|
||||
${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_DIR} ${API_METADATA} ${FUNCS_DATA}
|
||||
${CMAKE_CURRENT_LIST_DIR} ${GENERATED_DIR} ${API_METADATA} ${FUNCS_DATA}
|
||||
COMMAND ${GPERF_PRG}
|
||||
${GENERATED_FUNCS_HASH_INPUT} --output-file=${GENERATED_FUNCS}
|
||||
DEPENDS ${FUNCS_GENERATOR} ${EVAL_DEFS_FILE} ${API_METADATA}
|
||||
${GENERATED_DIR}/funcs.generated.h.gperf --output-file=${GENERATED_FUNCS}
|
||||
DEPENDS ${FUNCS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/eval.lua ${API_METADATA}
|
||||
)
|
||||
list(APPEND NVIM_GENERATED_FOR_SOURCES
|
||||
"${GENERATED_FUNCS}")
|
||||
|
||||
add_custom_command(OUTPUT ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP}
|
||||
COMMAND ${LUA_PRG} ${EVENTS_GENERATOR}
|
||||
${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP}
|
||||
DEPENDS ${EVENTS_GENERATOR} ${EVENTS_LIST_FILE}
|
||||
${CMAKE_CURRENT_LIST_DIR} ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP}
|
||||
DEPENDS ${EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/auevents.lua
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT ${GENERATED_OPTIONS}
|
||||
COMMAND ${LUA_PRG} ${OPTIONS_GENERATOR}
|
||||
${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_OPTIONS}
|
||||
DEPENDS ${OPTIONS_GENERATOR} ${OPTIONS_LIST_FILE}
|
||||
${CMAKE_CURRENT_LIST_DIR} ${GENERATED_OPTIONS}
|
||||
DEPENDS ${OPTIONS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/options.lua
|
||||
)
|
||||
|
||||
# NVIM_GENERATED_FOR_SOURCES and NVIM_GENERATED_FOR_HEADERS must be mutually exclusive.
|
||||
|
@ -296,7 +296,7 @@ void nvim_buf_set_lines(uint64_t channel_id,
|
||||
tabpage_T *save_curtab = NULL;
|
||||
size_t new_len = replacement.size;
|
||||
size_t old_len = (size_t)(end - start);
|
||||
ssize_t extra = 0; // lines added to text, can be negative
|
||||
ptrdiff_t extra = 0; // lines added to text, can be negative
|
||||
char **lines = (new_len != 0) ? xcalloc(new_len, sizeof(char *)) : NULL;
|
||||
|
||||
for (size_t i = 0; i < new_len; i++) {
|
||||
@ -342,8 +342,8 @@ void nvim_buf_set_lines(uint64_t channel_id,
|
||||
}
|
||||
}
|
||||
|
||||
if ((ssize_t)to_delete > 0) {
|
||||
extra -= (ssize_t)to_delete;
|
||||
if (to_delete > 0) {
|
||||
extra -= (ptrdiff_t)to_delete;
|
||||
}
|
||||
|
||||
// For as long as possible, replace the existing old_len with the
|
||||
@ -395,10 +395,10 @@ void nvim_buf_set_lines(uint64_t channel_id,
|
||||
mark_adjust((linenr_T)start, (linenr_T)(end - 1), MAXLNUM, extra);
|
||||
}
|
||||
|
||||
changed_lines((linenr_T)start, 0, (linenr_T)end, extra);
|
||||
changed_lines((linenr_T)start, 0, (linenr_T)end, (long)extra);
|
||||
|
||||
if (save_curbuf.br_buf == NULL) {
|
||||
fix_cursor((linenr_T)start, (linenr_T)end, extra);
|
||||
fix_cursor((linenr_T)start, (linenr_T)end, (linenr_T)extra);
|
||||
}
|
||||
|
||||
end:
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "nvim/window.h"
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/map_defs.h"
|
||||
#include "nvim/map.h"
|
||||
#include "nvim/option.h"
|
||||
@ -87,14 +88,13 @@ bool try_end(Error *err)
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
Object dict_get_value(dict_T *dict, String key, Error *err)
|
||||
{
|
||||
hashitem_T *hi = hash_find(&dict->dv_hashtab, (uint8_t *) key.data);
|
||||
dictitem_T *const di = tv_dict_find(dict, key.data, (ptrdiff_t)key.size);
|
||||
|
||||
if (HASHITEM_EMPTY(hi)) {
|
||||
if (di == NULL) {
|
||||
api_set_error(err, Validation, _("Key not found"));
|
||||
return (Object) OBJECT_INIT;
|
||||
}
|
||||
|
||||
dictitem_T *di = dict_lookup(hi);
|
||||
return vim_to_object(&di->di_tv);
|
||||
}
|
||||
|
||||
@ -129,7 +129,7 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del,
|
||||
return rv;
|
||||
}
|
||||
|
||||
dictitem_T *di = dict_find(dict, (char_u *)key.data, (int)key.size);
|
||||
dictitem_T *di = tv_dict_find(dict, key.data, (ptrdiff_t)key.size);
|
||||
|
||||
if (di != NULL) {
|
||||
if (di->di_flags & DI_FLAGS_RO) {
|
||||
@ -155,9 +155,7 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del,
|
||||
rv = vim_to_object(&di->di_tv);
|
||||
}
|
||||
// Delete the entry
|
||||
hashitem_T *hi = hash_find(&dict->dv_hashtab, di->di_key);
|
||||
hash_remove(&dict->dv_hashtab, hi);
|
||||
dictitem_free(di);
|
||||
tv_dict_item_remove(dict, di);
|
||||
}
|
||||
} else {
|
||||
// Update the key
|
||||
@ -170,20 +168,20 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del,
|
||||
|
||||
if (di == NULL) {
|
||||
// Need to create an entry
|
||||
di = dictitem_alloc((uint8_t *) key.data);
|
||||
dict_add(dict, di);
|
||||
di = tv_dict_item_alloc_len(key.data, key.size);
|
||||
tv_dict_add(dict, di);
|
||||
} else {
|
||||
// Return the old value
|
||||
if (retval) {
|
||||
rv = vim_to_object(&di->di_tv);
|
||||
}
|
||||
clear_tv(&di->di_tv);
|
||||
tv_clear(&di->di_tv);
|
||||
}
|
||||
|
||||
// Update the value
|
||||
copy_tv(&tv, &di->di_tv);
|
||||
tv_copy(&tv, &di->di_tv);
|
||||
// Clear the temporary variable
|
||||
clear_tv(&tv);
|
||||
tv_clear(&tv);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -627,7 +625,7 @@ String cstr_as_string(char *str) FUNC_ATTR_PURE
|
||||
if (str == NULL) {
|
||||
return (String) STRING_INIT;
|
||||
}
|
||||
return (String) {.data = str, .size = strlen(str)};
|
||||
return (String) { .data = str, .size = strlen(str) };
|
||||
}
|
||||
|
||||
/// Converts from type Object to a VimL value.
|
||||
@ -682,20 +680,20 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
|
||||
break;
|
||||
|
||||
case kObjectTypeArray: {
|
||||
list_T *list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
|
||||
for (uint32_t i = 0; i < obj.data.array.size; i++) {
|
||||
Object item = obj.data.array.items[i];
|
||||
listitem_T *li = listitem_alloc();
|
||||
listitem_T *li = tv_list_item_alloc();
|
||||
|
||||
if (!object_to_vim(item, &li->li_tv, err)) {
|
||||
// cleanup
|
||||
listitem_free(li);
|
||||
list_free(list);
|
||||
tv_list_item_free(li);
|
||||
tv_list_free(list);
|
||||
return false;
|
||||
}
|
||||
|
||||
list_append(list, li);
|
||||
tv_list_append(list, li);
|
||||
}
|
||||
list->lv_refcount++;
|
||||
|
||||
@ -705,7 +703,7 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
|
||||
}
|
||||
|
||||
case kObjectTypeDictionary: {
|
||||
dict_T *dict = dict_alloc();
|
||||
dict_T *const dict = tv_dict_alloc();
|
||||
|
||||
for (uint32_t i = 0; i < obj.data.dictionary.size; i++) {
|
||||
KeyValuePair item = obj.data.dictionary.items[i];
|
||||
@ -715,20 +713,20 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
|
||||
api_set_error(err, Validation,
|
||||
_("Empty dictionary keys aren't allowed"));
|
||||
// cleanup
|
||||
dict_free(dict);
|
||||
tv_dict_free(dict);
|
||||
return false;
|
||||
}
|
||||
|
||||
dictitem_T *di = dictitem_alloc((uint8_t *)key.data);
|
||||
dictitem_T *const di = tv_dict_item_alloc(key.data);
|
||||
|
||||
if (!object_to_vim(item.value, &di->di_tv, err)) {
|
||||
// cleanup
|
||||
dictitem_free(di);
|
||||
dict_free(dict);
|
||||
tv_dict_item_free(di);
|
||||
tv_dict_free(dict);
|
||||
return false;
|
||||
}
|
||||
|
||||
dict_add(dict, di);
|
||||
tv_dict_add(dict, di);
|
||||
}
|
||||
dict->dv_refcount++;
|
||||
|
||||
@ -959,11 +957,7 @@ static void set_option_value_err(char *key,
|
||||
{
|
||||
char *errmsg;
|
||||
|
||||
if ((errmsg = (char *)set_option_value((uint8_t *)key,
|
||||
numval,
|
||||
(uint8_t *)stringval,
|
||||
opt_flags)))
|
||||
{
|
||||
if ((errmsg = set_option_value(key, numval, stringval, opt_flags))) {
|
||||
if (try_end(err)) {
|
||||
return;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/message.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/option.h"
|
||||
#include "nvim/syntax.h"
|
||||
#include "nvim/getchar.h"
|
||||
@ -181,19 +182,20 @@ Object nvim_eval(String expr, Error *err)
|
||||
Object rv = OBJECT_INIT;
|
||||
// Evaluate the expression
|
||||
try_start();
|
||||
typval_T *expr_result = eval_expr((char_u *)expr.data, NULL);
|
||||
|
||||
if (!expr_result) {
|
||||
api_set_error(err, Exception, _("Failed to evaluate expression"));
|
||||
typval_T rettv;
|
||||
if (eval0((char_u *)expr.data, &rettv, NULL, true) == FAIL) {
|
||||
api_set_error(err, Exception, "Failed to evaluate expression");
|
||||
}
|
||||
|
||||
if (!try_end(err)) {
|
||||
// No errors, convert the result
|
||||
rv = vim_to_object(expr_result);
|
||||
rv = vim_to_object(&rettv);
|
||||
}
|
||||
|
||||
// Free the vim object
|
||||
free_tv(expr_result);
|
||||
// Free the Vim object
|
||||
tv_clear(&rettv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -237,11 +239,11 @@ Object nvim_call_function(String fname, Array args, Error *err)
|
||||
if (!try_end(err)) {
|
||||
rv = vim_to_object(&rettv);
|
||||
}
|
||||
clear_tv(&rettv);
|
||||
tv_clear(&rettv);
|
||||
|
||||
free_vim_args:
|
||||
while (i > 0) {
|
||||
clear_tv(&vim_args[--i]);
|
||||
tv_clear(&vim_args[--i]);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -8,9 +8,11 @@
|
||||
|
||||
// Definitions of various common control characters.
|
||||
|
||||
#define CharOrd(x) ((x) < 'a' ? (x) - 'A' : (x) - 'a')
|
||||
#define CharOrdLow(x) ((x) - 'a')
|
||||
#define CharOrdUp(x) ((x) - 'A')
|
||||
#define CharOrd(x) ((uint8_t)(x) < 'a' \
|
||||
? (uint8_t)(x) - 'A'\
|
||||
: (uint8_t)(x) - 'a')
|
||||
#define CharOrdLow(x) ((uint8_t)(x) - 'a')
|
||||
#define CharOrdUp(x) ((uint8_t)(x) - 'A')
|
||||
#define ROT13(c, a) (((((c) - (a)) + 13) % 26) + (a))
|
||||
|
||||
#define NUL '\000'
|
||||
@ -18,15 +20,14 @@
|
||||
#define BS '\010'
|
||||
#define TAB '\011'
|
||||
#define NL '\012'
|
||||
#define NL_STR (char_u *)"\012"
|
||||
#define NL_STR "\012"
|
||||
#define FF '\014'
|
||||
#define CAR '\015' /* CR is used by Mac OS X */
|
||||
#define ESC '\033'
|
||||
#define ESC_STR (char_u *)"\033"
|
||||
#define ESC_STR_nc "\033"
|
||||
#define ESC_STR "\033"
|
||||
#define DEL 0x7f
|
||||
#define DEL_STR (char_u *)"\177"
|
||||
#define CSI 0x9b /* Control Sequence Introducer */
|
||||
#define DEL_STR "\177"
|
||||
#define CSI 0x9b // Control Sequence Introducer
|
||||
#define CSI_STR "\233"
|
||||
#define DCS 0x90 /* Device Control String */
|
||||
#define STERM 0x9c /* String Terminator */
|
||||
|
@ -661,7 +661,7 @@ static void free_buffer(buf_T *buf)
|
||||
free_buffer_stuff(buf, true);
|
||||
unref_var_dict(buf->b_vars);
|
||||
aubuflocal_remove(buf);
|
||||
dict_unref(buf->additional_data);
|
||||
tv_dict_unref(buf->additional_data);
|
||||
clear_fmark(&buf->b_last_cursor);
|
||||
clear_fmark(&buf->b_last_insert);
|
||||
clear_fmark(&buf->b_last_change);
|
||||
@ -1472,7 +1472,7 @@ static inline void buf_init_changedtick(buf_T *const buf)
|
||||
{
|
||||
STATIC_ASSERT(sizeof("changedtick") <= sizeof(buf->changedtick_di.di_key),
|
||||
"buf->changedtick_di cannot hold large enough keys");
|
||||
buf->changedtick_di = (dictitem16_T) {
|
||||
buf->changedtick_di = (ChangedtickDictItem) {
|
||||
.di_flags = DI_FLAGS_RO|DI_FLAGS_FIX, // Must not include DI_FLAGS_ALLOC.
|
||||
.di_tv = (typval_T) {
|
||||
.v_type = VAR_NUMBER,
|
||||
@ -1481,7 +1481,7 @@ static inline void buf_init_changedtick(buf_T *const buf)
|
||||
},
|
||||
.di_key = "changedtick",
|
||||
};
|
||||
dict_add(buf->b_vars, (dictitem_T *)&buf->changedtick_di);
|
||||
tv_dict_add(buf->b_vars, (dictitem_T *)&buf->changedtick_di);
|
||||
}
|
||||
|
||||
/// Add a file name to the buffer list.
|
||||
@ -1573,7 +1573,7 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags)
|
||||
if (buf != curbuf || curbuf == NULL) {
|
||||
buf = xcalloc(1, sizeof(buf_T));
|
||||
// init b: variables
|
||||
buf->b_vars = dict_alloc();
|
||||
buf->b_vars = tv_dict_alloc();
|
||||
init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
|
||||
buf_init_changedtick(buf);
|
||||
}
|
||||
@ -3504,7 +3504,7 @@ int build_stl_str_hl(
|
||||
curbuf = o_curbuf;
|
||||
|
||||
// Remove the variable we just stored
|
||||
do_unlet((char_u *)"g:actual_curbuf", true);
|
||||
do_unlet(S_LEN("g:actual_curbuf"), true);
|
||||
|
||||
// }
|
||||
|
||||
@ -4207,11 +4207,11 @@ void fname_expand(buf_T *buf, char_u **ffname, char_u **sfname)
|
||||
#ifdef WIN32
|
||||
if (!buf->b_p_bin) {
|
||||
// If the file name is a shortcut file, use the file it links to.
|
||||
char_u *rfname = (char_u *)os_resolve_shortcut(*ffname);
|
||||
char *rfname = os_resolve_shortcut((const char *)(*ffname));
|
||||
if (rfname != NULL) {
|
||||
xfree(*ffname);
|
||||
*ffname = rfname;
|
||||
*sfname = rfname;
|
||||
*ffname = (char_u *)rfname;
|
||||
*sfname = (char_u *)rfname;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -5443,8 +5443,8 @@ void buf_open_scratch(handle_T bufnr, char *bufname)
|
||||
{
|
||||
(void)do_ecmd((int)bufnr, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL);
|
||||
(void)setfname(curbuf, (char_u *)bufname, NULL, true);
|
||||
set_option_value((char_u *)"bh", 0L, (char_u *)"hide", OPT_LOCAL);
|
||||
set_option_value((char_u *)"bt", 0L, (char_u *)"nofile", OPT_LOCAL);
|
||||
set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL);
|
||||
set_option_value("bh", 0L, "hide", OPT_LOCAL);
|
||||
set_option_value("bt", 0L, "nofile", OPT_LOCAL);
|
||||
set_option_value("swf", 0L, NULL, OPT_LOCAL);
|
||||
RESET_BINDING(curwin);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "nvim/screen.h" // for StlClickRecord
|
||||
#include "nvim/func_attr.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/macros.h"
|
||||
|
||||
// Values for buflist_getfile()
|
||||
enum getf_values {
|
||||
@ -91,8 +92,8 @@ static inline void buf_set_changedtick(buf_T *const buf, const int changedtick)
|
||||
static inline void buf_set_changedtick(buf_T *const buf, const int changedtick)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
dictitem_T *const changedtick_di = dict_find(
|
||||
buf->b_vars, (char_u *)"changedtick", sizeof("changedtick") - 1);
|
||||
dictitem_T *const changedtick_di = tv_dict_find(
|
||||
buf->b_vars, S_LEN("changedtick"));
|
||||
assert(changedtick_di != NULL);
|
||||
assert(changedtick_di->di_tv.v_type == VAR_NUMBER);
|
||||
assert(changedtick_di->di_tv.v_lock == VAR_FIXED);
|
||||
|
@ -21,8 +21,6 @@ typedef struct {
|
||||
#include "nvim/pos.h"
|
||||
// for the number window-local and buffer-local options
|
||||
#include "nvim/option_defs.h"
|
||||
// for optional iconv support
|
||||
#include "nvim/iconv.h"
|
||||
// for jump list and tag stack sizes in a buffer and mark types
|
||||
#include "nvim/mark_defs.h"
|
||||
// for u_header_T; needs buf_T.
|
||||
@ -30,7 +28,9 @@ typedef struct {
|
||||
// for hashtab_T
|
||||
#include "nvim/hashtab.h"
|
||||
// for dict_T
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
// for proftime_T
|
||||
#include "nvim/profile.h"
|
||||
// for String
|
||||
#include "nvim/api/private/defs.h"
|
||||
// for Map(K, V)
|
||||
@ -318,25 +318,6 @@ typedef struct {
|
||||
String save_inputbuf;
|
||||
} tasave_T;
|
||||
|
||||
/*
|
||||
* Used for conversion of terminal I/O and script files.
|
||||
*/
|
||||
typedef struct {
|
||||
int vc_type; /* zero or one of the CONV_ values */
|
||||
int vc_factor; /* max. expansion factor */
|
||||
# ifdef USE_ICONV
|
||||
iconv_t vc_fd; /* for CONV_ICONV */
|
||||
# endif
|
||||
bool vc_fail; /* fail for invalid char, don't use '?' */
|
||||
} vimconv_T;
|
||||
|
||||
#define CONV_NONE 0
|
||||
#define CONV_TO_UTF8 1
|
||||
#define CONV_9_TO_UTF8 2
|
||||
#define CONV_TO_LATIN1 3
|
||||
#define CONV_TO_LATIN9 4
|
||||
#define CONV_ICONV 5
|
||||
|
||||
/*
|
||||
* Structure used for mappings and abbreviations.
|
||||
*/
|
||||
@ -447,6 +428,10 @@ typedef struct {
|
||||
char_u *b_syn_isk; // iskeyword option
|
||||
} synblock_T;
|
||||
|
||||
/// Type used for changedtick_di member in buf_T
|
||||
///
|
||||
/// Primary exists so that literals of relevant type can be made.
|
||||
typedef TV_DICTITEM_STRUCT(sizeof("changedtick")) ChangedtickDictItem;
|
||||
|
||||
#define BUF_HAS_QF_ENTRY 1
|
||||
#define BUF_HAS_LL_ENTRY 2
|
||||
@ -491,7 +476,7 @@ struct file_buffer {
|
||||
// file has been changed and not written out.
|
||||
/// Change identifier incremented for each change, including undo
|
||||
#define b_changedtick changedtick_di.di_tv.vval.v_number
|
||||
dictitem16_T changedtick_di; // b:changedtick dictionary item.
|
||||
ChangedtickDictItem changedtick_di; // b:changedtick dictionary item.
|
||||
|
||||
bool b_saving; /* Set to true if we are in the middle of
|
||||
saving the buffer. */
|
||||
@ -735,8 +720,8 @@ struct file_buffer {
|
||||
int b_bad_char; /* "++bad=" argument when edit started or 0 */
|
||||
int b_start_bomb; /* 'bomb' when it was read */
|
||||
|
||||
dictitem_T b_bufvar; /* variable for "b:" Dictionary */
|
||||
dict_T *b_vars; /* internal variables, local to buffer */
|
||||
ScopeDictDictItem b_bufvar; ///< Variable for "b:" Dictionary.
|
||||
dict_T *b_vars; ///< b: scope dictionary.
|
||||
|
||||
/* When a buffer is created, it starts without a swap file. b_may_swap is
|
||||
* then set to indicate that a swap file may be opened later. It is reset
|
||||
@ -824,9 +809,9 @@ struct tabpage_S {
|
||||
buf_T *(tp_diffbuf[DB_COUNT]);
|
||||
int tp_diff_invalid; ///< list of diffs is outdated
|
||||
frame_T *(tp_snapshot[SNAP_COUNT]); ///< window layout snapshots
|
||||
dictitem_T tp_winvar; ///< variable for "t:" Dictionary
|
||||
dict_T *tp_vars; ///< internal variables, local to tab page
|
||||
char_u *tp_localdir; ///< Absolute path of local CWD or NULL
|
||||
ScopeDictDictItem tp_winvar; ///< Variable for "t:" Dictionary.
|
||||
dict_T *tp_vars; ///< Internal variables, local to tab page.
|
||||
char_u *tp_localdir; ///< Absolute path of local cwd or NULL.
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1118,8 +1103,8 @@ struct window_S {
|
||||
|
||||
long w_scbind_pos;
|
||||
|
||||
dictitem_T w_winvar; /* variable for "w:" Dictionary */
|
||||
dict_T *w_vars; /* internal variables, local to window */
|
||||
ScopeDictDictItem w_winvar; ///< Variable for "w:" dictionary.
|
||||
dict_T *w_vars; ///< Dictionary with w: variables.
|
||||
|
||||
int w_farsi; /* for the window dependent Farsi functions */
|
||||
|
||||
|
@ -41,8 +41,10 @@ static bool chartab_initialized = false;
|
||||
(buf)->b_chartab[(unsigned)(c) >> 6] |= (1ull << ((c) & 0x3f))
|
||||
#define RESET_CHARTAB(buf, c) \
|
||||
(buf)->b_chartab[(unsigned)(c) >> 6] &= ~(1ull << ((c) & 0x3f))
|
||||
#define GET_CHARTAB_TAB(chartab, c) \
|
||||
((chartab)[(unsigned)(c) >> 6] & (1ull << ((c) & 0x3f)))
|
||||
#define GET_CHARTAB(buf, c) \
|
||||
((buf)->b_chartab[(unsigned)(c) >> 6] & (1ull << ((c) & 0x3f)))
|
||||
GET_CHARTAB_TAB((buf)->b_chartab, c)
|
||||
|
||||
// Table used below, see init_chartab() for an explanation
|
||||
static char_u g_chartab[256];
|
||||
@ -88,7 +90,6 @@ int buf_init_chartab(buf_T *buf, int global)
|
||||
{
|
||||
int c;
|
||||
int c2;
|
||||
char_u *p;
|
||||
int i;
|
||||
bool tilde;
|
||||
bool do_isalpha;
|
||||
@ -142,7 +143,8 @@ int buf_init_chartab(buf_T *buf, int global)
|
||||
// Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint'
|
||||
// options Each option is a list of characters, character numbers or
|
||||
// ranges, separated by commas, e.g.: "200-210,x,#-178,-"
|
||||
for (i = global ? 0 : 3; i <= 3; ++i) {
|
||||
for (i = global ? 0 : 3; i <= 3; i++) {
|
||||
const char_u *p;
|
||||
if (i == 0) {
|
||||
// first round: 'isident'
|
||||
p = p_isi;
|
||||
@ -167,7 +169,7 @@ int buf_init_chartab(buf_T *buf, int global)
|
||||
}
|
||||
|
||||
if (ascii_isdigit(*p)) {
|
||||
c = getdigits_int(&p);
|
||||
c = getdigits_int((char_u **)&p);
|
||||
} else {
|
||||
c = mb_ptr2char_adv(&p);
|
||||
}
|
||||
@ -177,7 +179,7 @@ int buf_init_chartab(buf_T *buf, int global)
|
||||
++p;
|
||||
|
||||
if (ascii_isdigit(*p)) {
|
||||
c2 = getdigits_int(&p);
|
||||
c2 = getdigits_int((char_u **)&p);
|
||||
} else {
|
||||
c2 = mb_ptr2char_adv(&p);
|
||||
}
|
||||
@ -634,7 +636,7 @@ int char2cells(int c)
|
||||
/// @param p
|
||||
///
|
||||
/// @return number of display cells.
|
||||
int ptr2cells(char_u *p)
|
||||
int ptr2cells(const char_u *p)
|
||||
{
|
||||
// For UTF-8 we need to look at more bytes if the first byte is >= 0x80.
|
||||
if (*p >= 0x80) {
|
||||
@ -776,6 +778,20 @@ bool vim_iswordc(int c)
|
||||
return vim_iswordc_buf(c, curbuf);
|
||||
}
|
||||
|
||||
/// Check that "c" is a keyword character
|
||||
/// Letters and characters from 'iskeyword' option for given buffer.
|
||||
/// For multi-byte characters mb_get_class() is used (builtin rules).
|
||||
///
|
||||
/// @param[in] c Character to check.
|
||||
/// @param[in] chartab Buffer chartab.
|
||||
bool vim_iswordc_tab(const int c, const uint64_t *const chartab)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
return (c >= 0x100
|
||||
? (utf_class(c) >= 2)
|
||||
: (c > 0 && GET_CHARTAB_TAB(chartab, c) != 0));
|
||||
}
|
||||
|
||||
/// Check that "c" is a keyword character:
|
||||
/// Letters and characters from 'iskeyword' option for given buffer.
|
||||
/// For multi-byte characters mb_get_class() is used (builtin rules).
|
||||
@ -785,10 +801,7 @@ bool vim_iswordc(int c)
|
||||
bool vim_iswordc_buf(int c, buf_T *buf)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(2)
|
||||
{
|
||||
if (c >= 0x100) {
|
||||
return utf_class(c) >= 2;
|
||||
}
|
||||
return c > 0 && c < 0x100 && GET_CHARTAB(buf, c) != 0;
|
||||
return vim_iswordc_tab(c, buf->b_chartab);
|
||||
}
|
||||
|
||||
/// Just like vim_iswordc() but uses a pointer to the (multi-byte) character.
|
||||
@ -1384,7 +1397,8 @@ void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left,
|
||||
///
|
||||
/// @return Pointer to character after the skipped whitespace.
|
||||
char_u *skipwhite(const char_u *q)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||
FUNC_ATTR_NONNULL_RET
|
||||
{
|
||||
const char_u *p = q;
|
||||
while (ascii_iswhite(*p)) {
|
||||
@ -1393,19 +1407,21 @@ char_u *skipwhite(const char_u *q)
|
||||
return (char_u *)p;
|
||||
}
|
||||
|
||||
/// skip over digits
|
||||
/// Skip over digits
|
||||
///
|
||||
/// @param q
|
||||
/// @param[in] q String to skip digits in.
|
||||
///
|
||||
/// @return Pointer to the character after the skipped digits.
|
||||
char_u* skipdigits(char_u *q)
|
||||
char_u *skipdigits(const char_u *q)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||
FUNC_ATTR_NONNULL_RET
|
||||
{
|
||||
char_u *p = q;
|
||||
const char_u *p = q;
|
||||
while (ascii_isdigit(*p)) {
|
||||
// skip to next non-digit
|
||||
p++;
|
||||
}
|
||||
return p;
|
||||
return (char_u *)p;
|
||||
}
|
||||
|
||||
/// skip over binary digits
|
||||
@ -1551,17 +1567,17 @@ int vim_tolower(int c)
|
||||
return TOLOWER_LOC(c);
|
||||
}
|
||||
|
||||
/// skiptowhite: skip over text until ' ' or '\t' or NUL.
|
||||
/// Skip over text until ' ' or '\t' or NUL
|
||||
///
|
||||
/// @param p
|
||||
/// @param[in] p Text to skip over.
|
||||
///
|
||||
/// @return Pointer to the next whitespace or NUL character.
|
||||
char_u* skiptowhite(char_u *p)
|
||||
char_u *skiptowhite(const char_u *p)
|
||||
{
|
||||
while (*p != ' ' && *p != '\t' && *p != NUL) {
|
||||
p++;
|
||||
}
|
||||
return p;
|
||||
return (char_u *)p;
|
||||
}
|
||||
|
||||
/// skiptowhite_esc: Like skiptowhite(), but also skip escaped chars
|
||||
|
@ -5,6 +5,16 @@
|
||||
#include "nvim/pos.h"
|
||||
#include "nvim/buffer_defs.h"
|
||||
|
||||
/// Return the folded-case equivalent of the given character
|
||||
///
|
||||
/// @param[in] c Character to transform.
|
||||
///
|
||||
/// @return Folded variant.
|
||||
#define CH_FOLD(c) \
|
||||
utf_fold((sizeof(c) == sizeof(char)) \
|
||||
?((int)(uint8_t)(c)) \
|
||||
:((int)(c)))
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "charset.h.generated.h"
|
||||
#endif
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "nvim/state.h"
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/mark.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "cursor.c.generated.h"
|
||||
@ -227,9 +228,10 @@ static int coladvance2(
|
||||
}
|
||||
}
|
||||
|
||||
/* prevent from moving onto a trail byte */
|
||||
if (has_mbyte)
|
||||
mb_adjustpos(curbuf, pos);
|
||||
// Prevent from moving onto a trail byte.
|
||||
if (has_mbyte) {
|
||||
mark_mb_adjustpos(curbuf, pos);
|
||||
}
|
||||
|
||||
if (col < wcol)
|
||||
return FAIL;
|
||||
@ -361,9 +363,10 @@ void check_cursor_col_win(win_T *win)
|
||||
win->w_cursor.col = len;
|
||||
} else {
|
||||
win->w_cursor.col = len - 1;
|
||||
/* Move the cursor to the head byte. */
|
||||
if (has_mbyte)
|
||||
mb_adjustpos(win->w_buffer, &win->w_cursor);
|
||||
// Move the cursor to the head byte.
|
||||
if (has_mbyte) {
|
||||
mark_mb_adjustpos(win->w_buffer, &win->w_cursor);
|
||||
}
|
||||
}
|
||||
} else if (win->w_cursor.col < 0) {
|
||||
win->w_cursor.col = 0;
|
||||
|
@ -1586,7 +1586,7 @@ static int diff_cmp(char_u *s1, char_u *s2)
|
||||
}
|
||||
|
||||
if ((diff_flags & DIFF_ICASE) && !(diff_flags & DIFF_IWHITE)) {
|
||||
return mb_stricmp(s1, s2);
|
||||
return mb_stricmp((const char *)s1, (const char *)s2);
|
||||
}
|
||||
|
||||
// Ignore white space changes and possibly ignore case.
|
||||
|
435
src/nvim/edit.c
435
src/nvim/edit.c
@ -15,6 +15,7 @@
|
||||
#include "nvim/cursor.h"
|
||||
#include "nvim/digraph.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/ex_docmd.h"
|
||||
#include "nvim/ex_getln.h"
|
||||
#include "nvim/farsi.h"
|
||||
@ -1422,7 +1423,7 @@ static void ins_ctrl_v(void)
|
||||
edit_putchar('^', TRUE);
|
||||
did_putchar = TRUE;
|
||||
}
|
||||
AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */
|
||||
AppendToRedobuff(CTRL_V_STR);
|
||||
|
||||
add_to_showcmd_c(Ctrl_V);
|
||||
|
||||
@ -1976,7 +1977,6 @@ static bool ins_compl_accept_char(int c)
|
||||
*/
|
||||
int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int dir, int flags)
|
||||
{
|
||||
char_u *p;
|
||||
int i, c;
|
||||
int actual_len; /* Take multi-byte characters */
|
||||
int actual_compl_length; /* into account. */
|
||||
@ -1986,11 +1986,11 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
|
||||
int was_letter = FALSE;
|
||||
|
||||
if (p_ic && curbuf->b_p_inf && len > 0) {
|
||||
/* Infer case of completed part. */
|
||||
// Infer case of completed part.
|
||||
|
||||
/* Find actual length of completion. */
|
||||
// Find actual length of completion.
|
||||
if (has_mbyte) {
|
||||
p = str;
|
||||
const char_u *p = str;
|
||||
actual_len = 0;
|
||||
while (*p != NUL) {
|
||||
mb_ptr_adv(p);
|
||||
@ -2001,7 +2001,7 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
|
||||
|
||||
/* Find actual length of original text. */
|
||||
if (has_mbyte) {
|
||||
p = compl_orig_text;
|
||||
const char_u *p = compl_orig_text;
|
||||
actual_compl_length = 0;
|
||||
while (*p != NUL) {
|
||||
mb_ptr_adv(p);
|
||||
@ -2017,27 +2017,35 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
|
||||
|
||||
/* Allocate wide character array for the completion and fill it. */
|
||||
wca = xmalloc(actual_len * sizeof(*wca));
|
||||
p = str;
|
||||
for (i = 0; i < actual_len; ++i)
|
||||
if (has_mbyte)
|
||||
wca[i] = mb_ptr2char_adv(&p);
|
||||
else
|
||||
wca[i] = *(p++);
|
||||
{
|
||||
const char_u *p = str;
|
||||
for (i = 0; i < actual_len; i++) {
|
||||
if (has_mbyte) {
|
||||
wca[i] = mb_ptr2char_adv(&p);
|
||||
} else {
|
||||
wca[i] = *(p++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Rule 1: Were any chars converted to lower? */
|
||||
p = compl_orig_text;
|
||||
for (i = 0; i < min_len; ++i) {
|
||||
if (has_mbyte)
|
||||
c = mb_ptr2char_adv(&p);
|
||||
else
|
||||
c = *(p++);
|
||||
if (vim_islower(c)) {
|
||||
has_lower = TRUE;
|
||||
if (vim_isupper(wca[i])) {
|
||||
/* Rule 1 is satisfied. */
|
||||
for (i = actual_compl_length; i < actual_len; ++i)
|
||||
wca[i] = vim_tolower(wca[i]);
|
||||
break;
|
||||
// Rule 1: Were any chars converted to lower?
|
||||
{
|
||||
const char_u *p = compl_orig_text;
|
||||
for (i = 0; i < min_len; i++) {
|
||||
if (has_mbyte) {
|
||||
c = mb_ptr2char_adv(&p);
|
||||
} else {
|
||||
c = *(p++);
|
||||
}
|
||||
if (vim_islower(c)) {
|
||||
has_lower = true;
|
||||
if (vim_isupper(wca[i])) {
|
||||
// Rule 1 is satisfied.
|
||||
for (i = actual_compl_length; i < actual_len; i++) {
|
||||
wca[i] = vim_tolower(wca[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2047,84 +2055,110 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
|
||||
* upper case.
|
||||
*/
|
||||
if (!has_lower) {
|
||||
p = compl_orig_text;
|
||||
for (i = 0; i < min_len; ++i) {
|
||||
if (has_mbyte)
|
||||
const char_u *p = compl_orig_text;
|
||||
for (i = 0; i < min_len; i++) {
|
||||
if (has_mbyte) {
|
||||
c = mb_ptr2char_adv(&p);
|
||||
else
|
||||
} else {
|
||||
c = *(p++);
|
||||
}
|
||||
if (was_letter && vim_isupper(c) && vim_islower(wca[i])) {
|
||||
/* Rule 2 is satisfied. */
|
||||
for (i = actual_compl_length; i < actual_len; ++i)
|
||||
// Rule 2 is satisfied.
|
||||
for (i = actual_compl_length; i < actual_len; i++) {
|
||||
wca[i] = vim_toupper(wca[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
was_letter = vim_islower(c) || vim_isupper(c);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the original case of the part we typed. */
|
||||
p = compl_orig_text;
|
||||
for (i = 0; i < min_len; ++i) {
|
||||
if (has_mbyte)
|
||||
c = mb_ptr2char_adv(&p);
|
||||
else
|
||||
c = *(p++);
|
||||
if (vim_islower(c))
|
||||
wca[i] = vim_tolower(wca[i]);
|
||||
else if (vim_isupper(c))
|
||||
wca[i] = vim_toupper(wca[i]);
|
||||
// Copy the original case of the part we typed.
|
||||
{
|
||||
const char_u *p = compl_orig_text;
|
||||
for (i = 0; i < min_len; i++) {
|
||||
if (has_mbyte) {
|
||||
c = mb_ptr2char_adv(&p);
|
||||
} else {
|
||||
c = *(p++);
|
||||
}
|
||||
if (vim_islower(c)) {
|
||||
wca[i] = vim_tolower(wca[i]);
|
||||
} else if (vim_isupper(c)) {
|
||||
wca[i] = vim_toupper(wca[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate encoding specific output from wide character array.
|
||||
* Multi-byte characters can occupy up to five bytes more than
|
||||
* ASCII characters, and we also need one byte for NUL, so stay
|
||||
* six bytes away from the edge of IObuff.
|
||||
*/
|
||||
p = IObuff;
|
||||
i = 0;
|
||||
while (i < actual_len && (p - IObuff + 6) < IOSIZE)
|
||||
if (has_mbyte)
|
||||
p += (*mb_char2bytes)(wca[i++], p);
|
||||
else
|
||||
*(p++) = wca[i++];
|
||||
*p = NUL;
|
||||
// Generate encoding specific output from wide character array.
|
||||
// Multi-byte characters can occupy up to five bytes more than
|
||||
// ASCII characters, and we also need one byte for NUL, so stay
|
||||
// six bytes away from the edge of IObuff.
|
||||
{
|
||||
char_u *p = IObuff;
|
||||
i = 0;
|
||||
while (i < actual_len && (p - IObuff + 6) < IOSIZE) {
|
||||
if (has_mbyte) {
|
||||
p += (*mb_char2bytes)(wca[i++], p);
|
||||
} else {
|
||||
*(p++) = wca[i++];
|
||||
}
|
||||
}
|
||||
*p = NUL;
|
||||
}
|
||||
|
||||
xfree(wca);
|
||||
|
||||
return ins_compl_add(IObuff, len, icase, fname, NULL, dir,
|
||||
flags, FALSE);
|
||||
return ins_compl_add(IObuff, len, icase, fname, NULL, true, dir, flags,
|
||||
false);
|
||||
}
|
||||
return ins_compl_add(str, len, icase, fname, NULL, dir, flags, FALSE);
|
||||
return ins_compl_add(str, len, icase, fname, NULL, false, dir, flags, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a match to the list of matches.
|
||||
* If the given string is already in the list of completions, then return
|
||||
* NOTDONE, otherwise add it to the list and return OK. If there is an error
|
||||
* then FAIL is returned.
|
||||
*/
|
||||
static int
|
||||
ins_compl_add (
|
||||
char_u *str,
|
||||
int len,
|
||||
int icase,
|
||||
char_u *fname,
|
||||
char_u **cptext, /* extra text for popup menu or NULL */
|
||||
int cdir,
|
||||
int flags,
|
||||
int adup /* accept duplicate match */
|
||||
)
|
||||
/// Add a match to the list of matches
|
||||
///
|
||||
/// @param[in] str Match to add.
|
||||
/// @param[in] len Match length, -1 to use #STRLEN.
|
||||
/// @param[in] icase Whether case is to be ignored.
|
||||
/// @param[in] fname File name match comes from. May be NULL.
|
||||
/// @param[in] cptext Extra text for popup menu. May be NULL. If not NULL,
|
||||
/// must have exactly #CPT_COUNT items.
|
||||
/// @param[in] cptext_allocated If true, will not copy cptext strings.
|
||||
///
|
||||
/// @note Will free strings in case of error.
|
||||
/// cptext itself will not be freed.
|
||||
/// @param[in] cdir Completion direction.
|
||||
/// @param[in] adup True if duplicate matches are to be accepted.
|
||||
///
|
||||
/// @return NOTDONE if the given string is already in the list of completions,
|
||||
/// otherwise it is added to the list and OK is returned. FAIL will be
|
||||
/// returned in case of error.
|
||||
static int ins_compl_add(char_u *const str, int len,
|
||||
const bool icase, char_u *const fname,
|
||||
char_u *const *const cptext,
|
||||
const bool cptext_allocated,
|
||||
const Direction cdir, int flags, const bool adup)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
compl_T *match;
|
||||
int dir = (cdir == 0 ? compl_direction : cdir);
|
||||
int dir = (cdir == kDirectionNotSet ? compl_direction : cdir);
|
||||
|
||||
os_breakcheck();
|
||||
if (got_int)
|
||||
#define FREE_CPTEXT(cptext, cptext_allocated) \
|
||||
do { \
|
||||
if (cptext_allocated) { \
|
||||
for (size_t i = 0; i < CPT_COUNT; i++) { \
|
||||
xfree(cptext[i]); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
if (got_int) {
|
||||
FREE_CPTEXT(cptext, cptext_allocated);
|
||||
return FAIL;
|
||||
if (len < 0)
|
||||
}
|
||||
if (len < 0) {
|
||||
len = (int)STRLEN(str);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the same match is already present, don't add it.
|
||||
@ -2132,10 +2166,12 @@ ins_compl_add (
|
||||
if (compl_first_match != NULL && !adup) {
|
||||
match = compl_first_match;
|
||||
do {
|
||||
if ( !(match->cp_flags & ORIGINAL_TEXT)
|
||||
&& STRNCMP(match->cp_str, str, len) == 0
|
||||
&& match->cp_str[len] == NUL)
|
||||
if (!(match->cp_flags & ORIGINAL_TEXT)
|
||||
&& STRNCMP(match->cp_str, str, len) == 0
|
||||
&& match->cp_str[len] == NUL) {
|
||||
FREE_CPTEXT(cptext, cptext_allocated);
|
||||
return NOTDONE;
|
||||
}
|
||||
match = match->cp_next;
|
||||
} while (match != NULL && match != compl_first_match);
|
||||
}
|
||||
@ -2166,16 +2202,26 @@ ins_compl_add (
|
||||
else if (fname != NULL) {
|
||||
match->cp_fname = vim_strsave(fname);
|
||||
flags |= FREE_FNAME;
|
||||
} else
|
||||
} else {
|
||||
match->cp_fname = NULL;
|
||||
}
|
||||
match->cp_flags = flags;
|
||||
|
||||
if (cptext != NULL) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CPT_COUNT; ++i)
|
||||
if (cptext[i] != NULL && *cptext[i] != NUL)
|
||||
match->cp_text[i] = vim_strsave(cptext[i]);
|
||||
for (i = 0; i < CPT_COUNT; i++) {
|
||||
if (cptext[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (*cptext[i] != NUL) {
|
||||
match->cp_text[i] = (cptext_allocated
|
||||
? cptext[i]
|
||||
: (char_u *)xstrdup((char *)cptext[i]));
|
||||
} else if (cptext_allocated) {
|
||||
xfree(cptext[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2298,9 +2344,10 @@ static void ins_compl_add_matches(int num_matches, char_u **matches, int icase)
|
||||
|
||||
for (i = 0; i < num_matches && add_r != FAIL; i++)
|
||||
if ((add_r = ins_compl_add(matches[i], -1, icase,
|
||||
NULL, NULL, dir, 0, FALSE)) == OK)
|
||||
/* if dir was BACKWARD then honor it just once */
|
||||
NULL, NULL, false, dir, 0, false)) == OK) {
|
||||
// If dir was BACKWARD then honor it just once.
|
||||
dir = FORWARD;
|
||||
}
|
||||
FreeWild(num_matches, matches);
|
||||
}
|
||||
|
||||
@ -2364,8 +2411,8 @@ void set_completion(colnr_T startcol, list_T *list)
|
||||
/* compl_pattern doesn't need to be set */
|
||||
compl_orig_text = vim_strnsave(get_cursor_line_ptr() + compl_col,
|
||||
compl_length);
|
||||
if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, 0,
|
||||
ORIGINAL_TEXT, FALSE) != OK) {
|
||||
if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, false, 0,
|
||||
ORIGINAL_TEXT, false) != OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2887,7 +2934,7 @@ static void ins_compl_clear(void)
|
||||
compl_orig_text = NULL;
|
||||
compl_enter_selects = FALSE;
|
||||
// clear v:completed_item
|
||||
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
|
||||
set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc());
|
||||
}
|
||||
|
||||
/// Check that Insert completion is active.
|
||||
@ -3432,7 +3479,6 @@ expand_by_function (
|
||||
{
|
||||
list_T *matchlist = NULL;
|
||||
dict_T *matchdict = NULL;
|
||||
char_u *args[2];
|
||||
char_u *funcname;
|
||||
pos_T pos;
|
||||
win_T *curwin_save;
|
||||
@ -3443,9 +3489,8 @@ expand_by_function (
|
||||
if (*funcname == NUL)
|
||||
return;
|
||||
|
||||
/* Call 'completefunc' to obtain the list of matches. */
|
||||
args[0] = (char_u *)"0";
|
||||
args[1] = base;
|
||||
// Call 'completefunc' to obtain the list of matches.
|
||||
const char_u *const args[2] = { (char_u *)"0", base };
|
||||
|
||||
pos = curwin->w_cursor;
|
||||
curwin_save = curwin;
|
||||
@ -3461,8 +3506,8 @@ expand_by_function (
|
||||
matchdict = rettv.vval.v_dict;
|
||||
break;
|
||||
default:
|
||||
/* TODO: Give error message? */
|
||||
clear_tv(&rettv);
|
||||
// TODO(brammool): Give error message?
|
||||
tv_clear(&rettv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -3484,10 +3529,12 @@ expand_by_function (
|
||||
ins_compl_add_dict(matchdict);
|
||||
|
||||
theend:
|
||||
if (matchdict != NULL)
|
||||
dict_unref(matchdict);
|
||||
if (matchlist != NULL)
|
||||
list_unref(matchlist);
|
||||
if (matchdict != NULL) {
|
||||
tv_dict_unref(matchdict);
|
||||
}
|
||||
if (matchlist != NULL) {
|
||||
tv_list_unref(matchlist);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3516,53 +3563,60 @@ static void ins_compl_add_dict(dict_T *dict)
|
||||
dictitem_T *di_refresh;
|
||||
dictitem_T *di_words;
|
||||
|
||||
/* Check for optional "refresh" item. */
|
||||
compl_opt_refresh_always = FALSE;
|
||||
di_refresh = dict_find(dict, (char_u *)"refresh", 7);
|
||||
// Check for optional "refresh" item.
|
||||
compl_opt_refresh_always = false;
|
||||
di_refresh = tv_dict_find(dict, S_LEN("refresh"));
|
||||
if (di_refresh != NULL && di_refresh->di_tv.v_type == VAR_STRING) {
|
||||
char_u *v = di_refresh->di_tv.vval.v_string;
|
||||
const char *v = (const char *)di_refresh->di_tv.vval.v_string;
|
||||
|
||||
if (v != NULL && STRCMP(v, (char_u *)"always") == 0)
|
||||
compl_opt_refresh_always = TRUE;
|
||||
if (v != NULL && strcmp(v, "always") == 0) {
|
||||
compl_opt_refresh_always = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add completions from a "words" list. */
|
||||
di_words = dict_find(dict, (char_u *)"words", 5);
|
||||
if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST)
|
||||
// Add completions from a "words" list.
|
||||
di_words = tv_dict_find(dict, S_LEN("words"));
|
||||
if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST) {
|
||||
ins_compl_add_list(di_words->di_tv.vval.v_list);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a match to the list of matches from a typeval_T.
|
||||
* If the given string is already in the list of completions, then return
|
||||
* NOTDONE, otherwise add it to the list and return OK. If there is an error
|
||||
* then FAIL is returned.
|
||||
*/
|
||||
int ins_compl_add_tv(typval_T *tv, int dir)
|
||||
/// Add a match to the list of matches from VimL object
|
||||
///
|
||||
/// @param[in] tv Object to get matches from.
|
||||
/// @param[in] dir Completion direction.
|
||||
///
|
||||
/// @return NOTDONE if the given string is already in the list of completions,
|
||||
/// otherwise it is added to the list and OK is returned. FAIL will be
|
||||
/// returned in case of error.
|
||||
int ins_compl_add_tv(typval_T *const tv, const Direction dir)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
char_u *word;
|
||||
int icase = FALSE;
|
||||
int adup = FALSE;
|
||||
int aempty = FALSE;
|
||||
char_u *(cptext[CPT_COUNT]);
|
||||
const char *word;
|
||||
bool icase = false;
|
||||
bool adup = false;
|
||||
bool aempty = false;
|
||||
char *(cptext[CPT_COUNT]);
|
||||
|
||||
if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) {
|
||||
word = get_dict_string(tv->vval.v_dict, "word", false);
|
||||
cptext[CPT_ABBR] = get_dict_string(tv->vval.v_dict, "abbr", false);
|
||||
cptext[CPT_MENU] = get_dict_string(tv->vval.v_dict, "menu", false);
|
||||
cptext[CPT_KIND] = get_dict_string(tv->vval.v_dict, "kind", false);
|
||||
cptext[CPT_INFO] = get_dict_string(tv->vval.v_dict, "info", false);
|
||||
word = tv_dict_get_string(tv->vval.v_dict, "word", false);
|
||||
cptext[CPT_ABBR] = tv_dict_get_string(tv->vval.v_dict, "abbr", true);
|
||||
cptext[CPT_MENU] = tv_dict_get_string(tv->vval.v_dict, "menu", true);
|
||||
cptext[CPT_KIND] = tv_dict_get_string(tv->vval.v_dict, "kind", true);
|
||||
cptext[CPT_INFO] = tv_dict_get_string(tv->vval.v_dict, "info", true);
|
||||
|
||||
icase = get_dict_number(tv->vval.v_dict, "icase");
|
||||
adup = get_dict_number(tv->vval.v_dict, "dup");
|
||||
aempty = get_dict_number(tv->vval.v_dict, "empty");
|
||||
icase = (bool)tv_dict_get_number(tv->vval.v_dict, "icase");
|
||||
adup = (bool)tv_dict_get_number(tv->vval.v_dict, "dup");
|
||||
aempty = (bool)tv_dict_get_number(tv->vval.v_dict, "empty");
|
||||
} else {
|
||||
word = get_tv_string_chk(tv);
|
||||
word = (const char *)tv_get_string_chk(tv);
|
||||
memset(cptext, 0, sizeof(cptext));
|
||||
}
|
||||
if (word == NULL || (!aempty && *word == NUL))
|
||||
if (word == NULL || (!aempty && *word == NUL)) {
|
||||
return FAIL;
|
||||
return ins_compl_add(word, -1, icase, NULL, cptext, dir, 0, adup);
|
||||
}
|
||||
return ins_compl_add((char_u *)word, -1, icase, NULL,
|
||||
(char_u **)cptext, true, dir, 0, adup);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3977,7 +4031,7 @@ static void ins_compl_delete(void)
|
||||
// causes flicker, thus we can't do that.
|
||||
changed_cline_bef_curs();
|
||||
// clear v:completed_item
|
||||
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
|
||||
set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc());
|
||||
}
|
||||
|
||||
// Insert the new text being completed.
|
||||
@ -3992,17 +4046,21 @@ static void ins_compl_insert(int in_compl_func)
|
||||
|
||||
// Set completed item.
|
||||
// { word, abbr, menu, kind, info }
|
||||
dict_T *dict = dict_alloc();
|
||||
dict_add_nr_str(dict, "word", 0L,
|
||||
EMPTY_IF_NULL(compl_shown_match->cp_str));
|
||||
dict_add_nr_str(dict, "abbr", 0L,
|
||||
EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_ABBR]));
|
||||
dict_add_nr_str(dict, "menu", 0L,
|
||||
EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_MENU]));
|
||||
dict_add_nr_str(dict, "kind", 0L,
|
||||
EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_KIND]));
|
||||
dict_add_nr_str(dict, "info", 0L,
|
||||
EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_INFO]));
|
||||
dict_T *dict = tv_dict_alloc();
|
||||
tv_dict_add_str(dict, S_LEN("word"),
|
||||
(const char *)EMPTY_IF_NULL(compl_shown_match->cp_str));
|
||||
tv_dict_add_str(
|
||||
dict, S_LEN("abbr"),
|
||||
(const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_ABBR]));
|
||||
tv_dict_add_str(
|
||||
dict, S_LEN("menu"),
|
||||
(const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_MENU]));
|
||||
tv_dict_add_str(
|
||||
dict, S_LEN("kind"),
|
||||
(const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_KIND]));
|
||||
tv_dict_add_str(
|
||||
dict, S_LEN("info"),
|
||||
(const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_INFO]));
|
||||
set_vim_var_dict(VV_COMPLETED_ITEM, dict);
|
||||
if (!in_compl_func) {
|
||||
compl_curr_match = compl_shown_match;
|
||||
@ -4544,7 +4602,6 @@ static int ins_complete(int c, bool enable_pum)
|
||||
* Call user defined function 'completefunc' with "a:findstart"
|
||||
* set to 1 to obtain the length of text to use for completion.
|
||||
*/
|
||||
char_u *args[2];
|
||||
int col;
|
||||
char_u *funcname;
|
||||
pos_T pos;
|
||||
@ -4563,8 +4620,7 @@ static int ins_complete(int c, bool enable_pum)
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
args[0] = (char_u *)"1";
|
||||
args[1] = NULL;
|
||||
const char_u *const args[2] = { (char_u *)"1", NULL };
|
||||
pos = curwin->w_cursor;
|
||||
curwin_save = curwin;
|
||||
curbuf_save = curbuf;
|
||||
@ -4664,8 +4720,8 @@ static int ins_complete(int c, bool enable_pum)
|
||||
/* Always add completion for the original text. */
|
||||
xfree(compl_orig_text);
|
||||
compl_orig_text = vim_strnsave(line + compl_col, compl_length);
|
||||
if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, 0,
|
||||
ORIGINAL_TEXT, FALSE) != OK) {
|
||||
if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, false, 0,
|
||||
ORIGINAL_TEXT, false) != OK) {
|
||||
xfree(compl_pattern);
|
||||
compl_pattern = NULL;
|
||||
xfree(compl_orig_text);
|
||||
@ -5744,15 +5800,16 @@ comp_textwidth (
|
||||
*/
|
||||
static void redo_literal(int c)
|
||||
{
|
||||
char_u buf[10];
|
||||
char buf[10];
|
||||
|
||||
/* Only digits need special treatment. Translate them into a string of
|
||||
* three digits. */
|
||||
// Only digits need special treatment. Translate them into a string of
|
||||
// three digits.
|
||||
if (ascii_isdigit(c)) {
|
||||
vim_snprintf((char *)buf, sizeof(buf), "%03d", c);
|
||||
vim_snprintf(buf, sizeof(buf), "%03d", c);
|
||||
AppendToRedobuff(buf);
|
||||
} else
|
||||
} else {
|
||||
AppendCharToRedobuff(c);
|
||||
}
|
||||
}
|
||||
|
||||
// start_arrow() is called when an arrow key is used in insert mode.
|
||||
@ -5781,8 +5838,8 @@ static void start_arrow_common(pos_T *end_insert_pos, bool end_change)
|
||||
{
|
||||
if (!arrow_used && end_change) { // something has been inserted
|
||||
AppendToRedobuff(ESC_STR);
|
||||
stop_insert(end_insert_pos, FALSE, FALSE);
|
||||
arrow_used = TRUE; /* this means we stopped the current insert */
|
||||
stop_insert(end_insert_pos, false, false);
|
||||
arrow_used = true; // This means we stopped the current insert.
|
||||
}
|
||||
check_spell_redraw();
|
||||
}
|
||||
@ -5839,7 +5896,7 @@ int stop_arrow(void)
|
||||
vr_lines_changed = 1;
|
||||
}
|
||||
ResetRedobuff();
|
||||
AppendToRedobuff((char_u *)"1i"); /* pretend we start an insertion */
|
||||
AppendToRedobuff("1i"); // Pretend we start an insertion.
|
||||
new_insert_skip = 2;
|
||||
} else if (ins_need_undo) {
|
||||
if (u_save_cursor() == OK)
|
||||
@ -6304,12 +6361,13 @@ stuff_inserted (
|
||||
}
|
||||
|
||||
do {
|
||||
stuffReadbuff(ptr);
|
||||
/* a trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^" */
|
||||
if (last)
|
||||
stuffReadbuff((char_u *)(last == '0'
|
||||
? "\026\060\064\070"
|
||||
: "\026^"));
|
||||
stuffReadbuff((const char *)ptr);
|
||||
// A trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^".
|
||||
if (last) {
|
||||
stuffReadbuff((last == '0'
|
||||
? "\026\060\064\070"
|
||||
: "\026^"));
|
||||
}
|
||||
} while (--count > 0);
|
||||
|
||||
if (last)
|
||||
@ -7066,8 +7124,8 @@ static void ins_ctrl_g(void)
|
||||
*/
|
||||
static void ins_ctrl_hat(void)
|
||||
{
|
||||
if (map_to_exists_mode((char_u *)"", LANGMAP, FALSE)) {
|
||||
/* ":lmap" mappings exists, Toggle use of ":lmap" mappings. */
|
||||
if (map_to_exists_mode("", LANGMAP, false)) {
|
||||
// ":lmap" mappings exists, Toggle use of ":lmap" mappings.
|
||||
if (State & LANGMAP) {
|
||||
curbuf->b_p_iminsert = B_IMODE_NONE;
|
||||
State &= ~LANGMAP;
|
||||
@ -7102,13 +7160,12 @@ static bool ins_esc(long *count, int cmdchar, bool nomove)
|
||||
disabled_redraw = false;
|
||||
}
|
||||
if (!arrow_used) {
|
||||
/*
|
||||
* Don't append the ESC for "r<CR>" and "grx".
|
||||
* When 'insertmode' is set only CTRL-L stops Insert mode. Needed for
|
||||
* when "count" is non-zero.
|
||||
*/
|
||||
if (cmdchar != 'r' && cmdchar != 'v')
|
||||
AppendToRedobuff(p_im ? (char_u *)"\014" : ESC_STR);
|
||||
// Don't append the ESC for "r<CR>" and "grx".
|
||||
// When 'insertmode' is set only CTRL-L stops Insert mode. Needed for
|
||||
// when "count" is non-zero.
|
||||
if (cmdchar != 'r' && cmdchar != 'v') {
|
||||
AppendToRedobuff(p_im ? "\014" : ESC_STR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Repeating insert may take a long time. Check for
|
||||
@ -7262,7 +7319,8 @@ static bool ins_start_select(int c)
|
||||
// Execute the key in (insert) Select mode.
|
||||
stuffcharReadbuff(Ctrl_O);
|
||||
if (mod_mask) {
|
||||
char_u buf[4] = { K_SPECIAL, KS_MODIFIER, mod_mask, NUL };
|
||||
const char buf[] = { (char)K_SPECIAL, (char)KS_MODIFIER,
|
||||
(char)(uint8_t)mod_mask, NUL };
|
||||
stuffReadbuff(buf);
|
||||
}
|
||||
stuffcharReadbuff(c);
|
||||
@ -8070,11 +8128,11 @@ static bool ins_tab(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
did_ai = FALSE;
|
||||
did_si = FALSE;
|
||||
can_si = FALSE;
|
||||
can_si_back = FALSE;
|
||||
AppendToRedobuff((char_u *)"\t");
|
||||
did_ai = false;
|
||||
did_si = false;
|
||||
can_si = false;
|
||||
can_si_back = false;
|
||||
AppendToRedobuff("\t");
|
||||
|
||||
if (p_sta && ind) { // insert tab in indent, use "shiftwidth"
|
||||
temp = get_sw_value(curbuf);
|
||||
@ -8339,8 +8397,8 @@ static int ins_digraph(void)
|
||||
edit_unputchar();
|
||||
}
|
||||
if (cc != ESC) {
|
||||
AppendToRedobuff((char_u *)CTRL_V_STR);
|
||||
c = getdigraph(c, cc, TRUE);
|
||||
AppendToRedobuff(CTRL_V_STR);
|
||||
c = getdigraph(c, cc, true);
|
||||
clear_showcmd();
|
||||
return c;
|
||||
}
|
||||
@ -8402,12 +8460,13 @@ static int ins_ctrl_ey(int tc)
|
||||
if (c != NUL) {
|
||||
long tw_save;
|
||||
|
||||
/* The character must be taken literally, insert like it
|
||||
* was typed after a CTRL-V, and pretend 'textwidth'
|
||||
* wasn't set. Digits, 'o' and 'x' are special after a
|
||||
* CTRL-V, don't use it for these. */
|
||||
if (c < 256 && !isalnum(c))
|
||||
AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */
|
||||
// The character must be taken literally, insert like it
|
||||
// was typed after a CTRL-V, and pretend 'textwidth'
|
||||
// wasn't set. Digits, 'o' and 'x' are special after a
|
||||
// CTRL-V, don't use it for these.
|
||||
if (c < 256 && !isalnum(c)) {
|
||||
AppendToRedobuff(CTRL_V_STR);
|
||||
}
|
||||
tw_save = curbuf->b_p_tw;
|
||||
curbuf->b_p_tw = -1;
|
||||
insert_special(c, TRUE, FALSE);
|
||||
|
9189
src/nvim/eval.c
9189
src/nvim/eval.c
File diff suppressed because it is too large
Load Diff
@ -1,21 +1,23 @@
|
||||
#ifndef NVIM_EVAL_H
|
||||
#define NVIM_EVAL_H
|
||||
|
||||
#include "nvim/profile.h"
|
||||
#include "nvim/hashtab.h" // For hashtab_T
|
||||
#include "nvim/garray.h" // For garray_T
|
||||
#include "nvim/buffer_defs.h" // For scid_T
|
||||
#include "nvim/buffer_defs.h"
|
||||
#include "nvim/ex_cmds_defs.h" // For exarg_T
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/profile.h"
|
||||
#include "nvim/garray.h"
|
||||
|
||||
#define COPYID_INC 2
|
||||
#define COPYID_MASK (~0x1)
|
||||
|
||||
// All user-defined functions are found in this hashtable.
|
||||
extern hashtab_T func_hashtab;
|
||||
|
||||
// From user function to hashitem and back.
|
||||
EXTERN ufunc_T dumuf;
|
||||
#define UF2HIKEY(fp) ((fp)->uf_name)
|
||||
#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf)))
|
||||
#define HIKEY2UF(p) ((ufunc_T *)(p - offsetof(ufunc_T, uf_name)))
|
||||
#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
|
||||
|
||||
/// Defines for Vim variables
|
||||
|
@ -2,10 +2,11 @@
|
||||
|
||||
#include <msgpack.h>
|
||||
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/encode.h"
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/macros.h"
|
||||
#include "nvim/message.h"
|
||||
#include "nvim/charset.h" // vim_str2nr
|
||||
#include "nvim/lib/kvec.h"
|
||||
@ -51,16 +52,16 @@ static inline void create_special_dict(typval_T *const rettv,
|
||||
typval_T val)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
dict_T *const dict = dict_alloc();
|
||||
dictitem_T *const type_di = dictitem_alloc((char_u *) "_TYPE");
|
||||
dict_T *const dict = tv_dict_alloc();
|
||||
dictitem_T *const type_di = tv_dict_item_alloc_len(S_LEN("_TYPE"));
|
||||
type_di->di_tv.v_type = VAR_LIST;
|
||||
type_di->di_tv.v_lock = VAR_UNLOCKED;
|
||||
type_di->di_tv.vval.v_list = (list_T *) eval_msgpack_type_lists[type];
|
||||
type_di->di_tv.vval.v_list->lv_refcount++;
|
||||
dict_add(dict, type_di);
|
||||
dictitem_T *const val_di = dictitem_alloc((char_u *) "_VAL");
|
||||
tv_dict_add(dict, type_di);
|
||||
dictitem_T *const val_di = tv_dict_item_alloc_len(S_LEN("_VAL"));
|
||||
val_di->di_tv = val;
|
||||
dict_add(dict, val_di);
|
||||
tv_dict_add(dict, val_di);
|
||||
dict->dv_refcount++;
|
||||
*rettv = (typval_T) {
|
||||
.v_type = VAR_DICT,
|
||||
@ -118,18 +119,18 @@ static inline int json_decoder_pop(ValuesStackItem obj,
|
||||
if (last_container.container.vval.v_list->lv_len != 0
|
||||
&& !obj.didcomma) {
|
||||
EMSG2(_("E474: Expected comma before list item: %s"), val_location);
|
||||
clear_tv(&obj.val);
|
||||
tv_clear(&obj.val);
|
||||
return FAIL;
|
||||
}
|
||||
assert(last_container.special_val == NULL);
|
||||
listitem_T *obj_li = listitem_alloc();
|
||||
listitem_T *obj_li = tv_list_item_alloc();
|
||||
obj_li->li_tv = obj.val;
|
||||
list_append(last_container.container.vval.v_list, obj_li);
|
||||
tv_list_append(last_container.container.vval.v_list, obj_li);
|
||||
} else if (last_container.stack_index == kv_size(*stack) - 2) {
|
||||
if (!obj.didcolon) {
|
||||
EMSG2(_("E474: Expected colon before dictionary value: %s"),
|
||||
val_location);
|
||||
clear_tv(&obj.val);
|
||||
tv_clear(&obj.val);
|
||||
return FAIL;
|
||||
}
|
||||
ValuesStackItem key = kv_pop(*stack);
|
||||
@ -138,34 +139,35 @@ static inline int json_decoder_pop(ValuesStackItem obj,
|
||||
assert(!(key.is_special_string
|
||||
|| key.val.vval.v_string == NULL
|
||||
|| *key.val.vval.v_string == NUL));
|
||||
dictitem_T *obj_di = dictitem_alloc(key.val.vval.v_string);
|
||||
clear_tv(&key.val);
|
||||
if (dict_add(last_container.container.vval.v_dict, obj_di)
|
||||
dictitem_T *const obj_di = tv_dict_item_alloc(
|
||||
(const char *)key.val.vval.v_string);
|
||||
tv_clear(&key.val);
|
||||
if (tv_dict_add(last_container.container.vval.v_dict, obj_di)
|
||||
== FAIL) {
|
||||
assert(false);
|
||||
}
|
||||
obj_di->di_tv = obj.val;
|
||||
} else {
|
||||
list_T *const kv_pair = list_alloc();
|
||||
list_append_list(last_container.special_val, kv_pair);
|
||||
listitem_T *const key_li = listitem_alloc();
|
||||
list_T *const kv_pair = tv_list_alloc();
|
||||
tv_list_append_list(last_container.special_val, kv_pair);
|
||||
listitem_T *const key_li = tv_list_item_alloc();
|
||||
key_li->li_tv = key.val;
|
||||
list_append(kv_pair, key_li);
|
||||
listitem_T *const val_li = listitem_alloc();
|
||||
tv_list_append(kv_pair, key_li);
|
||||
listitem_T *const val_li = tv_list_item_alloc();
|
||||
val_li->li_tv = obj.val;
|
||||
list_append(kv_pair, val_li);
|
||||
tv_list_append(kv_pair, val_li);
|
||||
}
|
||||
} else {
|
||||
// Object with key only
|
||||
if (!obj.is_special_string && obj.val.v_type != VAR_STRING) {
|
||||
EMSG2(_("E474: Expected string key: %s"), *pp);
|
||||
clear_tv(&obj.val);
|
||||
tv_clear(&obj.val);
|
||||
return FAIL;
|
||||
} else if (!obj.didcomma
|
||||
&& (last_container.special_val == NULL
|
||||
&& (DICT_LEN(last_container.container.vval.v_dict) != 0))) {
|
||||
EMSG2(_("E474: Expected comma before dictionary key: %s"), val_location);
|
||||
clear_tv(&obj.val);
|
||||
tv_clear(&obj.val);
|
||||
return FAIL;
|
||||
}
|
||||
// Handle empty key and key represented as special dictionary
|
||||
@ -173,16 +175,16 @@ static inline int json_decoder_pop(ValuesStackItem obj,
|
||||
&& (obj.is_special_string
|
||||
|| obj.val.vval.v_string == NULL
|
||||
|| *obj.val.vval.v_string == NUL
|
||||
|| dict_find(last_container.container.vval.v_dict,
|
||||
obj.val.vval.v_string, -1))) {
|
||||
clear_tv(&obj.val);
|
||||
|| tv_dict_find(last_container.container.vval.v_dict,
|
||||
(const char *)obj.val.vval.v_string, -1))) {
|
||||
tv_clear(&obj.val);
|
||||
|
||||
// Restart
|
||||
(void) kv_pop(*container_stack);
|
||||
ValuesStackItem last_container_val =
|
||||
kv_A(*stack, last_container.stack_index);
|
||||
while (kv_size(*stack) > last_container.stack_index) {
|
||||
clear_tv(&(kv_pop(*stack).val));
|
||||
tv_clear(&(kv_pop(*stack).val));
|
||||
}
|
||||
*pp = last_container.s;
|
||||
*didcomma = last_container_val.didcomma;
|
||||
@ -430,7 +432,7 @@ static inline int parse_json_string(vimconv_T *const conv,
|
||||
}
|
||||
if (hasnul) {
|
||||
typval_T obj;
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
create_special_dict(&obj, kMPString, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@ -439,7 +441,7 @@ static inline int parse_json_string(vimconv_T *const conv,
|
||||
}));
|
||||
if (encode_list_write((void *) list, str, (size_t) (str_end - str))
|
||||
== -1) {
|
||||
clear_tv(&obj);
|
||||
tv_clear(&obj);
|
||||
goto parse_json_string_fail;
|
||||
}
|
||||
xfree(str);
|
||||
@ -806,7 +808,7 @@ json_decode_string_cycle_start:
|
||||
break;
|
||||
}
|
||||
case '[': {
|
||||
list_T *list = list_alloc();
|
||||
list_T *list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
typval_T tv = {
|
||||
.v_type = VAR_LIST,
|
||||
@ -827,7 +829,7 @@ json_decode_string_cycle_start:
|
||||
list_T *val_list = NULL;
|
||||
if (next_map_special) {
|
||||
next_map_special = false;
|
||||
val_list = list_alloc();
|
||||
val_list = tv_list_alloc();
|
||||
val_list->lv_refcount++;
|
||||
create_special_dict(&tv, kMPMap, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@ -835,7 +837,7 @@ json_decode_string_cycle_start:
|
||||
.vval = { .v_list = val_list },
|
||||
}));
|
||||
} else {
|
||||
dict_T *dict = dict_alloc();
|
||||
dict_T *dict = tv_dict_alloc();
|
||||
dict->dv_refcount++;
|
||||
tv = (typval_T) {
|
||||
.v_type = VAR_DICT,
|
||||
@ -887,7 +889,7 @@ json_decode_string_after_cycle:
|
||||
json_decode_string_fail:
|
||||
ret = FAIL;
|
||||
while (kv_size(stack)) {
|
||||
clear_tv(&(kv_pop(stack).val));
|
||||
tv_clear(&(kv_pop(stack).val));
|
||||
}
|
||||
json_decode_string_ret:
|
||||
kv_destroy(stack);
|
||||
@ -933,7 +935,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
.vval = { .v_number = (varnumber_T) mobj.via.u64 },
|
||||
};
|
||||
} else {
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
create_special_dict(rettv, kMPInteger, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@ -941,10 +943,10 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
.vval = { .v_list = list },
|
||||
}));
|
||||
uint64_t n = mobj.via.u64;
|
||||
list_append_number(list, 1);
|
||||
list_append_number(list, (varnumber_T) ((n >> 62) & 0x3));
|
||||
list_append_number(list, (varnumber_T) ((n >> 31) & 0x7FFFFFFF));
|
||||
list_append_number(list, (varnumber_T) (n & 0x7FFFFFFF));
|
||||
tv_list_append_number(list, 1);
|
||||
tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3));
|
||||
tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF));
|
||||
tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -956,18 +958,18 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
.vval = { .v_number = (varnumber_T) mobj.via.i64 },
|
||||
};
|
||||
} else {
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
create_special_dict(rettv, kMPInteger, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
.v_lock = VAR_UNLOCKED,
|
||||
.vval = { .v_list = list },
|
||||
}));
|
||||
uint64_t n = -((uint64_t) mobj.via.i64);
|
||||
list_append_number(list, -1);
|
||||
list_append_number(list, (varnumber_T) ((n >> 62) & 0x3));
|
||||
list_append_number(list, (varnumber_T) ((n >> 31) & 0x7FFFFFFF));
|
||||
list_append_number(list, (varnumber_T) (n & 0x7FFFFFFF));
|
||||
uint64_t n = -((uint64_t)mobj.via.i64);
|
||||
tv_list_append_number(list, -1);
|
||||
tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3));
|
||||
tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF));
|
||||
tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -980,7 +982,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
break;
|
||||
}
|
||||
case MSGPACK_OBJECT_STR: {
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
create_special_dict(rettv, kMPString, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@ -1002,7 +1004,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
};
|
||||
break;
|
||||
}
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
create_special_dict(rettv, kMPBinary, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@ -1016,7 +1018,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
break;
|
||||
}
|
||||
case MSGPACK_OBJECT_ARRAY: {
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
*rettv = (typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@ -1024,9 +1026,9 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
.vval = { .v_list = list },
|
||||
};
|
||||
for (size_t i = 0; i < mobj.via.array.size; i++) {
|
||||
listitem_T *const li = listitem_alloc();
|
||||
listitem_T *const li = tv_list_item_alloc();
|
||||
li->li_tv.v_type = VAR_UNKNOWN;
|
||||
list_append(list, li);
|
||||
tv_list_append(list, li);
|
||||
if (msgpack_to_vim(mobj.via.array.ptr[i], &li->li_tv) == FAIL) {
|
||||
return FAIL;
|
||||
}
|
||||
@ -1042,7 +1044,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
goto msgpack_to_vim_generic_map;
|
||||
}
|
||||
}
|
||||
dict_T *const dict = dict_alloc();
|
||||
dict_T *const dict = tv_dict_alloc();
|
||||
dict->dv_refcount++;
|
||||
*rettv = (typval_T) {
|
||||
.v_type = VAR_DICT,
|
||||
@ -1055,9 +1057,9 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
memcpy(&di->di_key[0], mobj.via.map.ptr[i].key.via.str.ptr,
|
||||
mobj.via.map.ptr[i].key.via.str.size);
|
||||
di->di_tv.v_type = VAR_UNKNOWN;
|
||||
if (dict_add(dict, di) == FAIL) {
|
||||
if (tv_dict_add(dict, di) == FAIL) {
|
||||
// Duplicate key: fallback to generic map
|
||||
clear_tv(rettv);
|
||||
tv_clear(rettv);
|
||||
xfree(di);
|
||||
goto msgpack_to_vim_generic_map;
|
||||
}
|
||||
@ -1067,7 +1069,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
}
|
||||
break;
|
||||
msgpack_to_vim_generic_map: {}
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
create_special_dict(rettv, kMPMap, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@ -1075,14 +1077,14 @@ msgpack_to_vim_generic_map: {}
|
||||
.vval = { .v_list = list },
|
||||
}));
|
||||
for (size_t i = 0; i < mobj.via.map.size; i++) {
|
||||
list_T *const kv_pair = list_alloc();
|
||||
list_append_list(list, kv_pair);
|
||||
listitem_T *const key_li = listitem_alloc();
|
||||
list_T *const kv_pair = tv_list_alloc();
|
||||
tv_list_append_list(list, kv_pair);
|
||||
listitem_T *const key_li = tv_list_item_alloc();
|
||||
key_li->li_tv.v_type = VAR_UNKNOWN;
|
||||
list_append(kv_pair, key_li);
|
||||
listitem_T *const val_li = listitem_alloc();
|
||||
tv_list_append(kv_pair, key_li);
|
||||
listitem_T *const val_li = tv_list_item_alloc();
|
||||
val_li->li_tv.v_type = VAR_UNKNOWN;
|
||||
list_append(kv_pair, val_li);
|
||||
tv_list_append(kv_pair, val_li);
|
||||
if (msgpack_to_vim(mobj.via.map.ptr[i].key, &key_li->li_tv) == FAIL) {
|
||||
return FAIL;
|
||||
}
|
||||
@ -1093,11 +1095,11 @@ msgpack_to_vim_generic_map: {}
|
||||
break;
|
||||
}
|
||||
case MSGPACK_OBJECT_EXT: {
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
list_append_number(list, mobj.via.ext.type);
|
||||
list_T *const ext_val_list = list_alloc();
|
||||
list_append_list(list, ext_val_list);
|
||||
tv_list_append_number(list, mobj.via.ext.type);
|
||||
list_T *const ext_val_list = tv_list_alloc();
|
||||
tv_list_append_list(list, ext_val_list);
|
||||
create_special_dict(rettv, kMPExt, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
.v_lock = VAR_UNLOCKED,
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include <msgpack.h>
|
||||
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/decode.h.generated.h"
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "nvim/eval/encode.h"
|
||||
#include "nvim/buffer_defs.h" // vimconv_T
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/garray.h"
|
||||
#include "nvim/mbyte.h"
|
||||
#include "nvim/message.h"
|
||||
@ -45,7 +45,8 @@ const char *const encode_special_var_names[] = {
|
||||
#endif
|
||||
|
||||
/// Msgpack callback for writing to readfile()-style list
|
||||
int encode_list_write(void *data, const char *buf, size_t len)
|
||||
int encode_list_write(void *const data, const char *const buf, const size_t len)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
@ -80,11 +81,11 @@ int encode_list_write(void *data, const char *buf, size_t len)
|
||||
str = xmemdupz(line_start, line_length);
|
||||
memchrsub(str, NUL, NL, line_length);
|
||||
}
|
||||
list_append_allocated_string(list, str);
|
||||
tv_list_append_allocated_string(list, str);
|
||||
line_end++;
|
||||
}
|
||||
if (line_end == end) {
|
||||
list_append_allocated_string(list, NULL);
|
||||
tv_list_append_allocated_string(list, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -743,11 +744,11 @@ bool encode_check_json_key(const typval_T *const tv)
|
||||
}
|
||||
const dictitem_T *type_di;
|
||||
const dictitem_T *val_di;
|
||||
if ((type_di = dict_find((dict_T *) spdict, (char_u *) "_TYPE", -1)) == NULL
|
||||
if ((type_di = tv_dict_find(spdict, S_LEN("_TYPE"))) == NULL
|
||||
|| type_di->di_tv.v_type != VAR_LIST
|
||||
|| (type_di->di_tv.vval.v_list != eval_msgpack_type_lists[kMPString]
|
||||
&& type_di->di_tv.vval.v_list != eval_msgpack_type_lists[kMPBinary])
|
||||
|| (val_di = dict_find((dict_T *) spdict, (char_u *) "_VAL", -1)) == NULL
|
||||
|| (val_di = tv_dict_find(spdict, S_LEN("_VAL"))) == NULL
|
||||
|| val_di->di_tv.v_type != VAR_LIST) {
|
||||
return false;
|
||||
}
|
||||
|
115
src/nvim/eval/executor.c
Normal file
115
src/nvim/eval/executor.c
Normal file
@ -0,0 +1,115 @@
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/eval/executor.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/message.h"
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/globals.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/executor.c.generated.h"
|
||||
#endif
|
||||
|
||||
static char *e_letwrong = N_("E734: Wrong variable type for %s=");
|
||||
|
||||
char *e_listidx = N_("E684: list index out of range: %" PRId64);
|
||||
|
||||
/// Hanle tv1 += tv2, -=, .=
|
||||
///
|
||||
/// @param[in,out] tv1 First operand, modified typval.
|
||||
/// @param[in] tv2 Second operand.
|
||||
/// @param[in] op Used operator.
|
||||
///
|
||||
/// @return OK or FAIL.
|
||||
int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2,
|
||||
const char *const op)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
// Can't do anything with a Funcref, a Dict or special value on the right.
|
||||
if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT) {
|
||||
switch (tv1->v_type) {
|
||||
case VAR_DICT:
|
||||
case VAR_FUNC:
|
||||
case VAR_PARTIAL:
|
||||
case VAR_SPECIAL: {
|
||||
break;
|
||||
}
|
||||
case VAR_LIST: {
|
||||
if (*op != '+' || tv2->v_type != VAR_LIST) {
|
||||
break;
|
||||
}
|
||||
// List += List
|
||||
if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL) {
|
||||
tv_list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
case VAR_NUMBER:
|
||||
case VAR_STRING: {
|
||||
if (tv2->v_type == VAR_LIST) {
|
||||
break;
|
||||
}
|
||||
if (*op == '+' || *op == '-') {
|
||||
// nr += nr or nr -= nr
|
||||
varnumber_T n = tv_get_number(tv1);
|
||||
if (tv2->v_type == VAR_FLOAT) {
|
||||
float_T f = n;
|
||||
|
||||
if (*op == '+') {
|
||||
f += tv2->vval.v_float;
|
||||
} else {
|
||||
f -= tv2->vval.v_float;
|
||||
}
|
||||
tv_clear(tv1);
|
||||
tv1->v_type = VAR_FLOAT;
|
||||
tv1->vval.v_float = f;
|
||||
} else {
|
||||
if (*op == '+') {
|
||||
n += tv_get_number(tv2);
|
||||
} else {
|
||||
n -= tv_get_number(tv2);
|
||||
}
|
||||
tv_clear(tv1);
|
||||
tv1->v_type = VAR_NUMBER;
|
||||
tv1->vval.v_number = n;
|
||||
}
|
||||
} else {
|
||||
// str .= str
|
||||
if (tv2->v_type == VAR_FLOAT) {
|
||||
break;
|
||||
}
|
||||
const char *tvs = tv_get_string(tv1);
|
||||
char numbuf[NUMBUFLEN];
|
||||
char *const s = (char *)concat_str(
|
||||
(const char_u *)tvs, (const char_u *)tv_get_string_buf(tv2,
|
||||
numbuf));
|
||||
tv_clear(tv1);
|
||||
tv1->v_type = VAR_STRING;
|
||||
tv1->vval.v_string = (char_u *)s;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
case VAR_FLOAT: {
|
||||
if (*op == '.' || (tv2->v_type != VAR_FLOAT
|
||||
&& tv2->v_type != VAR_NUMBER
|
||||
&& tv2->v_type != VAR_STRING)) {
|
||||
break;
|
||||
}
|
||||
const float_T f = (tv2->v_type == VAR_FLOAT
|
||||
? tv2->vval.v_float
|
||||
: tv_get_number(tv2));
|
||||
if (*op == '+') {
|
||||
tv1->vval.v_float += f;
|
||||
} else {
|
||||
tv1->vval.v_float -= f;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
case VAR_UNKNOWN: {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EMSG2(_(e_letwrong), op);
|
||||
return FAIL;
|
||||
}
|
11
src/nvim/eval/executor.h
Normal file
11
src/nvim/eval/executor.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef NVIM_EVAL_EXECUTOR_H
|
||||
#define NVIM_EVAL_EXECUTOR_H
|
||||
|
||||
#include "nvim/eval/typval.h"
|
||||
|
||||
extern char *e_listidx;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/executor.h.generated.h"
|
||||
#endif
|
||||
#endif // NVIM_EVAL_EXECUTOR_H
|
11
src/nvim/eval/gc.c
Normal file
11
src/nvim/eval/gc.c
Normal file
@ -0,0 +1,11 @@
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/eval/gc.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/gc.c.generated.h"
|
||||
#endif
|
||||
|
||||
/// Head of list of all dictionaries
|
||||
dict_T *gc_first_dict = NULL;
|
||||
/// Head of list of all lists
|
||||
list_T *gc_first_list = NULL;
|
12
src/nvim/eval/gc.h
Normal file
12
src/nvim/eval/gc.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef NVIM_EVAL_GC_H
|
||||
#define NVIM_EVAL_GC_H
|
||||
|
||||
#include "nvim/eval/typval.h"
|
||||
|
||||
extern dict_T *gc_first_dict;
|
||||
extern list_T *gc_first_list;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/gc.h.generated.h"
|
||||
#endif
|
||||
#endif // NVIM_EVAL_GC_H
|
2556
src/nvim/eval/typval.c
Normal file
2556
src/nvim/eval/typval.c
Normal file
File diff suppressed because it is too large
Load Diff
429
src/nvim/eval/typval.h
Normal file
429
src/nvim/eval/typval.h
Normal file
@ -0,0 +1,429 @@
|
||||
#ifndef NVIM_EVAL_TYPVAL_H
|
||||
#define NVIM_EVAL_TYPVAL_H
|
||||
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "nvim/types.h"
|
||||
#include "nvim/hashtab.h"
|
||||
#include "nvim/garray.h"
|
||||
#include "nvim/mbyte.h"
|
||||
#include "nvim/func_attr.h"
|
||||
#include "nvim/lib/queue.h"
|
||||
#include "nvim/profile.h" // for proftime_T
|
||||
#include "nvim/pos.h" // for linenr_T
|
||||
#include "nvim/gettext.h"
|
||||
#include "nvim/message.h"
|
||||
|
||||
/// Type used for VimL VAR_NUMBER values
|
||||
typedef int varnumber_T;
|
||||
|
||||
/// Type used for VimL VAR_FLOAT values
|
||||
typedef double float_T;
|
||||
|
||||
/// Maximal possible value of varnumber_T variable
|
||||
#define VARNUMBER_MAX INT_MAX
|
||||
|
||||
/// Mimimal possible value of varnumber_T variable
|
||||
#define VARNUMBER_MIN INT_MIN
|
||||
#define PRIdVARNUMBER "d"
|
||||
|
||||
/// %d printf format specifier for varnumber_T
|
||||
#define PRIdVARNUMBER "d"
|
||||
|
||||
typedef struct listvar_S list_T;
|
||||
typedef struct dictvar_S dict_T;
|
||||
typedef struct partial_S partial_T;
|
||||
|
||||
typedef struct ufunc ufunc_T;
|
||||
|
||||
typedef enum {
|
||||
kCallbackNone,
|
||||
kCallbackFuncref,
|
||||
kCallbackPartial,
|
||||
} CallbackType;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
char_u *funcref;
|
||||
partial_T *partial;
|
||||
} data;
|
||||
CallbackType type;
|
||||
} Callback;
|
||||
#define CALLBACK_NONE ((Callback){ .type = kCallbackNone })
|
||||
|
||||
/// Structure holding dictionary watcher
|
||||
typedef struct dict_watcher {
|
||||
Callback callback;
|
||||
char *key_pattern;
|
||||
size_t key_pattern_len;
|
||||
QUEUE node;
|
||||
bool busy; // prevent recursion if the dict is changed in the callback
|
||||
} DictWatcher;
|
||||
|
||||
/// Special variable values
|
||||
typedef enum {
|
||||
kSpecialVarFalse, ///< v:false
|
||||
kSpecialVarTrue, ///< v:true
|
||||
kSpecialVarNull, ///< v:null
|
||||
} SpecialVarValue;
|
||||
|
||||
/// Variable lock status for typval_T.v_lock
|
||||
typedef enum {
|
||||
VAR_UNLOCKED = 0, ///< Not locked.
|
||||
VAR_LOCKED = 1, ///< User lock, can be unlocked.
|
||||
VAR_FIXED = 2, ///< Locked forever.
|
||||
} VarLockStatus;
|
||||
|
||||
/// VimL variable types, for use in typval_T.v_type
|
||||
typedef enum {
|
||||
VAR_UNKNOWN = 0, ///< Unknown (unspecified) value.
|
||||
VAR_NUMBER, ///< Number, .v_number is used.
|
||||
VAR_STRING, ///< String, .v_string is used.
|
||||
VAR_FUNC, ///< Function reference, .v_string is used as function name.
|
||||
VAR_LIST, ///< List, .v_list is used.
|
||||
VAR_DICT, ///< Dictionary, .v_dict is used.
|
||||
VAR_FLOAT, ///< Floating-point value, .v_float is used.
|
||||
VAR_SPECIAL, ///< Special value (true, false, null), .v_special
|
||||
///< is used.
|
||||
VAR_PARTIAL, ///< Partial, .v_partial is used.
|
||||
} VarType;
|
||||
|
||||
/// Structure that holds an internal variable value
|
||||
typedef struct {
|
||||
VarType v_type; ///< Variable type.
|
||||
VarLockStatus v_lock; ///< Variable lock status.
|
||||
union typval_vval_union {
|
||||
varnumber_T v_number; ///< Number, for VAR_NUMBER.
|
||||
SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL.
|
||||
float_T v_float; ///< Floating-point number, for VAR_FLOAT.
|
||||
char_u *v_string; ///< String, for VAR_STRING and VAR_FUNC, can be NULL.
|
||||
list_T *v_list; ///< List for VAR_LIST, can be NULL.
|
||||
dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL.
|
||||
partial_T *v_partial; ///< Closure: function with args.
|
||||
} vval; ///< Actual value.
|
||||
} typval_T;
|
||||
|
||||
/// Values for (struct dictvar_S).dv_scope
|
||||
typedef enum {
|
||||
VAR_NO_SCOPE = 0, ///< Not a scope dictionary.
|
||||
VAR_SCOPE = 1, ///< Scope dictionary which requires prefix (a:, v:, …).
|
||||
VAR_DEF_SCOPE = 2, ///< Scope dictionary which may be accessed without prefix
|
||||
///< (l:, g:).
|
||||
} ScopeType;
|
||||
|
||||
/// Structure to hold an item of a list
|
||||
typedef struct listitem_S listitem_T;
|
||||
|
||||
struct listitem_S {
|
||||
listitem_T *li_next; ///< Next item in list.
|
||||
listitem_T *li_prev; ///< Previous item in list.
|
||||
typval_T li_tv; ///< Item value.
|
||||
};
|
||||
|
||||
/// Structure used by those that are using an item in a list
|
||||
typedef struct listwatch_S listwatch_T;
|
||||
|
||||
struct listwatch_S {
|
||||
listitem_T *lw_item; ///< Item being watched.
|
||||
listwatch_T *lw_next; ///< Next watcher.
|
||||
};
|
||||
|
||||
/// Structure to hold info about a list
|
||||
struct listvar_S {
|
||||
listitem_T *lv_first; ///< First item, NULL if none.
|
||||
listitem_T *lv_last; ///< Last item, NULL if none.
|
||||
int lv_refcount; ///< Reference count.
|
||||
int lv_len; ///< Number of items.
|
||||
listwatch_T *lv_watch; ///< First watcher, NULL if none.
|
||||
int lv_idx; ///< Index of a cached item, used for optimising repeated l[idx].
|
||||
listitem_T *lv_idx_item; ///< When not NULL item at index "lv_idx".
|
||||
int lv_copyID; ///< ID used by deepcopy().
|
||||
list_T *lv_copylist; ///< Copied list used by deepcopy().
|
||||
VarLockStatus lv_lock; ///< Zero, VAR_LOCKED, VAR_FIXED.
|
||||
list_T *lv_used_next; ///< next list in used lists list.
|
||||
list_T *lv_used_prev; ///< Previous list in used lists list.
|
||||
};
|
||||
|
||||
// Static list with 10 items. Use init_static_list() to initialize.
|
||||
typedef struct {
|
||||
list_T sl_list; // must be first
|
||||
listitem_T sl_items[10];
|
||||
} staticList10_T;
|
||||
|
||||
// Structure to hold an item of a Dictionary.
|
||||
// Also used for a variable.
|
||||
// The key is copied into "di_key" to avoid an extra alloc/free for it.
|
||||
struct dictitem_S {
|
||||
typval_T di_tv; ///< type and value of the variable
|
||||
char_u di_flags; ///< flags (only used for variable)
|
||||
char_u di_key[1]; ///< key (actually longer!)
|
||||
};
|
||||
|
||||
#define TV_DICTITEM_STRUCT(KEY_LEN) \
|
||||
struct { \
|
||||
typval_T di_tv; /* Structure that holds scope dictionary itself. */ \
|
||||
uint8_t di_flags; /* Flags. */ \
|
||||
char_u di_key[KEY_LEN]; /* Key value. */ \
|
||||
}
|
||||
|
||||
/// Structure to hold a scope dictionary
|
||||
///
|
||||
/// @warning Must be compatible with dictitem_T.
|
||||
///
|
||||
/// For use in find_var_in_ht to pretend that it found dictionary item when it
|
||||
/// finds scope dictionary.
|
||||
typedef TV_DICTITEM_STRUCT(1) ScopeDictDictItem;
|
||||
|
||||
/// Structure to hold an item of a Dictionary
|
||||
///
|
||||
/// @warning Must be compatible with ScopeDictDictItem.
|
||||
///
|
||||
/// Also used for a variable.
|
||||
typedef TV_DICTITEM_STRUCT() dictitem_T;
|
||||
|
||||
/// Flags for dictitem_T.di_flags
|
||||
typedef enum {
|
||||
DI_FLAGS_RO = 1, ///< Read-only value
|
||||
DI_FLAGS_RO_SBX = 2, ///< Value, read-only in the sandbox
|
||||
DI_FLAGS_FIX = 4, ///< Fixed value: cannot be :unlet or remove()d.
|
||||
DI_FLAGS_LOCK = 8, ///< Locked value.
|
||||
DI_FLAGS_ALLOC = 16, ///< Separately allocated.
|
||||
} DictItemFlags;
|
||||
|
||||
/// Structure representing a Dictionary
|
||||
struct dictvar_S {
|
||||
VarLockStatus dv_lock; ///< Whole dictionary lock status.
|
||||
ScopeType dv_scope; ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if
|
||||
///< dictionary represents a scope (i.e. g:, l: …).
|
||||
int dv_refcount; ///< Reference count.
|
||||
int dv_copyID; ///< ID used when recursivery traversing a value.
|
||||
hashtab_T dv_hashtab; ///< Hashtab containing all items.
|
||||
dict_T *dv_copydict; ///< Copied dict used by deepcopy().
|
||||
dict_T *dv_used_next; ///< Next dictionary in used dictionaries list.
|
||||
dict_T *dv_used_prev; ///< Previous dictionary in used dictionaries list.
|
||||
QUEUE watchers; ///< Dictionary key watchers set by user code.
|
||||
};
|
||||
|
||||
/// Type used for script ID
|
||||
typedef int scid_T;
|
||||
/// Format argument for scid_T
|
||||
#define PRIdSCID "d"
|
||||
|
||||
// Structure to hold info for a function that is currently being executed.
|
||||
typedef struct funccall_S funccall_T;
|
||||
|
||||
/// Structure to hold info for a user function.
|
||||
struct ufunc {
|
||||
int uf_varargs; ///< variable nr of arguments
|
||||
int uf_flags;
|
||||
int uf_calls; ///< nr of active calls
|
||||
bool uf_cleared; ///< func_clear() was already called
|
||||
garray_T uf_args; ///< arguments
|
||||
garray_T uf_lines; ///< function lines
|
||||
int uf_profiling; ///< true when func is being profiled
|
||||
// Profiling the function as a whole.
|
||||
int uf_tm_count; ///< nr of calls
|
||||
proftime_T uf_tm_total; ///< time spent in function + children
|
||||
proftime_T uf_tm_self; ///< time spent in function itself
|
||||
proftime_T uf_tm_children; ///< time spent in children this call
|
||||
// Profiling the function per line.
|
||||
int *uf_tml_count; ///< nr of times line was executed
|
||||
proftime_T *uf_tml_total; ///< time spent in a line + children
|
||||
proftime_T *uf_tml_self; ///< time spent in a line itself
|
||||
proftime_T uf_tml_start; ///< start time for current line
|
||||
proftime_T uf_tml_children; ///< time spent in children for this line
|
||||
proftime_T uf_tml_wait; ///< start wait time for current line
|
||||
int uf_tml_idx; ///< index of line being timed; -1 if none
|
||||
int uf_tml_execed; ///< line being timed was executed
|
||||
scid_T uf_script_ID; ///< ID of script where function was defined,
|
||||
///< used for s: variables
|
||||
int uf_refcount; ///< reference count, see func_name_refcount()
|
||||
funccall_T *uf_scoped; ///< l: local variables for closure
|
||||
char_u uf_name[1]; ///< name of function (actually longer); can
|
||||
///< start with <SNR>123_ (<SNR> is K_SPECIAL
|
||||
///< KS_EXTRA KE_SNR)
|
||||
};
|
||||
|
||||
/// Maximum number of function arguments
|
||||
#define MAX_FUNC_ARGS 20
|
||||
|
||||
struct partial_S {
|
||||
int pt_refcount; ///< Reference count.
|
||||
char_u *pt_name; ///< Function name; when NULL use pt_func->name.
|
||||
ufunc_T *pt_func; ///< Function pointer; when NULL lookup function with
|
||||
///< pt_name.
|
||||
bool pt_auto; ///< When true the partial was created by using dict.member
|
||||
///< in handle_subscript().
|
||||
int pt_argc; ///< Number of arguments.
|
||||
typval_T *pt_argv; ///< Arguments in allocated array.
|
||||
dict_T *pt_dict; ///< Dict for "self".
|
||||
};
|
||||
|
||||
/// Structure used for explicit stack while garbage collecting hash tables
|
||||
typedef struct ht_stack_S {
|
||||
hashtab_T *ht;
|
||||
struct ht_stack_S *prev;
|
||||
} ht_stack_T;
|
||||
|
||||
/// Structure used for explicit stack while garbage collecting lists
|
||||
typedef struct list_stack_S {
|
||||
list_T *list;
|
||||
struct list_stack_S *prev;
|
||||
} list_stack_T;
|
||||
|
||||
// In a hashtab item "hi_key" points to "di_key" in a dictitem.
|
||||
// This avoids adding a pointer to the hashtab item.
|
||||
|
||||
/// Convert a hashitem pointer to a dictitem pointer
|
||||
#define TV_DICT_HI2DI(hi) \
|
||||
((dictitem_T *)((hi)->hi_key - offsetof(dictitem_T, di_key)))
|
||||
|
||||
static inline long tv_list_len(const list_T *const l)
|
||||
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/// Get the number of items in a list
|
||||
///
|
||||
/// @param[in] l List to check.
|
||||
static inline long tv_list_len(const list_T *const l)
|
||||
{
|
||||
if (l == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return l->lv_len;
|
||||
}
|
||||
|
||||
static inline long tv_dict_len(const dict_T *const d)
|
||||
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/// Get the number of items in a Dictionary
|
||||
///
|
||||
/// @param[in] d Dictionary to check.
|
||||
static inline long tv_dict_len(const dict_T *const d)
|
||||
{
|
||||
if (d == NULL) {
|
||||
return 0L;
|
||||
}
|
||||
return (long)d->dv_hashtab.ht_used;
|
||||
}
|
||||
|
||||
static inline bool tv_dict_is_watched(const dict_T *const d)
|
||||
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/// Check if dictionary is watched
|
||||
///
|
||||
/// @param[in] d Dictionary to check.
|
||||
///
|
||||
/// @return true if there is at least one watcher.
|
||||
static inline bool tv_dict_is_watched(const dict_T *const d)
|
||||
{
|
||||
return d && !QUEUE_EMPTY(&d->watchers);
|
||||
}
|
||||
|
||||
/// Initialize VimL object
|
||||
///
|
||||
/// Initializes to unlocked VAR_UNKNOWN object.
|
||||
///
|
||||
/// @param[out] tv Object to initialize.
|
||||
static inline void tv_init(typval_T *const tv)
|
||||
{
|
||||
if (tv != NULL) {
|
||||
memset(tv, 0, sizeof(*tv));
|
||||
}
|
||||
}
|
||||
|
||||
#define TV_INITIAL_VALUE \
|
||||
((typval_T) { \
|
||||
.v_type = VAR_UNKNOWN, \
|
||||
.v_lock = VAR_UNLOCKED, \
|
||||
})
|
||||
|
||||
/// Empty string
|
||||
///
|
||||
/// Needed for hack which allows not allocating empty string and still not
|
||||
/// crashing when freeing it.
|
||||
extern const char *const tv_empty_string;
|
||||
|
||||
/// Specifies that free_unref_items() function has (not) been entered
|
||||
extern bool tv_in_free_unref_items;
|
||||
|
||||
/// Iterate over a dictionary
|
||||
///
|
||||
/// @param[in] d Dictionary to iterate over.
|
||||
/// @param di Name of the variable with current dictitem_T entry.
|
||||
/// @param code Cycle body.
|
||||
#define TV_DICT_ITER(d, di, code) \
|
||||
HASHTAB_ITER(&(d)->dv_hashtab, di##hi_, { \
|
||||
{ \
|
||||
dictitem_T *const di = TV_DICT_HI2DI(di##hi_); \
|
||||
{ \
|
||||
code \
|
||||
} \
|
||||
} \
|
||||
})
|
||||
|
||||
static inline bool tv_get_float_chk(const typval_T *const tv,
|
||||
float_T *const ret_f)
|
||||
REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
// FIXME circular dependency, cannot import message.h.
|
||||
bool emsgf(const char *const fmt, ...);
|
||||
|
||||
/// Get the float value
|
||||
///
|
||||
/// Raises an error if object is not number or floating-point.
|
||||
///
|
||||
/// @param[in] tv VimL object to get value from.
|
||||
/// @param[out] ret_f Location where resulting float is stored.
|
||||
///
|
||||
/// @return true in case of success, false if tv is not a number or float.
|
||||
static inline bool tv_get_float_chk(const typval_T *const tv,
|
||||
float_T *const ret_f)
|
||||
{
|
||||
if (tv->v_type == VAR_FLOAT) {
|
||||
*ret_f = tv->vval.v_float;
|
||||
return true;
|
||||
}
|
||||
if (tv->v_type == VAR_NUMBER) {
|
||||
*ret_f = (float_T)tv->vval.v_number;
|
||||
return true;
|
||||
}
|
||||
emsgf(_("E808: Number or Float required"));
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q)
|
||||
REAL_FATTR_NONNULL_ALL REAL_FATTR_NONNULL_RET REAL_FATTR_PURE
|
||||
REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE;
|
||||
|
||||
/// Compute the `DictWatcher` address from a QUEUE node.
|
||||
///
|
||||
/// This only exists for .asan-blacklist (ASAN doesn't handle QUEUE_DATA pointer
|
||||
/// arithmetic).
|
||||
static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q)
|
||||
{
|
||||
return QUEUE_DATA(q, DictWatcher, node);
|
||||
}
|
||||
|
||||
static inline bool tv_is_func(const typval_T tv)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_CONST;
|
||||
|
||||
/// Check whether given typval_T contains a function
|
||||
///
|
||||
/// That is, whether it contains VAR_FUNC or VAR_PARTIAL.
|
||||
///
|
||||
/// @param[in] tv Typval to check.
|
||||
///
|
||||
/// @return True if it is a function or a partial, false otherwise.
|
||||
static inline bool tv_is_func(const typval_T tv)
|
||||
{
|
||||
return tv.v_type == VAR_FUNC || tv.v_type == VAR_PARTIAL;
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/typval.h.generated.h"
|
||||
#endif
|
||||
#endif // NVIM_EVAL_TYPVAL_H
|
@ -242,7 +242,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "nvim/lib/kvec.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/eval/encode.h"
|
||||
#include "nvim/func_attr.h"
|
||||
#include "nvim/eval/typval_encode.h"
|
||||
@ -406,11 +406,11 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
|
||||
const dictitem_T *val_di;
|
||||
if (TYPVAL_ENCODE_ALLOW_SPECIALS
|
||||
&& tv->vval.v_dict->dv_hashtab.ht_used == 2
|
||||
&& (type_di = dict_find((dict_T *)tv->vval.v_dict,
|
||||
(char_u *)"_TYPE", -1)) != NULL
|
||||
&& (type_di = tv_dict_find((dict_T *)tv->vval.v_dict,
|
||||
S_LEN("_TYPE"))) != NULL
|
||||
&& type_di->di_tv.v_type == VAR_LIST
|
||||
&& (val_di = dict_find((dict_T *)tv->vval.v_dict,
|
||||
(char_u *)"_VAL", -1)) != NULL) {
|
||||
&& (val_di = tv_dict_find((dict_T *)tv->vval.v_dict,
|
||||
S_LEN("_VAL"))) != NULL) {
|
||||
size_t i;
|
||||
for (i = 0; i < ARRAY_SIZE(eval_msgpack_type_lists); i++) {
|
||||
if (type_di->di_tv.vval.v_list == eval_msgpack_type_lists[i]) {
|
||||
@ -662,7 +662,7 @@ typval_encode_stop_converting_one_item:
|
||||
while (HASHITEM_EMPTY(cur_mpsv->data.d.hi)) {
|
||||
cur_mpsv->data.d.hi++;
|
||||
}
|
||||
dictitem_T *const di = HI2DI(cur_mpsv->data.d.hi);
|
||||
dictitem_T *const di = TV_DICT_HI2DI(cur_mpsv->data.d.hi);
|
||||
cur_mpsv->data.d.todo--;
|
||||
cur_mpsv->data.d.hi++;
|
||||
TYPVAL_ENCODE_CONV_STR_STRING(NULL, &di->di_key[0],
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "nvim/lib/kvec.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/func_attr.h"
|
||||
|
||||
/// Type of the stack entry
|
||||
|
@ -1,286 +0,0 @@
|
||||
#ifndef NVIM_EVAL_DEFS_H
|
||||
#define NVIM_EVAL_DEFS_H
|
||||
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "nvim/hashtab.h"
|
||||
#include "nvim/lib/queue.h"
|
||||
#include "nvim/garray.h" // for garray_T
|
||||
#include "nvim/profile.h" // for proftime_T
|
||||
#include "nvim/pos.h" // for linenr_T
|
||||
|
||||
typedef int varnumber_T;
|
||||
typedef double float_T;
|
||||
|
||||
#define VARNUMBER_MAX INT_MAX
|
||||
#define VARNUMBER_MIN INT_MIN
|
||||
|
||||
typedef struct listvar_S list_T;
|
||||
typedef struct dictvar_S dict_T;
|
||||
typedef struct partial_S partial_T;
|
||||
|
||||
/// Special variable values
|
||||
typedef enum {
|
||||
kSpecialVarFalse, ///< v:false
|
||||
kSpecialVarTrue, ///< v:true
|
||||
kSpecialVarNull, ///< v:null
|
||||
} SpecialVarValue;
|
||||
|
||||
/// Variable lock status for typval_T.v_lock
|
||||
typedef enum {
|
||||
VAR_UNLOCKED = 0, ///< Not locked.
|
||||
VAR_LOCKED = 1, ///< User lock, can be unlocked.
|
||||
VAR_FIXED = 2, ///< Locked forever.
|
||||
} VarLockStatus;
|
||||
|
||||
/// VimL variable types, for use in typval_T.v_type
|
||||
typedef enum {
|
||||
VAR_UNKNOWN = 0, ///< Unknown (unspecified) value.
|
||||
VAR_NUMBER, ///< Number, .v_number is used.
|
||||
VAR_STRING, ///< String, .v_string is used.
|
||||
VAR_FUNC, ///< Function reference, .v_string is used as function name.
|
||||
VAR_LIST, ///< List, .v_list is used.
|
||||
VAR_DICT, ///< Dictionary, .v_dict is used.
|
||||
VAR_FLOAT, ///< Floating-point value, .v_float is used.
|
||||
VAR_SPECIAL, ///< Special value (true, false, null), .v_special
|
||||
///< is used.
|
||||
VAR_PARTIAL, ///< Partial, .v_partial is used.
|
||||
} VarType;
|
||||
|
||||
/// Structure that holds an internal variable value
|
||||
typedef struct {
|
||||
VarType v_type; ///< Variable type.
|
||||
VarLockStatus v_lock; ///< Variable lock status.
|
||||
union typval_vval_union {
|
||||
varnumber_T v_number; ///< Number, for VAR_NUMBER.
|
||||
SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL.
|
||||
float_T v_float; ///< Floating-point number, for VAR_FLOAT.
|
||||
char_u *v_string; ///< String, for VAR_STRING and VAR_FUNC, can be NULL.
|
||||
list_T *v_list; ///< List for VAR_LIST, can be NULL.
|
||||
dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL.
|
||||
partial_T *v_partial; ///< Closure: function with args.
|
||||
} vval; ///< Actual value.
|
||||
} typval_T;
|
||||
|
||||
/* Values for "dv_scope". */
|
||||
#define VAR_SCOPE 1 /* a:, v:, s:, etc. scope dictionaries */
|
||||
#define VAR_DEF_SCOPE 2 /* l:, g: scope dictionaries: here funcrefs are not
|
||||
allowed to mask existing functions */
|
||||
|
||||
/*
|
||||
* Structure to hold an item of a list: an internal variable without a name.
|
||||
*/
|
||||
typedef struct listitem_S listitem_T;
|
||||
|
||||
struct listitem_S {
|
||||
listitem_T *li_next; /* next item in list */
|
||||
listitem_T *li_prev; /* previous item in list */
|
||||
typval_T li_tv; /* type and value of the variable */
|
||||
};
|
||||
|
||||
/*
|
||||
* Struct used by those that are using an item in a list.
|
||||
*/
|
||||
typedef struct listwatch_S listwatch_T;
|
||||
|
||||
struct listwatch_S {
|
||||
listitem_T *lw_item; /* item being watched */
|
||||
listwatch_T *lw_next; /* next watcher */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure to hold info about a list.
|
||||
*/
|
||||
struct listvar_S {
|
||||
listitem_T *lv_first; ///< First item, NULL if none.
|
||||
listitem_T *lv_last; ///< Last item, NULL if none.
|
||||
int lv_refcount; ///< Reference count.
|
||||
int lv_len; ///< Number of items.
|
||||
listwatch_T *lv_watch; ///< First watcher, NULL if none.
|
||||
int lv_idx; ///< Index of a cached item, used for optimising repeated l[idx].
|
||||
listitem_T *lv_idx_item; ///< When not NULL item at index "lv_idx".
|
||||
int lv_copyID; ///< ID used by deepcopy().
|
||||
list_T *lv_copylist; ///< Copied list used by deepcopy().
|
||||
VarLockStatus lv_lock; ///< Zero, VAR_LOCKED, VAR_FIXED.
|
||||
list_T *lv_used_next; ///< next list in used lists list.
|
||||
list_T *lv_used_prev; ///< Previous list in used lists list.
|
||||
};
|
||||
|
||||
// Static list with 10 items. Use init_static_list() to initialize.
|
||||
typedef struct {
|
||||
list_T sl_list; // must be first
|
||||
listitem_T sl_items[10];
|
||||
} staticList10_T;
|
||||
|
||||
// Structure to hold an item of a Dictionary.
|
||||
// Also used for a variable.
|
||||
// The key is copied into "di_key" to avoid an extra alloc/free for it.
|
||||
struct dictitem_S {
|
||||
typval_T di_tv; ///< type and value of the variable
|
||||
char_u di_flags; ///< flags (only used for variable)
|
||||
char_u di_key[1]; ///< key (actually longer!)
|
||||
};
|
||||
|
||||
typedef struct dictitem_S dictitem_T;
|
||||
|
||||
/// A dictitem with a 16 character key (plus NUL)
|
||||
struct dictitem16_S {
|
||||
typval_T di_tv; ///< type and value of the variable
|
||||
char_u di_flags; ///< flags (only used for variable)
|
||||
char_u di_key[17]; ///< key
|
||||
};
|
||||
|
||||
typedef struct dictitem16_S dictitem16_T;
|
||||
|
||||
|
||||
#define DI_FLAGS_RO 1 // "di_flags" value: read-only variable
|
||||
#define DI_FLAGS_RO_SBX 2 // "di_flags" value: read-only in the sandbox
|
||||
#define DI_FLAGS_FIX 4 // "di_flags" value: fixed: no :unlet or remove()
|
||||
#define DI_FLAGS_LOCK 8 // "di_flags" value: locked variable
|
||||
#define DI_FLAGS_ALLOC 16 // "di_flags" value: separately allocated
|
||||
|
||||
/// Structure representing a Dictionary
|
||||
struct dictvar_S {
|
||||
VarLockStatus dv_lock; ///< Whole dictionary lock status.
|
||||
char dv_scope; ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if
|
||||
///< dictionary represents a scope (i.e. g:, l: …).
|
||||
int dv_refcount; ///< Reference count.
|
||||
int dv_copyID; ///< ID used when recursivery traversing a value.
|
||||
hashtab_T dv_hashtab; ///< Hashtab containing all items.
|
||||
dict_T *dv_copydict; ///< Copied dict used by deepcopy().
|
||||
dict_T *dv_used_next; ///< Next dictionary in used dictionaries list.
|
||||
dict_T *dv_used_prev; ///< Previous dictionary in used dictionaries list.
|
||||
QUEUE watchers; ///< Dictionary key watchers set by user code.
|
||||
};
|
||||
|
||||
typedef int scid_T; // script ID
|
||||
typedef struct funccall_S funccall_T;
|
||||
|
||||
// Structure to hold info for a user function.
|
||||
typedef struct ufunc ufunc_T;
|
||||
|
||||
struct ufunc {
|
||||
int uf_varargs; ///< variable nr of arguments
|
||||
int uf_flags;
|
||||
int uf_calls; ///< nr of active calls
|
||||
bool uf_cleared; ///< func_clear() was already called
|
||||
garray_T uf_args; ///< arguments
|
||||
garray_T uf_lines; ///< function lines
|
||||
int uf_profiling; ///< true when func is being profiled
|
||||
// Profiling the function as a whole.
|
||||
int uf_tm_count; ///< nr of calls
|
||||
proftime_T uf_tm_total; ///< time spent in function + children
|
||||
proftime_T uf_tm_self; ///< time spent in function itself
|
||||
proftime_T uf_tm_children; ///< time spent in children this call
|
||||
// Profiling the function per line.
|
||||
int *uf_tml_count; ///< nr of times line was executed
|
||||
proftime_T *uf_tml_total; ///< time spent in a line + children
|
||||
proftime_T *uf_tml_self; ///< time spent in a line itself
|
||||
proftime_T uf_tml_start; ///< start time for current line
|
||||
proftime_T uf_tml_children; ///< time spent in children for this line
|
||||
proftime_T uf_tml_wait; ///< start wait time for current line
|
||||
int uf_tml_idx; ///< index of line being timed; -1 if none
|
||||
int uf_tml_execed; ///< line being timed was executed
|
||||
scid_T uf_script_ID; ///< ID of script where function was defined,
|
||||
// used for s: variables
|
||||
int uf_refcount; ///< reference count, see func_name_refcount()
|
||||
funccall_T *uf_scoped; ///< l: local variables for closure
|
||||
char_u uf_name[1]; ///< name of function (actually longer); can
|
||||
// start with <SNR>123_ (<SNR> is K_SPECIAL
|
||||
// KS_EXTRA KE_SNR)
|
||||
};
|
||||
|
||||
/// Maximum number of function arguments
|
||||
#define MAX_FUNC_ARGS 20
|
||||
#define VAR_SHORT_LEN 20 // short variable name length
|
||||
#define FIXVAR_CNT 12 // number of fixed variables
|
||||
|
||||
// structure to hold info for a function that is currently being executed.
|
||||
struct funccall_S {
|
||||
ufunc_T *func; ///< function being called
|
||||
int linenr; ///< next line to be executed
|
||||
int returned; ///< ":return" used
|
||||
struct { ///< fixed variables for arguments
|
||||
dictitem_T var; ///< variable (without room for name)
|
||||
char_u room[VAR_SHORT_LEN]; ///< room for the name
|
||||
} fixvar[FIXVAR_CNT];
|
||||
dict_T l_vars; ///< l: local function variables
|
||||
dictitem_T l_vars_var; ///< variable for l: scope
|
||||
dict_T l_avars; ///< a: argument variables
|
||||
dictitem_T l_avars_var; ///< variable for a: scope
|
||||
list_T l_varlist; ///< list for a:000
|
||||
listitem_T l_listitems[MAX_FUNC_ARGS]; ///< listitems for a:000
|
||||
typval_T *rettv; ///< return value
|
||||
linenr_T breakpoint; ///< next line with breakpoint or zero
|
||||
int dbg_tick; ///< debug_tick when breakpoint was set
|
||||
int level; ///< top nesting level of executed function
|
||||
proftime_T prof_child; ///< time spent in a child
|
||||
funccall_T *caller; ///< calling function or NULL
|
||||
int fc_refcount; ///< number of user functions that reference
|
||||
// this funccal
|
||||
int fc_copyID; ///< for garbage collection
|
||||
garray_T fc_funcs; ///< list of ufunc_T* which keep a reference
|
||||
// to "func"
|
||||
};
|
||||
|
||||
// structure used by trans_function_name()
|
||||
typedef struct {
|
||||
dict_T *fd_dict; ///< Dictionary used.
|
||||
char_u *fd_newkey; ///< New key in "dict" in allocated memory.
|
||||
dictitem_T *fd_di; ///< Dictionary item used.
|
||||
} funcdict_T;
|
||||
|
||||
struct partial_S {
|
||||
int pt_refcount; ///< Reference count.
|
||||
char_u *pt_name; ///< Function name; when NULL use pt_func->name.
|
||||
ufunc_T *pt_func; ///< Function pointer; when NULL lookup function
|
||||
///< with pt_name.
|
||||
bool pt_auto; ///< when true the partial was created for using
|
||||
///< dict.member in handle_subscript().
|
||||
int pt_argc; ///< Number of arguments.
|
||||
typval_T *pt_argv; ///< Arguments in allocated array.
|
||||
dict_T *pt_dict; ///< Dict for "self".
|
||||
};
|
||||
|
||||
// structure used for explicit stack while garbage collecting hash tables
|
||||
typedef struct ht_stack_S {
|
||||
hashtab_T *ht;
|
||||
struct ht_stack_S *prev;
|
||||
} ht_stack_T;
|
||||
|
||||
// structure used for explicit stack while garbage collecting lists
|
||||
typedef struct list_stack_S {
|
||||
list_T *list;
|
||||
struct list_stack_S *prev;
|
||||
} list_stack_T;
|
||||
|
||||
// In a hashtab item "hi_key" points to "di_key" in a dictitem.
|
||||
// This avoids adding a pointer to the hashtab item.
|
||||
|
||||
/// Convert a dictitem pointer to a hashitem key pointer
|
||||
#define DI2HIKEY(di) ((di)->di_key)
|
||||
|
||||
/// Convert a hashitem key pointer to a dictitem pointer
|
||||
#define HIKEY2DI(p) ((dictitem_T *)(p - offsetof(dictitem_T, di_key)))
|
||||
|
||||
/// Convert a hashitem value pointer to a dictitem pointer
|
||||
#define HIVAL2DI(p) \
|
||||
((dictitem_T *)(((char *)p) - offsetof(dictitem_T, di_tv)))
|
||||
|
||||
/// Convert a hashitem pointer to a dictitem pointer
|
||||
#define HI2DI(hi) HIKEY2DI((hi)->hi_key)
|
||||
|
||||
/// Type of assert_* check being performed
|
||||
typedef enum
|
||||
{
|
||||
ASSERT_EQUAL,
|
||||
ASSERT_NOTEQUAL,
|
||||
ASSERT_MATCH,
|
||||
ASSERT_NOTMATCH,
|
||||
ASSERT_INRANGE,
|
||||
ASSERT_OTHER,
|
||||
} assert_type_T;
|
||||
|
||||
#endif // NVIM_EVAL_DEFS_H
|
@ -21,7 +21,7 @@ struct process {
|
||||
int pid, status, refcount;
|
||||
// set to the hrtime of when process_stop was called for the process.
|
||||
uint64_t stopped_time;
|
||||
char *cwd;
|
||||
const char *cwd;
|
||||
char **argv;
|
||||
Stream *in, *out, *err;
|
||||
process_exit_cb cb;
|
||||
|
@ -89,7 +89,10 @@ static void on_rbuffer_nonfull(RBuffer *buf, void *data)
|
||||
static void alloc_cb(uv_handle_t *handle, size_t suggested, uv_buf_t *buf)
|
||||
{
|
||||
Stream *stream = handle->data;
|
||||
buf->base = rbuffer_write_ptr(stream->buffer, &buf->len);
|
||||
// `uv_buf_t.len` happens to have different size on Windows.
|
||||
size_t write_count;
|
||||
buf->base = rbuffer_write_ptr(stream->buffer, &write_count);
|
||||
buf->len = write_count;
|
||||
}
|
||||
|
||||
// Callback invoked by libuv after it copies the data into the buffer provided
|
||||
@ -136,7 +139,10 @@ static void fread_idle_cb(uv_idle_t *handle)
|
||||
uv_fs_t req;
|
||||
Stream *stream = handle->data;
|
||||
|
||||
stream->uvbuf.base = rbuffer_write_ptr(stream->buffer, &stream->uvbuf.len);
|
||||
// `uv_buf_t.len` happens to have different size on Windows.
|
||||
size_t write_count;
|
||||
stream->uvbuf.base = rbuffer_write_ptr(stream->buffer, &write_count);
|
||||
stream->uvbuf.len = write_count;
|
||||
|
||||
// the offset argument to uv_fs_read is int64_t, could someone really try
|
||||
// to read more than 9 quintillion (9e18) bytes?
|
||||
|
@ -1008,8 +1008,8 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
|
||||
|
||||
AppendToRedobuffLit(cmd, -1);
|
||||
xfree(cmd);
|
||||
AppendToRedobuff((char_u *)"\n");
|
||||
bangredo = FALSE;
|
||||
AppendToRedobuff("\n");
|
||||
bangredo = false;
|
||||
}
|
||||
/*
|
||||
* Add quotes around the command, for shells that need them.
|
||||
@ -2958,7 +2958,7 @@ void sub_set_replacement(SubReplacementString sub)
|
||||
{
|
||||
xfree(old_sub.sub);
|
||||
if (sub.additional_elements != old_sub.additional_elements) {
|
||||
list_unref(old_sub.additional_elements);
|
||||
tv_list_unref(old_sub.additional_elements);
|
||||
}
|
||||
old_sub = sub;
|
||||
}
|
||||
@ -4764,8 +4764,8 @@ void fix_help_buffer(void)
|
||||
char_u *p;
|
||||
char_u *rt;
|
||||
|
||||
/* set filetype to "help". */
|
||||
set_option_value((char_u *)"ft", 0L, (char_u *)"help", OPT_LOCAL);
|
||||
// Set filetype to "help".
|
||||
set_option_value("ft", 0L, "help", OPT_LOCAL);
|
||||
|
||||
if (!syntax_present(curwin)) {
|
||||
for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) {
|
||||
|
@ -4,8 +4,8 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "nvim/os/time.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/pos.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
|
||||
// flags for do_ecmd()
|
||||
#define ECMD_HIDE 0x01 // don't free the current buffer
|
||||
|
@ -957,23 +957,21 @@ char_u *get_profile_name(expand_T *xp, int idx)
|
||||
}
|
||||
|
||||
/// Handle command line completion for :profile command.
|
||||
void set_context_in_profile_cmd(expand_T *xp, char_u *arg)
|
||||
void set_context_in_profile_cmd(expand_T *xp, const char *arg)
|
||||
{
|
||||
char_u *end_subcmd;
|
||||
|
||||
// Default: expand subcommands.
|
||||
xp->xp_context = EXPAND_PROFILE;
|
||||
pexpand_what = PEXP_SUBCMD;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
|
||||
end_subcmd = skiptowhite(arg);
|
||||
char_u *const end_subcmd = skiptowhite((const char_u *)arg);
|
||||
if (*end_subcmd == NUL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (end_subcmd - arg == 5 && STRNCMP(arg, "start", 5) == 0) {
|
||||
if ((const char *)end_subcmd - arg == 5 && strncmp(arg, "start", 5) == 0) {
|
||||
xp->xp_context = EXPAND_FILES;
|
||||
xp->xp_pattern = skipwhite(end_subcmd);
|
||||
xp->xp_pattern = skipwhite((const char_u *)end_subcmd);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2073,9 +2071,9 @@ void ex_listdo(exarg_T *eap)
|
||||
// Clear 'shm' to avoid that the file message overwrites
|
||||
// any output from the command.
|
||||
p_shm_save = vim_strsave(p_shm);
|
||||
set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
|
||||
set_option_value("shm", 0L, "", 0);
|
||||
do_argfile(eap, i);
|
||||
set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
|
||||
set_option_value("shm", 0L, (char *)p_shm_save, 0);
|
||||
xfree(p_shm_save);
|
||||
}
|
||||
if (curwin->w_arg_idx != i) {
|
||||
@ -2138,9 +2136,9 @@ void ex_listdo(exarg_T *eap)
|
||||
// Go to the next buffer. Clear 'shm' to avoid that the file
|
||||
// message overwrites any output from the command.
|
||||
p_shm_save = vim_strsave(p_shm);
|
||||
set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
|
||||
set_option_value("shm", 0L, "", 0);
|
||||
goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
|
||||
set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
|
||||
set_option_value("shm", 0L, (char *)p_shm_save, 0);
|
||||
xfree(p_shm_save);
|
||||
|
||||
// If autocommands took us elsewhere, quit here.
|
||||
@ -2256,8 +2254,8 @@ void ex_compiler(exarg_T *eap)
|
||||
}
|
||||
do_cmdline_cmd("command -nargs=* CompilerSet setlocal <args>");
|
||||
}
|
||||
do_unlet((char_u *)"g:current_compiler", true);
|
||||
do_unlet((char_u *)"b:current_compiler", true);
|
||||
do_unlet(S_LEN("g:current_compiler"), true);
|
||||
do_unlet(S_LEN("b:current_compiler"), true);
|
||||
|
||||
snprintf((char *)buf, bufsize, "compiler/%s.vim", eap->arg);
|
||||
if (source_runtime(buf, DIP_ALL) == FAIL) {
|
||||
@ -2280,7 +2278,7 @@ void ex_compiler(exarg_T *eap)
|
||||
old_cur_comp);
|
||||
xfree(old_cur_comp);
|
||||
} else {
|
||||
do_unlet((char_u *)"g:current_compiler", true);
|
||||
do_unlet(S_LEN("g:current_compiler"), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2496,16 +2494,16 @@ static int APP_BOTH;
|
||||
static void add_pack_plugin(char_u *fname, void *cookie)
|
||||
{
|
||||
char_u *p4, *p3, *p2, *p1, *p;
|
||||
char_u *new_rtp;
|
||||
char_u *ffname = (char_u *)fix_fname((char *)fname);
|
||||
|
||||
char *const ffname = fix_fname((char *)fname);
|
||||
|
||||
if (ffname == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cookie != &APP_LOAD && strstr((char *)p_rtp, (char *)ffname) == NULL) {
|
||||
if (cookie != &APP_LOAD && strstr((char *)p_rtp, ffname) == NULL) {
|
||||
// directory is not yet in 'runtimepath', add it
|
||||
p4 = p3 = p2 = p1 = get_past_head(ffname);
|
||||
p4 = p3 = p2 = p1 = get_past_head((char_u *)ffname);
|
||||
for (p = p1; *p; mb_ptr_adv(p)) {
|
||||
if (vim_ispathsep_nocolon(*p)) {
|
||||
p4 = p3; p3 = p2; p2 = p1; p1 = p;
|
||||
@ -2521,13 +2519,13 @@ static void add_pack_plugin(char_u *fname, void *cookie)
|
||||
*p4 = NUL;
|
||||
|
||||
// Find "ffname" in "p_rtp", ignoring '/' vs '\' differences
|
||||
size_t fname_len = STRLEN(ffname);
|
||||
char_u *insp = p_rtp;
|
||||
size_t fname_len = strlen(ffname);
|
||||
const char *insp = (const char *)p_rtp;
|
||||
for (;;) {
|
||||
if (vim_fnamencmp(insp, ffname, fname_len) == 0) {
|
||||
if (path_fnamencmp(insp, ffname, fname_len) == 0) {
|
||||
break;
|
||||
}
|
||||
insp = vim_strchr(insp, ',');
|
||||
insp = strchr(insp, ',');
|
||||
if (insp == NULL) {
|
||||
break;
|
||||
}
|
||||
@ -2536,10 +2534,10 @@ static void add_pack_plugin(char_u *fname, void *cookie)
|
||||
|
||||
if (insp == NULL) {
|
||||
// not found, append at the end
|
||||
insp = p_rtp + STRLEN(p_rtp);
|
||||
insp = (const char *)p_rtp + STRLEN(p_rtp);
|
||||
} else {
|
||||
// append after the matching directory.
|
||||
insp += STRLEN(ffname);
|
||||
insp += strlen(ffname);
|
||||
while (*insp != NUL && *insp != ',') {
|
||||
insp++;
|
||||
}
|
||||
@ -2547,31 +2545,40 @@ static void add_pack_plugin(char_u *fname, void *cookie)
|
||||
*p4 = c;
|
||||
|
||||
// check if rtp/pack/name/start/name/after exists
|
||||
char *afterdir = concat_fnames((char *)ffname, "after", true);
|
||||
char *afterdir = concat_fnames(ffname, "after", true);
|
||||
size_t afterlen = 0;
|
||||
if (os_isdir((char_u *)afterdir)) {
|
||||
afterlen = STRLEN(afterdir) + 1; // add one for comma
|
||||
afterlen = strlen(afterdir) + 1; // add one for comma
|
||||
}
|
||||
|
||||
size_t oldlen = STRLEN(p_rtp);
|
||||
size_t addlen = STRLEN(ffname) + 1; // add one for comma
|
||||
new_rtp = try_malloc(oldlen + addlen + afterlen + 1); // add one for NUL
|
||||
const size_t oldlen = STRLEN(p_rtp);
|
||||
const size_t addlen = strlen(ffname) + 1; // add one for comma
|
||||
const size_t new_rtp_len = oldlen + addlen + afterlen + 1;
|
||||
// add one for NUL -------------------------------------^
|
||||
char *const new_rtp = try_malloc(new_rtp_len);
|
||||
if (new_rtp == NULL) {
|
||||
goto theend;
|
||||
}
|
||||
uintptr_t keep = (uintptr_t)(insp - p_rtp);
|
||||
const size_t keep = (size_t)(insp - (const char *)p_rtp);
|
||||
size_t new_rtp_fill = 0;
|
||||
memmove(new_rtp, p_rtp, keep);
|
||||
new_rtp[keep] = ',';
|
||||
memmove(new_rtp + keep + 1, ffname, addlen);
|
||||
new_rtp_fill += keep;
|
||||
new_rtp[new_rtp_fill++] = ',';
|
||||
memmove(new_rtp + new_rtp_fill, ffname, addlen);
|
||||
new_rtp_fill += addlen - 1;
|
||||
assert(new_rtp[new_rtp_fill] == NUL || new_rtp[new_rtp_fill] == ',');
|
||||
if (p_rtp[keep] != NUL) {
|
||||
memmove(new_rtp + keep + addlen, p_rtp + keep,
|
||||
oldlen - keep + 1);
|
||||
memmove(new_rtp + new_rtp_fill, p_rtp + keep, oldlen - keep + 1);
|
||||
new_rtp_fill += oldlen - keep;
|
||||
}
|
||||
if (afterlen > 0) {
|
||||
STRCAT(new_rtp, ",");
|
||||
STRCAT(new_rtp, afterdir);
|
||||
assert(new_rtp[new_rtp_fill] == NUL);
|
||||
new_rtp[new_rtp_fill++] = ',';
|
||||
memmove(new_rtp + new_rtp_fill, afterdir, afterlen - 1);
|
||||
new_rtp_fill += afterlen - 1;
|
||||
}
|
||||
set_option_value((char_u *)"rtp", 0L, new_rtp, 0);
|
||||
new_rtp[new_rtp_fill] = NUL;
|
||||
set_option_value("rtp", 0L, new_rtp, 0);
|
||||
xfree(new_rtp);
|
||||
xfree(afterdir);
|
||||
}
|
||||
@ -2580,7 +2587,7 @@ static void add_pack_plugin(char_u *fname, void *cookie)
|
||||
static const char *plugpat = "%s/plugin/**/*.vim"; // NOLINT
|
||||
static const char *ftpat = "%s/ftdetect/*.vim"; // NOLINT
|
||||
|
||||
size_t len = STRLEN(ffname) + STRLEN(ftpat);
|
||||
size_t len = strlen(ffname) + STRLEN(ftpat);
|
||||
char_u *pat = try_malloc(len + 1);
|
||||
if (pat == NULL) {
|
||||
goto theend;
|
||||
@ -3698,12 +3705,12 @@ static void script_host_execute(char *name, exarg_T *eap)
|
||||
uint8_t *script = script_get(eap, eap->arg);
|
||||
|
||||
if (!eap->skip) {
|
||||
list_T *args = list_alloc();
|
||||
list_T *args = tv_list_alloc();
|
||||
// script
|
||||
list_append_string(args, script ? script : eap->arg, -1);
|
||||
tv_list_append_string(args, (const char *)(script ? script : eap->arg), -1);
|
||||
// current range
|
||||
list_append_number(args, (int)eap->line1);
|
||||
list_append_number(args, (int)eap->line2);
|
||||
tv_list_append_number(args, (int)eap->line1);
|
||||
tv_list_append_number(args, (int)eap->line2);
|
||||
(void)eval_call_provider(name, "execute", args);
|
||||
}
|
||||
|
||||
@ -3715,21 +3722,21 @@ static void script_host_execute_file(char *name, exarg_T *eap)
|
||||
uint8_t buffer[MAXPATHL];
|
||||
vim_FullName((char *)eap->arg, (char *)buffer, sizeof(buffer), false);
|
||||
|
||||
list_T *args = list_alloc();
|
||||
list_T *args = tv_list_alloc();
|
||||
// filename
|
||||
list_append_string(args, buffer, -1);
|
||||
tv_list_append_string(args, (const char *)buffer, -1);
|
||||
// current range
|
||||
list_append_number(args, (int)eap->line1);
|
||||
list_append_number(args, (int)eap->line2);
|
||||
tv_list_append_number(args, (int)eap->line1);
|
||||
tv_list_append_number(args, (int)eap->line2);
|
||||
(void)eval_call_provider(name, "execute_file", args);
|
||||
}
|
||||
|
||||
static void script_host_do_range(char *name, exarg_T *eap)
|
||||
{
|
||||
list_T *args = list_alloc();
|
||||
list_append_number(args, (int)eap->line1);
|
||||
list_append_number(args, (int)eap->line2);
|
||||
list_append_string(args, eap->arg, -1);
|
||||
list_T *args = tv_list_alloc();
|
||||
tv_list_append_number(args, (int)eap->line1);
|
||||
tv_list_append_number(args, (int)eap->line2);
|
||||
tv_list_append_string(args, (const char *)eap->arg, -1);
|
||||
(void)eval_call_provider(name, "do_range", args);
|
||||
}
|
||||
|
||||
|
@ -270,7 +270,7 @@ do_exmode (
|
||||
/*
|
||||
* Execute a simple command line. Used for translated commands like "*".
|
||||
*/
|
||||
int do_cmdline_cmd(char *cmd)
|
||||
int do_cmdline_cmd(const char *cmd)
|
||||
{
|
||||
return do_cmdline((char_u *)cmd, NULL, NULL,
|
||||
DOCMD_NOWAIT|DOCMD_KEYTYPED);
|
||||
@ -2633,32 +2633,27 @@ int cmd_exists(const char *const name)
|
||||
* perfectly compatible with each other, but then the command line syntax
|
||||
* probably won't change that much -- webb.
|
||||
*/
|
||||
char_u *
|
||||
set_one_cmd_context (
|
||||
const char * set_one_cmd_context(
|
||||
expand_T *xp,
|
||||
char_u *buff /* buffer for command string */
|
||||
const char *buff // buffer for command string
|
||||
)
|
||||
{
|
||||
char_u *p;
|
||||
char_u *cmd, *arg;
|
||||
int len = 0;
|
||||
size_t len = 0;
|
||||
exarg_T ea;
|
||||
int compl = EXPAND_NOTHING;
|
||||
int delim;
|
||||
int forceit = FALSE;
|
||||
int usefilter = FALSE; /* filter instead of file name */
|
||||
int context = EXPAND_NOTHING;
|
||||
int forceit = false;
|
||||
int usefilter = false; // Filter instead of file name.
|
||||
|
||||
ExpandInit(xp);
|
||||
xp->xp_pattern = buff;
|
||||
xp->xp_context = EXPAND_COMMANDS; /* Default until we get past command */
|
||||
xp->xp_pattern = (char_u *)buff;
|
||||
xp->xp_context = EXPAND_COMMANDS; // Default until we get past command
|
||||
ea.argt = 0;
|
||||
|
||||
/*
|
||||
* 2. skip comment lines and leading space, colons or bars
|
||||
*/
|
||||
for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++)
|
||||
;
|
||||
xp->xp_pattern = cmd;
|
||||
// 2. skip comment lines and leading space, colons or bars
|
||||
const char *cmd;
|
||||
for (cmd = buff; strchr(" \t:|", *cmd) != NULL; cmd++) {
|
||||
}
|
||||
xp->xp_pattern = (char_u *)cmd;
|
||||
|
||||
if (*cmd == NUL)
|
||||
return NULL;
|
||||
@ -2670,14 +2665,15 @@ set_one_cmd_context (
|
||||
/*
|
||||
* 3. parse a range specifier of the form: addr [,addr] [;addr] ..
|
||||
*/
|
||||
cmd = skip_range(cmd, &xp->xp_context);
|
||||
cmd = (const char *)skip_range((const char_u *)cmd, &xp->xp_context);
|
||||
|
||||
/*
|
||||
* 4. parse command
|
||||
*/
|
||||
xp->xp_pattern = cmd;
|
||||
if (*cmd == NUL)
|
||||
xp->xp_pattern = (char_u *)cmd;
|
||||
if (*cmd == NUL) {
|
||||
return NULL;
|
||||
}
|
||||
if (*cmd == '"') {
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
return NULL;
|
||||
@ -2693,6 +2689,7 @@ set_one_cmd_context (
|
||||
* do accept "keepmarks", "keepalt" and "keepjumps".
|
||||
* - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
|
||||
*/
|
||||
const char *p;
|
||||
if (*cmd == 'k' && cmd[1] != 'e') {
|
||||
ea.cmdidx = CMD_k;
|
||||
p = cmd + 1;
|
||||
@ -2715,20 +2712,21 @@ set_one_cmd_context (
|
||||
}
|
||||
}
|
||||
// check for non-alpha command
|
||||
if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL) {
|
||||
if (p == cmd && strchr("@*!=><&~#", *p) != NULL) {
|
||||
p++;
|
||||
}
|
||||
len = (int)(p - cmd);
|
||||
len = (size_t)(p - cmd);
|
||||
|
||||
if (len == 0) {
|
||||
xp->xp_context = EXPAND_UNSUCCESSFUL;
|
||||
return NULL;
|
||||
}
|
||||
for (ea.cmdidx = (cmdidx_T)0; (int)ea.cmdidx < (int)CMD_SIZE;
|
||||
ea.cmdidx = (cmdidx_T)((int)ea.cmdidx + 1))
|
||||
if (STRNCMP(cmdnames[(int)ea.cmdidx].cmd_name, cmd,
|
||||
(size_t)len) == 0)
|
||||
ea.cmdidx = (cmdidx_T)((int)ea.cmdidx + 1)) {
|
||||
if (STRNCMP(cmdnames[(int)ea.cmdidx].cmd_name, cmd, len) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd[0] >= 'A' && cmd[0] <= 'Z') {
|
||||
while (ASCII_ISALNUM(*p) || *p == '*') { // Allow * wild card
|
||||
@ -2745,16 +2743,15 @@ set_one_cmd_context (
|
||||
return NULL;
|
||||
|
||||
if (ea.cmdidx == CMD_SIZE) {
|
||||
if (*cmd == 's' && vim_strchr((char_u *)"cgriI", cmd[1]) != NULL) {
|
||||
if (*cmd == 's' && strchr("cgriI", cmd[1]) != NULL) {
|
||||
ea.cmdidx = CMD_substitute;
|
||||
p = cmd + 1;
|
||||
} else if (cmd[0] >= 'A' && cmd[0] <= 'Z') {
|
||||
ea.cmd = cmd;
|
||||
p = find_ucmd(&ea, p, NULL, xp,
|
||||
&compl
|
||||
);
|
||||
if (p == NULL)
|
||||
ea.cmdidx = CMD_SIZE; /* ambiguous user command */
|
||||
ea.cmd = (char_u *)cmd;
|
||||
p = (const char *)find_ucmd(&ea, (char_u *)p, NULL, xp, &context);
|
||||
if (p == NULL) {
|
||||
ea.cmdidx = CMD_SIZE; // Ambiguous user command.
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ea.cmdidx == CMD_SIZE) {
|
||||
@ -2777,16 +2774,17 @@ set_one_cmd_context (
|
||||
ea.argt = cmdnames[(int)ea.cmdidx].cmd_argt;
|
||||
}
|
||||
|
||||
arg = skipwhite(p);
|
||||
const char *arg = (const char *)skipwhite((const char_u *)p);
|
||||
|
||||
if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) {
|
||||
if (*arg == '>') { /* append */
|
||||
if (*++arg == '>')
|
||||
++arg;
|
||||
arg = skipwhite(arg);
|
||||
} else if (*arg == '!' && ea.cmdidx == CMD_write) { /* :w !filter */
|
||||
++arg;
|
||||
usefilter = TRUE;
|
||||
if (*arg == '>') { // Append.
|
||||
if (*++arg == '>') {
|
||||
arg++;
|
||||
}
|
||||
arg = (const char *)skipwhite((const char_u *)arg);
|
||||
} else if (*arg == '!' && ea.cmdidx == CMD_write) { // :w !filter
|
||||
arg++;
|
||||
usefilter = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2799,23 +2797,24 @@ set_one_cmd_context (
|
||||
}
|
||||
|
||||
if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) {
|
||||
while (*arg == *cmd) /* allow any number of '>' or '<' */
|
||||
++arg;
|
||||
arg = skipwhite(arg);
|
||||
while (*arg == *cmd) { // allow any number of '>' or '<'
|
||||
arg++;
|
||||
}
|
||||
arg = (const char *)skipwhite((const char_u *)arg);
|
||||
}
|
||||
|
||||
/* Does command allow "+command"? */
|
||||
if ((ea.argt & EDITCMD) && !usefilter && *arg == '+') {
|
||||
/* Check if we're in the +command */
|
||||
p = arg + 1;
|
||||
arg = skip_cmd_arg(arg, FALSE);
|
||||
arg = (const char *)skip_cmd_arg((char_u *)arg, false);
|
||||
|
||||
/* Still touching the command after '+'? */
|
||||
if (*arg == NUL)
|
||||
return p;
|
||||
|
||||
/* Skip space(s) after +command to get to the real argument */
|
||||
arg = skipwhite(arg);
|
||||
// Skip space(s) after +command to get to the real argument.
|
||||
arg = (const char *)skipwhite((const char_u *)arg);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2844,19 +2843,18 @@ set_one_cmd_context (
|
||||
}
|
||||
|
||||
// no arguments allowed
|
||||
if (!(ea.argt & EXTRA) && *arg != NUL
|
||||
&& vim_strchr((char_u *)"|\"", *arg) == NULL) {
|
||||
if (!(ea.argt & EXTRA) && *arg != NUL && strchr("|\"", *arg) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find start of last argument (argument just before cursor): */
|
||||
p = buff;
|
||||
xp->xp_pattern = p;
|
||||
len = (int)STRLEN(buff);
|
||||
xp->xp_pattern = (char_u *)p;
|
||||
len = strlen(buff);
|
||||
while (*p && p < buff + len) {
|
||||
if (*p == ' ' || *p == TAB) {
|
||||
/* argument starts after a space */
|
||||
xp->xp_pattern = ++p;
|
||||
// Argument starts after a space.
|
||||
xp->xp_pattern = (char_u *)++p;
|
||||
} else {
|
||||
if (*p == '\\' && *(p + 1) != NUL)
|
||||
++p; /* skip over escaped character */
|
||||
@ -2866,25 +2864,26 @@ set_one_cmd_context (
|
||||
|
||||
if (ea.argt & XFILE) {
|
||||
int c;
|
||||
int in_quote = FALSE;
|
||||
char_u *bow = NULL; /* Beginning of word */
|
||||
int in_quote = false;
|
||||
const char *bow = NULL; // Beginning of word.
|
||||
|
||||
/*
|
||||
* Allow spaces within back-quotes to count as part of the argument
|
||||
* being expanded.
|
||||
*/
|
||||
xp->xp_pattern = skipwhite(arg);
|
||||
p = xp->xp_pattern;
|
||||
xp->xp_pattern = skipwhite((const char_u *)arg);
|
||||
p = (const char *)xp->xp_pattern;
|
||||
while (*p != NUL) {
|
||||
if (has_mbyte)
|
||||
c = mb_ptr2char(p);
|
||||
else
|
||||
c = *p;
|
||||
if (c == '\\' && p[1] != NUL)
|
||||
++p;
|
||||
else if (c == '`') {
|
||||
if (has_mbyte) {
|
||||
c = mb_ptr2char((const char_u *)p);
|
||||
} else {
|
||||
c = (uint8_t)(*p);
|
||||
}
|
||||
if (c == '\\' && p[1] != NUL) {
|
||||
p++;
|
||||
} else if (c == '`') {
|
||||
if (!in_quote) {
|
||||
xp->xp_pattern = p;
|
||||
xp->xp_pattern = (char_u *)p;
|
||||
bow = p + 1;
|
||||
}
|
||||
in_quote = !in_quote;
|
||||
@ -2897,22 +2896,26 @@ set_one_cmd_context (
|
||||
|| ascii_iswhite(c)) {
|
||||
len = 0; /* avoid getting stuck when space is in 'isfname' */
|
||||
while (*p != NUL) {
|
||||
if (has_mbyte)
|
||||
c = mb_ptr2char(p);
|
||||
else
|
||||
if (has_mbyte) {
|
||||
c = mb_ptr2char((const char_u *)p);
|
||||
} else {
|
||||
c = *p;
|
||||
if (c == '`' || vim_isfilec_or_wc(c))
|
||||
}
|
||||
if (c == '`' || vim_isfilec_or_wc(c)) {
|
||||
break;
|
||||
if (has_mbyte)
|
||||
len = (*mb_ptr2len)(p);
|
||||
else
|
||||
}
|
||||
if (has_mbyte) {
|
||||
len = (size_t)(*mb_ptr2len)((const char_u *)p);
|
||||
} else {
|
||||
len = 1;
|
||||
}
|
||||
mb_ptr_adv(p);
|
||||
}
|
||||
if (in_quote)
|
||||
if (in_quote) {
|
||||
bow = p;
|
||||
else
|
||||
xp->xp_pattern = p;
|
||||
} else {
|
||||
xp->xp_pattern = (char_u *)p;
|
||||
}
|
||||
p -= len;
|
||||
}
|
||||
mb_ptr_adv(p);
|
||||
@ -2922,8 +2925,9 @@ set_one_cmd_context (
|
||||
* If we are still inside the quotes, and we passed a space, just
|
||||
* expand from there.
|
||||
*/
|
||||
if (bow != NULL && in_quote)
|
||||
xp->xp_pattern = bow;
|
||||
if (bow != NULL && in_quote) {
|
||||
xp->xp_pattern = (char_u *)bow;
|
||||
}
|
||||
xp->xp_context = EXPAND_FILES;
|
||||
|
||||
/* For a shell command more chars need to be escaped. */
|
||||
@ -2931,33 +2935,36 @@ set_one_cmd_context (
|
||||
#ifndef BACKSLASH_IN_FILENAME
|
||||
xp->xp_shell = TRUE;
|
||||
#endif
|
||||
/* When still after the command name expand executables. */
|
||||
if (xp->xp_pattern == skipwhite(arg))
|
||||
// When still after the command name expand executables.
|
||||
if (xp->xp_pattern == skipwhite((const char_u *)arg)) {
|
||||
xp->xp_context = EXPAND_SHELLCMD;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for environment variable */
|
||||
if (*xp->xp_pattern == '$'
|
||||
) {
|
||||
for (p = xp->xp_pattern + 1; *p != NUL; ++p)
|
||||
if (!vim_isIDc(*p))
|
||||
// Check for environment variable.
|
||||
if (*xp->xp_pattern == '$') {
|
||||
for (p = (const char *)xp->xp_pattern + 1; *p != NUL; p++) {
|
||||
if (!vim_isIDc((uint8_t)(*p))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*p == NUL) {
|
||||
xp->xp_context = EXPAND_ENV_VARS;
|
||||
++xp->xp_pattern;
|
||||
/* Avoid that the assignment uses EXPAND_FILES again. */
|
||||
if (compl != EXPAND_USER_DEFINED && compl != EXPAND_USER_LIST)
|
||||
compl = EXPAND_ENV_VARS;
|
||||
xp->xp_pattern++;
|
||||
// Avoid that the assignment uses EXPAND_FILES again.
|
||||
if (context != EXPAND_USER_DEFINED && context != EXPAND_USER_LIST) {
|
||||
context = EXPAND_ENV_VARS;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Check for user names */
|
||||
if (*xp->xp_pattern == '~') {
|
||||
for (p = xp->xp_pattern + 1; *p != NUL && *p != '/'; ++p)
|
||||
;
|
||||
/* Complete ~user only if it partially matches a user name.
|
||||
* A full match ~user<Tab> will be replaced by user's home
|
||||
* directory i.e. something like ~user<Tab> -> /home/user/ */
|
||||
if (*p == NUL && p > xp->xp_pattern + 1
|
||||
for (p = (const char *)xp->xp_pattern + 1; *p != NUL && *p != '/'; p++) {
|
||||
}
|
||||
// Complete ~user only if it partially matches a user name.
|
||||
// A full match ~user<Tab> will be replaced by user's home
|
||||
// directory i.e. something like ~user<Tab> -> /home/user/
|
||||
if (*p == NUL && p > (const char *)xp->xp_pattern + 1
|
||||
&& match_user(xp->xp_pattern + 1) == 1) {
|
||||
xp->xp_context = EXPAND_USER;
|
||||
++xp->xp_pattern;
|
||||
@ -2987,7 +2994,7 @@ set_one_cmd_context (
|
||||
break;
|
||||
case CMD_help:
|
||||
xp->xp_context = EXPAND_HELP;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
/* Command modifiers: return the argument.
|
||||
@ -3030,13 +3037,14 @@ set_one_cmd_context (
|
||||
if (*arg == NUL || !ends_excmd(*arg)) {
|
||||
/* also complete "None" */
|
||||
set_context_in_echohl_cmd(xp, arg);
|
||||
arg = skipwhite(skiptowhite(arg));
|
||||
arg = (const char *)skipwhite(skiptowhite((const char_u *)arg));
|
||||
if (*arg != NUL) {
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
arg = skip_regexp(arg + 1, *arg, p_magic, NULL);
|
||||
arg = (const char *)skip_regexp((char_u *)arg + 1, (uint8_t)(*arg),
|
||||
p_magic, NULL);
|
||||
}
|
||||
}
|
||||
return find_nextcmd(arg);
|
||||
return (const char *)find_nextcmd((char_u *)arg);
|
||||
|
||||
/*
|
||||
* All completion for the +cmdline_compl feature goes here.
|
||||
@ -3045,15 +3053,15 @@ set_one_cmd_context (
|
||||
case CMD_command:
|
||||
/* Check for attributes */
|
||||
while (*arg == '-') {
|
||||
arg++; /* Skip "-" */
|
||||
p = skiptowhite(arg);
|
||||
arg++; // Skip "-".
|
||||
p = (const char *)skiptowhite((const char_u *)arg);
|
||||
if (*p == NUL) {
|
||||
/* Cursor is still in the attribute */
|
||||
p = vim_strchr(arg, '=');
|
||||
// Cursor is still in the attribute.
|
||||
p = strchr(arg, '=');
|
||||
if (p == NULL) {
|
||||
/* No "=", so complete attribute names */
|
||||
// No "=", so complete attribute names.
|
||||
xp->xp_context = EXPAND_USER_CMD_FLAGS;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -3061,73 +3069,81 @@ set_one_cmd_context (
|
||||
// their arguments as well.
|
||||
if (STRNICMP(arg, "complete", p - arg) == 0) {
|
||||
xp->xp_context = EXPAND_USER_COMPLETE;
|
||||
xp->xp_pattern = p + 1;
|
||||
xp->xp_pattern = (char_u *)p + 1;
|
||||
return NULL;
|
||||
} else if (STRNICMP(arg, "nargs", p - arg) == 0) {
|
||||
xp->xp_context = EXPAND_USER_NARGS;
|
||||
xp->xp_pattern = p + 1;
|
||||
xp->xp_pattern = (char_u *)p + 1;
|
||||
return NULL;
|
||||
} else if (STRNICMP(arg, "addr", p - arg) == 0) {
|
||||
xp->xp_context = EXPAND_USER_ADDR_TYPE;
|
||||
xp->xp_pattern = p + 1;
|
||||
xp->xp_pattern = (char_u *)p + 1;
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
arg = skipwhite(p);
|
||||
arg = (const char *)skipwhite((char_u *)p);
|
||||
}
|
||||
|
||||
/* After the attributes comes the new command name */
|
||||
p = skiptowhite(arg);
|
||||
// After the attributes comes the new command name.
|
||||
p = (const char *)skiptowhite((const char_u *)arg);
|
||||
if (*p == NUL) {
|
||||
xp->xp_context = EXPAND_USER_COMMANDS;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
}
|
||||
|
||||
/* And finally comes a normal command */
|
||||
return skipwhite(p);
|
||||
// And finally comes a normal command.
|
||||
return (const char *)skipwhite((const char_u *)p);
|
||||
|
||||
case CMD_delcommand:
|
||||
xp->xp_context = EXPAND_USER_COMMANDS;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_global:
|
||||
case CMD_vglobal:
|
||||
delim = *arg; /* get the delimiter */
|
||||
if (delim)
|
||||
++arg; /* skip delimiter if there is one */
|
||||
case CMD_vglobal: {
|
||||
const int delim = (uint8_t)(*arg); // Get the delimiter.
|
||||
if (delim) {
|
||||
arg++; // Skip delimiter if there is one.
|
||||
}
|
||||
|
||||
while (arg[0] != NUL && arg[0] != delim) {
|
||||
if (arg[0] == '\\' && arg[1] != NUL)
|
||||
++arg;
|
||||
++arg;
|
||||
while (arg[0] != NUL && (uint8_t)arg[0] != delim) {
|
||||
if (arg[0] == '\\' && arg[1] != NUL) {
|
||||
arg++;
|
||||
}
|
||||
arg++;
|
||||
}
|
||||
if (arg[0] != NUL)
|
||||
return arg + 1;
|
||||
break;
|
||||
}
|
||||
case CMD_and:
|
||||
case CMD_substitute:
|
||||
delim = *arg;
|
||||
case CMD_substitute: {
|
||||
const int delim = (uint8_t)(*arg);
|
||||
if (delim) {
|
||||
/* skip "from" part */
|
||||
++arg;
|
||||
arg = skip_regexp(arg, delim, p_magic, NULL);
|
||||
// Skip "from" part.
|
||||
arg++;
|
||||
arg = (const char *)skip_regexp((char_u *)arg, delim, p_magic, NULL);
|
||||
}
|
||||
/* skip "to" part */
|
||||
while (arg[0] != NUL && arg[0] != delim) {
|
||||
if (arg[0] == '\\' && arg[1] != NUL)
|
||||
++arg;
|
||||
++arg;
|
||||
// Skip "to" part.
|
||||
while (arg[0] != NUL && (uint8_t)arg[0] != delim) {
|
||||
if (arg[0] == '\\' && arg[1] != NUL) {
|
||||
arg++;
|
||||
}
|
||||
arg++;
|
||||
}
|
||||
if (arg[0] != NUL) /* skip delimiter */
|
||||
++arg;
|
||||
while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL)
|
||||
++arg;
|
||||
if (arg[0] != NUL)
|
||||
if (arg[0] != NUL) { // Skip delimiter.
|
||||
arg++;
|
||||
}
|
||||
while (arg[0] && strchr("|\"#", arg[0]) == NULL) {
|
||||
arg++;
|
||||
}
|
||||
if (arg[0] != NUL) {
|
||||
return arg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CMD_isearch:
|
||||
case CMD_dsearch:
|
||||
case CMD_ilist:
|
||||
@ -3137,36 +3153,40 @@ set_one_cmd_context (
|
||||
case CMD_djump:
|
||||
case CMD_isplit:
|
||||
case CMD_dsplit:
|
||||
arg = skipwhite(skipdigits(arg)); /* skip count */
|
||||
if (*arg == '/') { /* Match regexp, not just whole words */
|
||||
for (++arg; *arg && *arg != '/'; arg++)
|
||||
if (*arg == '\\' && arg[1] != NUL)
|
||||
// Skip count.
|
||||
arg = (const char *)skipwhite(skipdigits((const char_u *)arg));
|
||||
if (*arg == '/') { // Match regexp, not just whole words.
|
||||
for (++arg; *arg && *arg != '/'; arg++) {
|
||||
if (*arg == '\\' && arg[1] != NUL) {
|
||||
arg++;
|
||||
}
|
||||
}
|
||||
if (*arg) {
|
||||
arg = skipwhite(arg + 1);
|
||||
arg = (const char *)skipwhite((const char_u *)arg + 1);
|
||||
|
||||
/* Check for trailing illegal characters */
|
||||
if (*arg && vim_strchr((char_u *)"|\"\n", *arg) == NULL)
|
||||
// Check for trailing illegal characters.
|
||||
if (*arg && strchr("|\"\n", *arg) == NULL) {
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
else
|
||||
} else {
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CMD_autocmd:
|
||||
return set_context_in_autocmd(xp, arg, FALSE);
|
||||
return (const char *)set_context_in_autocmd(xp, (char_u *)arg, false);
|
||||
|
||||
case CMD_doautocmd:
|
||||
case CMD_doautoall:
|
||||
return set_context_in_autocmd(xp, arg, TRUE);
|
||||
return (const char *)set_context_in_autocmd(xp, (char_u *)arg, true);
|
||||
case CMD_set:
|
||||
set_context_in_set_cmd(xp, arg, 0);
|
||||
set_context_in_set_cmd(xp, (char_u *)arg, 0);
|
||||
break;
|
||||
case CMD_setglobal:
|
||||
set_context_in_set_cmd(xp, arg, OPT_GLOBAL);
|
||||
set_context_in_set_cmd(xp, (char_u *)arg, OPT_GLOBAL);
|
||||
break;
|
||||
case CMD_setlocal:
|
||||
set_context_in_set_cmd(xp, arg, OPT_LOCAL);
|
||||
set_context_in_set_cmd(xp, (char_u *)arg, OPT_LOCAL);
|
||||
break;
|
||||
case CMD_tag:
|
||||
case CMD_stag:
|
||||
@ -3178,15 +3198,16 @@ set_one_cmd_context (
|
||||
case CMD_tjump:
|
||||
case CMD_stjump:
|
||||
case CMD_ptjump:
|
||||
if (*p_wop != NUL)
|
||||
if (*p_wop != NUL) {
|
||||
xp->xp_context = EXPAND_TAGS_LISTFILES;
|
||||
else
|
||||
} else {
|
||||
xp->xp_context = EXPAND_TAGS;
|
||||
xp->xp_pattern = arg;
|
||||
}
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
case CMD_augroup:
|
||||
xp->xp_context = EXPAND_AUGROUP;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
case CMD_syntax:
|
||||
set_context_in_syntax_cmd(xp, arg);
|
||||
@ -3203,20 +3224,21 @@ set_one_cmd_context (
|
||||
case CMD_echoerr:
|
||||
case CMD_call:
|
||||
case CMD_return:
|
||||
set_context_for_expression(xp, arg, ea.cmdidx);
|
||||
set_context_for_expression(xp, (char_u *)arg, ea.cmdidx);
|
||||
break;
|
||||
|
||||
case CMD_unlet:
|
||||
while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
|
||||
arg = xp->xp_pattern + 1;
|
||||
while ((xp->xp_pattern = (char_u *)strchr(arg, ' ')) != NULL) {
|
||||
arg = (const char *)xp->xp_pattern + 1;
|
||||
}
|
||||
xp->xp_context = EXPAND_USER_VARS;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_function:
|
||||
case CMD_delfunction:
|
||||
xp->xp_context = EXPAND_USER_FUNC;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_echohl:
|
||||
@ -3231,33 +3253,37 @@ set_one_cmd_context (
|
||||
set_context_in_cscope_cmd(xp, arg, ea.cmdidx);
|
||||
break;
|
||||
case CMD_sign:
|
||||
set_context_in_sign_cmd(xp, arg);
|
||||
set_context_in_sign_cmd(xp, (char_u *)arg);
|
||||
break;
|
||||
case CMD_bdelete:
|
||||
case CMD_bwipeout:
|
||||
case CMD_bunload:
|
||||
while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
|
||||
arg = xp->xp_pattern + 1;
|
||||
/*FALLTHROUGH*/
|
||||
while ((xp->xp_pattern = (char_u *)strchr(arg, ' ')) != NULL) {
|
||||
arg = (const char *)xp->xp_pattern + 1;
|
||||
}
|
||||
// FALLTHROUGH
|
||||
case CMD_buffer:
|
||||
case CMD_sbuffer:
|
||||
case CMD_checktime:
|
||||
xp->xp_context = EXPAND_BUFFERS;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
case CMD_USER:
|
||||
case CMD_USER_BUF:
|
||||
if (compl != EXPAND_NOTHING) {
|
||||
/* XFILE: file names are handled above */
|
||||
if (context != EXPAND_NOTHING) {
|
||||
// XFILE: file names are handled above.
|
||||
if (!(ea.argt & XFILE)) {
|
||||
if (compl == EXPAND_MENUS)
|
||||
return set_context_in_menu_cmd(xp, cmd, arg, forceit);
|
||||
if (compl == EXPAND_COMMANDS)
|
||||
if (context == EXPAND_MENUS) {
|
||||
return (const char *)set_context_in_menu_cmd(xp, (char_u *)cmd,
|
||||
(char_u *)arg, forceit);
|
||||
} else if (context == EXPAND_COMMANDS) {
|
||||
return arg;
|
||||
if (compl == EXPAND_MAPPINGS)
|
||||
return set_context_in_map_cmd(xp, (char_u *)"map",
|
||||
arg, forceit, FALSE, FALSE, CMD_map);
|
||||
/* Find start of last argument. */
|
||||
} else if (context == EXPAND_MAPPINGS) {
|
||||
return (const char *)set_context_in_map_cmd(
|
||||
xp, (char_u *)"map", (char_u *)arg, forceit, false, false,
|
||||
CMD_map);
|
||||
}
|
||||
// Find start of last argument.
|
||||
p = arg;
|
||||
while (*p) {
|
||||
if (*p == ' ')
|
||||
@ -3267,9 +3293,9 @@ set_one_cmd_context (
|
||||
++p; /* skip over escaped character */
|
||||
mb_ptr_adv(p);
|
||||
}
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
}
|
||||
xp->xp_context = compl;
|
||||
xp->xp_context = context;
|
||||
}
|
||||
break;
|
||||
case CMD_map: case CMD_noremap:
|
||||
@ -3281,8 +3307,8 @@ set_one_cmd_context (
|
||||
case CMD_lmap: case CMD_lnoremap:
|
||||
case CMD_smap: case CMD_snoremap:
|
||||
case CMD_xmap: case CMD_xnoremap:
|
||||
return set_context_in_map_cmd(xp, cmd, arg, forceit,
|
||||
FALSE, FALSE, ea.cmdidx);
|
||||
return (const char *)set_context_in_map_cmd(
|
||||
xp, (char_u *)cmd, (char_u *)arg, forceit, false, false, ea.cmdidx);
|
||||
case CMD_unmap:
|
||||
case CMD_nunmap:
|
||||
case CMD_vunmap:
|
||||
@ -3292,18 +3318,18 @@ set_one_cmd_context (
|
||||
case CMD_lunmap:
|
||||
case CMD_sunmap:
|
||||
case CMD_xunmap:
|
||||
return set_context_in_map_cmd(xp, cmd, arg, forceit,
|
||||
FALSE, TRUE, ea.cmdidx);
|
||||
return (const char *)set_context_in_map_cmd(
|
||||
xp, (char_u *)cmd, (char_u *)arg, forceit, false, true, ea.cmdidx);
|
||||
case CMD_abbreviate: case CMD_noreabbrev:
|
||||
case CMD_cabbrev: case CMD_cnoreabbrev:
|
||||
case CMD_iabbrev: case CMD_inoreabbrev:
|
||||
return set_context_in_map_cmd(xp, cmd, arg, forceit,
|
||||
TRUE, FALSE, ea.cmdidx);
|
||||
return (const char *)set_context_in_map_cmd(
|
||||
xp, (char_u *)cmd, (char_u *)arg, forceit, true, false, ea.cmdidx);
|
||||
case CMD_unabbreviate:
|
||||
case CMD_cunabbrev:
|
||||
case CMD_iunabbrev:
|
||||
return set_context_in_map_cmd(xp, cmd, arg, forceit,
|
||||
TRUE, TRUE, ea.cmdidx);
|
||||
return (const char *)set_context_in_map_cmd(
|
||||
xp, (char_u *)cmd, (char_u *)arg, forceit, true, true, ea.cmdidx);
|
||||
case CMD_menu: case CMD_noremenu: case CMD_unmenu:
|
||||
case CMD_amenu: case CMD_anoremenu: case CMD_aunmenu:
|
||||
case CMD_nmenu: case CMD_nnoremenu: case CMD_nunmenu:
|
||||
@ -3313,47 +3339,49 @@ set_one_cmd_context (
|
||||
case CMD_cmenu: case CMD_cnoremenu: case CMD_cunmenu:
|
||||
case CMD_tmenu: case CMD_tunmenu:
|
||||
case CMD_popup: case CMD_emenu:
|
||||
return set_context_in_menu_cmd(xp, cmd, arg, forceit);
|
||||
return (const char *)set_context_in_menu_cmd(
|
||||
xp, (char_u *)cmd, (char_u *)arg, forceit);
|
||||
|
||||
case CMD_colorscheme:
|
||||
xp->xp_context = EXPAND_COLORS;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_compiler:
|
||||
xp->xp_context = EXPAND_COMPILER;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_ownsyntax:
|
||||
xp->xp_context = EXPAND_OWNSYNTAX;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_setfiletype:
|
||||
xp->xp_context = EXPAND_FILETYPE;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_packadd:
|
||||
xp->xp_context = EXPAND_PACKADD;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
#ifdef HAVE_WORKING_LIBINTL
|
||||
case CMD_language:
|
||||
p = skiptowhite(arg);
|
||||
p = (const char *)skiptowhite((const char_u *)arg);
|
||||
if (*p == NUL) {
|
||||
xp->xp_context = EXPAND_LANGUAGE;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
} else {
|
||||
if ( STRNCMP(arg, "messages", p - arg) == 0
|
||||
|| STRNCMP(arg, "ctype", p - arg) == 0
|
||||
|| STRNCMP(arg, "time", p - arg) == 0) {
|
||||
if (strncmp(arg, "messages", p - arg) == 0
|
||||
|| strncmp(arg, "ctype", p - arg) == 0
|
||||
|| strncmp(arg, "time", p - arg) == 0) {
|
||||
xp->xp_context = EXPAND_LOCALES;
|
||||
xp->xp_pattern = skipwhite(p);
|
||||
} else
|
||||
xp->xp_pattern = skipwhite((const char_u *)p);
|
||||
} else {
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@ -3362,16 +3390,16 @@ set_one_cmd_context (
|
||||
break;
|
||||
case CMD_behave:
|
||||
xp->xp_context = EXPAND_BEHAVE;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_history:
|
||||
xp->xp_context = EXPAND_HISTORY;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
case CMD_syntime:
|
||||
xp->xp_context = EXPAND_SYNTIME;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
|
||||
@ -3390,10 +3418,9 @@ set_one_cmd_context (
|
||||
* Also skip white space and ":" characters.
|
||||
* Returns the "cmd" pointer advanced to beyond the range.
|
||||
*/
|
||||
char_u *
|
||||
skip_range (
|
||||
char_u *cmd,
|
||||
int *ctx /* pointer to xp_context or NULL */
|
||||
char_u *skip_range(
|
||||
const char_u *cmd,
|
||||
int *ctx // pointer to xp_context or NULL
|
||||
)
|
||||
{
|
||||
unsigned delim;
|
||||
@ -3418,7 +3445,7 @@ skip_range (
|
||||
while (*cmd == ':')
|
||||
cmd = skipwhite(cmd + 1);
|
||||
|
||||
return cmd;
|
||||
return (char_u *)cmd;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4585,14 +4612,15 @@ int ends_excmd(int c) FUNC_ATTR_CONST
|
||||
* Return the next command, after the first '|' or '\n'.
|
||||
* Return NULL if not found.
|
||||
*/
|
||||
char_u *find_nextcmd(char_u *p)
|
||||
char_u *find_nextcmd(const char_u *p)
|
||||
{
|
||||
while (*p != '|' && *p != '\n') {
|
||||
if (*p == NUL)
|
||||
if (*p == NUL) {
|
||||
return NULL;
|
||||
++p;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return p + 1;
|
||||
return (char_u *)p + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -6794,7 +6822,7 @@ do_exedit (
|
||||
int ms = msg_scroll;
|
||||
|
||||
if (eap->nextcmd != NULL) {
|
||||
stuffReadbuff(eap->nextcmd);
|
||||
stuffReadbuff((const char *)eap->nextcmd);
|
||||
eap->nextcmd = NULL;
|
||||
}
|
||||
|
||||
@ -7724,7 +7752,7 @@ static void ex_mkrc(exarg_T *eap)
|
||||
|
||||
/* When using 'viewdir' may have to create the directory. */
|
||||
if (using_vdir && !os_isdir(p_vdir)) {
|
||||
vim_mkdir_emsg(p_vdir, 0755);
|
||||
vim_mkdir_emsg((const char *)p_vdir, 0755);
|
||||
}
|
||||
|
||||
fd = open_exfile((char_u *) fname, eap->forceit, WRITEBIN);
|
||||
@ -7836,10 +7864,17 @@ static void ex_mkrc(exarg_T *eap)
|
||||
xfree(viewFile);
|
||||
}
|
||||
|
||||
int vim_mkdir_emsg(char_u *name, int prot)
|
||||
/// Try creating a directory, give error message on failure
|
||||
///
|
||||
/// @param[in] name Directory to create.
|
||||
/// @param[in] prot Directory permissions.
|
||||
///
|
||||
/// @return OK in case of success, FAIL otherwise.
|
||||
int vim_mkdir_emsg(const char *const name, const int prot)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
int ret;
|
||||
if ((ret = os_mkdir((char *)name, prot)) != 0) {
|
||||
if ((ret = os_mkdir(name, prot)) != 0) {
|
||||
EMSG3(_(e_mkdir), name, os_strerror(ret));
|
||||
return FAIL;
|
||||
}
|
||||
@ -8416,8 +8451,8 @@ eval_vars (
|
||||
*usedlen = 1;
|
||||
return NULL;
|
||||
}
|
||||
result = list_find_str(get_vim_var_list(VV_OLDFILES),
|
||||
(long)i);
|
||||
result = (char_u *)tv_list_find_str(get_vim_var_list(VV_OLDFILES),
|
||||
i - 1);
|
||||
if (result == NULL) {
|
||||
*errormsg = (char_u *)"";
|
||||
return NULL;
|
||||
@ -9347,8 +9382,8 @@ static int ses_put_fname(FILE *fd, char_u *name, unsigned *flagp)
|
||||
*p = '/';
|
||||
}
|
||||
|
||||
/* escape special characters */
|
||||
p = vim_strsave_fnameescape(sname, FALSE);
|
||||
// Escape special characters.
|
||||
p = (char_u *)vim_strsave_fnameescape((const char *)sname, false);
|
||||
xfree(sname);
|
||||
|
||||
/* write the result */
|
||||
@ -9483,18 +9518,18 @@ void dialog_msg(char_u *buff, char *format, char_u *fname)
|
||||
static void ex_behave(exarg_T *eap)
|
||||
{
|
||||
if (STRCMP(eap->arg, "mswin") == 0) {
|
||||
set_option_value((char_u *)"selection", 0L, (char_u *)"exclusive", 0);
|
||||
set_option_value((char_u *)"selectmode", 0L, (char_u *)"mouse,key", 0);
|
||||
set_option_value((char_u *)"mousemodel", 0L, (char_u *)"popup", 0);
|
||||
set_option_value((char_u *)"keymodel", 0L,
|
||||
(char_u *)"startsel,stopsel", 0);
|
||||
set_option_value("selection", 0L, "exclusive", 0);
|
||||
set_option_value("selectmode", 0L, "mouse,key", 0);
|
||||
set_option_value("mousemodel", 0L, "popup", 0);
|
||||
set_option_value("keymodel", 0L, "startsel,stopsel", 0);
|
||||
} else if (STRCMP(eap->arg, "xterm") == 0) {
|
||||
set_option_value((char_u *)"selection", 0L, (char_u *)"inclusive", 0);
|
||||
set_option_value((char_u *)"selectmode", 0L, (char_u *)"", 0);
|
||||
set_option_value((char_u *)"mousemodel", 0L, (char_u *)"extend", 0);
|
||||
set_option_value((char_u *)"keymodel", 0L, (char_u *)"", 0);
|
||||
} else
|
||||
set_option_value("selection", 0L, "inclusive", 0);
|
||||
set_option_value("selectmode", 0L, "", 0);
|
||||
set_option_value("mousemodel", 0L, "extend", 0);
|
||||
set_option_value("keymodel", 0L, "", 0);
|
||||
} else {
|
||||
EMSG2(_(e_invarg2), eap->arg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -9608,8 +9643,9 @@ void filetype_maybe_enable(void)
|
||||
*/
|
||||
static void ex_setfiletype(exarg_T *eap)
|
||||
{
|
||||
if (!did_filetype)
|
||||
set_option_value((char_u *)"filetype", 0L, eap->arg, OPT_LOCAL);
|
||||
if (!did_filetype) {
|
||||
set_option_value("filetype", 0L, (char *)eap->arg, OPT_LOCAL);
|
||||
}
|
||||
}
|
||||
|
||||
static void ex_digraphs(exarg_T *eap)
|
||||
@ -9695,7 +9731,8 @@ static void ex_match(exarg_T *eap)
|
||||
|
||||
c = *end;
|
||||
*end = NUL;
|
||||
match_add(curwin, g, p + 1, 10, id, NULL, NULL);
|
||||
match_add(curwin, (const char *)g, (const char *)p + 1, 10, id,
|
||||
NULL, NULL);
|
||||
xfree(g);
|
||||
*end = c;
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
/*
|
||||
* ex_eval.c: functions for Ex command line for the +eval feature.
|
||||
*/
|
||||
// TODO(ZyX-I): move to eval/executor
|
||||
|
||||
/// @file ex_eval.c
|
||||
///
|
||||
/// Functions for Ex command line for the +eval feature.
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
@ -12,6 +14,7 @@
|
||||
#include "nvim/ex_eval.h"
|
||||
#include "nvim/charset.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/ex_cmds2.h"
|
||||
#include "nvim/ex_docmd.h"
|
||||
#include "nvim/message.h"
|
||||
@ -19,8 +22,6 @@
|
||||
#include "nvim/regexp.h"
|
||||
#include "nvim/strings.h"
|
||||
|
||||
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "ex_eval.c.generated.h"
|
||||
#endif
|
||||
@ -57,12 +58,14 @@
|
||||
* is an error exception.) - The macros can be defined as expressions checking
|
||||
* for a variable that is allowed to be changed during execution of a script.
|
||||
*/
|
||||
/* Values used for the Vim release. */
|
||||
# define THROW_ON_ERROR TRUE
|
||||
# define THROW_ON_ERROR_TRUE
|
||||
# define THROW_ON_INTERRUPT TRUE
|
||||
# define THROW_ON_INTERRUPT_TRUE
|
||||
|
||||
// Values used for the Vim release.
|
||||
#define THROW_ON_ERROR true
|
||||
#define THROW_ON_ERROR_TRUE
|
||||
#define THROW_ON_INTERRUPT true
|
||||
#define THROW_ON_INTERRUPT_TRUE
|
||||
|
||||
#define discard_pending_return(p) tv_free((typval_T *)(p))
|
||||
|
||||
/*
|
||||
* When several errors appear in a row, setting "force_abort" is delayed until
|
||||
@ -779,7 +782,6 @@ void report_discard_pending(int pending, void *value)
|
||||
*/
|
||||
void ex_if(exarg_T *eap)
|
||||
{
|
||||
int error;
|
||||
int skip;
|
||||
int result;
|
||||
struct condstack *cstack = eap->cstack;
|
||||
@ -800,6 +802,7 @@ void ex_if(exarg_T *eap)
|
||||
1] &
|
||||
CSF_ACTIVE));
|
||||
|
||||
bool error;
|
||||
result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
|
||||
|
||||
if (!skip && !error) {
|
||||
@ -844,7 +847,6 @@ void ex_endif(exarg_T *eap)
|
||||
*/
|
||||
void ex_else(exarg_T *eap)
|
||||
{
|
||||
int error;
|
||||
int skip;
|
||||
int result;
|
||||
struct condstack *cstack = eap->cstack;
|
||||
@ -901,6 +903,7 @@ void ex_else(exarg_T *eap)
|
||||
}
|
||||
|
||||
if (eap->cmdidx == CMD_elseif) {
|
||||
bool error;
|
||||
result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
|
||||
/* When throwing error exceptions, we want to throw always the first
|
||||
* of several errors in a row. This is what actually happens when
|
||||
@ -925,7 +928,7 @@ void ex_else(exarg_T *eap)
|
||||
*/
|
||||
void ex_while(exarg_T *eap)
|
||||
{
|
||||
int error;
|
||||
bool error;
|
||||
int skip;
|
||||
int result;
|
||||
struct condstack *cstack = eap->cstack;
|
||||
@ -1147,23 +1150,25 @@ void ex_endwhile(exarg_T *eap)
|
||||
*/
|
||||
void ex_throw(exarg_T *eap)
|
||||
{
|
||||
char_u *arg = eap->arg;
|
||||
char_u *value;
|
||||
const char *arg = (const char *)eap->arg;
|
||||
char *value;
|
||||
|
||||
if (*arg != NUL && *arg != '|' && *arg != '\n')
|
||||
value = eval_to_string_skip(arg, &eap->nextcmd, eap->skip);
|
||||
else {
|
||||
if (*arg != NUL && *arg != '|' && *arg != '\n') {
|
||||
value = eval_to_string_skip(arg, (const char **)&eap->nextcmd,
|
||||
(bool)eap->skip);
|
||||
} else {
|
||||
EMSG(_(e_argreq));
|
||||
value = NULL;
|
||||
}
|
||||
|
||||
/* On error or when an exception is thrown during argument evaluation, do
|
||||
* not throw. */
|
||||
// On error or when an exception is thrown during argument evaluation, do
|
||||
// not throw.
|
||||
if (!eap->skip && value != NULL) {
|
||||
if (throw_exception(value, ET_USER, NULL) == FAIL)
|
||||
if (throw_exception((char_u *)value, ET_USER, NULL) == FAIL) {
|
||||
xfree(value);
|
||||
else
|
||||
} else {
|
||||
do_throw(eap->cstack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "nvim/assert.h"
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/arabic.h"
|
||||
@ -578,7 +579,7 @@ static int command_line_execute(VimState *state, int key)
|
||||
}
|
||||
if (vim_ispathsep(ccline.cmdbuff[s->j])
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
&& vim_strchr(" *?[{`$%#", ccline.cmdbuff[s->j + 1])
|
||||
&& strchr(" *?[{`$%#", ccline.cmdbuff[s->j + 1])
|
||||
== NULL
|
||||
#endif
|
||||
) {
|
||||
@ -960,7 +961,7 @@ static int command_line_handle_key(CommandLineState *s)
|
||||
return command_line_not_changed(s);
|
||||
|
||||
case Ctrl_HAT:
|
||||
if (map_to_exists_mode((char_u *)"", LANGMAP, false)) {
|
||||
if (map_to_exists_mode("", LANGMAP, false)) {
|
||||
// ":lmap" mappings exists, toggle use of mappings.
|
||||
State ^= LANGMAP;
|
||||
if (s->b_im_ptr != NULL) {
|
||||
@ -2553,19 +2554,22 @@ void cmdline_paste_str(char_u *s, int literally)
|
||||
else
|
||||
while (*s != NUL) {
|
||||
cv = *s;
|
||||
if (cv == Ctrl_V && s[1])
|
||||
++s;
|
||||
if (has_mbyte)
|
||||
c = mb_cptr2char_adv(&s);
|
||||
else
|
||||
if (cv == Ctrl_V && s[1]) {
|
||||
s++;
|
||||
}
|
||||
if (has_mbyte) {
|
||||
c = mb_cptr2char_adv((const char_u **)&s);
|
||||
} else {
|
||||
c = *s++;
|
||||
}
|
||||
if (cv == Ctrl_V || c == ESC || c == Ctrl_C
|
||||
|| c == CAR || c == NL || c == Ctrl_L
|
||||
#ifdef UNIX
|
||||
|| c == intr_char
|
||||
#endif
|
||||
|| (c == Ctrl_BSL && *s == Ctrl_N))
|
||||
|| (c == Ctrl_BSL && *s == Ctrl_N)) {
|
||||
stuffcharReadbuff(Ctrl_V);
|
||||
}
|
||||
stuffcharReadbuff(c);
|
||||
}
|
||||
}
|
||||
@ -3120,9 +3124,10 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o
|
||||
#endif
|
||||
}
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
p = vim_strsave_fnameescape(files[i], FALSE);
|
||||
p = (char_u *)vim_strsave_fnameescape((const char *)files[i], false);
|
||||
#else
|
||||
p = vim_strsave_fnameescape(files[i], xp->xp_shell);
|
||||
p = (char_u *)vim_strsave_fnameescape((const char *)files[i],
|
||||
xp->xp_shell);
|
||||
#endif
|
||||
xfree(files[i]);
|
||||
files[i] = p;
|
||||
@ -3152,42 +3157,49 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Escape special characters in "fname" for when used as a file name argument
|
||||
* after a Vim command, or, when "shell" is non-zero, a shell command.
|
||||
* Returns the result in allocated memory.
|
||||
*/
|
||||
char_u *vim_strsave_fnameescape(char_u *fname, int shell) FUNC_ATTR_NONNULL_RET
|
||||
/// Escape special characters in a file name for use as a command argument
|
||||
///
|
||||
/// @param[in] fname File name to escape.
|
||||
/// @param[in] shell What to escape for: if false, escapes for VimL command,
|
||||
/// if true then it escapes for a shell command.
|
||||
///
|
||||
/// @return [allocated] escaped file name.
|
||||
char *vim_strsave_fnameescape(const char *const fname, const bool shell)
|
||||
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
char_u *p;
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
#define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`%#'\"|!<")
|
||||
char_u buf[20];
|
||||
#define PATH_ESC_CHARS " \t\n*?[{`%#'\"|!<"
|
||||
char_u buf[sizeof(PATH_ESC_CHARS)];
|
||||
int j = 0;
|
||||
|
||||
/* Don't escape '[', '{' and '!' if they are in 'isfname'. */
|
||||
for (p = PATH_ESC_CHARS; *p != NUL; ++p)
|
||||
if ((*p != '[' && *p != '{' && *p != '!') || !vim_isfilec(*p))
|
||||
buf[j++] = *p;
|
||||
// Don't escape '[', '{' and '!' if they are in 'isfname'.
|
||||
for (const char *s = PATH_ESC_CHARS; *s != NUL; s++) {
|
||||
if ((*s != '[' && *s != '{' && *s != '!') || !vim_isfilec(*s)) {
|
||||
buf[j++] = *s;
|
||||
}
|
||||
}
|
||||
buf[j] = NUL;
|
||||
p = vim_strsave_escaped(fname, buf);
|
||||
char *p = (char *)vim_strsave_escaped((const char_u *)fname,
|
||||
(const char_u *)buf);
|
||||
#else
|
||||
#define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<")
|
||||
#define SHELL_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<>();&")
|
||||
p = vim_strsave_escaped(fname, shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS);
|
||||
char *p = (char *)vim_strsave_escaped(
|
||||
(const char_u *)fname, (shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS));
|
||||
if (shell && csh_like_shell()) {
|
||||
/* For csh and similar shells need to put two backslashes before '!'.
|
||||
* One is taken by Vim, one by the shell. */
|
||||
char_u *s = vim_strsave_escaped(p, (char_u *)"!");
|
||||
// For csh and similar shells need to put two backslashes before '!'.
|
||||
// One is taken by Vim, one by the shell.
|
||||
char *s = (char *)vim_strsave_escaped((const char_u *)p,
|
||||
(const char_u *)"!");
|
||||
xfree(p);
|
||||
p = s;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* '>' and '+' are special at the start of some commands, e.g. ":edit" and
|
||||
* ":write". "cd -" has a special meaning. */
|
||||
// '>' and '+' are special at the start of some commands, e.g. ":edit" and
|
||||
// ":write". "cd -" has a special meaning.
|
||||
if (*p == '>' || *p == '+' || (*p == '-' && p[1] == NUL)) {
|
||||
escape_fname(&p);
|
||||
escape_fname((char_u **)&p);
|
||||
}
|
||||
|
||||
return p;
|
||||
@ -3624,7 +3636,6 @@ set_cmd_context (
|
||||
)
|
||||
{
|
||||
int old_char = NUL;
|
||||
char_u *nextcomm;
|
||||
|
||||
/*
|
||||
* Avoid a UMR warning from Purify, only save the character if it has been
|
||||
@ -3633,7 +3644,7 @@ set_cmd_context (
|
||||
if (col < len)
|
||||
old_char = str[col];
|
||||
str[col] = NUL;
|
||||
nextcomm = str;
|
||||
const char *nextcomm = (const char *)str;
|
||||
|
||||
if (use_ccline && ccline.cmdfirstc == '=') {
|
||||
// pass CMD_SIZE because there is no real command
|
||||
@ -3642,9 +3653,11 @@ set_cmd_context (
|
||||
xp->xp_context = ccline.xp_context;
|
||||
xp->xp_pattern = ccline.cmdbuff;
|
||||
xp->xp_arg = ccline.xp_arg;
|
||||
} else
|
||||
while (nextcomm != NULL)
|
||||
} else {
|
||||
while (nextcomm != NULL) {
|
||||
nextcomm = set_one_cmd_context(xp, nextcomm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Store the string here so that call_user_expand_func() can get to them
|
||||
* easily. */
|
||||
@ -4197,9 +4210,11 @@ static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file,
|
||||
char_u keep;
|
||||
garray_T ga;
|
||||
|
||||
retstr = call_user_expand_func(call_func_retstr, xp, num_file, file);
|
||||
if (retstr == NULL)
|
||||
retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp,
|
||||
num_file, file);
|
||||
if (retstr == NULL) {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
ga_init(&ga, (int)sizeof(char *), 3);
|
||||
for (s = retstr; *s != NUL; s = e) {
|
||||
@ -4237,9 +4252,11 @@ static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file)
|
||||
listitem_T *li;
|
||||
garray_T ga;
|
||||
|
||||
retlist = call_user_expand_func(call_func_retlist, xp, num_file, file);
|
||||
if (retlist == NULL)
|
||||
retlist = call_user_expand_func((user_expand_func_T)call_func_retlist, xp,
|
||||
num_file, file);
|
||||
if (retlist == NULL) {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
ga_init(&ga, (int)sizeof(char *), 3);
|
||||
/* Loop over the items in the list. */
|
||||
@ -4249,7 +4266,7 @@ static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file)
|
||||
|
||||
GA_APPEND(char_u *, &ga, vim_strsave(li->li_tv.vval.v_string));
|
||||
}
|
||||
list_unref(retlist);
|
||||
tv_list_unref(retlist);
|
||||
|
||||
*file = ga.ga_data;
|
||||
*num_file = ga.ga_len;
|
||||
@ -4545,7 +4562,7 @@ static inline void hist_free_entry(histentry_T *hisptr)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
xfree(hisptr->hisstr);
|
||||
list_unref(hisptr->additional_elements);
|
||||
tv_list_unref(hisptr->additional_elements);
|
||||
clear_hist_entry(hisptr);
|
||||
}
|
||||
|
||||
@ -4601,7 +4618,7 @@ in_history (
|
||||
history[type][last_i] = history[type][i];
|
||||
last_i = i;
|
||||
}
|
||||
list_unref(list);
|
||||
tv_list_unref(list);
|
||||
history[type][i].hisnum = ++hisnum[type];
|
||||
history[type][i].hisstr = str;
|
||||
history[type][i].timestamp = os_time();
|
||||
@ -4623,7 +4640,7 @@ in_history (
|
||||
///
|
||||
/// @return Any value from HistoryType enum, including HIST_INVALID. May not
|
||||
/// return HIST_DEFAULT unless return_default is true.
|
||||
HistoryType get_histtype(const char_u *const name, const size_t len,
|
||||
HistoryType get_histtype(const char *const name, const size_t len,
|
||||
const bool return_default)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
@ -5016,7 +5033,7 @@ void ex_history(exarg_T *eap)
|
||||
while (ASCII_ISALPHA(*end)
|
||||
|| vim_strchr((char_u *)":=@>/?", *end) != NULL)
|
||||
end++;
|
||||
histype1 = get_histtype(arg, end - arg, false);
|
||||
histype1 = get_histtype((const char *)arg, end - arg, false);
|
||||
if (histype1 == HIST_INVALID) {
|
||||
if (STRNICMP(arg, "all", end - arg) == 0) {
|
||||
histype1 = 0;
|
||||
@ -5173,7 +5190,7 @@ static int ex_window(void)
|
||||
// Create empty command-line buffer.
|
||||
buf_open_scratch(0, "[Command Line]");
|
||||
// Command-line buffer has bufhidden=wipe, unlike a true "scratch" buffer.
|
||||
set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL);
|
||||
set_option_value("bh", 0L, "wipe", OPT_LOCAL);
|
||||
curwin->w_p_rl = cmdmsg_rl;
|
||||
cmdmsg_rl = false;
|
||||
curbuf->b_p_ma = true;
|
||||
@ -5191,7 +5208,7 @@ static int ex_window(void)
|
||||
add_map((char_u *)"<buffer> <Tab> <C-X><C-V>", INSERT);
|
||||
add_map((char_u *)"<buffer> <Tab> a<C-X><C-V>", NORMAL);
|
||||
}
|
||||
set_option_value((char_u *)"ft", 0L, (char_u *)"vim", OPT_LOCAL);
|
||||
set_option_value("ft", 0L, "vim", OPT_LOCAL);
|
||||
}
|
||||
|
||||
/* Reset 'textwidth' after setting 'filetype' (the Vim filetype plugin
|
||||
@ -5275,18 +5292,18 @@ static int ex_window(void)
|
||||
cmdwin_result = Ctrl_C;
|
||||
/* Set the new command line from the cmdline buffer. */
|
||||
xfree(ccline.cmdbuff);
|
||||
if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { /* :qa[!] typed */
|
||||
char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!";
|
||||
if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { // :qa[!] typed
|
||||
const char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!";
|
||||
|
||||
if (histtype == HIST_CMD) {
|
||||
/* Execute the command directly. */
|
||||
ccline.cmdbuff = vim_strsave((char_u *)p);
|
||||
// Execute the command directly.
|
||||
ccline.cmdbuff = (char_u *)xstrdup(p);
|
||||
cmdwin_result = CAR;
|
||||
} else {
|
||||
/* First need to cancel what we were doing. */
|
||||
// First need to cancel what we were doing.
|
||||
ccline.cmdbuff = NULL;
|
||||
stuffcharReadbuff(':');
|
||||
stuffReadbuff((char_u *)p);
|
||||
stuffReadbuff(p);
|
||||
stuffcharReadbuff(CAR);
|
||||
}
|
||||
} else if (cmdwin_result == K_XF2) { /* :qa typed */
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef NVIM_EX_GETLN_H
|
||||
#define NVIM_EX_GETLN_H
|
||||
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/ex_cmds.h"
|
||||
|
||||
/* Values for nextwild() and ExpandOne(). See ExpandOne() for meaning. */
|
||||
|
@ -322,8 +322,11 @@ vim_findfile_init (
|
||||
drive[0] = path[0];
|
||||
drive[1] = ':';
|
||||
drive[2] = NUL;
|
||||
if (vim_FullName(drive, ff_expand_buffer, MAXPATHL, TRUE) == FAIL)
|
||||
if (vim_FullName((const char *)drive, (char *)ff_expand_buffer, MAXPATHL,
|
||||
true)
|
||||
== FAIL) {
|
||||
goto error_return;
|
||||
}
|
||||
path += 2;
|
||||
} else
|
||||
#endif
|
||||
@ -1549,14 +1552,14 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope)
|
||||
assert(false);
|
||||
}
|
||||
|
||||
dict_add_nr_str(dict, "scope", 0L, (char_u *)buf);
|
||||
dict_add_nr_str(dict, "cwd", 0L, (char_u *)new_dir);
|
||||
dict_set_keys_readonly(dict);
|
||||
tv_dict_add_str(dict, S_LEN("scope"), buf);
|
||||
tv_dict_add_str(dict, S_LEN("cwd"), new_dir);
|
||||
tv_dict_set_keys_readonly(dict);
|
||||
|
||||
apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, (char_u *)new_dir, false,
|
||||
NULL);
|
||||
|
||||
dict_clear(dict);
|
||||
tv_dict_clear(dict);
|
||||
|
||||
recursive = false;
|
||||
}
|
||||
|
@ -428,7 +428,7 @@ readfile (
|
||||
}
|
||||
|
||||
if (!read_buffer && !read_stdin) {
|
||||
perm = os_getperm(fname);
|
||||
perm = os_getperm((const char *)fname);
|
||||
#ifdef UNIX
|
||||
// On Unix it is possible to read a directory, so we have to
|
||||
// check for it before os_open().
|
||||
@ -614,10 +614,12 @@ readfile (
|
||||
return FAIL;
|
||||
}
|
||||
#ifdef UNIX
|
||||
/* Set swap file protection bits after creating it. */
|
||||
// Set swap file protection bits after creating it.
|
||||
if (swap_mode > 0 && curbuf->b_ml.ml_mfp != NULL
|
||||
&& curbuf->b_ml.ml_mfp->mf_fname != NULL)
|
||||
(void)os_setperm(curbuf->b_ml.ml_mfp->mf_fname, (long)swap_mode);
|
||||
&& curbuf->b_ml.ml_mfp->mf_fname != NULL) {
|
||||
(void)os_setperm((const char *)curbuf->b_ml.ml_mfp->mf_fname,
|
||||
(long)swap_mode);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2606,10 +2608,10 @@ buf_write (
|
||||
newfile = TRUE;
|
||||
perm = -1;
|
||||
} else {
|
||||
perm = os_getperm(fname);
|
||||
if (perm < 0)
|
||||
newfile = TRUE;
|
||||
else if (os_isdir(fname)) {
|
||||
perm = os_getperm((const char *)fname);
|
||||
if (perm < 0) {
|
||||
newfile = true;
|
||||
} else if (os_isdir(fname)) {
|
||||
errnum = (char_u *)"E502: ";
|
||||
errmsg = (char_u *)_("is a directory");
|
||||
goto fail;
|
||||
@ -2870,9 +2872,9 @@ buf_write (
|
||||
xfree(backup);
|
||||
backup = NULL;
|
||||
} else {
|
||||
/* set file protection same as original file, but
|
||||
* strip s-bit */
|
||||
(void)os_setperm(backup, perm & 0777);
|
||||
// set file protection same as original file, but
|
||||
// strip s-bit.
|
||||
(void)os_setperm((const char *)backup, perm & 0777);
|
||||
|
||||
#ifdef UNIX
|
||||
/*
|
||||
@ -2883,7 +2885,8 @@ buf_write (
|
||||
*/
|
||||
if (file_info_new.stat.st_gid != file_info_old.stat.st_gid
|
||||
&& os_fchown(bfd, -1, file_info_old.stat.st_gid) != 0) {
|
||||
os_setperm(backup, (perm & 0707) | ((perm & 07) << 3));
|
||||
os_setperm((const char *)backup,
|
||||
(perm & 0707) | ((perm & 07) << 3));
|
||||
}
|
||||
# ifdef HAVE_SELINUX
|
||||
mch_copy_sec(fname, backup);
|
||||
@ -3037,8 +3040,8 @@ nobackup:
|
||||
&& file_info_old.stat.st_uid == getuid()
|
||||
&& vim_strchr(p_cpo, CPO_FWRITE) == NULL) {
|
||||
perm |= 0200;
|
||||
(void)os_setperm(fname, perm);
|
||||
made_writable = TRUE;
|
||||
(void)os_setperm((const char *)fname, perm);
|
||||
made_writable = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -3402,8 +3405,9 @@ restore_backup:
|
||||
|| file_info.stat.st_uid != file_info_old.stat.st_uid
|
||||
|| file_info.stat.st_gid != file_info_old.stat.st_gid) {
|
||||
os_fchown(fd, file_info_old.stat.st_uid, file_info_old.stat.st_gid);
|
||||
if (perm >= 0) /* set permission again, may have changed */
|
||||
(void)os_setperm(wfname, perm);
|
||||
if (perm >= 0) { // Set permission again, may have changed.
|
||||
(void)os_setperm((const char *)wfname, perm);
|
||||
}
|
||||
}
|
||||
buf_set_file_id(buf);
|
||||
} else if (!buf->file_id_valid) {
|
||||
@ -3421,8 +3425,9 @@ restore_backup:
|
||||
if (made_writable)
|
||||
perm &= ~0200; /* reset 'w' bit for security reasons */
|
||||
#endif
|
||||
if (perm >= 0) /* set perm. of new file same as old file */
|
||||
(void)os_setperm(wfname, perm);
|
||||
if (perm >= 0) { // Set perm. of new file same as old file.
|
||||
(void)os_setperm((const char *)wfname, perm);
|
||||
}
|
||||
#ifdef HAVE_ACL
|
||||
/* Probably need to set the ACL before changing the user (can't set the
|
||||
* ACL on a file the user doesn't own). */
|
||||
@ -3628,7 +3633,7 @@ restore_backup:
|
||||
close(empty_fd);
|
||||
}
|
||||
if (org != NULL) {
|
||||
os_setperm((char_u *)org, os_getperm(fname) & 0777);
|
||||
os_setperm(org, os_getperm((const char *)fname) & 0777);
|
||||
xfree(org);
|
||||
}
|
||||
}
|
||||
@ -4548,9 +4553,9 @@ int put_time(FILE *fd, time_t time_)
|
||||
|
||||
/// os_rename() only works if both files are on the same file system, this
|
||||
/// function will (attempts to?) copy the file across if rename fails -- webb
|
||||
//
|
||||
///
|
||||
/// @return -1 for failure, 0 for success
|
||||
int vim_rename(char_u *from, char_u *to)
|
||||
int vim_rename(const char_u *from, const char_u *to)
|
||||
{
|
||||
int fd_in;
|
||||
int fd_out;
|
||||
@ -4569,10 +4574,12 @@ int vim_rename(char_u *from, char_u *to)
|
||||
* the file name differs we need to go through a temp file.
|
||||
*/
|
||||
if (fnamecmp(from, to) == 0) {
|
||||
if (p_fic && STRCMP(path_tail(from), path_tail(to)) != 0)
|
||||
if (p_fic && (STRCMP(path_tail((char_u *)from), path_tail((char_u *)to))
|
||||
!= 0)) {
|
||||
use_tmp_file = true;
|
||||
else
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
|
||||
@ -4638,9 +4645,9 @@ int vim_rename(char_u *from, char_u *to)
|
||||
/*
|
||||
* Rename() failed, try copying the file.
|
||||
*/
|
||||
perm = os_getperm(from);
|
||||
perm = os_getperm((const char *)from);
|
||||
#ifdef HAVE_ACL
|
||||
/* For systems that support ACL: get the ACL from the original file. */
|
||||
// For systems that support ACL: get the ACL from the original file.
|
||||
acl = mch_get_acl(from);
|
||||
#endif
|
||||
fd_in = os_open((char *)from, O_RDONLY, 0);
|
||||
@ -4688,8 +4695,8 @@ int vim_rename(char_u *from, char_u *to)
|
||||
errmsg = _("E210: Error reading \"%s\"");
|
||||
to = from;
|
||||
}
|
||||
#ifndef UNIX /* for Unix os_open() already set the permission */
|
||||
os_setperm(to, perm);
|
||||
#ifndef UNIX // For Unix os_open() already set the permission.
|
||||
os_setperm((const char *)to, perm);
|
||||
#endif
|
||||
#ifdef HAVE_ACL
|
||||
mch_set_acl(to, acl);
|
||||
@ -5200,7 +5207,7 @@ void forward_slash(char_u *fname)
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
if (path_with_url(fname)) {
|
||||
if (path_with_url((const char *)fname)) {
|
||||
return;
|
||||
}
|
||||
for (p = fname; *p != NUL; p++) {
|
||||
@ -5261,7 +5268,7 @@ static void vim_maketempdir(void)
|
||||
/// Delete "name" and everything in it, recursively.
|
||||
/// @param name The path which should be deleted.
|
||||
/// @return 0 for success, -1 if some file was not deleted.
|
||||
int delete_recursive(char_u *name)
|
||||
int delete_recursive(const char *name)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
@ -5275,7 +5282,7 @@ int delete_recursive(char_u *name)
|
||||
EW_DIR | EW_FILE | EW_SILENT | EW_ALLLINKS
|
||||
| EW_DODOT | EW_EMPTYOK) == OK) {
|
||||
for (int i = 0; i < file_count; i++) {
|
||||
if (delete_recursive(files[i]) != 0) {
|
||||
if (delete_recursive((const char *)files[i]) != 0) {
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
@ -5285,9 +5292,9 @@ int delete_recursive(char_u *name)
|
||||
}
|
||||
|
||||
xfree(exp);
|
||||
os_rmdir((char *)name);
|
||||
os_rmdir(name);
|
||||
} else {
|
||||
result = os_remove((char *)name) == 0 ? 0 : -1;
|
||||
result = os_remove(name) == 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -5299,7 +5306,7 @@ void vim_deltempdir(void)
|
||||
if (vim_tempdir != NULL) {
|
||||
// remove the trailing path separator
|
||||
path_tail(vim_tempdir)[-1] = NUL;
|
||||
delete_recursive(vim_tempdir);
|
||||
delete_recursive((const char *)vim_tempdir);
|
||||
xfree(vim_tempdir);
|
||||
vim_tempdir = NULL;
|
||||
}
|
||||
|
@ -235,19 +235,18 @@ char_u *get_inserted(void)
|
||||
return get_buffcont(&redobuff, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add string "s" after the current block of buffer "buf".
|
||||
* K_SPECIAL and CSI should have been escaped already.
|
||||
*/
|
||||
static void
|
||||
add_buff (
|
||||
buffheader_T *buf,
|
||||
char_u *s,
|
||||
ssize_t slen // length of "s" or -1
|
||||
)
|
||||
/// Add string after the current block of the given buffer
|
||||
///
|
||||
/// K_SPECIAL and CSI should have been escaped already.
|
||||
///
|
||||
/// @param[out] buf Buffer to add to.
|
||||
/// @param[in] s String to add.
|
||||
/// @param[in] slen String length or -1 for NUL-terminated string.
|
||||
static void add_buff(buffheader_T *const buf, const char *const s,
|
||||
ptrdiff_t slen)
|
||||
{
|
||||
if (slen < 0) {
|
||||
slen = (ssize_t)STRLEN(s);
|
||||
slen = (ptrdiff_t)strlen(s);
|
||||
}
|
||||
if (slen == 0) { // don't add empty strings
|
||||
return;
|
||||
@ -292,9 +291,8 @@ add_buff (
|
||||
*/
|
||||
static void add_num_buff(buffheader_T *buf, long n)
|
||||
{
|
||||
char_u number[32];
|
||||
|
||||
sprintf((char *)number, "%" PRId64, (int64_t)n);
|
||||
char number[32];
|
||||
snprintf(number, sizeof(number), "%ld", n);
|
||||
add_buff(buf, number, -1L);
|
||||
}
|
||||
|
||||
@ -304,27 +302,29 @@ static void add_num_buff(buffheader_T *buf, long n)
|
||||
*/
|
||||
static void add_char_buff(buffheader_T *buf, int c)
|
||||
{
|
||||
char_u bytes[MB_MAXBYTES + 1];
|
||||
char bytes[MB_MAXBYTES + 1];
|
||||
|
||||
int len;
|
||||
int i;
|
||||
char_u temp[4];
|
||||
|
||||
if (IS_SPECIAL(c))
|
||||
if (IS_SPECIAL(c)) {
|
||||
len = 1;
|
||||
else
|
||||
len = (*mb_char2bytes)(c, bytes);
|
||||
for (i = 0; i < len; ++i) {
|
||||
if (!IS_SPECIAL(c))
|
||||
c = bytes[i];
|
||||
} else {
|
||||
len = (*mb_char2bytes)(c, (char_u *)bytes);
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (!IS_SPECIAL(c)) {
|
||||
c = bytes[i];
|
||||
}
|
||||
|
||||
char temp[4];
|
||||
if (IS_SPECIAL(c) || c == K_SPECIAL || c == NUL) {
|
||||
/* translate special key code into three byte sequence */
|
||||
temp[0] = K_SPECIAL;
|
||||
temp[1] = (char_u)K_SECOND(c);
|
||||
temp[2] = (char_u)K_THIRD(c);
|
||||
// Translate special key code into three byte sequence.
|
||||
temp[0] = (char)K_SPECIAL;
|
||||
temp[1] = (char)K_SECOND(c);
|
||||
temp[2] = (char)K_THIRD(c);
|
||||
temp[3] = NUL;
|
||||
} else {
|
||||
temp[0] = (char_u)c;
|
||||
temp[0] = (char)c;
|
||||
temp[1] = NUL;
|
||||
}
|
||||
add_buff(buf, temp, -1L);
|
||||
@ -479,16 +479,14 @@ static int save_level = 0;
|
||||
|
||||
void saveRedobuff(void)
|
||||
{
|
||||
char_u *s;
|
||||
|
||||
if (save_level++ == 0) {
|
||||
save_redobuff = redobuff;
|
||||
redobuff.bh_first.b_next = NULL;
|
||||
save_old_redobuff = old_redobuff;
|
||||
old_redobuff.bh_first.b_next = NULL;
|
||||
|
||||
/* Make a copy, so that ":normal ." in a function works. */
|
||||
s = get_buffcont(&save_redobuff, FALSE);
|
||||
// Make a copy, so that ":normal ." in a function works.
|
||||
char *const s = (char *)get_buffcont(&save_redobuff, false);
|
||||
if (s != NULL) {
|
||||
add_buff(&redobuff, s, -1L);
|
||||
xfree(s);
|
||||
@ -514,10 +512,11 @@ void restoreRedobuff(void)
|
||||
* Append "s" to the redo buffer.
|
||||
* K_SPECIAL and CSI should already have been escaped.
|
||||
*/
|
||||
void AppendToRedobuff(char_u *s)
|
||||
void AppendToRedobuff(const char *s)
|
||||
{
|
||||
if (!block_redo)
|
||||
add_buff(&redobuff, s, -1L);
|
||||
if (!block_redo) {
|
||||
add_buff(&redobuff, (const char *)s, -1L);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -530,44 +529,47 @@ AppendToRedobuffLit (
|
||||
int len /* length of "str" or -1 for up to the NUL */
|
||||
)
|
||||
{
|
||||
char_u *s = str;
|
||||
int c;
|
||||
char_u *start;
|
||||
|
||||
if (block_redo)
|
||||
if (block_redo) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (len < 0 ? *s != NUL : s - str < len) {
|
||||
/* Put a string of normal characters in the redo buffer (that's
|
||||
* faster). */
|
||||
start = s;
|
||||
while (*s >= ' ' && *s < DEL && (len < 0 || s - str < len))
|
||||
++s;
|
||||
const char *s = (const char *)str;
|
||||
while (len < 0 ? *s != NUL : s - (const char *)str < len) {
|
||||
// Put a string of normal characters in the redo buffer (that's
|
||||
// faster).
|
||||
const char *start = s;
|
||||
while (*s >= ' ' && *s < DEL && (len < 0 || s - (const char *)str < len)) {
|
||||
s++;
|
||||
}
|
||||
|
||||
/* Don't put '0' or '^' as last character, just in case a CTRL-D is
|
||||
* typed next. */
|
||||
if (*s == NUL && (s[-1] == '0' || s[-1] == '^'))
|
||||
--s;
|
||||
if (s > start)
|
||||
// Don't put '0' or '^' as last character, just in case a CTRL-D is
|
||||
// typed next.
|
||||
if (*s == NUL && (s[-1] == '0' || s[-1] == '^')) {
|
||||
s--;
|
||||
}
|
||||
if (s > start) {
|
||||
add_buff(&redobuff, start, (long)(s - start));
|
||||
}
|
||||
|
||||
if (*s == NUL || (len >= 0 && s - str >= len))
|
||||
if (*s == NUL || (len >= 0 && s - (const char *)str >= len)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Handle a special or multibyte character. */
|
||||
if (has_mbyte)
|
||||
/* Handle composing chars separately. */
|
||||
c = mb_cptr2char_adv(&s);
|
||||
else
|
||||
c = *s++;
|
||||
if (c < ' ' || c == DEL || (*s == NUL && (c == '0' || c == '^')))
|
||||
// Handle a special or multibyte character.
|
||||
// Composing chars separately are handled separately.
|
||||
const int c = (has_mbyte
|
||||
? mb_cptr2char_adv((const char_u **)&s)
|
||||
: (uint8_t)(*s++));
|
||||
if (c < ' ' || c == DEL || (*s == NUL && (c == '0' || c == '^'))) {
|
||||
add_char_buff(&redobuff, Ctrl_V);
|
||||
}
|
||||
|
||||
/* CTRL-V '0' must be inserted as CTRL-V 048 */
|
||||
if (*s == NUL && c == '0')
|
||||
add_buff(&redobuff, (char_u *)"048", 3L);
|
||||
else
|
||||
// CTRL-V '0' must be inserted as CTRL-V 048.
|
||||
if (*s == NUL && c == '0') {
|
||||
add_buff(&redobuff, "048", 3L);
|
||||
} else {
|
||||
add_char_buff(&redobuff, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -594,19 +596,19 @@ void AppendNumberToRedobuff(long n)
|
||||
* Append string "s" to the stuff buffer.
|
||||
* CSI and K_SPECIAL must already have been escaped.
|
||||
*/
|
||||
void stuffReadbuff(char_u *s)
|
||||
void stuffReadbuff(const char *s)
|
||||
{
|
||||
add_buff(&readbuf1, s, -1L);
|
||||
}
|
||||
|
||||
/// Append string "s" to the redo stuff buffer.
|
||||
/// @remark CSI and K_SPECIAL must already have been escaped.
|
||||
void stuffRedoReadbuff(char_u *s)
|
||||
void stuffRedoReadbuff(const char *s)
|
||||
{
|
||||
add_buff(&readbuf2, s, -1L);
|
||||
}
|
||||
|
||||
void stuffReadbuffLen(char_u *s, long len)
|
||||
void stuffReadbuffLen(const char *s, long len)
|
||||
{
|
||||
add_buff(&readbuf1, s, len);
|
||||
}
|
||||
@ -616,19 +618,18 @@ void stuffReadbuffLen(char_u *s, long len)
|
||||
* escaping other K_SPECIAL and CSI bytes.
|
||||
* Change CR, LF and ESC into a space.
|
||||
*/
|
||||
void stuffReadbuffSpec(char_u *s)
|
||||
void stuffReadbuffSpec(const char *s)
|
||||
{
|
||||
int c;
|
||||
|
||||
while (*s != NUL) {
|
||||
if (*s == K_SPECIAL && s[1] != NUL && s[2] != NUL) {
|
||||
/* Insert special key literally. */
|
||||
stuffReadbuffLen(s, 3L);
|
||||
if ((uint8_t)(*s) == K_SPECIAL && s[1] != NUL && s[2] != NUL) {
|
||||
// Insert special key literally.
|
||||
stuffReadbuffLen(s, 3);
|
||||
s += 3;
|
||||
} else {
|
||||
c = mb_ptr2char_adv(&s);
|
||||
if (c == CAR || c == NL || c == ESC)
|
||||
int c = mb_ptr2char_adv((const char_u **)&s);
|
||||
if (c == CAR || c == NL || c == ESC) {
|
||||
c = ' ';
|
||||
}
|
||||
stuffcharReadbuff(c);
|
||||
}
|
||||
}
|
||||
@ -747,8 +748,8 @@ int start_redo(long count, int old_redo)
|
||||
|
||||
/* copy the buffer name, if present */
|
||||
if (c == '"') {
|
||||
add_buff(&readbuf2, (char_u *)"\"", 1L);
|
||||
c = read_redo(FALSE, old_redo);
|
||||
add_buff(&readbuf2, "\"", 1L);
|
||||
c = read_redo(false, old_redo);
|
||||
|
||||
/* if a numbered buffer is used, increment the number */
|
||||
if (c >= '1' && c < '9')
|
||||
@ -1091,21 +1092,19 @@ static void gotchars(char_u *chars, size_t len)
|
||||
{
|
||||
char_u *s = chars;
|
||||
int c;
|
||||
char_u buf[2];
|
||||
|
||||
// remember how many chars were last recorded
|
||||
if (Recording) {
|
||||
last_recorded_len += len;
|
||||
}
|
||||
|
||||
buf[1] = NUL;
|
||||
while (len--) {
|
||||
// Handle one byte at a time; no translation to be done.
|
||||
c = *s++;
|
||||
updatescript(c);
|
||||
|
||||
if (Recording) {
|
||||
buf[0] = (char_u)c;
|
||||
char buf[2] = { (char)c, NUL };
|
||||
add_buff(&recordbuff, buf, 1L);
|
||||
}
|
||||
}
|
||||
@ -1881,9 +1880,8 @@ static int vgetorpeek(int advance)
|
||||
(size_t)(mlen - typebuf.tb_maplen));
|
||||
}
|
||||
|
||||
del_typebuf(mlen, 0); /* remove the chars */
|
||||
set_option_value((char_u *)"paste",
|
||||
(long)!p_paste, NULL, 0);
|
||||
del_typebuf(mlen, 0); // Remove the chars.
|
||||
set_option_value("paste", !p_paste, NULL, 0);
|
||||
if (!(State & INSERT)) {
|
||||
msg_col = 0;
|
||||
msg_row = (int)Rows - 1;
|
||||
@ -3219,82 +3217,99 @@ showmap (
|
||||
ui_flush(); /* show one line at a time */
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if a map exists that has "str" in the rhs for mode "modechars".
|
||||
* Recognize termcap codes in "str".
|
||||
* Also checks mappings local to the current buffer.
|
||||
*/
|
||||
int map_to_exists(char_u *str, char_u *modechars, int abbr)
|
||||
/// Check if a map exists that has given string in the rhs
|
||||
///
|
||||
/// Also checks mappings local to the current buffer.
|
||||
///
|
||||
/// @param[in] str String which mapping must have in the rhs. Termcap codes
|
||||
/// are recognized in this argument.
|
||||
/// @param[in] modechars Mode(s) in which mappings are checked.
|
||||
/// @param[in] abbr true if checking abbreviations in place of mappings.
|
||||
///
|
||||
/// @return true if there is at least one mapping with given parameters.
|
||||
bool map_to_exists(const char *const str, const char *const modechars,
|
||||
const bool abbr)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
|
||||
{
|
||||
int mode = 0;
|
||||
char_u *rhs;
|
||||
char_u *buf;
|
||||
int retval;
|
||||
|
||||
rhs = replace_termcodes(str, STRLEN(str), &buf, false, true, false,
|
||||
CPO_TO_CPO_FLAGS);
|
||||
char_u *buf;
|
||||
char_u *const rhs = replace_termcodes((const char_u *)str, strlen(str), &buf,
|
||||
false, true, false,
|
||||
CPO_TO_CPO_FLAGS);
|
||||
|
||||
if (vim_strchr(modechars, 'n') != NULL)
|
||||
mode |= NORMAL;
|
||||
if (vim_strchr(modechars, 'v') != NULL)
|
||||
mode |= VISUAL + SELECTMODE;
|
||||
if (vim_strchr(modechars, 'x') != NULL)
|
||||
mode |= VISUAL;
|
||||
if (vim_strchr(modechars, 's') != NULL)
|
||||
mode |= SELECTMODE;
|
||||
if (vim_strchr(modechars, 'o') != NULL)
|
||||
mode |= OP_PENDING;
|
||||
if (vim_strchr(modechars, 'i') != NULL)
|
||||
mode |= INSERT;
|
||||
if (vim_strchr(modechars, 'l') != NULL)
|
||||
mode |= LANGMAP;
|
||||
if (vim_strchr(modechars, 'c') != NULL)
|
||||
mode |= CMDLINE;
|
||||
#define MAPMODE(mode, modechars, chr, modeflags) \
|
||||
do { \
|
||||
if (strchr(modechars, chr) != NULL) { \
|
||||
mode |= modeflags; \
|
||||
} \
|
||||
} while (0)
|
||||
MAPMODE(mode, modechars, 'n', NORMAL);
|
||||
MAPMODE(mode, modechars, 'v', VISUAL|SELECTMODE);
|
||||
MAPMODE(mode, modechars, 'x', VISUAL);
|
||||
MAPMODE(mode, modechars, 's', SELECTMODE);
|
||||
MAPMODE(mode, modechars, 'o', OP_PENDING);
|
||||
MAPMODE(mode, modechars, 'i', INSERT);
|
||||
MAPMODE(mode, modechars, 'l', LANGMAP);
|
||||
MAPMODE(mode, modechars, 'c', CMDLINE);
|
||||
#undef MAPMODE
|
||||
|
||||
retval = map_to_exists_mode(rhs, mode, abbr);
|
||||
retval = map_to_exists_mode((const char *)rhs, mode, abbr);
|
||||
xfree(buf);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if a map exists that has "str" in the rhs for mode "mode".
|
||||
* Also checks mappings local to the current buffer.
|
||||
*/
|
||||
int map_to_exists_mode(char_u *rhs, int mode, int abbr)
|
||||
/// Check if a map exists that has given string in the rhs
|
||||
///
|
||||
/// Also checks mappings local to the current buffer.
|
||||
///
|
||||
/// @param[in] rhs String which mapping must have in the rhs. Termcap codes
|
||||
/// are recognized in this argument.
|
||||
/// @param[in] mode Mode(s) in which mappings are checked.
|
||||
/// @param[in] abbr true if checking abbreviations in place of mappings.
|
||||
///
|
||||
/// @return true if there is at least one mapping with given parameters.
|
||||
int map_to_exists_mode(const char *const rhs, const int mode, const bool abbr)
|
||||
{
|
||||
mapblock_T *mp;
|
||||
int hash;
|
||||
int expand_buffer = FALSE;
|
||||
bool expand_buffer = false;
|
||||
|
||||
validate_maphash();
|
||||
|
||||
/* Do it twice: once for global maps and once for local maps. */
|
||||
for (;; ) {
|
||||
for (hash = 0; hash < 256; ++hash) {
|
||||
// Do it twice: once for global maps and once for local maps.
|
||||
for (;;) {
|
||||
for (hash = 0; hash < 256; hash++) {
|
||||
if (abbr) {
|
||||
if (hash > 0) /* there is only one abbr list */
|
||||
if (hash > 0) { // There is only one abbr list.
|
||||
break;
|
||||
if (expand_buffer)
|
||||
}
|
||||
if (expand_buffer) {
|
||||
mp = curbuf->b_first_abbr;
|
||||
else
|
||||
} else {
|
||||
mp = first_abbr;
|
||||
} else if (expand_buffer)
|
||||
}
|
||||
} else if (expand_buffer) {
|
||||
mp = curbuf->b_maphash[hash];
|
||||
else
|
||||
} else {
|
||||
mp = maphash[hash];
|
||||
}
|
||||
for (; mp; mp = mp->m_next) {
|
||||
if ((mp->m_mode & mode)
|
||||
&& strstr((char *)mp->m_str, (char *)rhs) != NULL)
|
||||
return TRUE;
|
||||
&& strstr((char *)mp->m_str, rhs) != NULL) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (expand_buffer)
|
||||
if (expand_buffer) {
|
||||
break;
|
||||
expand_buffer = TRUE;
|
||||
}
|
||||
expand_buffer = true;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
21
src/nvim/gettext.h
Normal file
21
src/nvim/gettext.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef NVIM_GETTEXT_H
|
||||
#define NVIM_GETTEXT_H
|
||||
|
||||
#ifdef HAVE_WORKING_LIBINTL
|
||||
# include <libintl.h>
|
||||
# define _(x) gettext((char *)(x))
|
||||
// XXX do we actually need this?
|
||||
# ifdef gettext_noop
|
||||
# define N_(x) gettext_noop(x)
|
||||
# else
|
||||
# define N_(x) x
|
||||
# endif
|
||||
#else
|
||||
# define _(x) ((char *)(x))
|
||||
# define N_(x) x
|
||||
# define bindtextdomain(x, y) // empty
|
||||
# define bind_textdomain_codeset(x, y) // empty
|
||||
# define textdomain(x) // empty
|
||||
#endif
|
||||
|
||||
#endif // NVIM_GETTEXT_H
|
@ -12,6 +12,7 @@
|
||||
#include "nvim/syntax_defs.h"
|
||||
#include "nvim/types.h"
|
||||
#include "nvim/event/loop.h"
|
||||
#include "nvim/os/os_defs.h"
|
||||
|
||||
#define IOSIZE (1024+1) // file I/O and sprintf buffer size
|
||||
|
||||
@ -21,16 +22,6 @@
|
||||
# define MSG_BUF_CLEN (MSG_BUF_LEN / 6) // cell length (worst case: utf-8
|
||||
// takes 6 bytes for one cell)
|
||||
|
||||
// Maximum length of a file path. Make it a bit long, to stay
|
||||
// on the safe side. But not too long to put on the stack.
|
||||
#ifndef MAXPATHL
|
||||
# ifdef MAXPATHLEN
|
||||
# define MAXPATHL MAXPATHLEN
|
||||
# else
|
||||
# define MAXPATHL 256
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
# define _PATHSEPSTR "\\"
|
||||
#else
|
||||
@ -1208,6 +1199,7 @@ EXTERN char_u e_dirnotf[] INIT(= N_(
|
||||
"E919: Directory not found in '%s': \"%s\""));
|
||||
EXTERN char_u e_unsupportedoption[] INIT(= N_("E519: Option not supported"));
|
||||
EXTERN char_u e_fnametoolong[] INIT(= N_("E856: Filename too long"));
|
||||
EXTERN char_u e_float_as_string[] INIT(= N_("E806: using Float as a String"));
|
||||
|
||||
|
||||
EXTERN char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM"));
|
||||
@ -1226,11 +1218,6 @@ EXTERN FILE *time_fd INIT(= NULL); /* where to write startup timing */
|
||||
EXTERN int ignored;
|
||||
EXTERN char *ignoredp;
|
||||
|
||||
EXTERN bool in_free_unref_items INIT(= false);
|
||||
|
||||
// Used for checking if local variables or arguments used in a lambda.
|
||||
EXTERN int *eval_lavars_used INIT(= NULL);
|
||||
|
||||
// If a msgpack-rpc channel should be started over stdin/stdout
|
||||
EXTERN bool embedded_mode INIT(= false);
|
||||
|
||||
|
@ -369,7 +369,6 @@ static void prt_get_attr(int hl_id, prt_text_attr_T *pattr, int modec)
|
||||
{
|
||||
int colorindex;
|
||||
uint32_t fg_color;
|
||||
char *color;
|
||||
|
||||
pattr->bold = (highlight_has_attr(hl_id, HL_BOLD, modec) != NULL);
|
||||
pattr->italic = (highlight_has_attr(hl_id, HL_ITALIC, modec) != NULL);
|
||||
@ -377,11 +376,12 @@ static void prt_get_attr(int hl_id, prt_text_attr_T *pattr, int modec)
|
||||
pattr->undercurl = (highlight_has_attr(hl_id, HL_UNDERCURL, modec) != NULL);
|
||||
|
||||
{
|
||||
color = (char *)highlight_color(hl_id, (char_u *)"fg", modec);
|
||||
if (color == NULL)
|
||||
const char *color = highlight_color(hl_id, "fg", modec);
|
||||
if (color == NULL) {
|
||||
colorindex = 0;
|
||||
else
|
||||
} else {
|
||||
colorindex = atoi(color);
|
||||
}
|
||||
|
||||
if (colorindex >= 0 && colorindex < t_colors)
|
||||
fg_color = prt_get_term_color(colorindex);
|
||||
|
@ -82,7 +82,7 @@ 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, const char_u *key)
|
||||
hashitem_T *hash_find(const hashtab_T *const ht, const char_u *const key)
|
||||
{
|
||||
return hash_lookup(ht, (const char *)key, STRLEN(key), hash_hash(key));
|
||||
}
|
||||
@ -99,7 +99,8 @@ hashitem_T *hash_find(hashtab_T *ht, const char_u *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)
|
||||
hashitem_T *hash_find_len(const hashtab_T *const ht, const char *const key,
|
||||
const size_t len)
|
||||
{
|
||||
return hash_lookup(ht, key, len, hash_hash_len(key, len));
|
||||
}
|
||||
@ -115,7 +116,7 @@ hashitem_T *hash_find_len(hashtab_T *ht, const char *key, const size_t len)
|
||||
/// 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 *const ht,
|
||||
hashitem_T *hash_lookup(const hashtab_T *const ht,
|
||||
const char *const key, const size_t key_len,
|
||||
const hash_T hash)
|
||||
{
|
||||
|
@ -70,6 +70,25 @@ typedef struct hashtable_S {
|
||||
hashitem_T ht_smallarray[HT_INIT_SIZE]; /// initial array
|
||||
} hashtab_T;
|
||||
|
||||
/// Iterate over a hashtab
|
||||
///
|
||||
/// @param[in] ht Hashtab to iterate over.
|
||||
/// @param hi Name of the variable with current hashtab entry.
|
||||
/// @param code Cycle body.
|
||||
#define HASHTAB_ITER(ht, hi, code) \
|
||||
do { \
|
||||
hashtab_T *const hi##ht_ = (ht); \
|
||||
size_t hi##todo_ = hi##ht_->ht_used; \
|
||||
for (hashitem_T *hi = hi##ht_->ht_array; hi##todo_; hi++) { \
|
||||
if (!HASHITEM_EMPTY(hi)) { \
|
||||
{ \
|
||||
code \
|
||||
} \
|
||||
hi##todo_--; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "hashtab.h.generated.h"
|
||||
#endif
|
||||
|
@ -140,31 +140,30 @@ char_u *get_cscope_name(expand_T *xp, int idx)
|
||||
/*
|
||||
* Handle command line completion for :cscope command.
|
||||
*/
|
||||
void set_context_in_cscope_cmd(expand_T *xp, char_u *arg, cmdidx_T cmdidx)
|
||||
void set_context_in_cscope_cmd(expand_T *xp, const char *arg, cmdidx_T cmdidx)
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
/* Default: expand subcommands */
|
||||
// Default: expand subcommands.
|
||||
xp->xp_context = EXPAND_CSCOPE;
|
||||
xp->xp_pattern = arg;
|
||||
expand_what = (cmdidx == CMD_scscope)
|
||||
? EXP_SCSCOPE_SUBCMD : EXP_CSCOPE_SUBCMD;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
expand_what = ((cmdidx == CMD_scscope)
|
||||
? EXP_SCSCOPE_SUBCMD : EXP_CSCOPE_SUBCMD);
|
||||
|
||||
/* (part of) subcommand already typed */
|
||||
if (*arg != NUL) {
|
||||
p = skiptowhite(arg);
|
||||
if (*p != NUL) { /* past first word */
|
||||
xp->xp_pattern = skipwhite(p);
|
||||
if (*skiptowhite(xp->xp_pattern) != NUL)
|
||||
const char *p = (const char *)skiptowhite((const char_u *)arg);
|
||||
if (*p != NUL) { // Past first word.
|
||||
xp->xp_pattern = skipwhite((const char_u *)p);
|
||||
if (*skiptowhite(xp->xp_pattern) != NUL) {
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
else if (STRNICMP(arg, "add", p - arg) == 0)
|
||||
} else if (STRNICMP(arg, "add", p - arg) == 0) {
|
||||
xp->xp_context = EXPAND_FILES;
|
||||
else if (STRNICMP(arg, "kill", p - arg) == 0)
|
||||
} else if (STRNICMP(arg, "kill", p - arg) == 0) {
|
||||
expand_what = EXP_CSCOPE_KILL;
|
||||
else if (STRNICMP(arg, "find", p - arg) == 0)
|
||||
} else if (STRNICMP(arg, "find", p - arg) == 0) {
|
||||
expand_what = EXP_CSCOPE_FIND;
|
||||
else
|
||||
} else {
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ static char_u *skip_string(char_u *p)
|
||||
char_u *paren = vim_strchr(delim, '(');
|
||||
|
||||
if (paren != NULL) {
|
||||
ptrdiff_t delim_len = paren - delim;
|
||||
const ptrdiff_t delim_len = paren - delim;
|
||||
|
||||
for (p += 3; *p; ++p)
|
||||
if (p[0] == ')' && STRNCMP(p + 1, delim, delim_len) == 0
|
||||
|
@ -19,6 +19,15 @@
|
||||
# define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
|
||||
#endif
|
||||
|
||||
/// String with length
|
||||
///
|
||||
/// For use in functions which accept (char *s, size_t len) pair in arguments.
|
||||
///
|
||||
/// @param[in] s Static string.
|
||||
///
|
||||
/// @return `s, sizeof(s) - 1`
|
||||
#define S_LEN(s) (s), (sizeof(s) - 1)
|
||||
|
||||
/*
|
||||
* Position comparisons
|
||||
*/
|
||||
|
@ -391,9 +391,10 @@ int main(int argc, char **argv)
|
||||
shada_read_everything(NULL, false, true);
|
||||
TIME_MSG("reading ShaDa");
|
||||
}
|
||||
/* It's better to make v:oldfiles an empty list than NULL. */
|
||||
if (get_vim_var_list(VV_OLDFILES) == NULL)
|
||||
set_vim_var_list(VV_OLDFILES, list_alloc());
|
||||
// It's better to make v:oldfiles an empty list than NULL.
|
||||
if (get_vim_var_list(VV_OLDFILES) == NULL) {
|
||||
set_vim_var_list(VV_OLDFILES, tv_list_alloc());
|
||||
}
|
||||
|
||||
/*
|
||||
* "-q errorfile": Load the error file now.
|
||||
@ -802,17 +803,18 @@ static void command_line_scan(mparm_T *parmp)
|
||||
argv_idx = -1; /* skip to next argument */
|
||||
break;
|
||||
|
||||
case 'A': /* "-A" start in Arabic mode */
|
||||
set_option_value((char_u *)"arabic", 1L, NULL, 0);
|
||||
case 'A': { // "-A" start in Arabic mode.
|
||||
set_option_value("arabic", 1L, NULL, 0);
|
||||
break;
|
||||
|
||||
case 'b': /* "-b" binary mode */
|
||||
/* Needs to be effective before expanding file names, because
|
||||
* for Win32 this makes us edit a shortcut file itself,
|
||||
* instead of the file it links to. */
|
||||
}
|
||||
case 'b': { // "-b" binary mode.
|
||||
// Needs to be effective before expanding file names, because
|
||||
// for Win32 this makes us edit a shortcut file itself,
|
||||
// instead of the file it links to.
|
||||
set_options_bin(curbuf->b_p_bin, 1, 0);
|
||||
curbuf->b_p_bin = 1; /* binary file I/O */
|
||||
curbuf->b_p_bin = 1; // Binary file I/O.
|
||||
break;
|
||||
}
|
||||
|
||||
case 'e': /* "-e" Ex mode */
|
||||
exmode_active = EXMODE_NORMAL;
|
||||
@ -829,24 +831,27 @@ static void command_line_scan(mparm_T *parmp)
|
||||
main_start_gui();
|
||||
break;
|
||||
|
||||
case 'F': /* "-F" start in Farsi mode: rl + fkmap set */
|
||||
p_fkmap = TRUE;
|
||||
set_option_value((char_u *)"rl", 1L, NULL, 0);
|
||||
case 'F': { // "-F" start in Farsi mode: rl + fkmap set.
|
||||
p_fkmap = true;
|
||||
set_option_value("rl", 1L, NULL, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'h': /* "-h" give help message */
|
||||
usage();
|
||||
mch_exit(0);
|
||||
|
||||
case 'H': /* "-H" start in Hebrew mode: rl + hkmap set */
|
||||
p_hkmap = TRUE;
|
||||
set_option_value((char_u *)"rl", 1L, NULL, 0);
|
||||
case 'H': { // "-H" start in Hebrew mode: rl + hkmap set.
|
||||
p_hkmap = true;
|
||||
set_option_value("rl", 1L, NULL, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'l': /* "-l" lisp mode, 'lisp' and 'showmatch' on */
|
||||
set_option_value((char_u *)"lisp", 1L, NULL, 0);
|
||||
p_sm = TRUE;
|
||||
case 'l': { // "-l" lisp mode, 'lisp' and 'showmatch' on.
|
||||
set_option_value("lisp", 1L, NULL, 0);
|
||||
p_sm = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'M': /* "-M" no changes or writing of files */
|
||||
reset_modifiable();
|
||||
@ -945,8 +950,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
/* default is 10: a little bit verbose */
|
||||
p_verbose = get_number_arg(argv[0], &argv_idx, 10);
|
||||
if (argv[0][argv_idx] != NUL) {
|
||||
set_option_value((char_u *)"verbosefile", 0L,
|
||||
(char_u *)argv[0] + argv_idx, 0);
|
||||
set_option_value("verbosefile", 0L, argv[0] + argv_idx, 0);
|
||||
argv_idx = (int)STRLEN(argv[0]);
|
||||
}
|
||||
break;
|
||||
@ -955,7 +959,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
/* "-w {scriptout}" write to script */
|
||||
if (ascii_isdigit(((char_u *)argv[0])[argv_idx])) {
|
||||
n = get_number_arg(argv[0], &argv_idx, 10);
|
||||
set_option_value((char_u *)"window", n, NULL, 0);
|
||||
set_option_value("window", n, NULL, 0);
|
||||
break;
|
||||
}
|
||||
want_argument = TRUE;
|
||||
@ -1087,7 +1091,7 @@ scripterror:
|
||||
if (ascii_isdigit(*((char_u *)argv[0]))) {
|
||||
argv_idx = 0;
|
||||
n = get_number_arg(argv[0], &argv_idx, 10);
|
||||
set_option_value((char_u *)"window", n, NULL, 0);
|
||||
set_option_value("window", n, NULL, 0);
|
||||
argv_idx = -1;
|
||||
break;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ int setmark(int c)
|
||||
/// Free fmark_T item
|
||||
void free_fmark(fmark_T fm)
|
||||
{
|
||||
dict_unref(fm.additional_data);
|
||||
tv_dict_unref(fm.additional_data);
|
||||
}
|
||||
|
||||
/// Free xfmark_T item
|
||||
@ -1431,3 +1431,26 @@ void free_all_marks(void)
|
||||
memset(&namedfm[0], 0, sizeof(namedfm));
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Adjust position to point to the first byte of a multi-byte character
|
||||
///
|
||||
/// If it points to a tail byte it is move backwards to the head byte.
|
||||
///
|
||||
/// @param[in] buf Buffer to adjust position in.
|
||||
/// @param[out] lp Position to adjust.
|
||||
void mark_mb_adjustpos(buf_T *buf, pos_T *lp)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
if (lp->col > 0 || lp->coladd > 1) {
|
||||
const char_u *const p = ml_get_buf(buf, lp->lnum, false);
|
||||
lp->col -= (*mb_head_off)(p, p + lp->col);
|
||||
// Reset "coladd" when the cursor would be on the right half of a
|
||||
// double-wide character.
|
||||
if (lp->coladd == 1
|
||||
&& p[lp->col] != TAB
|
||||
&& vim_isprintc((*mb_ptr2char)(p + lp->col))
|
||||
&& ptr2cells(p + lp->col) > 1) {
|
||||
lp->coladd = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "nvim/pos.h"
|
||||
#include "nvim/os/time.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
|
||||
/*
|
||||
* marks: positions in a file
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "nvim/strings.h"
|
||||
#include "nvim/os/os.h"
|
||||
#include "nvim/arabic.h"
|
||||
#include "nvim/mark.h"
|
||||
|
||||
typedef struct {
|
||||
int rangeStart;
|
||||
@ -375,16 +376,18 @@ void remove_bom(char_u *s)
|
||||
*/
|
||||
int mb_get_class(const char_u *p)
|
||||
{
|
||||
return mb_get_class_buf(p, curbuf);
|
||||
return mb_get_class_tab(p, curbuf->b_chartab);
|
||||
}
|
||||
|
||||
int mb_get_class_buf(const char_u *p, buf_T *buf)
|
||||
int mb_get_class_tab(const char_u *p, const uint64_t *const chartab)
|
||||
{
|
||||
if (MB_BYTE2LEN(p[0]) == 1) {
|
||||
if (p[0] == NUL || ascii_iswhite(p[0]))
|
||||
if (p[0] == NUL || ascii_iswhite(p[0])) {
|
||||
return 0;
|
||||
if (vim_iswordc_buf(p[0], buf))
|
||||
}
|
||||
if (vim_iswordc_tab(p[0], chartab)) {
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return utf_class(utf_ptr2char(p));
|
||||
@ -580,7 +583,7 @@ int utf_ptr2char(const char_u *p)
|
||||
* If byte sequence is illegal or incomplete, returns -1 and does not advance
|
||||
* "s".
|
||||
*/
|
||||
static int utf_safe_read_char_adv(char_u **s, size_t *n)
|
||||
static int utf_safe_read_char_adv(const char_u **s, size_t *n)
|
||||
{
|
||||
int c;
|
||||
|
||||
@ -622,7 +625,7 @@ static int utf_safe_read_char_adv(char_u **s, size_t *n)
|
||||
* Get character at **pp and advance *pp to the next character.
|
||||
* Note: composing characters are skipped!
|
||||
*/
|
||||
int mb_ptr2char_adv(char_u **pp)
|
||||
int mb_ptr2char_adv(const char_u **const pp)
|
||||
{
|
||||
int c;
|
||||
|
||||
@ -635,7 +638,7 @@ int mb_ptr2char_adv(char_u **pp)
|
||||
* Get character at **pp and advance *pp to the next character.
|
||||
* Note: composing characters are returned as separate characters.
|
||||
*/
|
||||
int mb_cptr2char_adv(char_u **pp)
|
||||
int mb_cptr2char_adv(const char_u **pp)
|
||||
{
|
||||
int c;
|
||||
|
||||
@ -1230,7 +1233,8 @@ bool utf_isupper(int a)
|
||||
return utf_tolower(a) != a;
|
||||
}
|
||||
|
||||
static int utf_strnicmp(char_u *s1, char_u *s2, size_t n1, size_t n2)
|
||||
static int utf_strnicmp(const char_u *s1, const char_u *s2, size_t n1,
|
||||
size_t n2)
|
||||
{
|
||||
int c1, c2, cdiff;
|
||||
char_u buffer[6];
|
||||
@ -1389,19 +1393,26 @@ int utf16_to_utf8(const WCHAR *strw, char **str)
|
||||
* Returns zero if s1 and s2 are equal (ignoring case), the difference between
|
||||
* two characters otherwise.
|
||||
*/
|
||||
int mb_strnicmp(char_u *s1, char_u *s2, size_t nn)
|
||||
int mb_strnicmp(const char_u *s1, const char_u *s2, const size_t nn)
|
||||
{
|
||||
return utf_strnicmp(s1, s2, nn, nn);
|
||||
}
|
||||
|
||||
/* We need to call mb_stricmp() even when we aren't dealing with a multi-byte
|
||||
* encoding because mb_stricmp() takes care of all ascii and non-ascii
|
||||
* encodings, including characters with umlauts in latin1, etc., while
|
||||
* STRICMP() only handles the system locale version, which often does not
|
||||
* handle non-ascii properly. */
|
||||
int mb_stricmp(char_u *s1, char_u *s2)
|
||||
/// Compare strings case-insensitively
|
||||
///
|
||||
/// @note We need to call mb_stricmp() even when we aren't dealing with
|
||||
/// a multi-byte encoding because mb_stricmp() takes care of all ASCII and
|
||||
/// non-ascii encodings, including characters with umlauts in latin1,
|
||||
/// etc., while STRICMP() only handles the system locale version, which
|
||||
/// often does not handle non-ascii properly.
|
||||
///
|
||||
/// @param[in] s1 First string to compare, not more then #MAXCOL characters.
|
||||
/// @param[in] s2 Second string to compare, not more then #MAXCOL characters.
|
||||
///
|
||||
/// @return 0 if strings are equal, <0 if s1 < s2, >0 if s1 > s2.
|
||||
int mb_stricmp(const char *s1, const char *s2)
|
||||
{
|
||||
return mb_strnicmp(s1, s2, MAXCOL);
|
||||
return mb_strnicmp((const char_u *)s1, (const char_u *)s2, MAXCOL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1639,38 +1650,16 @@ theend:
|
||||
*/
|
||||
void mb_adjust_cursor(void)
|
||||
{
|
||||
mb_adjustpos(curbuf, &curwin->w_cursor);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust position "*lp" to point to the first byte of a multi-byte character.
|
||||
* If it points to a tail byte it's moved backwards to the head byte.
|
||||
*/
|
||||
void mb_adjustpos(buf_T *buf, pos_T *lp)
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
if (lp->col > 0
|
||||
|| lp->coladd > 1
|
||||
) {
|
||||
p = ml_get_buf(buf, lp->lnum, FALSE);
|
||||
lp->col -= (*mb_head_off)(p, p + lp->col);
|
||||
/* Reset "coladd" when the cursor would be on the right half of a
|
||||
* double-wide character. */
|
||||
if (lp->coladd == 1
|
||||
&& p[lp->col] != TAB
|
||||
&& vim_isprintc((*mb_ptr2char)(p + lp->col))
|
||||
&& ptr2cells(p + lp->col) > 1)
|
||||
lp->coladd = 0;
|
||||
}
|
||||
mark_mb_adjustpos(curbuf, &curwin->w_cursor);
|
||||
}
|
||||
|
||||
/// Checks and adjusts cursor column. Not mode-dependent.
|
||||
/// @see check_cursor_col_win
|
||||
///
|
||||
/// @param win Places cursor on a valid column for this window.
|
||||
void mb_check_adjust_col(win_T *win)
|
||||
/// @param win_ Places cursor on a valid column for this window.
|
||||
void mb_check_adjust_col(void *win_)
|
||||
{
|
||||
win_T *win = (win_T *)win_;
|
||||
colnr_T oldcol = win->w_cursor.col;
|
||||
|
||||
// Column 0 is always valid.
|
||||
@ -2039,8 +2028,8 @@ void * my_iconv_open(char_u *to, char_u *from)
|
||||
* Returns the converted string in allocated memory. NULL for an error.
|
||||
* If resultlenp is not NULL, sets it to the result length in bytes.
|
||||
*/
|
||||
static char_u * iconv_string(vimconv_T *vcp, char_u *str, size_t slen,
|
||||
size_t *unconvlenp, size_t *resultlenp)
|
||||
static char_u *iconv_string(const vimconv_T *const vcp, char_u *str,
|
||||
size_t slen, size_t *unconvlenp, size_t *resultlenp)
|
||||
{
|
||||
const char *from;
|
||||
size_t fromlen;
|
||||
@ -2325,7 +2314,7 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8,
|
||||
* Illegal chars are often changed to "?", unless vcp->vc_fail is set.
|
||||
* When something goes wrong, NULL is returned and "*lenp" is unchanged.
|
||||
*/
|
||||
char_u * string_convert(vimconv_T *vcp, char_u *ptr, size_t *lenp)
|
||||
char_u *string_convert(const vimconv_T *const vcp, char_u *ptr, size_t *lenp)
|
||||
{
|
||||
return string_convert_ext(vcp, ptr, lenp, NULL);
|
||||
}
|
||||
@ -2335,7 +2324,7 @@ char_u * string_convert(vimconv_T *vcp, char_u *ptr, size_t *lenp)
|
||||
* an incomplete sequence at the end it is not converted and "*unconvlenp" is
|
||||
* set to the number of remaining bytes.
|
||||
*/
|
||||
char_u * string_convert_ext(vimconv_T *vcp, char_u *ptr,
|
||||
char_u * string_convert_ext(const vimconv_T *const vcp, char_u *ptr,
|
||||
size_t *lenp, size_t *unconvlenp)
|
||||
{
|
||||
char_u *retval = NULL;
|
||||
|
@ -2,6 +2,11 @@
|
||||
#define NVIM_MBYTE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nvim/iconv.h"
|
||||
#include "nvim/func_attr.h"
|
||||
#include "nvim/os/os_defs.h" // For WCHAR, indirect
|
||||
|
||||
/*
|
||||
* Return byte length of character that starts with byte "b".
|
||||
@ -40,7 +45,41 @@
|
||||
#define mb_ptr2char utf_ptr2char
|
||||
#define mb_head_off utf_head_off
|
||||
|
||||
/// Flags for vimconv_T
|
||||
typedef enum {
|
||||
CONV_NONE = 0,
|
||||
CONV_TO_UTF8 = 1,
|
||||
CONV_9_TO_UTF8 = 2,
|
||||
CONV_TO_LATIN1 = 3,
|
||||
CONV_TO_LATIN9 = 4,
|
||||
CONV_ICONV = 5,
|
||||
} ConvFlags;
|
||||
|
||||
/// Structure used for string conversions
|
||||
typedef struct {
|
||||
int vc_type; ///< Zero or more ConvFlags.
|
||||
int vc_factor; ///< Maximal expansion factor.
|
||||
# ifdef USE_ICONV
|
||||
iconv_t vc_fd; ///< Value for CONV_ICONV.
|
||||
# endif
|
||||
bool vc_fail; ///< What to do with invalid characters: if true, fail,
|
||||
///< otherwise use '?'.
|
||||
} vimconv_T;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "mbyte.h.generated.h"
|
||||
#endif
|
||||
|
||||
static inline int mb_strcmp_ic(bool ic, const char *s1, const char *s2)
|
||||
REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/// Compare strings
|
||||
///
|
||||
/// @param[in] ic True if case is to be ignored.
|
||||
///
|
||||
/// @return 0 if s1 == s2, <0 if s1 < s2, >0 if s1 > s2.
|
||||
static inline int mb_strcmp_ic(bool ic, const char *s1, const char *s2)
|
||||
{
|
||||
return (ic ? mb_stricmp(s1, s2) : strcmp(s1, s2));
|
||||
}
|
||||
#endif // NVIM_MBYTE_H
|
||||
|
@ -992,7 +992,7 @@ void ml_recover(void)
|
||||
if (b0_ff != 0)
|
||||
set_fileformat(b0_ff - 1, OPT_LOCAL);
|
||||
if (b0_fenc != NULL) {
|
||||
set_option_value((char_u *)"fenc", 0L, b0_fenc, OPT_LOCAL);
|
||||
set_option_value("fenc", 0L, (char *)b0_fenc, OPT_LOCAL);
|
||||
xfree(b0_fenc);
|
||||
}
|
||||
unchanged(curbuf, TRUE);
|
||||
|
@ -430,6 +430,19 @@ char *xstrdup(const char *str)
|
||||
return xmemdupz(str, strlen(str));
|
||||
}
|
||||
|
||||
/// strdup() wrapper
|
||||
///
|
||||
/// Unlike xstrdup() allocates a new empty string if it receives NULL.
|
||||
char *xstrdupnul(const char *const str)
|
||||
FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET
|
||||
{
|
||||
if (str == NULL) {
|
||||
return xmallocz(0);
|
||||
} else {
|
||||
return xstrdup(str);
|
||||
}
|
||||
}
|
||||
|
||||
/// A version of memchr that starts the search at `src + len`.
|
||||
///
|
||||
/// Based on glibc's memrchr.
|
||||
|
@ -718,7 +718,7 @@ int delete_first_msg(void)
|
||||
void ex_messages(void *const eap_p)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
exarg_T *eap = (exarg_T *)eap_p;
|
||||
const exarg_T *const eap = (const exarg_T *)eap_p;
|
||||
struct msg_hist *p;
|
||||
int c = 0;
|
||||
|
||||
@ -1562,13 +1562,17 @@ void msg_puts_attr(const char *const s, const int attr)
|
||||
msg_puts_attr_len(s, -1, attr);
|
||||
}
|
||||
|
||||
/// Like msg_puts_attr(), but with a maximum length "maxlen" (in bytes).
|
||||
/// When "maxlen" is -1 there is no maximum length.
|
||||
/// When "maxlen" is >= 0 the message is not put in the history.
|
||||
void msg_puts_attr_len(const char *str, const ptrdiff_t maxlen, int attr)
|
||||
/// Write a message with highlight attributes
|
||||
///
|
||||
/// @param[in] str NUL-terminated message string.
|
||||
/// @param[in] len Length of the string or -1.
|
||||
/// @param[in] attr Highlight attribute.
|
||||
void msg_puts_attr_len(const char *const str, const ptrdiff_t len, int attr)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
assert(len < 0 || memchr(str, 0, len) == NULL);
|
||||
// If redirection is on, also write to the redirection file.
|
||||
redir_write(str, maxlen);
|
||||
redir_write(str, len);
|
||||
|
||||
// Don't print anything when using ":silent cmd".
|
||||
if (msg_silent != 0) {
|
||||
@ -1576,8 +1580,8 @@ void msg_puts_attr_len(const char *str, const ptrdiff_t maxlen, int attr)
|
||||
}
|
||||
|
||||
// if MSG_HIST flag set, add message to history
|
||||
if ((attr & MSG_HIST) && maxlen < 0) {
|
||||
add_msg_hist(str, -1, attr);
|
||||
if (attr & MSG_HIST) {
|
||||
add_msg_hist(str, (int)len, attr);
|
||||
attr &= ~MSG_HIST;
|
||||
}
|
||||
|
||||
@ -1596,9 +1600,9 @@ void msg_puts_attr_len(const char *str, const ptrdiff_t maxlen, int attr)
|
||||
// different, e.g. for Win32 console) or we just don't know where the
|
||||
// cursor is.
|
||||
if (msg_use_printf()) {
|
||||
msg_puts_printf(str, maxlen);
|
||||
msg_puts_printf(str, len);
|
||||
} else {
|
||||
msg_puts_display((const char_u *)str, maxlen, attr, false);
|
||||
msg_puts_display((const char_u *)str, len, attr, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2211,39 +2211,44 @@ change_warning (
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask for a reply from the user, a 'y' or a 'n'.
|
||||
* No other characters are accepted, the message is repeated until a valid
|
||||
* reply is entered or CTRL-C is hit.
|
||||
* If direct is TRUE, don't use vgetc() but ui_inchar(), don't get characters
|
||||
* from any buffers but directly from the user.
|
||||
*
|
||||
* return the 'y' or 'n'
|
||||
*/
|
||||
int ask_yesno(const char *str, bool direct)
|
||||
/// Ask for a reply from the user, 'y' or 'n'
|
||||
///
|
||||
/// No other characters are accepted, the message is repeated until a valid
|
||||
/// reply is entered or <C-c> is hit.
|
||||
///
|
||||
/// @param[in] str Prompt: question to ask user. Is always followed by
|
||||
/// " (y/n)?".
|
||||
/// @param[in] direct Determines what function to use to get user input. If
|
||||
/// true then ui_inchar() will be used, otherwise vgetc().
|
||||
/// I.e. when direct is true then characters are obtained
|
||||
/// directly from the user without buffers involved.
|
||||
///
|
||||
/// @return 'y' or 'n'. Last is also what will be returned in case of interrupt.
|
||||
int ask_yesno(const char *const str, const bool direct)
|
||||
{
|
||||
int r = ' ';
|
||||
int save_State = State;
|
||||
const int save_State = State;
|
||||
|
||||
no_wait_return++;
|
||||
State = CONFIRM; // mouse behaves like with :confirm
|
||||
setmouse(); // disables mouse for xterm
|
||||
State = CONFIRM; // Mouse behaves like with :confirm.
|
||||
setmouse(); // Disable mouse in xterm.
|
||||
no_mapping++;
|
||||
|
||||
int r = ' ';
|
||||
while (r != 'y' && r != 'n') {
|
||||
/* same highlighting as for wait_return */
|
||||
smsg_attr(hl_attr(HLF_R),
|
||||
"%s (y/n)?", str);
|
||||
if (direct)
|
||||
// Same highlighting as for wait_return.
|
||||
smsg_attr(hl_attr(HLF_R), "%s (y/n)?", str);
|
||||
if (direct) {
|
||||
r = get_keystroke();
|
||||
else
|
||||
} else {
|
||||
r = plain_vgetc();
|
||||
if (r == Ctrl_C || r == ESC)
|
||||
}
|
||||
if (r == Ctrl_C || r == ESC) {
|
||||
r = 'n';
|
||||
msg_putchar(r); /* show what you typed */
|
||||
}
|
||||
msg_putchar(r); // Show what you typed.
|
||||
ui_flush();
|
||||
}
|
||||
--no_wait_return;
|
||||
no_wait_return--;
|
||||
State = save_State;
|
||||
setmouse();
|
||||
no_mapping--;
|
||||
|
10
src/nvim/move.PVS-Studio.cfg
Normal file
10
src/nvim/move.PVS-Studio.cfg
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
source-file=/home/zyx/a.a/Proj/c/neovim/src/nvim/move.c
|
||||
i-file=/home/zyx/a.a/Proj/c/neovim/src/nvim/move.i
|
||||
language=C
|
||||
skip-cl-exe=yes
|
||||
preprocessor=gcc
|
||||
platform=linux64
|
||||
lic-file=/home/zyx/a.a/Proj/c/neovim/build/../PVS-Studio.lic
|
||||
output-file=/home/zyx/a.a/Proj/c/neovim/build/../PVS-Studio.log.x
|
||||
analysis-mode=4
|
@ -147,7 +147,7 @@ void channel_from_connection(SocketWatcher *watcher)
|
||||
/// @param name The event name, an arbitrary string
|
||||
/// @param args Array with event arguments
|
||||
/// @return True if the event was sent successfully, false otherwise.
|
||||
bool channel_send_event(uint64_t id, char *name, Array args)
|
||||
bool channel_send_event(uint64_t id, const char *name, Array args)
|
||||
{
|
||||
Channel *channel = NULL;
|
||||
|
||||
@ -160,7 +160,7 @@ bool channel_send_event(uint64_t id, char *name, Array args)
|
||||
if (channel) {
|
||||
if (channel->pending_requests) {
|
||||
// Pending request, queue the notification for later sending.
|
||||
String method = cstr_as_string(name);
|
||||
const String method = cstr_as_string((char *)name);
|
||||
WBuffer *buffer = serialize_request(id, 0, method, args, &out_buffer, 1);
|
||||
kv_push(channel->delayed_notifications, buffer);
|
||||
} else {
|
||||
@ -182,7 +182,7 @@ bool channel_send_event(uint64_t id, char *name, Array args)
|
||||
/// @param[out] error True if the return value is an error
|
||||
/// @return Whatever the remote method returned
|
||||
Object channel_send_call(uint64_t id,
|
||||
char *method_name,
|
||||
const char *method_name,
|
||||
Array args,
|
||||
Error *err)
|
||||
{
|
||||
@ -519,10 +519,10 @@ static void send_error(Channel *channel, uint64_t id, char *err)
|
||||
|
||||
static void send_request(Channel *channel,
|
||||
uint64_t id,
|
||||
char *name,
|
||||
const char *name,
|
||||
Array args)
|
||||
{
|
||||
String method = {.size = strlen(name), .data = name};
|
||||
const String method = cstr_as_string((char *)name);
|
||||
channel_write(channel, serialize_request(channel->id,
|
||||
id,
|
||||
method,
|
||||
@ -532,10 +532,10 @@ static void send_request(Channel *channel,
|
||||
}
|
||||
|
||||
static void send_event(Channel *channel,
|
||||
char *name,
|
||||
const char *name,
|
||||
Array args)
|
||||
{
|
||||
String method = {.size = strlen(name), .data = name};
|
||||
const String method = cstr_as_string((char *)name);
|
||||
channel_write(channel, serialize_request(channel->id,
|
||||
0,
|
||||
method,
|
||||
@ -544,7 +544,7 @@ static void send_event(Channel *channel,
|
||||
1));
|
||||
}
|
||||
|
||||
static void broadcast_event(char *name, Array args)
|
||||
static void broadcast_event(const char *name, Array args)
|
||||
{
|
||||
kvec_t(Channel *) subscribed = KV_INITIAL_VALUE;
|
||||
Channel *channel;
|
||||
@ -560,7 +560,7 @@ static void broadcast_event(char *name, Array args)
|
||||
goto end;
|
||||
}
|
||||
|
||||
String method = {.size = strlen(name), .data = name};
|
||||
const String method = cstr_as_string((char *)name);
|
||||
WBuffer *buffer = serialize_request(0,
|
||||
0,
|
||||
method,
|
||||
@ -728,7 +728,7 @@ static void call_set_error(Channel *channel, char *msg)
|
||||
|
||||
static WBuffer *serialize_request(uint64_t channel_id,
|
||||
uint64_t request_id,
|
||||
String method,
|
||||
const String method,
|
||||
Array args,
|
||||
msgpack_sbuffer *sbuffer,
|
||||
size_t refcount)
|
||||
|
@ -322,7 +322,7 @@ void msgpack_rpc_from_float(Float result, msgpack_packer *res)
|
||||
msgpack_pack_double(res, result);
|
||||
}
|
||||
|
||||
void msgpack_rpc_from_string(String result, msgpack_packer *res)
|
||||
void msgpack_rpc_from_string(const String result, msgpack_packer *res)
|
||||
FUNC_ATTR_NONNULL_ARG(2)
|
||||
{
|
||||
msgpack_pack_str(res, result.size);
|
||||
@ -478,7 +478,7 @@ Object msgpack_rpc_handle_invalid_arguments(uint64_t channel_id,
|
||||
|
||||
/// Serializes a msgpack-rpc request or notification(id == 0)
|
||||
void msgpack_rpc_serialize_request(uint64_t request_id,
|
||||
String method,
|
||||
const String method,
|
||||
Array args,
|
||||
msgpack_packer *pac)
|
||||
FUNC_ATTR_NONNULL_ARG(4)
|
||||
|
@ -1155,7 +1155,7 @@ static void normal_check_stuff_buffer(NormalState *s)
|
||||
|
||||
if (need_start_insertmode && goto_im() && !VIsual_active) {
|
||||
need_start_insertmode = false;
|
||||
stuffReadbuff((uint8_t *)"i"); // start insert mode next
|
||||
stuffReadbuff("i"); // start insert mode next
|
||||
// skip the fileinfo message now, because it would be shown
|
||||
// after insert mode finishes!
|
||||
need_fileinfo = false;
|
||||
@ -1469,8 +1469,9 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
|
||||
* If 'cpoptions' does not contain 'r', insert the search
|
||||
* pattern to really repeat the same command.
|
||||
*/
|
||||
if (vim_strchr(p_cpo, CPO_REDO) == NULL)
|
||||
if (vim_strchr(p_cpo, CPO_REDO) == NULL) {
|
||||
AppendToRedobuffLit(cap->searchbuf, -1);
|
||||
}
|
||||
AppendToRedobuff(NL_STR);
|
||||
} else if (cap->cmdchar == ':') {
|
||||
/* do_cmdline() has stored the first typed line in
|
||||
@ -1853,10 +1854,11 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
|
||||
break;
|
||||
|
||||
case OP_FILTER:
|
||||
if (vim_strchr(p_cpo, CPO_FILTER) != NULL)
|
||||
AppendToRedobuff((char_u *)"!\r"); /* use any last used !cmd */
|
||||
else
|
||||
bangredo = true; /* do_bang() will put cmd in redo buffer */
|
||||
if (vim_strchr(p_cpo, CPO_FILTER) != NULL) {
|
||||
AppendToRedobuff("!\r"); // Use any last used !cmd.
|
||||
} else {
|
||||
bangredo = true; // do_bang() will put cmd in redo buffer.
|
||||
}
|
||||
|
||||
case OP_INDENT:
|
||||
case OP_COLON:
|
||||
@ -2026,43 +2028,44 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
|
||||
static void op_colon(oparg_T *oap)
|
||||
{
|
||||
stuffcharReadbuff(':');
|
||||
if (oap->is_VIsual)
|
||||
stuffReadbuff((char_u *)"'<,'>");
|
||||
else {
|
||||
/*
|
||||
* Make the range look nice, so it can be repeated.
|
||||
*/
|
||||
if (oap->start.lnum == curwin->w_cursor.lnum)
|
||||
if (oap->is_VIsual) {
|
||||
stuffReadbuff("'<,'>");
|
||||
} else {
|
||||
// Make the range look nice, so it can be repeated.
|
||||
if (oap->start.lnum == curwin->w_cursor.lnum) {
|
||||
stuffcharReadbuff('.');
|
||||
else
|
||||
} else {
|
||||
stuffnumReadbuff((long)oap->start.lnum);
|
||||
}
|
||||
if (oap->end.lnum != oap->start.lnum) {
|
||||
stuffcharReadbuff(',');
|
||||
if (oap->end.lnum == curwin->w_cursor.lnum)
|
||||
if (oap->end.lnum == curwin->w_cursor.lnum) {
|
||||
stuffcharReadbuff('.');
|
||||
else if (oap->end.lnum == curbuf->b_ml.ml_line_count)
|
||||
} else if (oap->end.lnum == curbuf->b_ml.ml_line_count) {
|
||||
stuffcharReadbuff('$');
|
||||
else if (oap->start.lnum == curwin->w_cursor.lnum) {
|
||||
stuffReadbuff((char_u *)".+");
|
||||
} else if (oap->start.lnum == curwin->w_cursor.lnum) {
|
||||
stuffReadbuff(".+");
|
||||
stuffnumReadbuff(oap->line_count - 1);
|
||||
} else
|
||||
} else {
|
||||
stuffnumReadbuff((long)oap->end.lnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (oap->op_type != OP_COLON)
|
||||
stuffReadbuff((char_u *)"!");
|
||||
if (oap->op_type != OP_COLON) {
|
||||
stuffReadbuff("!");
|
||||
}
|
||||
if (oap->op_type == OP_INDENT) {
|
||||
stuffReadbuff(get_equalprg());
|
||||
stuffReadbuff((char_u *)"\n");
|
||||
stuffReadbuff((const char *)get_equalprg());
|
||||
stuffReadbuff("\n");
|
||||
} else if (oap->op_type == OP_FORMAT) {
|
||||
if (*curbuf->b_p_fp != NUL) {
|
||||
stuffReadbuff(curbuf->b_p_fp);
|
||||
stuffReadbuff((const char *)curbuf->b_p_fp);
|
||||
} else if (*p_fp != NUL) {
|
||||
stuffReadbuff(p_fp);
|
||||
stuffReadbuff((const char *)p_fp);
|
||||
} else {
|
||||
stuffReadbuff((char_u *)"fmt");
|
||||
stuffReadbuff("fmt");
|
||||
}
|
||||
stuffReadbuff((char_u *)"\n']");
|
||||
stuffReadbuff("\n']");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2075,7 +2078,6 @@ static void op_colon(oparg_T *oap)
|
||||
*/
|
||||
static void op_function(oparg_T *oap)
|
||||
{
|
||||
char_u *(argv[1]);
|
||||
int save_virtual_op = virtual_op;
|
||||
|
||||
if (*p_opfunc == NUL)
|
||||
@ -2089,16 +2091,16 @@ static void op_function(oparg_T *oap)
|
||||
decl(&curbuf->b_op_end);
|
||||
}
|
||||
|
||||
if (oap->motion_type == kMTBlockWise) {
|
||||
argv[0] = (char_u *)"block";
|
||||
} else if (oap->motion_type == kMTLineWise) {
|
||||
argv[0] = (char_u *)"line";
|
||||
} else {
|
||||
argv[0] = (char_u *)"char";
|
||||
}
|
||||
const char_u *const argv[1] = {
|
||||
(const char_u *)(((const char *const[]) {
|
||||
[kMTBlockWise] = "block",
|
||||
[kMTLineWise] = "line",
|
||||
[kMTCharWise] = "char",
|
||||
})[oap->motion_type]),
|
||||
};
|
||||
|
||||
/* Reset virtual_op so that 'virtualedit' can be changed in the
|
||||
* function. */
|
||||
// Reset virtual_op so that 'virtualedit' can be changed in the
|
||||
// function.
|
||||
virtual_op = MAYBE;
|
||||
|
||||
(void)call_func_retnr(p_opfunc, 1, argv, false);
|
||||
@ -2305,7 +2307,7 @@ do_mouse (
|
||||
if (VIsual_active) {
|
||||
if (VIsual_select) {
|
||||
stuffcharReadbuff(Ctrl_G);
|
||||
stuffReadbuff((char_u *)"\"+p");
|
||||
stuffReadbuff("\"+p");
|
||||
} else {
|
||||
stuffcharReadbuff('y');
|
||||
stuffcharReadbuff(K_MIDDLEMOUSE);
|
||||
@ -2465,7 +2467,7 @@ do_mouse (
|
||||
&rettv, ARRAY_SIZE(argv), argv, NULL,
|
||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
||||
&doesrange, true, NULL, NULL);
|
||||
clear_tv(&rettv);
|
||||
tv_clear(&rettv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -4477,7 +4479,7 @@ static void nv_colon(cmdarg_T *cap)
|
||||
/* translate "count:" into ":.,.+(count - 1)" */
|
||||
stuffcharReadbuff('.');
|
||||
if (cap->count0 > 1) {
|
||||
stuffReadbuff((char_u *)",.+");
|
||||
stuffReadbuff(",.+");
|
||||
stuffnumReadbuff(cap->count0 - 1L);
|
||||
}
|
||||
}
|
||||
@ -4757,7 +4759,7 @@ static void nv_ident(cmdarg_T *cap)
|
||||
ptr = vim_strnsave(ptr, n);
|
||||
if (kp_ex) {
|
||||
// Escape the argument properly for an Ex command
|
||||
p = vim_strsave_fnameescape(ptr, false);
|
||||
p = (char_u *)vim_strsave_fnameescape((const char *)ptr, false);
|
||||
} else {
|
||||
// Escape the argument properly for a shell command
|
||||
p = vim_strsave_shellescape(ptr, true, true);
|
||||
@ -6157,17 +6159,15 @@ static void nv_abbrev(cmdarg_T *cap)
|
||||
*/
|
||||
static void nv_optrans(cmdarg_T *cap)
|
||||
{
|
||||
static char_u *(ar[8]) = {(char_u *)"dl", (char_u *)"dh",
|
||||
(char_u *)"d$", (char_u *)"c$",
|
||||
(char_u *)"cl", (char_u *)"cc",
|
||||
(char_u *)"yy", (char_u *)":s\r"};
|
||||
static char_u *str = (char_u *)"xXDCsSY&";
|
||||
static const char *(ar[]) = { "dl", "dh", "d$", "c$", "cl", "cc", "yy",
|
||||
":s\r" };
|
||||
static const char *str = "xXDCsSY&";
|
||||
|
||||
if (!checkclearopq(cap->oap)) {
|
||||
if (cap->count0) {
|
||||
stuffnumReadbuff(cap->count0);
|
||||
}
|
||||
stuffReadbuff(ar[(int)(vim_strchr(str, cap->cmdchar) - str)]);
|
||||
stuffReadbuff(ar[strchr(str, (char)cap->cmdchar) - str]);
|
||||
}
|
||||
cap->opcount = 0;
|
||||
}
|
||||
@ -7290,11 +7290,11 @@ static bool unadjust_for_sel(void)
|
||||
pp = &curwin->w_cursor;
|
||||
else
|
||||
pp = &VIsual;
|
||||
if (pp->coladd > 0)
|
||||
--pp->coladd;
|
||||
else if (pp->col > 0) {
|
||||
--pp->col;
|
||||
mb_adjustpos(curbuf, pp);
|
||||
if (pp->coladd > 0) {
|
||||
pp->coladd--;
|
||||
} else if (pp->col > 0) {
|
||||
pp->col--;
|
||||
mark_mb_adjustpos(curbuf, pp);
|
||||
} else if (pp->lnum > 1) {
|
||||
--pp->lnum;
|
||||
pp->col = (colnr_T)STRLEN(ml_get(pp->lnum));
|
||||
@ -7829,7 +7829,7 @@ static void get_op_vcol(
|
||||
|
||||
// prevent from moving onto a trail byte
|
||||
if (has_mbyte) {
|
||||
mb_adjustpos(curwin->w_buffer, &oap->end);
|
||||
mark_mb_adjustpos(curwin->w_buffer, &oap->end);
|
||||
}
|
||||
|
||||
getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol);
|
||||
|
168
src/nvim/ops.c
168
src/nvim/ops.c
@ -14,8 +14,10 @@
|
||||
#include "nvim/buffer.h"
|
||||
#include "nvim/charset.h"
|
||||
#include "nvim/cursor.h"
|
||||
#include "nvim/assert.h"
|
||||
#include "nvim/edit.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/ex_cmds.h"
|
||||
#include "nvim/ex_cmds2.h"
|
||||
#include "nvim/ex_getln.h"
|
||||
@ -41,6 +43,7 @@
|
||||
#include "nvim/terminal.h"
|
||||
#include "nvim/ui.h"
|
||||
#include "nvim/undo.h"
|
||||
#include "nvim/macros.h"
|
||||
#include "nvim/window.h"
|
||||
#include "nvim/os/input.h"
|
||||
#include "nvim/os/time.h"
|
||||
@ -888,7 +891,7 @@ static void set_yreg_additional_data(yankreg_T *reg, dict_T *additional_data)
|
||||
if (reg->additional_data == additional_data) {
|
||||
return;
|
||||
}
|
||||
dict_unref(reg->additional_data);
|
||||
tv_dict_unref(reg->additional_data);
|
||||
reg->additional_data = additional_data;
|
||||
}
|
||||
|
||||
@ -1106,7 +1109,6 @@ int insert_reg(
|
||||
)
|
||||
{
|
||||
int retval = OK;
|
||||
char_u *arg;
|
||||
int allocated;
|
||||
|
||||
/*
|
||||
@ -1122,21 +1124,24 @@ int insert_reg(
|
||||
if (regname != NUL && !valid_yank_reg(regname, false))
|
||||
return FAIL;
|
||||
|
||||
if (regname == '.') /* insert last inserted text */
|
||||
retval = stuff_inserted(NUL, 1L, TRUE);
|
||||
else if (get_spec_reg(regname, &arg, &allocated, TRUE)) {
|
||||
if (arg == NULL)
|
||||
char_u *arg;
|
||||
if (regname == '.') { // Insert last inserted text.
|
||||
retval = stuff_inserted(NUL, 1L, true);
|
||||
} else if (get_spec_reg(regname, &arg, &allocated, true)) {
|
||||
if (arg == NULL) {
|
||||
return FAIL;
|
||||
stuffescaped(arg, literally);
|
||||
if (allocated)
|
||||
}
|
||||
stuffescaped((const char *)arg, literally);
|
||||
if (allocated) {
|
||||
xfree(arg);
|
||||
} else { /* name or number register */
|
||||
}
|
||||
} else { // Name or number register.
|
||||
yankreg_T *reg = get_yank_register(regname, YREG_PASTE);
|
||||
if (reg->y_array == NULL) {
|
||||
retval = FAIL;
|
||||
} else {
|
||||
for (size_t i = 0; i < reg->y_size; i++) {
|
||||
stuffescaped(reg->y_array[i], literally);
|
||||
stuffescaped((const char *)reg->y_array[i], literally);
|
||||
// Insert a newline between lines and after last line if
|
||||
// y_type is kMTLineWise.
|
||||
if (reg->y_type == kMTLineWise || i < reg->y_size - 1) {
|
||||
@ -1153,29 +1158,29 @@ int insert_reg(
|
||||
* Stuff a string into the typeahead buffer, such that edit() will insert it
|
||||
* literally ("literally" TRUE) or interpret is as typed characters.
|
||||
*/
|
||||
static void stuffescaped(char_u *arg, int literally)
|
||||
static void stuffescaped(const char *arg, int literally)
|
||||
{
|
||||
int c;
|
||||
char_u *start;
|
||||
|
||||
while (*arg != NUL) {
|
||||
/* Stuff a sequence of normal ASCII characters, that's fast. Also
|
||||
* stuff K_SPECIAL to get the effect of a special key when "literally"
|
||||
* is TRUE. */
|
||||
start = arg;
|
||||
while ((*arg >= ' ' && *arg < DEL) || (*arg == K_SPECIAL && !literally))
|
||||
++arg;
|
||||
if (arg > start)
|
||||
// Stuff a sequence of normal ASCII characters, that's fast. Also
|
||||
// stuff K_SPECIAL to get the effect of a special key when "literally"
|
||||
// is TRUE.
|
||||
const char *const start = arg;
|
||||
while ((*arg >= ' ' && *arg < DEL) || ((uint8_t)(*arg) == K_SPECIAL
|
||||
&& !literally)) {
|
||||
arg++;
|
||||
}
|
||||
if (arg > start) {
|
||||
stuffReadbuffLen(start, (long)(arg - start));
|
||||
}
|
||||
|
||||
/* stuff a single special character */
|
||||
if (*arg != NUL) {
|
||||
if (has_mbyte)
|
||||
c = mb_cptr2char_adv(&arg);
|
||||
else
|
||||
c = *arg++;
|
||||
if (literally && ((c < ' ' && c != TAB) || c == DEL))
|
||||
const int c = (has_mbyte
|
||||
? mb_cptr2char_adv((const char_u **)&arg)
|
||||
: (uint8_t)(*arg++));
|
||||
if (literally && ((c < ' ' && c != TAB) || c == DEL)) {
|
||||
stuffcharReadbuff(Ctrl_V);
|
||||
}
|
||||
stuffcharReadbuff(c);
|
||||
}
|
||||
}
|
||||
@ -2555,33 +2560,33 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
|
||||
dict_T *dict = get_vim_var_dict(VV_EVENT);
|
||||
|
||||
// the yanked text
|
||||
list_T *list = list_alloc();
|
||||
list_T *list = tv_list_alloc();
|
||||
for (size_t i = 0; i < reg->y_size; i++) {
|
||||
list_append_string(list, reg->y_array[i], -1);
|
||||
tv_list_append_string(list, (const char *)reg->y_array[i], -1);
|
||||
}
|
||||
list->lv_lock = VAR_FIXED;
|
||||
dict_add_list(dict, "regcontents", list);
|
||||
tv_dict_add_list(dict, S_LEN("regcontents"), list);
|
||||
|
||||
// the register type
|
||||
char buf[NUMBUFLEN+2];
|
||||
format_reg_type(reg->y_type, reg->y_width, buf, ARRAY_SIZE(buf));
|
||||
dict_add_nr_str(dict, "regtype", 0, (char_u *)buf);
|
||||
tv_dict_add_str(dict, S_LEN("regtype"), buf);
|
||||
|
||||
// name of requested register or the empty string for an unnamed operation.
|
||||
buf[0] = (char)oap->regname;
|
||||
buf[1] = NUL;
|
||||
dict_add_nr_str(dict, "regname", 0, (char_u *)buf);
|
||||
tv_dict_add_str(dict, S_LEN("regname"), buf);
|
||||
|
||||
// kind of operation (yank/delete/change)
|
||||
buf[0] = (char)get_op_char(oap->op_type);
|
||||
buf[1] = NUL;
|
||||
dict_add_nr_str(dict, "operator", 0, (char_u *)buf);
|
||||
tv_dict_add_str(dict, S_LEN("operator"), buf);
|
||||
|
||||
dict_set_keys_readonly(dict);
|
||||
tv_dict_set_keys_readonly(dict);
|
||||
textlock++;
|
||||
apply_autocmds(EVENT_TEXTYANKPOST, NULL, NULL, false, curbuf);
|
||||
textlock--;
|
||||
dict_clear(dict);
|
||||
tv_dict_clear(dict);
|
||||
|
||||
recursive = false;
|
||||
}
|
||||
@ -2660,7 +2665,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
|
||||
// back to the previous line in the case of 'noautoindent' and
|
||||
// 'backspace' includes "eol". So we insert a dummy space for Ctrl_U
|
||||
// to consume.
|
||||
stuffReadbuff((char_u *)"\n ");
|
||||
stuffReadbuff("\n ");
|
||||
stuffcharReadbuff(Ctrl_U);
|
||||
}
|
||||
}
|
||||
@ -2672,7 +2677,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
|
||||
// character. Simulate it with motion commands after the insert.
|
||||
if (flags & PUT_CURSEND) {
|
||||
if (flags & PUT_LINE) {
|
||||
stuffReadbuff((char_u *)"j0");
|
||||
stuffReadbuff("j0");
|
||||
} else {
|
||||
// Avoid ringing the bell from attempting to move into the space after
|
||||
// the current line. We can stuff the readbuffer with "l" if:
|
||||
@ -2702,7 +2707,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
|
||||
}
|
||||
}
|
||||
} else if (flags & PUT_LINE) {
|
||||
stuffReadbuff((char_u *)"g'[");
|
||||
stuffReadbuff("g'[");
|
||||
}
|
||||
|
||||
// So the 'u' command restores cursor position after ".p, save the cursor
|
||||
@ -4844,8 +4849,8 @@ static void *get_reg_wrap_one_line(char_u *s, int flags)
|
||||
if (!(flags & kGRegList)) {
|
||||
return s;
|
||||
}
|
||||
list_T *list = list_alloc();
|
||||
list_append_string(list, NULL, -1);
|
||||
list_T *list = tv_list_alloc();
|
||||
tv_list_append_string(list, NULL, 0);
|
||||
list->lv_first->li_tv.vval.v_string = s;
|
||||
return list;
|
||||
}
|
||||
@ -4895,9 +4900,9 @@ void *get_reg_contents(int regname, int flags)
|
||||
return NULL;
|
||||
|
||||
if (flags & kGRegList) {
|
||||
list_T *list = list_alloc();
|
||||
list_T *list = tv_list_alloc();
|
||||
for (size_t i = 0; i < reg->y_size; i++) {
|
||||
list_append_string(list, reg->y_array[i], -1);
|
||||
tv_list_append_string(list, (const char *)reg->y_array[i], -1);
|
||||
}
|
||||
|
||||
return list;
|
||||
@ -4978,7 +4983,7 @@ void write_reg_contents(int name, const char_u *str, ssize_t len,
|
||||
write_reg_contents_ex(name, str, len, must_append, kMTUnknown, 0L);
|
||||
}
|
||||
|
||||
void write_reg_contents_lst(int name, char_u **strings, int maxlen,
|
||||
void write_reg_contents_lst(int name, char_u **strings,
|
||||
bool must_append, MotionType yank_type,
|
||||
colnr_T block_len)
|
||||
{
|
||||
@ -5482,17 +5487,19 @@ void cursor_pos_info(dict_T *dict)
|
||||
|
||||
if (dict != NULL) {
|
||||
// Don't shorten this message, the user asked for it.
|
||||
dict_add_nr_str(dict, "words", word_count, NULL);
|
||||
dict_add_nr_str(dict, "chars", char_count, NULL);
|
||||
dict_add_nr_str(dict, "bytes", byte_count + bom_count, NULL);
|
||||
tv_dict_add_nr(dict, S_LEN("words"), (varnumber_T)word_count);
|
||||
tv_dict_add_nr(dict, S_LEN("chars"), (varnumber_T)char_count);
|
||||
tv_dict_add_nr(dict, S_LEN("bytes"), (varnumber_T)(byte_count + bom_count));
|
||||
|
||||
dict_add_nr_str(dict, l_VIsual_active ? "visual_bytes" : "cursor_bytes",
|
||||
byte_count_cursor, NULL);
|
||||
dict_add_nr_str(dict, l_VIsual_active ? "visual_chars" : "cursor_chars",
|
||||
char_count_cursor, NULL);
|
||||
dict_add_nr_str(dict, l_VIsual_active ? "visual_words" : "cursor_words",
|
||||
word_count_cursor, NULL);
|
||||
}
|
||||
STATIC_ASSERT(sizeof("visual") == sizeof("cursor"),
|
||||
"key_len argument in tv_dict_add_nr is wrong");
|
||||
tv_dict_add_nr(dict, l_VIsual_active ? "visual_bytes" : "cursor_bytes",
|
||||
sizeof("visual_bytes") - 1, (varnumber_T)byte_count_cursor);
|
||||
tv_dict_add_nr(dict, l_VIsual_active ? "visual_chars" : "cursor_chars",
|
||||
sizeof("visual_chars") - 1, (varnumber_T)char_count_cursor);
|
||||
tv_dict_add_nr(dict, l_VIsual_active ? "visual_words" : "cursor_words",
|
||||
sizeof("visual_words") - 1, (varnumber_T)word_count_cursor);
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if the default register (used in an unnamed paste) should be a
|
||||
@ -5570,9 +5577,9 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
|
||||
}
|
||||
free_register(reg);
|
||||
|
||||
list_T *args = list_alloc();
|
||||
char_u regname = (char_u)name;
|
||||
list_append_string(args, ®name, 1);
|
||||
list_T *const args = tv_list_alloc();
|
||||
const char regname = (char)name;
|
||||
tv_list_append_string(args, ®name, 1);
|
||||
|
||||
typval_T result = eval_call_provider("clipboard", "get", args);
|
||||
|
||||
@ -5584,7 +5591,8 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
|
||||
goto err;
|
||||
}
|
||||
|
||||
list_T *res = result.vval.v_list, *lines = NULL;
|
||||
list_T *res = result.vval.v_list;
|
||||
list_T *lines = NULL;
|
||||
if (res->lv_len == 2 && res->lv_first->li_tv.v_type == VAR_LIST) {
|
||||
lines = res->lv_first->li_tv.vval.v_list;
|
||||
if (res->lv_last->li_tv.v_type != VAR_STRING) {
|
||||
@ -5628,7 +5636,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
|
||||
if (li->li_tv.v_type != VAR_STRING) {
|
||||
goto err;
|
||||
}
|
||||
reg->y_array[i++] = (uint8_t *)xstrdup((char *)li->li_tv.vval.v_string);
|
||||
reg->y_array[i++] = (char_u *)xstrdupnul((char *)li->li_tv.vval.v_string);
|
||||
}
|
||||
|
||||
if (reg->y_size > 0 && strlen((char*)reg->y_array[reg->y_size-1]) == 0) {
|
||||
@ -5686,35 +5694,39 @@ static void set_clipboard(int name, yankreg_T *reg)
|
||||
return;
|
||||
}
|
||||
|
||||
list_T *lines = list_alloc();
|
||||
list_T *lines = tv_list_alloc();
|
||||
|
||||
for (size_t i = 0; i < reg->y_size; i++) {
|
||||
list_append_string(lines, reg->y_array[i], -1);
|
||||
tv_list_append_string(lines, (const char *)reg->y_array[i], -1);
|
||||
}
|
||||
|
||||
list_T *args = list_alloc();
|
||||
list_append_list(args, lines);
|
||||
list_T *args = tv_list_alloc();
|
||||
tv_list_append_list(args, lines);
|
||||
|
||||
char_u regtype;
|
||||
char regtype;
|
||||
switch (reg->y_type) {
|
||||
case kMTLineWise:
|
||||
regtype = 'V';
|
||||
list_append_string(lines, (char_u*)"", 0);
|
||||
break;
|
||||
case kMTCharWise:
|
||||
regtype = 'v';
|
||||
break;
|
||||
case kMTBlockWise:
|
||||
regtype = 'b';
|
||||
list_append_string(lines, (char_u*)"", 0);
|
||||
break;
|
||||
case kMTUnknown:
|
||||
assert(false);
|
||||
case kMTLineWise: {
|
||||
regtype = 'V';
|
||||
tv_list_append_string(lines, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case kMTCharWise: {
|
||||
regtype = 'v';
|
||||
break;
|
||||
}
|
||||
case kMTBlockWise: {
|
||||
regtype = 'b';
|
||||
tv_list_append_string(lines, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case kMTUnknown: {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
list_append_string(args, ®type, 1);
|
||||
tv_list_append_string(args, ®type, 1);
|
||||
|
||||
char_u regname = (char_u)name;
|
||||
list_append_string(args, ®name, 1);
|
||||
const char regname = (char)name;
|
||||
tv_list_append_string(args, ®name, 1);
|
||||
|
||||
(void)eval_call_provider("clipboard", "set", args);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "nvim/macros.h"
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/types.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/os/time.h"
|
||||
|
||||
typedef int (*Indenter)(void);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <limits.h>
|
||||
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/macros.h"
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/edit.h"
|
||||
#include "nvim/option.h"
|
||||
@ -34,6 +35,7 @@
|
||||
#include "nvim/diff.h"
|
||||
#include "nvim/digraph.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/ex_cmds2.h"
|
||||
#include "nvim/ex_docmd.h"
|
||||
#include "nvim/ex_getln.h"
|
||||
@ -604,7 +606,7 @@ void set_init_1(void)
|
||||
/*
|
||||
* 'maxmemtot' and 'maxmem' may have to be adjusted for available memory
|
||||
*/
|
||||
opt_idx = findoption((char_u *)"maxmemtot");
|
||||
opt_idx = findoption("maxmemtot");
|
||||
if (opt_idx >= 0) {
|
||||
{
|
||||
/* Use half of amount of memory available to Vim. */
|
||||
@ -614,7 +616,7 @@ void set_init_1(void)
|
||||
? UINTPTR_MAX
|
||||
: (uintptr_t)(available_kib /2);
|
||||
options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n;
|
||||
opt_idx = findoption((char_u *)"maxmem");
|
||||
opt_idx = findoption("maxmem");
|
||||
if (opt_idx >= 0) {
|
||||
options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n;
|
||||
}
|
||||
@ -645,7 +647,7 @@ void set_init_1(void)
|
||||
}
|
||||
}
|
||||
buf[j] = NUL;
|
||||
opt_idx = findoption((char_u *)"cdpath");
|
||||
opt_idx = findoption("cdpath");
|
||||
if (opt_idx >= 0) {
|
||||
options[opt_idx].def_val[VI_DEFAULT] = buf;
|
||||
options[opt_idx].flags |= P_DEF_ALLOCED;
|
||||
@ -764,8 +766,9 @@ void set_init_1(void)
|
||||
* NOTE: mlterm's author is being asked to 'set' a variable
|
||||
* instead of an environment variable due to inheritance.
|
||||
*/
|
||||
if (os_env_exists("MLTERM"))
|
||||
set_option_value((char_u *)"tbidi", 1L, NULL, 0);
|
||||
if (os_env_exists("MLTERM")) {
|
||||
set_option_value("tbidi", 1L, NULL, 0);
|
||||
}
|
||||
|
||||
didset_options2();
|
||||
|
||||
@ -775,7 +778,7 @@ void set_init_1(void)
|
||||
char_u *p = enc_locale();
|
||||
if (p == NULL) {
|
||||
// use utf-8 as 'default' if locale encoding can't be detected.
|
||||
p = vim_strsave((char_u *)"utf-8");
|
||||
p = (char_u *)xmemdupz(S_LEN("utf-8"));
|
||||
}
|
||||
fenc_default = p;
|
||||
|
||||
@ -882,7 +885,7 @@ set_options_default (
|
||||
static void set_string_default(const char *name, char *val, bool allocated)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
int opt_idx = findoption((char_u *)name);
|
||||
int opt_idx = findoption(name);
|
||||
if (opt_idx >= 0) {
|
||||
if (options[opt_idx].flags & P_DEF_ALLOCED) {
|
||||
xfree(options[opt_idx].def_val[VI_DEFAULT]);
|
||||
@ -904,9 +907,10 @@ void set_number_default(char *name, long val)
|
||||
{
|
||||
int opt_idx;
|
||||
|
||||
opt_idx = findoption((char_u *)name);
|
||||
if (opt_idx >= 0)
|
||||
opt_idx = findoption(name);
|
||||
if (opt_idx >= 0) {
|
||||
options[opt_idx].def_val[VI_DEFAULT] = (char_u *)val;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(EXITFREE)
|
||||
@ -947,17 +951,19 @@ void set_init_2(void)
|
||||
* wrong when the window height changes.
|
||||
*/
|
||||
set_number_default("scroll", Rows / 2);
|
||||
idx = findoption((char_u *)"scroll");
|
||||
if (idx >= 0 && !(options[idx].flags & P_WAS_SET))
|
||||
idx = findoption("scroll");
|
||||
if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) {
|
||||
set_option_default(idx, OPT_LOCAL, p_cp);
|
||||
}
|
||||
comp_col();
|
||||
|
||||
/*
|
||||
* 'window' is only for backwards compatibility with Vi.
|
||||
* Default is Rows - 1.
|
||||
*/
|
||||
if (!option_was_set((char_u *)"window"))
|
||||
if (!option_was_set("window")) {
|
||||
p_window = Rows - 1;
|
||||
}
|
||||
set_number_default("window", Rows - 1);
|
||||
parse_shape_opt(SHAPE_CURSOR); /* set cursor shapes from 'guicursor' */
|
||||
(void)parse_printoptions(); /* parse 'printoptions' default value */
|
||||
@ -976,16 +982,18 @@ void set_init_3(void)
|
||||
int idx_sp;
|
||||
int do_sp;
|
||||
|
||||
idx_srr = findoption((char_u *)"srr");
|
||||
if (idx_srr < 0)
|
||||
do_srr = FALSE;
|
||||
else
|
||||
idx_srr = findoption("srr");
|
||||
if (idx_srr < 0) {
|
||||
do_srr = false;
|
||||
} else {
|
||||
do_srr = !(options[idx_srr].flags & P_WAS_SET);
|
||||
idx_sp = findoption((char_u *)"sp");
|
||||
if (idx_sp < 0)
|
||||
do_sp = FALSE;
|
||||
else
|
||||
}
|
||||
idx_sp = findoption("sp");
|
||||
if (idx_sp < 0) {
|
||||
do_sp = false;
|
||||
} else {
|
||||
do_sp = !(options[idx_sp].flags & P_WAS_SET);
|
||||
}
|
||||
|
||||
size_t len = 0;
|
||||
char_u *p = (char_u *)invocation_path_tail(p_sh, &len);
|
||||
@ -1029,7 +1037,7 @@ void set_init_3(void)
|
||||
}
|
||||
|
||||
if (bufempty()) {
|
||||
int idx_ffs = findoption((char_u *)"ffs");
|
||||
int idx_ffs = findoption_len(S_LEN("ffs"));
|
||||
|
||||
// Apply the first entry of 'fileformats' to the initial buffer.
|
||||
if (idx_ffs >= 0 && (options[idx_ffs].flags & P_WAS_SET)) {
|
||||
@ -1048,14 +1056,16 @@ void set_helplang_default(const char *lang)
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (lang == NULL || STRLEN(lang) < 2) /* safety check */
|
||||
const size_t lang_len = strlen(lang);
|
||||
if (lang == NULL || lang_len < 2) { // safety check
|
||||
return;
|
||||
idx = findoption((char_u *)"hlg");
|
||||
}
|
||||
idx = findoption("hlg");
|
||||
if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) {
|
||||
if (options[idx].flags & P_ALLOCED)
|
||||
free_string_option(p_hlg);
|
||||
p_hlg = (char_u *)xstrdup(lang);
|
||||
/* zh_CN becomes "cn", zh_TW becomes "tw". */
|
||||
p_hlg = (char_u *)xmemdupz(lang, lang_len);
|
||||
// zh_CN becomes "cn", zh_TW becomes "tw".
|
||||
if (STRNICMP(p_hlg, "zh_", 3) == 0 && STRLEN(p_hlg) >= 5) {
|
||||
p_hlg[0] = (char_u)TOLOWER_ASC(p_hlg[3]);
|
||||
p_hlg[1] = (char_u)TOLOWER_ASC(p_hlg[4]);
|
||||
@ -1082,12 +1092,12 @@ void set_title_defaults(void)
|
||||
* icon name. Saves a bit of time, because the X11 display server does
|
||||
* not need to be contacted.
|
||||
*/
|
||||
idx1 = findoption((char_u *)"title");
|
||||
idx1 = findoption("title");
|
||||
if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) {
|
||||
options[idx1].def_val[VI_DEFAULT] = (char_u *)(intptr_t)0;
|
||||
p_title = 0;
|
||||
}
|
||||
idx1 = findoption((char_u *)"icon");
|
||||
idx1 = findoption("icon");
|
||||
if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) {
|
||||
options[idx1].def_val[VI_DEFAULT] = (char_u *)(intptr_t)0;
|
||||
p_icon = 0;
|
||||
@ -1193,7 +1203,7 @@ do_set (
|
||||
goto skip;
|
||||
}
|
||||
if (arg[1] == 't' && arg[2] == '_') { // could be term code
|
||||
opt_idx = findoption_len(arg + 1, (size_t) (len - 1));
|
||||
opt_idx = findoption_len((const char *)arg + 1, (size_t)(len - 1));
|
||||
}
|
||||
len++;
|
||||
if (opt_idx == -1) {
|
||||
@ -1209,7 +1219,7 @@ do_set (
|
||||
len++;
|
||||
}
|
||||
}
|
||||
opt_idx = findoption_len(arg, (size_t) len);
|
||||
opt_idx = findoption_len((const char *)arg, (size_t)len);
|
||||
if (opt_idx == -1) {
|
||||
key = find_key_option(arg);
|
||||
}
|
||||
@ -1391,11 +1401,10 @@ do_set (
|
||||
value = prefix;
|
||||
}
|
||||
|
||||
errmsg = set_bool_option(opt_idx, varp, (int)value,
|
||||
opt_flags);
|
||||
} else { /* numeric or string */
|
||||
if (vim_strchr((char_u *)"=:&<", nextchar) == NULL
|
||||
|| prefix != 1) {
|
||||
errmsg = (char_u *)set_bool_option(opt_idx, varp, (int)value,
|
||||
opt_flags);
|
||||
} else { // Numeric or string.
|
||||
if (strchr("=:&<", nextchar) == NULL || prefix != 1) {
|
||||
errmsg = e_invarg;
|
||||
goto skip;
|
||||
}
|
||||
@ -1448,15 +1457,19 @@ do_set (
|
||||
goto skip;
|
||||
}
|
||||
|
||||
if (adding)
|
||||
if (adding) {
|
||||
value = *(long *)varp + value;
|
||||
if (prepending)
|
||||
}
|
||||
if (prepending) {
|
||||
value = *(long *)varp * value;
|
||||
if (removing)
|
||||
}
|
||||
if (removing) {
|
||||
value = *(long *)varp - value;
|
||||
errmsg = set_num_option(opt_idx, varp, value,
|
||||
errbuf, sizeof(errbuf), opt_flags);
|
||||
} else if (opt_idx >= 0) { /* string */
|
||||
}
|
||||
errmsg = (char_u *)set_num_option(opt_idx, varp, value,
|
||||
errbuf, sizeof(errbuf),
|
||||
opt_flags);
|
||||
} else if (opt_idx >= 0) { // String.
|
||||
char_u *save_arg = NULL;
|
||||
char_u *s = NULL;
|
||||
char_u *oldval = NULL; // previous value if *varp
|
||||
@ -2221,7 +2234,7 @@ static void check_string_option(char_u **pp)
|
||||
*/
|
||||
int was_set_insecurely(char_u *opt, int opt_flags)
|
||||
{
|
||||
int idx = findoption(opt);
|
||||
int idx = findoption((const char *)opt);
|
||||
|
||||
if (idx >= 0) {
|
||||
uint32_t *flagp = insecure_flag(idx, opt_flags);
|
||||
@ -2283,9 +2296,9 @@ set_string_option_direct (
|
||||
int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
|
||||
int idx = opt_idx;
|
||||
|
||||
if (idx == -1) { /* use name */
|
||||
idx = findoption(name);
|
||||
if (idx < 0) { /* not found (should not happen) */
|
||||
if (idx == -1) { // Use name.
|
||||
idx = findoption((const char *)name);
|
||||
if (idx < 0) { // Not found (should not happen).
|
||||
EMSG2(_(e_intern2), "set_string_option_direct()");
|
||||
EMSG2(_("For option %s"), name);
|
||||
return;
|
||||
@ -2569,7 +2582,7 @@ did_set_string_option (
|
||||
// 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);
|
||||
do_unlet(S_LEN("g:colors_name"), true);
|
||||
free_string_option(p_bg);
|
||||
p_bg = vim_strsave((char_u *)(dark ? "dark" : "light"));
|
||||
check_string_option(&p_bg);
|
||||
@ -2765,7 +2778,7 @@ did_set_string_option (
|
||||
// option.
|
||||
opt_idx = ((options[opt_idx].fullname[0] == 'v')
|
||||
? (shada_idx == -1
|
||||
? ((shada_idx = findoption((char_u *) "shada")))
|
||||
? ((shada_idx = findoption("shada")))
|
||||
: shada_idx)
|
||||
: opt_idx);
|
||||
// Update free_oldval now that we have the opt_idx for 'shada', otherwise
|
||||
@ -3406,15 +3419,18 @@ static char_u *set_chars_option(char_u **varp)
|
||||
&& p[len] == ':'
|
||||
&& p[len + 1] != NUL) {
|
||||
s = p + len + 1;
|
||||
c1 = mb_ptr2char_adv(&s);
|
||||
if (mb_char2cells(c1) > 1)
|
||||
c1 = mb_ptr2char_adv((const char_u **)&s);
|
||||
if (mb_char2cells(c1) > 1) {
|
||||
continue;
|
||||
}
|
||||
if (tab[i].cp == &lcs_tab2) {
|
||||
if (*s == NUL)
|
||||
if (*s == NUL) {
|
||||
continue;
|
||||
c2 = mb_ptr2char_adv(&s);
|
||||
if (mb_char2cells(c2) > 1)
|
||||
}
|
||||
c2 = mb_ptr2char_adv((const char_u **)&s);
|
||||
if (mb_char2cells(c2) > 1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (*s == ',' || *s == NUL) {
|
||||
if (round) {
|
||||
@ -3575,24 +3591,24 @@ static void set_option_scriptID_idx(int opt_idx, int opt_flags, int id)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the value of a boolean option, and take care of side effects.
|
||||
* Returns NULL for success, or an error message for an error.
|
||||
*/
|
||||
static char_u *
|
||||
set_bool_option (
|
||||
int opt_idx, /* index in options[] table */
|
||||
char_u *varp, /* pointer to the option variable */
|
||||
int value, /* new value */
|
||||
int opt_flags /* OPT_LOCAL and/or OPT_GLOBAL */
|
||||
)
|
||||
/// Set the value of a boolean option, taking care of side effects
|
||||
///
|
||||
/// @param[in] opt_idx Option index in options[] table.
|
||||
/// @param[out] varp Pointer to the option variable.
|
||||
/// @param[in] value New value.
|
||||
/// @param[in] opt_flags OPT_LOCAL and/or OPT_GLOBAL.
|
||||
///
|
||||
/// @return NULL on success, error message on error.
|
||||
static char *set_bool_option(const int opt_idx, char_u *const varp,
|
||||
const int value,
|
||||
const int opt_flags)
|
||||
{
|
||||
int old_value = *(int *)varp;
|
||||
|
||||
/* Disallow changing some options from secure mode */
|
||||
if ((secure || sandbox != 0)
|
||||
&& (options[opt_idx].flags & P_SECURE)) {
|
||||
return e_secure;
|
||||
return (char *)e_secure;
|
||||
}
|
||||
|
||||
*(int *)varp = value; /* set the new value */
|
||||
@ -3605,20 +3621,18 @@ set_bool_option (
|
||||
*(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = value;
|
||||
|
||||
// Ensure that options set to p_force_on cannot be disabled.
|
||||
if ((int *)varp == &p_force_on && p_force_on == FALSE) {
|
||||
p_force_on = TRUE;
|
||||
return e_unsupportedoption;
|
||||
}
|
||||
if ((int *)varp == &p_force_on && p_force_on == false) {
|
||||
p_force_on = true;
|
||||
return (char *)e_unsupportedoption;
|
||||
// Ensure that options set to p_force_off cannot be enabled.
|
||||
else if ((int *)varp == &p_force_off && p_force_off == TRUE) {
|
||||
p_force_off = FALSE;
|
||||
return e_unsupportedoption;
|
||||
}
|
||||
/* 'undofile' */
|
||||
else if ((int *)varp == &curbuf->b_p_udf || (int *)varp == &p_udf) {
|
||||
/* Only take action when the option was set. When reset we do not
|
||||
* delete the undo file, the option may be set again without making
|
||||
* any changes in between. */
|
||||
} else if ((int *)varp == &p_force_off && p_force_off == true) {
|
||||
p_force_off = false;
|
||||
return (char *)e_unsupportedoption;
|
||||
// 'undofile'
|
||||
} else if ((int *)varp == &curbuf->b_p_udf || (int *)varp == &p_udf) {
|
||||
// Only take action when the option was set. When reset we do not
|
||||
// delete the undo file, the option may be set again without making
|
||||
// any changes in between.
|
||||
if (curbuf->b_p_udf || p_udf) {
|
||||
char_u hash[UNDO_HASH_SIZE];
|
||||
buf_T *save_curbuf = curbuf;
|
||||
@ -3740,8 +3754,8 @@ set_bool_option (
|
||||
if (curwin->w_p_pvw) {
|
||||
FOR_ALL_WINDOWS_IN_TAB(win, curtab) {
|
||||
if (win->w_p_pvw && win != curwin) {
|
||||
curwin->w_p_pvw = FALSE;
|
||||
return (char_u *)N_("E590: A preview window already exists");
|
||||
curwin->w_p_pvw = false;
|
||||
return N_("E590: A preview window already exists");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3889,9 +3903,8 @@ set_bool_option (
|
||||
/* set 'delcombine' */
|
||||
p_deco = TRUE;
|
||||
|
||||
/* Force-set the necessary keymap for arabic */
|
||||
set_option_value((char_u *)"keymap", 0L, (char_u *)"arabic",
|
||||
OPT_LOCAL);
|
||||
// Force-set the necessary keymap for arabic.
|
||||
set_option_value("keymap", 0L, "arabic", OPT_LOCAL);
|
||||
p_altkeymap = 0;
|
||||
p_hkmap = 0;
|
||||
p_fkmap = 0;
|
||||
@ -3957,20 +3970,18 @@ set_bool_option (
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the value of a number option, and take care of side effects.
|
||||
* Returns NULL for success, or an error message for an error.
|
||||
*/
|
||||
static char_u *
|
||||
set_num_option (
|
||||
int opt_idx, /* index in options[] table */
|
||||
char_u *varp, /* pointer to the option variable */
|
||||
long value, /* new value */
|
||||
char_u *errbuf, /* buffer for error messages */
|
||||
size_t errbuflen, /* length of "errbuf" */
|
||||
int opt_flags /* OPT_LOCAL, OPT_GLOBAL and
|
||||
OPT_MODELINE */
|
||||
)
|
||||
/// Set the value of a number option, taking care of side effects
|
||||
///
|
||||
/// @param[in] opt_idx Option index in options[] table.
|
||||
/// @param[out] varp Pointer to the option variable.
|
||||
/// @param[in] value New value.
|
||||
/// @param errbuf Buffer for error messages.
|
||||
/// @param[in] errbuflen Length of `errbuf`.
|
||||
/// @param[in] opt_flags OPT_LOCAL, OPT_GLOBAL or OPT_MODELINE.
|
||||
///
|
||||
/// @return NULL on success, error message on error.
|
||||
static char *set_num_option(int opt_idx, char_u *varp, long value,
|
||||
char_u *errbuf, size_t errbuflen, int opt_flags)
|
||||
{
|
||||
char_u *errmsg = NULL;
|
||||
long old_value = *(long *)varp;
|
||||
@ -3981,7 +3992,7 @@ set_num_option (
|
||||
/* Disallow changing some options from secure mode. */
|
||||
if ((secure || sandbox != 0)
|
||||
&& (options[opt_idx].flags & P_SECURE)) {
|
||||
return e_secure;
|
||||
return (char *)e_secure;
|
||||
}
|
||||
|
||||
*pp = value;
|
||||
@ -4251,8 +4262,9 @@ set_num_option (
|
||||
cmdline_row = (int)(Rows - p_ch);
|
||||
}
|
||||
}
|
||||
if (p_window >= Rows || !option_was_set((char_u *)"window"))
|
||||
if (p_window >= Rows || !option_was_set("window")) {
|
||||
p_window = Rows - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (curbuf->b_p_ts <= 0) {
|
||||
@ -4357,7 +4369,7 @@ set_num_option (
|
||||
curwin->w_set_curswant = TRUE;
|
||||
check_redraw(options[opt_idx].flags);
|
||||
|
||||
return errmsg;
|
||||
return (char *)errmsg;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4395,39 +4407,36 @@ static void check_redraw(uint32_t flags)
|
||||
/// @param[in] len Length of the option.
|
||||
///
|
||||
/// @return Index of the option or -1 if option was not found.
|
||||
int findoption_len(const char_u *const arg, const size_t len)
|
||||
int findoption_len(const char *const arg, const size_t len)
|
||||
{
|
||||
char *s, *p;
|
||||
const char *s;
|
||||
const char *p;
|
||||
static int quick_tab[27] = { 0, 0 }; // quick access table
|
||||
int is_term_opt;
|
||||
|
||||
/*
|
||||
* For first call: Initialize the quick-access table.
|
||||
* It contains the index for the first option that starts with a certain
|
||||
* letter. There are 26 letters, plus the first "t_" option.
|
||||
*/
|
||||
// For first call: Initialize the quick-access table.
|
||||
// It contains the index for the first option that starts with a certain
|
||||
// letter. There are 26 letters, plus the first "t_" option.
|
||||
if (quick_tab[1] == 0) {
|
||||
p = options[0].fullname;
|
||||
for (short int i = 1; (s = options[i].fullname) != NULL; i++) {
|
||||
if (s[0] != p[0]) {
|
||||
if (s[0] == 't' && s[1] == '_')
|
||||
if (s[0] == 't' && s[1] == '_') {
|
||||
quick_tab[26] = i;
|
||||
else
|
||||
} else {
|
||||
quick_tab[CharOrdLow(s[0])] = i;
|
||||
}
|
||||
}
|
||||
p = s;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for name starting with an illegal character.
|
||||
*/
|
||||
// Check for name starting with an illegal character.
|
||||
if (len == 0 || arg[0] < 'a' || arg[0] > 'z') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int opt_idx;
|
||||
is_term_opt = (len > 2 && arg[0] == 't' && arg[1] == '_');
|
||||
const bool is_term_opt = (len > 2 && arg[0] == 't' && arg[1] == '_');
|
||||
if (is_term_opt) {
|
||||
opt_idx = quick_tab[26];
|
||||
} else {
|
||||
@ -4435,7 +4444,7 @@ int findoption_len(const char_u *const arg, const size_t len)
|
||||
}
|
||||
// Match full name
|
||||
for (; (s = options[opt_idx].fullname) != NULL; opt_idx++) {
|
||||
if (STRNCMP(arg, s, len) == 0 && s[len] == NUL) {
|
||||
if (strncmp(arg, s, len) == 0 && s[len] == NUL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -4444,20 +4453,22 @@ int findoption_len(const char_u *const arg, const size_t len)
|
||||
// Match short name
|
||||
for (; options[opt_idx].fullname != NULL; opt_idx++) {
|
||||
s = options[opt_idx].shortname;
|
||||
if (s != NULL && STRNCMP(arg, s, len) == 0 && s[len] == NUL) {
|
||||
if (s != NULL && strncmp(arg, s, len) == 0 && s[len] == NUL) {
|
||||
break;
|
||||
}
|
||||
s = NULL;
|
||||
}
|
||||
}
|
||||
if (s == NULL)
|
||||
if (s == NULL) {
|
||||
opt_idx = -1;
|
||||
}
|
||||
return opt_idx;
|
||||
}
|
||||
|
||||
bool is_tty_option(char *name)
|
||||
bool is_tty_option(const char *name)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
return (name[0] == 't' && name[1] == '_') || !strcmp((char *)name, "term");
|
||||
return (name[0] == 't' && name[1] == '_') || strcmp(name, "term") == 0;
|
||||
}
|
||||
|
||||
#define TCO_BUFFER_SIZE 8
|
||||
@ -4493,7 +4504,7 @@ bool get_tty_option(char *name, char **value)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set_tty_option(char *name, char *value)
|
||||
bool set_tty_option(const char *name, const char *value)
|
||||
{
|
||||
if (!strcmp(name, "t_Co")) {
|
||||
int colors = atoi(value);
|
||||
@ -4504,23 +4515,24 @@ bool set_tty_option(char *name, char *value)
|
||||
if (colors != t_colors) {
|
||||
t_colors = colors;
|
||||
// We now have a different color setup, initialize it again.
|
||||
init_highlight(TRUE, FALSE);
|
||||
init_highlight(true, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return is_tty_option(name) || !strcmp(name, "term")
|
||||
|| !strcmp(name, "ttytype");
|
||||
return (is_tty_option(name) || !strcmp(name, "term")
|
||||
|| !strcmp(name, "ttytype"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Find index for option 'arg'.
|
||||
* Return -1 if not found.
|
||||
*/
|
||||
static int findoption(char_u *arg)
|
||||
/// Find index for an option
|
||||
///
|
||||
/// @param[in] arg Option name.
|
||||
///
|
||||
/// @return Option index or -1 if option was not found.
|
||||
static int findoption(const char *const arg)
|
||||
{
|
||||
return findoption_len(arg, STRLEN(arg));
|
||||
return findoption_len(arg, strlen(arg));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4548,9 +4560,10 @@ get_option_value (
|
||||
int opt_idx;
|
||||
char_u *varp;
|
||||
|
||||
opt_idx = findoption(name);
|
||||
if (opt_idx < 0) /* unknown option */
|
||||
opt_idx = findoption((const char *)name);
|
||||
if (opt_idx < 0) { // Unknown option.
|
||||
return -3;
|
||||
}
|
||||
|
||||
varp = get_varp_scope(&(options[opt_idx]), opt_flags);
|
||||
|
||||
@ -4608,7 +4621,7 @@ int get_option_value_strict(char *name,
|
||||
char_u *varp = NULL;
|
||||
vimoption_T *p;
|
||||
int rv = 0;
|
||||
int opt_idx = findoption((uint8_t *)name);
|
||||
int opt_idx = findoption(name);
|
||||
if (opt_idx < 0) {
|
||||
return 0;
|
||||
}
|
||||
@ -4702,21 +4715,19 @@ int get_option_value_strict(char *name,
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the value of option "name".
|
||||
* Use "string" for string options, use "number" for other options.
|
||||
*
|
||||
* Returns NULL on success or error message on error.
|
||||
*/
|
||||
char_u *
|
||||
set_option_value (
|
||||
char_u *name,
|
||||
long number,
|
||||
char_u *string,
|
||||
int opt_flags /* OPT_LOCAL or 0 (both) */
|
||||
)
|
||||
/// Set the value of an option
|
||||
///
|
||||
/// @param[in] name Option name.
|
||||
/// @param[in] number New value for the number or boolean option.
|
||||
/// @param[in] string New value for string option.
|
||||
/// @param[in] opt_flags Flags: OPT_LOCAL or 0 (both).
|
||||
///
|
||||
/// @return NULL on success, error message on error.
|
||||
char *set_option_value(const char *const name, const long number,
|
||||
const char *const string, const int opt_flags)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
if (set_tty_option((char *)name, (char *)string)) {
|
||||
if (set_tty_option(name, string)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -4724,9 +4735,9 @@ set_option_value (
|
||||
char_u *varp;
|
||||
|
||||
opt_idx = findoption(name);
|
||||
if (opt_idx < 0)
|
||||
if (opt_idx < 0) {
|
||||
EMSG2(_("E355: Unknown option: %s"), name);
|
||||
else {
|
||||
} else {
|
||||
uint32_t flags = options[opt_idx].flags;
|
||||
// Disallow changing some options in the sandbox
|
||||
if (sandbox > 0 && (flags & P_SECURE)) {
|
||||
@ -4734,11 +4745,11 @@ set_option_value (
|
||||
return NULL;
|
||||
}
|
||||
if (flags & P_STRING) {
|
||||
const char *s = (const char *)string;
|
||||
const char *s = string;
|
||||
if (s == NULL) {
|
||||
s = "";
|
||||
}
|
||||
return (char_u *)set_string_option(opt_idx, s, opt_flags);
|
||||
return set_string_option(opt_idx, s, opt_flags);
|
||||
} else {
|
||||
varp = get_varp_scope(&(options[opt_idx]), opt_flags);
|
||||
if (varp != NULL) { /* hidden option is not changed */
|
||||
@ -4757,12 +4768,11 @@ set_option_value (
|
||||
return NULL; // do nothing as we hit an error
|
||||
}
|
||||
}
|
||||
if (flags & P_NUM)
|
||||
return set_num_option(opt_idx, varp, number,
|
||||
NULL, 0, opt_flags);
|
||||
else
|
||||
return set_bool_option(opt_idx, varp, (int)number,
|
||||
opt_flags);
|
||||
if (flags & P_NUM) {
|
||||
return set_num_option(opt_idx, varp, number, NULL, 0, opt_flags);
|
||||
} else {
|
||||
return set_bool_option(opt_idx, varp, (int)number, opt_flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4773,9 +4783,10 @@ char_u *get_highlight_default(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = findoption((char_u *)"hl");
|
||||
if (i >= 0)
|
||||
i = findoption("hl");
|
||||
if (i >= 0) {
|
||||
return options[i].def_val[VI_DEFAULT];
|
||||
}
|
||||
return (char_u *)NULL;
|
||||
}
|
||||
|
||||
@ -5212,7 +5223,7 @@ void unset_global_local_option(char *name, void *from)
|
||||
vimoption_T *p;
|
||||
buf_T *buf = (buf_T *)from;
|
||||
|
||||
int opt_idx = findoption((uint8_t *)name);
|
||||
int opt_idx = findoption(name);
|
||||
if (opt_idx < 0) {
|
||||
EMSG2(_("E355: Unknown option: %s"), name);
|
||||
return;
|
||||
@ -5775,11 +5786,12 @@ void reset_modifiable(void)
|
||||
{
|
||||
int opt_idx;
|
||||
|
||||
curbuf->b_p_ma = FALSE;
|
||||
p_ma = FALSE;
|
||||
opt_idx = findoption((char_u *)"ma");
|
||||
if (opt_idx >= 0)
|
||||
options[opt_idx].def_val[VI_DEFAULT] = FALSE;
|
||||
curbuf->b_p_ma = false;
|
||||
p_ma = false;
|
||||
opt_idx = findoption("ma");
|
||||
if (opt_idx >= 0) {
|
||||
options[opt_idx].def_val[VI_DEFAULT] = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -5877,15 +5889,15 @@ set_context_in_set_cmd (
|
||||
expand_option_name[2] = p[-2];
|
||||
expand_option_name[3] = p[-1];
|
||||
} else {
|
||||
/* Allow * wildcard */
|
||||
while (ASCII_ISALNUM(*p) || *p == '_' || *p == '*')
|
||||
// Allow * wildcard.
|
||||
while (ASCII_ISALNUM(*p) || *p == '_' || *p == '*') {
|
||||
p++;
|
||||
if (*p == NUL)
|
||||
}
|
||||
if (*p == NUL) {
|
||||
return;
|
||||
}
|
||||
nextchar = *p;
|
||||
*p = NUL;
|
||||
opt_idx = findoption(arg);
|
||||
*p = nextchar;
|
||||
opt_idx = findoption_len((const char *)arg, (size_t)(p - arg));
|
||||
if (opt_idx == -1 || options[opt_idx].var == NULL) {
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
return;
|
||||
@ -6047,7 +6059,7 @@ void ExpandOldSetting(int *num_file, char_u ***file)
|
||||
* For a terminal key code expand_option_idx is < 0.
|
||||
*/
|
||||
if (expand_option_idx < 0) {
|
||||
expand_option_idx = findoption(expand_option_name);
|
||||
expand_option_idx = findoption((const char *)expand_option_name);
|
||||
}
|
||||
|
||||
if (expand_option_idx >= 0) {
|
||||
@ -6447,20 +6459,22 @@ void vimrc_found(char_u *fname, char_u *envname)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE when option "name" has been set.
|
||||
* Only works correctly for global options.
|
||||
*/
|
||||
int option_was_set(char_u *name)
|
||||
/// Check whether global option has been set
|
||||
///
|
||||
/// @param[in] name Option name.
|
||||
///
|
||||
/// @return True if it was set.
|
||||
static bool option_was_set(const char *name)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = findoption(name);
|
||||
if (idx < 0) /* unknown option */
|
||||
return FALSE;
|
||||
if (options[idx].flags & P_WAS_SET)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
if (idx < 0) { // Unknown option.
|
||||
return false;
|
||||
} else if (options[idx].flags & P_WAS_SET) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -6876,8 +6890,8 @@ void set_fileformat(int eol_style, int opt_flags)
|
||||
need_maketitle = true; // Set window title later.
|
||||
}
|
||||
|
||||
/// Skip to next part of an option argument: Skip space and comma.
|
||||
char_u *skip_to_option_part(char_u *p)
|
||||
/// Skip to next part of an option argument: skip space and comma
|
||||
char_u *skip_to_option_part(const char_u *p)
|
||||
{
|
||||
if (*p == ',') {
|
||||
p++;
|
||||
@ -6885,7 +6899,7 @@ char_u *skip_to_option_part(char_u *p)
|
||||
while (*p == ' ') {
|
||||
p++;
|
||||
}
|
||||
return p;
|
||||
return (char_u *)p;
|
||||
}
|
||||
|
||||
/// Isolate one part of a string option separated by `sep_chars`.
|
||||
@ -6945,10 +6959,11 @@ bool signcolumn_on(win_T *wp)
|
||||
return wp->w_buffer->b_signlist != NULL;
|
||||
}
|
||||
|
||||
/// Get window or buffer local options.
|
||||
dict_T * get_winbuf_options(int bufopt)
|
||||
/// Get window or buffer local options
|
||||
dict_T *get_winbuf_options(const int bufopt)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC
|
||||
{
|
||||
dict_T *d = dict_alloc();
|
||||
dict_T *const d = tv_dict_alloc();
|
||||
|
||||
for (int opt_idx = 0; options[opt_idx].fullname; opt_idx++) {
|
||||
struct vimoption *opt = &options[opt_idx];
|
||||
@ -6959,9 +6974,10 @@ dict_T * get_winbuf_options(int bufopt)
|
||||
|
||||
if (varp != NULL) {
|
||||
if (opt->flags & P_STRING) {
|
||||
dict_add_nr_str(d, opt->fullname, 0L, *(char_u **)varp);
|
||||
tv_dict_add_str(d, opt->fullname, strlen(opt->fullname),
|
||||
*(const char **)varp);
|
||||
} else {
|
||||
dict_add_nr_str(d, opt->fullname, *varp, NULL);
|
||||
tv_dict_add_nr(d, opt->fullname, strlen(opt->fullname), *varp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,11 +91,11 @@ int os_dirname(char_u *buf, size_t len)
|
||||
/// Check if the given path is a directory and not a symlink to a directory.
|
||||
/// @return `true` if `name` is a directory and NOT a symlink to a directory.
|
||||
/// `false` if `name` is not a directory or if an error occurred.
|
||||
bool os_isrealdir(const char_u *name)
|
||||
bool os_isrealdir(const char *name)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
uv_fs_t request;
|
||||
if (uv_fs_lstat(&fs_loop, &request, (char *)name, NULL) != kLibuvSuccess) {
|
||||
if (uv_fs_lstat(&fs_loop, &request, name, NULL) != kLibuvSuccess) {
|
||||
return false;
|
||||
}
|
||||
if (S_ISLNK(request.statbuf.st_mode)) {
|
||||
@ -111,7 +111,7 @@ bool os_isrealdir(const char_u *name)
|
||||
bool os_isdir(const char_u *name)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
int32_t mode = os_getperm(name);
|
||||
int32_t mode = os_getperm((const char *)name);
|
||||
if (mode < 0) {
|
||||
return false;
|
||||
}
|
||||
@ -236,7 +236,8 @@ bool os_can_exe(const char_u *name, char_u **abspath, bool use_path)
|
||||
pathext);
|
||||
#else
|
||||
// Must have path separator, cannot execute files in the current directory.
|
||||
bool ok = gettail_dir(name) != name && is_executable((char *)name);
|
||||
const bool ok = ((const char_u *)gettail_dir((const char *)name) != name
|
||||
&& is_executable((char *)name));
|
||||
#endif
|
||||
if (ok) {
|
||||
if (abspath != NULL) {
|
||||
@ -254,7 +255,7 @@ bool os_can_exe(const char_u *name, char_u **abspath, bool use_path)
|
||||
static bool is_executable(const char *name)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
int32_t mode = os_getperm((char_u *)name);
|
||||
int32_t mode = os_getperm((const char *)name);
|
||||
|
||||
if (mode < 0) {
|
||||
return false;
|
||||
@ -606,11 +607,11 @@ static int os_stat(const char *name, uv_stat_t *statbuf)
|
||||
/// Get the file permissions for a given file.
|
||||
///
|
||||
/// @return libuv error code on error.
|
||||
int32_t os_getperm(const char_u *name)
|
||||
int32_t os_getperm(const char *name)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
uv_stat_t statbuf;
|
||||
int stat_result = os_stat((char *)name, &statbuf);
|
||||
int stat_result = os_stat(name, &statbuf);
|
||||
if (stat_result == kLibuvSuccess) {
|
||||
return (int32_t)statbuf.st_mode;
|
||||
} else {
|
||||
@ -621,11 +622,11 @@ int32_t os_getperm(const char_u *name)
|
||||
/// Set the permission of a file.
|
||||
///
|
||||
/// @return `OK` for success, `FAIL` for failure.
|
||||
int os_setperm(const char_u *name, int perm)
|
||||
int os_setperm(const char *const name, int perm)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
int r;
|
||||
RUN_UV_FS_FUNC(r, uv_fs_chmod, (const char *)name, perm, NULL);
|
||||
RUN_UV_FS_FUNC(r, uv_fs_chmod, name, perm, NULL);
|
||||
return (r == kLibuvSuccess ? OK : FAIL);
|
||||
}
|
||||
|
||||
@ -979,13 +980,13 @@ bool os_fileid_equal_fileinfo(const FileID *file_id,
|
||||
/// When "fname" is the name of a shortcut (*.lnk) resolve the file it points
|
||||
/// to and return that name in allocated memory.
|
||||
/// Otherwise NULL is returned.
|
||||
char *os_resolve_shortcut(char_u *fname)
|
||||
char *os_resolve_shortcut(const char *fname)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC
|
||||
{
|
||||
HRESULT hr;
|
||||
IPersistFile *ppf = NULL;
|
||||
OLECHAR wsz[MAX_PATH];
|
||||
char *rfname = NULL;
|
||||
int len;
|
||||
IShellLinkW *pslw = NULL;
|
||||
WIN32_FIND_DATAW ffdw;
|
||||
|
||||
@ -994,7 +995,7 @@ char *os_resolve_shortcut(char_u *fname)
|
||||
if (fname == NULL) {
|
||||
return rfname;
|
||||
}
|
||||
len = (int)STRLEN(fname);
|
||||
const size_t len = strlen(fname);
|
||||
if (len <= 4 || STRNICMP(fname + len - 4, ".lnk", 4) != 0) {
|
||||
return rfname;
|
||||
}
|
||||
@ -1006,7 +1007,7 @@ char *os_resolve_shortcut(char_u *fname)
|
||||
&IID_IShellLinkW, (void **)&pslw);
|
||||
if (hr == S_OK) {
|
||||
WCHAR *p;
|
||||
int conversion_result = utf8_to_utf16((char *)fname, &p);
|
||||
const int conversion_result = utf8_to_utf16(fname, &p);
|
||||
if (conversion_result != 0) {
|
||||
EMSG2("utf8_to_utf16 failed: %s", uv_strerror(conversion_result));
|
||||
}
|
||||
@ -1036,7 +1037,7 @@ char *os_resolve_shortcut(char_u *fname)
|
||||
ZeroMemory(wsz, MAX_PATH * sizeof(WCHAR));
|
||||
hr = pslw->lpVtbl->GetPath(pslw, wsz, MAX_PATH, &ffdw, 0);
|
||||
if (hr == S_OK && wsz[0] != NUL) {
|
||||
int conversion_result = utf16_to_utf8(wsz, &rfname);
|
||||
const int conversion_result = utf16_to_utf8(wsz, &rfname);
|
||||
if (conversion_result != 0) {
|
||||
EMSG2("utf16_to_utf8 failed: %s", uv_strerror(conversion_result));
|
||||
}
|
||||
|
@ -12,8 +12,9 @@ typedef struct pty_process {
|
||||
#define pty_process_spawn(job) libuv_process_spawn((LibuvProcess *)job)
|
||||
#define pty_process_close(job) libuv_process_close((LibuvProcess *)job)
|
||||
#define pty_process_close_master(job) libuv_process_close((LibuvProcess *)job)
|
||||
#define pty_process_resize(job, width, height)
|
||||
#define pty_process_teardown(loop)
|
||||
#define pty_process_resize(job, width, height) ( \
|
||||
(void)job, (void)width, (void)height, 0)
|
||||
#define pty_process_teardown(loop) ((void)loop, 0)
|
||||
|
||||
static inline PtyProcess pty_process_init(Loop *loop, void *data)
|
||||
{
|
||||
|
@ -110,14 +110,14 @@ void mch_copy_sec(char_u *from_file, char_u *to_file)
|
||||
|
||||
// Return a pointer to the ACL of file "fname" in allocated memory.
|
||||
// Return NULL if the ACL is not available for whatever reason.
|
||||
vim_acl_T mch_get_acl(char_u *fname)
|
||||
vim_acl_T mch_get_acl(const char_u *fname)
|
||||
{
|
||||
vim_acl_T ret = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Set the ACL of file "fname" to "acl" (unless it's NULL).
|
||||
void mch_set_acl(char_u *fname, vim_acl_T aclent)
|
||||
void mch_set_acl(const char_u *fname, vim_acl_T aclent)
|
||||
{
|
||||
if (aclent == NULL)
|
||||
return;
|
||||
|
117
src/nvim/path.c
117
src/nvim/path.c
@ -159,7 +159,7 @@ const char_u *invocation_path_tail(const char_u *invocation, size_t *len)
|
||||
/// @param fname A file path. (Must be != NULL.)
|
||||
/// @return Pointer to first found path separator + 1.
|
||||
/// An empty string, if `fname` doesn't contain a path separator,
|
||||
char_u *path_next_component(char_u *fname)
|
||||
const char *path_next_component(const char *fname)
|
||||
{
|
||||
assert(fname != NULL);
|
||||
while (*fname != NUL && !vim_ispathsep(*fname)) {
|
||||
@ -282,48 +282,63 @@ bool dir_of_file_exists(char_u *fname)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Versions of fnamecmp() and fnamencmp() that handle '/' and '\' equally
|
||||
* and deal with 'fileignorecase'.
|
||||
*/
|
||||
int vim_fnamecmp(char_u *x, char_u *y)
|
||||
/// Compare two file names
|
||||
///
|
||||
/// Handles '/' and '\\' correctly and deals with &fileignorecase option.
|
||||
///
|
||||
/// @param[in] fname1 First file name.
|
||||
/// @param[in] fname2 Second file name.
|
||||
///
|
||||
/// @return 0 if they are equal, non-zero otherwise.
|
||||
int path_fnamecmp(const char *fname1, const char *fname2)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
return vim_fnamencmp(x, y, MAXPATHL);
|
||||
const size_t len1 = strlen(fname1);
|
||||
const size_t len2 = strlen(fname2);
|
||||
return path_fnamencmp(fname1, fname2, MAX(len1, len2));
|
||||
#else
|
||||
if (p_fic)
|
||||
return mb_stricmp(x, y);
|
||||
return STRCMP(x, y);
|
||||
return mb_strcmp_ic((bool)p_fic, fname1, fname2);
|
||||
#endif
|
||||
}
|
||||
|
||||
int vim_fnamencmp(char_u *x, char_u *y, size_t len)
|
||||
/// Compare two file names
|
||||
///
|
||||
/// Handles '/' and '\\' correctly and deals with &fileignorecase option.
|
||||
///
|
||||
/// @param[in] fname1 First file name.
|
||||
/// @param[in] fname2 Second file name.
|
||||
/// @param[in] len Compare at most len bytes.
|
||||
///
|
||||
/// @return 0 if they are equal, non-zero otherwise.
|
||||
int path_fnamencmp(const char *const fname1, const char *const fname2,
|
||||
size_t len)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
char_u *px = x;
|
||||
char_u *py = y;
|
||||
int cx = NUL;
|
||||
int cy = NUL;
|
||||
int c1 = NUL;
|
||||
int c2 = NUL;
|
||||
|
||||
const char *p1 = fname1;
|
||||
const char *p2 = fname2;
|
||||
while (len > 0) {
|
||||
cx = PTR2CHAR(px);
|
||||
cy = PTR2CHAR(py);
|
||||
if (cx == NUL || cy == NUL
|
||||
|| ((p_fic ? vim_tolower(cx) != vim_tolower(cy) : cx != cy)
|
||||
&& !(cx == '/' && cy == '\\')
|
||||
&& !(cx == '\\' && cy == '/')))
|
||||
c1 = PTR2CHAR((const char_u *)p1);
|
||||
c2 = PTR2CHAR((const char_u *)p2);
|
||||
if ((c1 == NUL || c2 == NUL
|
||||
|| (!((c1 == '/' || c1 == '\\') && (c2 == '\\' || c2 == '/'))))
|
||||
&& (p_fic ? (c1 != c2 && CH_FOLD(c1) != CH_FOLD(c2)) : c1 != c2)) {
|
||||
break;
|
||||
len -= MB_PTR2LEN(px);
|
||||
px += MB_PTR2LEN(px);
|
||||
py += MB_PTR2LEN(py);
|
||||
}
|
||||
len -= MB_PTR2LEN((const char_u *)p1);
|
||||
p1 += MB_PTR2LEN((const char_u *)p1);
|
||||
p2 += MB_PTR2LEN((const char_u *)p2);
|
||||
}
|
||||
if (len == 0)
|
||||
return 0;
|
||||
return cx - cy;
|
||||
return c1 - c2;
|
||||
#else
|
||||
if (p_fic)
|
||||
return mb_strnicmp(x, y, len);
|
||||
return STRNCMP(x, y, len);
|
||||
if (p_fic) {
|
||||
return mb_strnicmp((const char_u *)fname1, (const char_u *)fname2, len);
|
||||
}
|
||||
return strncmp(fname1, fname2, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -416,7 +431,7 @@ bool add_pathsep(char *p)
|
||||
///
|
||||
/// @return [allocated] Copy of absolute path to `fname` or NULL when
|
||||
/// `fname` is NULL.
|
||||
char *FullName_save(char *fname, bool force)
|
||||
char *FullName_save(const char *fname, bool force)
|
||||
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC
|
||||
{
|
||||
if (fname == NULL) {
|
||||
@ -804,7 +819,7 @@ static void expand_path_option(char_u *curdir, garray_T *gap)
|
||||
}
|
||||
STRMOVE(buf + len + 1, buf);
|
||||
STRCPY(buf, curdir);
|
||||
buf[len] = PATHSEP;
|
||||
buf[len] = (char_u)PATHSEP;
|
||||
simplify_filename(buf);
|
||||
}
|
||||
|
||||
@ -891,9 +906,9 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
|
||||
in_curdir = xcalloc((size_t)gap->ga_len, sizeof(char_u *));
|
||||
|
||||
for (int i = 0; i < gap->ga_len && !got_int; i++) {
|
||||
char_u *path = fnames[i];
|
||||
char_u *path = fnames[i];
|
||||
int is_in_curdir;
|
||||
char_u *dir_end = gettail_dir(path);
|
||||
char_u *dir_end = (char_u *)gettail_dir((const char *)path);
|
||||
char_u *pathsep_p;
|
||||
char_u *path_cutoff;
|
||||
|
||||
@ -995,18 +1010,22 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
|
||||
ga_remove_duplicate_strings(gap);
|
||||
}
|
||||
|
||||
/// Return the end of the directory name, on the first path
|
||||
/// separator:
|
||||
/// "/path/file", "/path/dir/", "/path//dir", "/file"
|
||||
/// ^ ^ ^ ^
|
||||
char_u *gettail_dir(const char_u *fname)
|
||||
/// Find end of the directory name
|
||||
///
|
||||
/// @param[in] fname File name to process.
|
||||
///
|
||||
/// @return end of the directory name, on the first path separator:
|
||||
///
|
||||
/// "/path/file", "/path/dir/", "/path//dir", "/file"
|
||||
/// ^ ^ ^ ^
|
||||
const char *gettail_dir(const char *const fname)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
const char_u *dir_end = fname;
|
||||
const char_u *next_dir_end = fname;
|
||||
const char *dir_end = fname;
|
||||
const char *next_dir_end = fname;
|
||||
bool look_for_sep = true;
|
||||
const char_u *p;
|
||||
|
||||
for (p = fname; *p != NUL; ) {
|
||||
for (const char *p = fname; *p != NUL; ) {
|
||||
if (vim_ispathsep(*p)) {
|
||||
if (look_for_sep) {
|
||||
next_dir_end = p;
|
||||
@ -1019,7 +1038,7 @@ char_u *gettail_dir(const char_u *fname)
|
||||
}
|
||||
mb_ptr_adv(p);
|
||||
}
|
||||
return (char_u *)dir_end;
|
||||
return dir_end;
|
||||
}
|
||||
|
||||
|
||||
@ -1314,12 +1333,12 @@ static int expand_backtick(
|
||||
/// When the path looks like a URL leave it unmodified.
|
||||
void slash_adjust(char_u *p)
|
||||
{
|
||||
if (path_with_url(p)) {
|
||||
if (path_with_url((const char *)p)) {
|
||||
return;
|
||||
}
|
||||
while (*p) {
|
||||
if (*p == psepcN) {
|
||||
*p = psepc;
|
||||
if (*p == (char_u)psepcN) {
|
||||
*p = (char_u)psepc;
|
||||
}
|
||||
mb_ptr_adv(p);
|
||||
}
|
||||
@ -1538,8 +1557,8 @@ void simplify_filename(char_u *filename)
|
||||
p = tail; /* skip to char after ".." or "../" */
|
||||
}
|
||||
} else {
|
||||
++components; /* simple path component */
|
||||
p = path_next_component(p);
|
||||
components++; // Simple path component.
|
||||
p = (char_u *)path_next_component((const char *)p);
|
||||
}
|
||||
} while (*p != NUL);
|
||||
}
|
||||
|
@ -610,13 +610,10 @@ static int pum_set_selected(int n, int repeat)
|
||||
if (res == OK) {
|
||||
// Edit a new, empty buffer. Set options for a "wipeout"
|
||||
// buffer.
|
||||
set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL);
|
||||
set_option_value((char_u *)"bt", 0L,
|
||||
(char_u *)"nofile", OPT_LOCAL);
|
||||
set_option_value((char_u *)"bh", 0L,
|
||||
(char_u *)"wipe", OPT_LOCAL);
|
||||
set_option_value((char_u *)"diff", 0L,
|
||||
NULL, OPT_LOCAL);
|
||||
set_option_value("swf", 0L, NULL, OPT_LOCAL);
|
||||
set_option_value("bt", 0L, "nofile", OPT_LOCAL);
|
||||
set_option_value("bh", 0L, "wipe", OPT_LOCAL);
|
||||
set_option_value("diff", 0L, NULL, OPT_LOCAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1236,7 +1236,7 @@ static int qf_add_entry(qf_info_T *qi, char_u *dir, char_u *fname, int bufnum,
|
||||
qfp->qf_nr = nr;
|
||||
if (type != 1 && !vim_isprintc(type)) /* only printable chars allowed */
|
||||
type = 0;
|
||||
qfp->qf_type = type;
|
||||
qfp->qf_type = (char_u)type;
|
||||
qfp->qf_valid = valid;
|
||||
|
||||
lastp = &qi->qf_lists[qi->qf_curlist].qf_last;
|
||||
@ -2581,15 +2581,13 @@ void ex_copen(exarg_T *eap)
|
||||
else {
|
||||
/* Create a new quickfix buffer */
|
||||
(void)do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, oldwin);
|
||||
/* switch off 'swapfile' */
|
||||
set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL);
|
||||
set_option_value((char_u *)"bt", 0L, (char_u *)"quickfix",
|
||||
OPT_LOCAL);
|
||||
set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL);
|
||||
// Switch off 'swapfile'.
|
||||
set_option_value("swf", 0L, NULL, OPT_LOCAL);
|
||||
set_option_value("bt", 0L, "quickfix", OPT_LOCAL);
|
||||
set_option_value("bh", 0L, "wipe", OPT_LOCAL);
|
||||
RESET_BINDING(curwin);
|
||||
curwin->w_p_diff = FALSE;
|
||||
set_option_value((char_u *)"fdm", 0L, (char_u *)"manual",
|
||||
OPT_LOCAL);
|
||||
curwin->w_p_diff = false;
|
||||
set_option_value("fdm", 0L, "manual", OPT_LOCAL);
|
||||
}
|
||||
|
||||
/* Only set the height when still in the same tab page and there is no
|
||||
@ -2901,14 +2899,14 @@ static void qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last)
|
||||
}
|
||||
}
|
||||
|
||||
/* correct cursor position */
|
||||
check_lnums(TRUE);
|
||||
// Correct cursor position.
|
||||
check_lnums(true);
|
||||
|
||||
if (old_last == NULL) {
|
||||
// Set the 'filetype' to "qf" each time after filling the buffer. This
|
||||
// resembles reading a file into a buffer, it's more logical when using
|
||||
// autocommands.
|
||||
set_option_value((char_u *)"ft", 0L, (char_u *)"qf", OPT_LOCAL);
|
||||
set_option_value("ft", 0L, "qf", OPT_LOCAL);
|
||||
curbuf->b_p_ma = false;
|
||||
|
||||
keep_filetype = true; // don't detect 'filetype'
|
||||
@ -3974,7 +3972,6 @@ static void unload_dummy_buffer(buf_T *buf, char_u *dirname_start)
|
||||
int get_errorlist(win_T *wp, int qf_idx, list_T *list)
|
||||
{
|
||||
qf_info_T *qi = &ql_info;
|
||||
dict_T *dict;
|
||||
char_u buf[2];
|
||||
qfline_T *qfp;
|
||||
int i;
|
||||
@ -4002,23 +3999,34 @@ int get_errorlist(win_T *wp, int qf_idx, list_T *list)
|
||||
if (bufnum != 0 && (buflist_findnr(bufnum) == NULL))
|
||||
bufnum = 0;
|
||||
|
||||
dict = dict_alloc();
|
||||
list_append_dict(list, dict);
|
||||
dict_T *const dict = tv_dict_alloc();
|
||||
tv_list_append_dict(list, dict);
|
||||
|
||||
buf[0] = qfp->qf_type;
|
||||
buf[1] = NUL;
|
||||
if ( dict_add_nr_str(dict, "bufnr", (long)bufnum, NULL) == FAIL
|
||||
|| dict_add_nr_str(dict, "lnum", (long)qfp->qf_lnum, NULL) == FAIL
|
||||
|| dict_add_nr_str(dict, "col", (long)qfp->qf_col, NULL) == FAIL
|
||||
|| dict_add_nr_str(dict, "vcol", (long)qfp->qf_viscol, NULL) == FAIL
|
||||
|| dict_add_nr_str(dict, "nr", (long)qfp->qf_nr, NULL) == FAIL
|
||||
|| dict_add_nr_str(dict, "pattern", 0L,
|
||||
qfp->qf_pattern == NULL ? (char_u *)"" : qfp->qf_pattern) == FAIL
|
||||
|| dict_add_nr_str(dict, "text", 0L,
|
||||
qfp->qf_text == NULL ? (char_u *)"" : qfp->qf_text) == FAIL
|
||||
|| dict_add_nr_str(dict, "type", 0L, buf) == FAIL
|
||||
|| dict_add_nr_str(dict, "valid", (long)qfp->qf_valid, NULL) == FAIL)
|
||||
return FAIL;
|
||||
if (tv_dict_add_nr(dict, S_LEN("bufnr"), (varnumber_T)bufnum) == FAIL
|
||||
|| (tv_dict_add_nr(dict, S_LEN("lnum"), (varnumber_T)qfp->qf_lnum)
|
||||
== FAIL)
|
||||
|| (tv_dict_add_nr(dict, S_LEN("col"), (varnumber_T)qfp->qf_col)
|
||||
== FAIL)
|
||||
|| (tv_dict_add_nr(dict, S_LEN("vcol"), (varnumber_T)qfp->qf_viscol)
|
||||
== FAIL)
|
||||
|| (tv_dict_add_nr(dict, S_LEN("nr"), (varnumber_T)qfp->qf_nr) == FAIL)
|
||||
|| tv_dict_add_str(dict, S_LEN("pattern"),
|
||||
(qfp->qf_pattern == NULL
|
||||
? ""
|
||||
: (const char *)qfp->qf_pattern)) == FAIL
|
||||
|| tv_dict_add_str(dict, S_LEN("text"),
|
||||
(qfp->qf_text == NULL
|
||||
? ""
|
||||
: (const char *)qfp->qf_text)) == FAIL
|
||||
|| tv_dict_add_str(dict, S_LEN("type"), (const char *)buf) == FAIL
|
||||
|| (tv_dict_add_nr(dict, S_LEN("valid"), (varnumber_T)qfp->qf_valid)
|
||||
== FAIL)) {
|
||||
// tv_dict_add* fail only if key already exist, but this is a newly
|
||||
// allocated dictionary which is thus guaranteed to have no existing keys.
|
||||
assert(false);
|
||||
}
|
||||
|
||||
qfp = qfp->qf_next;
|
||||
if (qfp == NULL) {
|
||||
@ -4057,7 +4065,7 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
||||
int flags = QF_GETLIST_NONE;
|
||||
|
||||
int qf_idx = qi->qf_curlist; // default is the current list
|
||||
if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL) {
|
||||
if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) {
|
||||
// Use the specified quickfix/location list
|
||||
if (di->di_tv.v_type == VAR_NUMBER) {
|
||||
qf_idx = di->di_tv.vval.v_number - 1;
|
||||
@ -4070,15 +4078,15 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
||||
}
|
||||
}
|
||||
|
||||
if (dict_find(what, (char_u *)"all", -1) != NULL) {
|
||||
if (tv_dict_find(what, S_LEN("all")) != NULL) {
|
||||
flags |= QF_GETLIST_ALL;
|
||||
}
|
||||
|
||||
if (dict_find(what, (char_u *)"title", -1) != NULL) {
|
||||
if (tv_dict_find(what, S_LEN("title")) != NULL) {
|
||||
flags |= QF_GETLIST_TITLE;
|
||||
}
|
||||
|
||||
if (dict_find(what, (char_u *)"winid", -1) != NULL) {
|
||||
if (tv_dict_find(what, S_LEN("winid")) != NULL) {
|
||||
flags |= QF_GETLIST_WINID;
|
||||
}
|
||||
|
||||
@ -4087,15 +4095,15 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
||||
if (t == NULL) {
|
||||
t = (char_u *)"";
|
||||
}
|
||||
status = dict_add_nr_str(retdict, "title", 0L, t);
|
||||
status = tv_dict_add_str(retdict, S_LEN("title"), (const char *)t);
|
||||
}
|
||||
if ((status == OK) && (flags & QF_GETLIST_NR)) {
|
||||
status = dict_add_nr_str(retdict, "nr", qf_idx + 1, NULL);
|
||||
status = tv_dict_add_nr(retdict, S_LEN("nr"), qf_idx + 1);
|
||||
}
|
||||
if ((status == OK) && (flags & QF_GETLIST_WINID)) {
|
||||
win_T *win = qf_find_win(qi);
|
||||
if (win != NULL) {
|
||||
status = dict_add_nr_str(retdict, "winid", win->handle, NULL);
|
||||
status = tv_dict_add_nr(retdict, S_LEN("winid"), win->handle);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4132,17 +4140,18 @@ static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title,
|
||||
if (d == NULL)
|
||||
continue;
|
||||
|
||||
char_u *filename = get_dict_string(d, "filename", true);
|
||||
int bufnum = (int)get_dict_number(d, "bufnr");
|
||||
long lnum = get_dict_number(d, "lnum");
|
||||
int col = (int)get_dict_number(d, "col");
|
||||
char_u vcol = (char_u)get_dict_number(d, "vcol");
|
||||
int nr = (int)get_dict_number(d, "nr");
|
||||
char_u *type = get_dict_string(d, "type", true);
|
||||
char_u *pattern = get_dict_string(d, "pattern", true);
|
||||
char_u *text = get_dict_string(d, "text", true);
|
||||
char *const filename = tv_dict_get_string(d, "filename", true);
|
||||
int bufnum = (int)tv_dict_get_number(d, "bufnr");
|
||||
long lnum = tv_dict_get_number(d, "lnum");
|
||||
int col = (int)tv_dict_get_number(d, "col");
|
||||
char_u vcol = (char_u)tv_dict_get_number(d, "vcol");
|
||||
int nr = (int)tv_dict_get_number(d, "nr");
|
||||
const char *type_str = tv_dict_get_string(d, "type", false);
|
||||
const char_u type = (char_u)(uint8_t)(type_str == NULL ? NUL : *type_str);
|
||||
char *const pattern = tv_dict_get_string(d, "pattern", true);
|
||||
char *text = tv_dict_get_string(d, "text", true);
|
||||
if (text == NULL) {
|
||||
text = vim_strsave((char_u *)"");
|
||||
text = xcalloc(1, 1);
|
||||
}
|
||||
bool valid = true;
|
||||
if ((filename == NULL && bufnum == 0) || (lnum == 0 && pattern == NULL)) {
|
||||
@ -4162,21 +4171,20 @@ static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title,
|
||||
|
||||
int status = qf_add_entry(qi,
|
||||
NULL, // dir
|
||||
filename,
|
||||
(char_u *)filename,
|
||||
bufnum,
|
||||
text,
|
||||
(char_u *)text,
|
||||
lnum,
|
||||
col,
|
||||
vcol, // vis_col
|
||||
pattern, // search pattern
|
||||
(char_u *)pattern, // search pattern
|
||||
nr,
|
||||
(char_u)(type == NULL ? NUL : *type),
|
||||
type,
|
||||
valid);
|
||||
|
||||
xfree(filename);
|
||||
xfree(pattern);
|
||||
xfree(text);
|
||||
xfree(type);
|
||||
|
||||
if (status == FAIL) {
|
||||
retval = FAIL;
|
||||
@ -4213,7 +4221,7 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action)
|
||||
newlist = true;
|
||||
}
|
||||
int qf_idx = qi->qf_curlist; // default is the current list
|
||||
if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL) {
|
||||
if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) {
|
||||
// Use the specified quickfix/location list
|
||||
if (di->di_tv.v_type == VAR_NUMBER) {
|
||||
qf_idx = di->di_tv.vval.v_number - 1;
|
||||
@ -4231,10 +4239,11 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action)
|
||||
qf_idx = qi->qf_curlist;
|
||||
}
|
||||
|
||||
if ((di = dict_find(what, (char_u *)"title", -1)) != NULL) {
|
||||
if ((di = tv_dict_find(what, S_LEN("title"))) != NULL) {
|
||||
if (di->di_tv.v_type == VAR_STRING) {
|
||||
xfree(qi->qf_lists[qf_idx].qf_title);
|
||||
qi->qf_lists[qf_idx].qf_title = get_dict_string(what, "title", true);
|
||||
qi->qf_lists[qf_idx].qf_title = (char_u *)tv_dict_get_string(
|
||||
what, "title", true);
|
||||
if (qf_idx == qi->qf_curlist) {
|
||||
qf_update_win_titlevar(qi);
|
||||
}
|
||||
@ -4363,7 +4372,6 @@ void ex_cbuffer(exarg_T *eap)
|
||||
*/
|
||||
void ex_cexpr(exarg_T *eap)
|
||||
{
|
||||
typval_T *tv;
|
||||
qf_info_T *qi = &ql_info;
|
||||
const char *au_name = NULL;
|
||||
|
||||
@ -4403,11 +4411,11 @@ void ex_cexpr(exarg_T *eap)
|
||||
|
||||
/* Evaluate the expression. When the result is a string or a list we can
|
||||
* use it to fill the errorlist. */
|
||||
tv = eval_expr(eap->arg, NULL);
|
||||
if (tv != NULL) {
|
||||
if ((tv->v_type == VAR_STRING && tv->vval.v_string != NULL)
|
||||
|| (tv->v_type == VAR_LIST && tv->vval.v_list != NULL)) {
|
||||
if (qf_init_ext(qi, NULL, NULL, tv, p_efm,
|
||||
typval_T tv;
|
||||
if (eval0(eap->arg, &tv, NULL, true) != FAIL) {
|
||||
if ((tv.v_type == VAR_STRING && tv.vval.v_string != NULL)
|
||||
|| (tv.v_type == VAR_LIST && tv.vval.v_list != NULL)) {
|
||||
if (qf_init_ext(qi, NULL, NULL, &tv, p_efm,
|
||||
(eap->cmdidx != CMD_caddexpr
|
||||
&& eap->cmdidx != CMD_laddexpr),
|
||||
(linenr_T)0, (linenr_T)0, *eap->cmdlinep) > 0) {
|
||||
@ -4422,7 +4430,7 @@ void ex_cexpr(exarg_T *eap)
|
||||
} else {
|
||||
EMSG(_("E777: String or List expected"));
|
||||
}
|
||||
free_tv(tv);
|
||||
tv_clear(&tv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2221,10 +2221,11 @@ collection:
|
||||
if (*regparse == '[')
|
||||
endc = get_coll_element(®parse);
|
||||
if (endc == 0) {
|
||||
if (has_mbyte)
|
||||
endc = mb_ptr2char_adv(®parse);
|
||||
else
|
||||
if (has_mbyte) {
|
||||
endc = mb_ptr2char_adv((const char_u **)®parse);
|
||||
} else {
|
||||
endc = *regparse++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle \o40, \x20 and \u20AC style sequences */
|
||||
@ -3650,9 +3651,11 @@ static long regtry(bt_regprog_T *prog, colnr_T col)
|
||||
*/
|
||||
static int reg_prev_class(void)
|
||||
{
|
||||
if (reginput > regline)
|
||||
return mb_get_class_buf(reginput - 1
|
||||
- (*mb_head_off)(regline, reginput - 1), reg_buf);
|
||||
if (reginput > regline) {
|
||||
return mb_get_class_tab(reginput - 1 - (*mb_head_off)(regline,
|
||||
reginput - 1),
|
||||
reg_buf->b_chartab);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -3918,12 +3921,13 @@ regmatch (
|
||||
else if (has_mbyte) {
|
||||
int this_class;
|
||||
|
||||
/* Get class of current and previous char (if it exists). */
|
||||
this_class = mb_get_class_buf(reginput, reg_buf);
|
||||
if (this_class <= 1)
|
||||
status = RA_NOMATCH; /* not on a word at all */
|
||||
else if (reg_prev_class() == this_class)
|
||||
status = RA_NOMATCH; /* previous char is in same word */
|
||||
// Get class of current and previous char (if it exists).
|
||||
this_class = mb_get_class_tab(reginput, reg_buf->b_chartab);
|
||||
if (this_class <= 1) {
|
||||
status = RA_NOMATCH; // Not on a word at all.
|
||||
} else if (reg_prev_class() == this_class) {
|
||||
status = RA_NOMATCH; // Previous char is in same word.
|
||||
}
|
||||
} else {
|
||||
if (!vim_iswordc_buf(c, reg_buf) || (reginput > regline
|
||||
&& vim_iswordc_buf(reginput[-1
|
||||
@ -3938,8 +3942,8 @@ regmatch (
|
||||
else if (has_mbyte) {
|
||||
int this_class, prev_class;
|
||||
|
||||
/* Get class of current and previous char (if it exists). */
|
||||
this_class = mb_get_class_buf(reginput, reg_buf);
|
||||
// Get class of current and previous char (if it exists).
|
||||
this_class = mb_get_class_tab(reginput, reg_buf->b_chartab);
|
||||
prev_class = reg_prev_class();
|
||||
if (this_class == prev_class
|
||||
|| prev_class == 0 || prev_class == 1)
|
||||
@ -6268,8 +6272,8 @@ static int cstrncmp(char_u *s1, char_u *s2, int *n)
|
||||
str2 = s2;
|
||||
c1 = c2 = 0;
|
||||
while ((int)(str1 - s1) < *n) {
|
||||
c1 = mb_ptr2char_adv(&str1);
|
||||
c2 = mb_ptr2char_adv(&str2);
|
||||
c1 = mb_ptr2char_adv((const char_u **)&str1);
|
||||
c2 = mb_ptr2char_adv((const char_u **)&str2);
|
||||
|
||||
/* decompose the character if necessary, into 'base' characters
|
||||
* because I don't care about Arabic, I will hard-code the Hebrew
|
||||
@ -6583,7 +6587,6 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest,
|
||||
if (expr != NULL) {
|
||||
typval_T argv[2];
|
||||
int dummy;
|
||||
char_u buf[NUMBUFLEN];
|
||||
typval_T rettv;
|
||||
staticList10_T matchList;
|
||||
|
||||
@ -6613,11 +6616,12 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest,
|
||||
clear_submatch_list(&matchList);
|
||||
}
|
||||
}
|
||||
eval_result = get_tv_string_buf_chk(&rettv, buf);
|
||||
char buf[NUMBUFLEN];
|
||||
eval_result = (char_u *)tv_get_string_buf_chk(&rettv, buf);
|
||||
if (eval_result != NULL) {
|
||||
eval_result = vim_strsave(eval_result);
|
||||
}
|
||||
clear_tv(&rettv);
|
||||
tv_clear(&rettv);
|
||||
} else {
|
||||
eval_result = eval_to_string(source + 2, NULL, true);
|
||||
}
|
||||
@ -6976,7 +6980,7 @@ list_T *reg_submatch_list(int no)
|
||||
linenr_T slnum;
|
||||
linenr_T elnum;
|
||||
list_T *list;
|
||||
char_u *s;
|
||||
const char *s;
|
||||
|
||||
if (submatch_match == NULL) {
|
||||
slnum = submatch_mmatch->startpos[no].lnum;
|
||||
@ -6988,27 +6992,27 @@ list_T *reg_submatch_list(int no)
|
||||
colnr_T scol = submatch_mmatch->startpos[no].col;
|
||||
colnr_T ecol = submatch_mmatch->endpos[no].col;
|
||||
|
||||
list = list_alloc();
|
||||
list = tv_list_alloc();
|
||||
|
||||
s = reg_getline_submatch(slnum) + scol;
|
||||
s = (const char *)reg_getline_submatch(slnum) + scol;
|
||||
if (slnum == elnum) {
|
||||
list_append_string(list, s, ecol - scol);
|
||||
tv_list_append_string(list, s, ecol - scol);
|
||||
} else {
|
||||
list_append_string(list, s, -1);
|
||||
tv_list_append_string(list, s, -1);
|
||||
for (int i = 1; i < elnum - slnum; i++) {
|
||||
s = reg_getline_submatch(slnum + i);
|
||||
list_append_string(list, s, -1);
|
||||
s = (const char *)reg_getline_submatch(slnum + i);
|
||||
tv_list_append_string(list, s, -1);
|
||||
}
|
||||
s = reg_getline_submatch(elnum);
|
||||
list_append_string(list, s, ecol);
|
||||
s = (const char *)reg_getline_submatch(elnum);
|
||||
tv_list_append_string(list, s, ecol);
|
||||
}
|
||||
} else {
|
||||
s = submatch_match->startp[no];
|
||||
s = (const char *)submatch_match->startp[no];
|
||||
if (s == NULL || submatch_match->endp[no] == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
list = list_alloc();
|
||||
list_append_string(list, s, (int)(submatch_match->endp[no] - s));
|
||||
list = tv_list_alloc();
|
||||
tv_list_append_string(list, s, (const char *)submatch_match->endp[no] - s);
|
||||
}
|
||||
|
||||
return list;
|
||||
|
@ -5410,7 +5410,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
int this_class;
|
||||
|
||||
// Get class of current and previous char (if it exists).
|
||||
this_class = mb_get_class_buf(reginput, reg_buf);
|
||||
this_class = mb_get_class_tab(reginput, reg_buf->b_chartab);
|
||||
if (this_class <= 1) {
|
||||
result = false;
|
||||
} else if (reg_prev_class() == this_class) {
|
||||
@ -5435,7 +5435,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
int this_class, prev_class;
|
||||
|
||||
// Get class of current and previous char (if it exists).
|
||||
this_class = mb_get_class_buf(reginput, reg_buf);
|
||||
this_class = mb_get_class_tab(reginput, reg_buf->b_chartab);
|
||||
prev_class = reg_prev_class();
|
||||
if (this_class == prev_class
|
||||
|| prev_class == 0 || prev_class == 1) {
|
||||
|
@ -3141,7 +3141,7 @@ win_line (
|
||||
|
||||
p_extra = extra;
|
||||
c = *p_extra;
|
||||
mb_c = mb_ptr2char_adv(&p_extra);
|
||||
mb_c = mb_ptr2char_adv((const char_u **)&p_extra);
|
||||
mb_utf8 = (c >= 0x80);
|
||||
n_extra = (int)STRLEN(p_extra);
|
||||
c_extra = NUL;
|
||||
|
@ -282,7 +282,7 @@ void restore_search_patterns(void)
|
||||
static inline void free_spat(struct spat *const spat)
|
||||
{
|
||||
xfree(spat->pat);
|
||||
dict_unref(spat->additional_data);
|
||||
tv_dict_unref(spat->additional_data);
|
||||
}
|
||||
|
||||
#if defined(EXITFREE)
|
||||
@ -356,9 +356,10 @@ int pat_has_uppercase(char_u *pat)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
char_u *last_csearch(void)
|
||||
const char *last_csearch(void)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
return lastc_bytes;
|
||||
return (const char *)lastc_bytes;
|
||||
}
|
||||
|
||||
int last_csearch_forward(void)
|
||||
@ -1290,10 +1291,11 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, int dir, char_u *pat)
|
||||
* ignored because we are interested in the next line -- Acevedo */
|
||||
if ((compl_cont_status & CONT_ADDING)
|
||||
&& !(compl_cont_status & CONT_SOL)) {
|
||||
if ((p_ic ? mb_stricmp(p, pat) : STRCMP(p, pat)) == 0)
|
||||
if (mb_strcmp_ic((bool)p_ic, (const char *)p, (const char *)pat) == 0) {
|
||||
return OK;
|
||||
} else if (*p != NUL) { /* ignore empty lines */
|
||||
/* expanding lines or words */
|
||||
}
|
||||
} else if (*p != NUL) { // Ignore empty lines.
|
||||
// Expanding lines or words.
|
||||
assert(compl_length >= 0);
|
||||
if ((p_ic ? mb_strnicmp(p, pat, (size_t)compl_length)
|
||||
: STRNCMP(p, pat, compl_length)) == 0)
|
||||
|
@ -259,11 +259,11 @@ void sha256_finish(context_sha256_T *ctx, char_u digest[SHA256_SUM_SIZE])
|
||||
///
|
||||
/// @returns hex digest of "buf[buf_len]" in a static array.
|
||||
/// if "salt" is not NULL also do "salt[salt_len]".
|
||||
char_u *sha256_bytes(const char_u *restrict buf, size_t buf_len,
|
||||
const char_u *restrict salt, size_t salt_len)
|
||||
const char *sha256_bytes(const uint8_t *restrict buf, size_t buf_len,
|
||||
const uint8_t *restrict salt, size_t salt_len)
|
||||
{
|
||||
char_u sha256sum[SHA256_SUM_SIZE];
|
||||
static char_u hexit[SHA256_BUFFER_SIZE + 1]; // buf size + NULL
|
||||
static char hexit[SHA256_BUFFER_SIZE + 1]; // buf size + NULL
|
||||
context_sha256_T ctx;
|
||||
|
||||
sha256_self_test();
|
||||
@ -277,7 +277,7 @@ char_u *sha256_bytes(const char_u *restrict buf, size_t buf_len,
|
||||
sha256_finish(&ctx, sha256sum);
|
||||
|
||||
for (size_t j = 0; j < SHA256_SUM_SIZE; j++) {
|
||||
snprintf((char *) hexit + j * SHA_STEP, SHA_STEP+1, "%02x", sha256sum[j]);
|
||||
snprintf(hexit + j * SHA_STEP, SHA_STEP + 1, "%02x", sha256sum[j]);
|
||||
}
|
||||
hexit[sizeof(hexit) - 1] = '\0';
|
||||
return hexit;
|
||||
@ -308,7 +308,7 @@ bool sha256_self_test(void)
|
||||
context_sha256_T ctx;
|
||||
char_u buf[1000];
|
||||
char_u sha256sum[SHA256_SUM_SIZE];
|
||||
char_u *hexit;
|
||||
const char *hexit;
|
||||
|
||||
static bool sha256_self_tested = false;
|
||||
static bool failures = false;
|
||||
@ -320,8 +320,8 @@ bool sha256_self_test(void)
|
||||
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
if (i < 2) {
|
||||
hexit = sha256_bytes((char_u *) sha_self_test_msg[i],
|
||||
STRLEN(sha_self_test_msg[i]),
|
||||
hexit = sha256_bytes((uint8_t *)sha_self_test_msg[i],
|
||||
strlen(sha_self_test_msg[i]),
|
||||
NULL, 0);
|
||||
STRCPY(output, hexit);
|
||||
} else {
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "nvim/ex_getln.h"
|
||||
#include "nvim/search.h"
|
||||
#include "nvim/regexp.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/version.h"
|
||||
#include "nvim/path.h"
|
||||
#include "nvim/fileio.h"
|
||||
@ -82,8 +82,6 @@ KHASH_SET_INIT_STR(strset)
|
||||
(buflist_new((char_u *)ffname, (char_u *)sfname, __VA_ARGS__))
|
||||
#define convert_setup(vcp, from, to) \
|
||||
(convert_setup(vcp, (char_u *)from, (char_u *)to))
|
||||
#define os_getperm(f) \
|
||||
(os_getperm((char_u *) f))
|
||||
#define os_isdir(f) (os_isdir((char_u *) f))
|
||||
#define regtilde(s, m) ((char *) regtilde((char_u *) s, m))
|
||||
#define path_tail_with_sep(f) ((char *) path_tail_with_sep((char_u *)f))
|
||||
@ -1223,7 +1221,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
|
||||
khash_t(fnamebufs) fname_bufs = KHASH_EMPTY_TABLE(fnamebufs);
|
||||
khash_t(strset) oldfiles_set = KHASH_EMPTY_TABLE(strset);
|
||||
if (get_old_files && (oldfiles_list == NULL || force)) {
|
||||
oldfiles_list = list_alloc();
|
||||
oldfiles_list = tv_list_alloc();
|
||||
set_vim_var_list(VV_OLDFILES, oldfiles_list);
|
||||
}
|
||||
ShaDaReadResult srni_ret;
|
||||
@ -1435,8 +1433,8 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
|
||||
fname = xstrdup(fname);
|
||||
}
|
||||
int kh_ret;
|
||||
(void) kh_put(strset, &oldfiles_set, fname, &kh_ret);
|
||||
list_append_allocated_string(oldfiles_list, fname);
|
||||
(void)kh_put(strset, &oldfiles_set, fname, &kh_ret);
|
||||
tv_list_append_allocated_string(oldfiles_list, fname);
|
||||
if (!want_marks) {
|
||||
// Avoid free because this string was already used.
|
||||
cur_entry.data.filemark.fname = NULL;
|
||||
@ -1573,7 +1571,9 @@ static char *shada_filename(const char *file)
|
||||
do { \
|
||||
const String s_ = (s); \
|
||||
msgpack_pack_str(spacker, s_.size); \
|
||||
msgpack_pack_str_body(spacker, s_.data, s_.size); \
|
||||
if (s_.size) { \
|
||||
msgpack_pack_str_body(spacker, s_.data, s_.size); \
|
||||
} \
|
||||
} while (0)
|
||||
#define PACK_BIN(s) \
|
||||
do { \
|
||||
@ -1621,10 +1621,10 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
|
||||
for (const hashitem_T *hi= d->dv_hashtab.ht_array; todo; hi++) { \
|
||||
if (!HASHITEM_EMPTY(hi)) { \
|
||||
todo--; \
|
||||
dictitem_T *const di = HI2DI(hi); \
|
||||
const size_t key_len = strlen((const char *) hi->hi_key); \
|
||||
dictitem_T *const di = TV_DICT_HI2DI(hi); \
|
||||
const size_t key_len = strlen((const char *)hi->hi_key); \
|
||||
msgpack_pack_str(spacker, key_len); \
|
||||
msgpack_pack_str_body(spacker, (const char *) hi->hi_key, key_len); \
|
||||
msgpack_pack_str_body(spacker, (const char *)hi->hi_key, key_len); \
|
||||
if (encode_vim_to_msgpack(spacker, &di->di_tv, \
|
||||
_("additional data of ShaDa " what)) \
|
||||
== FAIL) { \
|
||||
@ -1965,7 +1965,7 @@ static ShaDaWriteResult shada_pack_encoded_entry(msgpack_packer *const packer,
|
||||
typval_T tgttv;
|
||||
var_item_copy(sd_conv, &entry.data.data.global_var.value, &tgttv,
|
||||
true, 0);
|
||||
clear_tv(&entry.data.data.global_var.value);
|
||||
tv_clear(&entry.data.data.global_var.value);
|
||||
entry.data.data.global_var.value = tgttv;
|
||||
}
|
||||
ret = shada_pack_entry(packer, entry.data, max_kbyte);
|
||||
@ -2559,7 +2559,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer,
|
||||
if (sd_writer->sd_conv.vc_type != CONV_NONE) {
|
||||
var_item_copy(&sd_writer->sd_conv, &vartv, &tgttv, true, 0);
|
||||
} else {
|
||||
copy_tv(&vartv, &tgttv);
|
||||
tv_copy(&vartv, &tgttv);
|
||||
}
|
||||
ShaDaWriteResult spe_ret;
|
||||
if ((spe_ret = shada_pack_entry(packer, (ShadaEntry) {
|
||||
@ -2573,13 +2573,13 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer,
|
||||
}
|
||||
}
|
||||
}, max_kbyte)) == kSDWriteFailed) {
|
||||
clear_tv(&vartv);
|
||||
clear_tv(&tgttv);
|
||||
tv_clear(&vartv);
|
||||
tv_clear(&tgttv);
|
||||
ret = kSDWriteFailed;
|
||||
goto shada_write_exit;
|
||||
}
|
||||
clear_tv(&vartv);
|
||||
clear_tv(&tgttv);
|
||||
tv_clear(&vartv);
|
||||
tv_clear(&tgttv);
|
||||
if (spe_ret == kSDWriteSuccessfull) {
|
||||
int kh_ret;
|
||||
(void) kh_put(strset, &wms->dumped_variables, name, &kh_ret);
|
||||
@ -3154,17 +3154,17 @@ static void shada_free_shada_entry(ShadaEntry *const entry)
|
||||
case kSDItemJump:
|
||||
case kSDItemGlobalMark:
|
||||
case kSDItemLocalMark: {
|
||||
dict_unref(entry->data.filemark.additional_data);
|
||||
tv_dict_unref(entry->data.filemark.additional_data);
|
||||
xfree(entry->data.filemark.fname);
|
||||
break;
|
||||
}
|
||||
case kSDItemSearchPattern: {
|
||||
dict_unref(entry->data.search_pattern.additional_data);
|
||||
tv_dict_unref(entry->data.search_pattern.additional_data);
|
||||
xfree(entry->data.search_pattern.pat);
|
||||
break;
|
||||
}
|
||||
case kSDItemRegister: {
|
||||
dict_unref(entry->data.reg.additional_data);
|
||||
tv_dict_unref(entry->data.reg.additional_data);
|
||||
for (size_t i = 0; i < entry->data.reg.contents_size; i++) {
|
||||
xfree(entry->data.reg.contents[i]);
|
||||
}
|
||||
@ -3172,25 +3172,25 @@ static void shada_free_shada_entry(ShadaEntry *const entry)
|
||||
break;
|
||||
}
|
||||
case kSDItemHistoryEntry: {
|
||||
list_unref(entry->data.history_item.additional_elements);
|
||||
tv_list_unref(entry->data.history_item.additional_elements);
|
||||
xfree(entry->data.history_item.string);
|
||||
break;
|
||||
}
|
||||
case kSDItemVariable: {
|
||||
list_unref(entry->data.global_var.additional_elements);
|
||||
tv_list_unref(entry->data.global_var.additional_elements);
|
||||
xfree(entry->data.global_var.name);
|
||||
clear_tv(&entry->data.global_var.value);
|
||||
tv_clear(&entry->data.global_var.value);
|
||||
break;
|
||||
}
|
||||
case kSDItemSubString: {
|
||||
list_unref(entry->data.sub_string.additional_elements);
|
||||
tv_list_unref(entry->data.sub_string.additional_elements);
|
||||
xfree(entry->data.sub_string.sub);
|
||||
break;
|
||||
}
|
||||
case kSDItemBufferList: {
|
||||
for (size_t i = 0; i < entry->data.buffer_list.size; i++) {
|
||||
xfree(entry->data.buffer_list.buffers[i].fname);
|
||||
dict_unref(entry->data.buffer_list.buffers[i].additional_data);
|
||||
tv_dict_unref(entry->data.buffer_list.buffers[i].additional_data);
|
||||
}
|
||||
xfree(entry->data.buffer_list.buffers);
|
||||
break;
|
||||
@ -3451,7 +3451,7 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv,
|
||||
"cannot be converted to a VimL dictionary")), \
|
||||
initial_fpos); \
|
||||
ga_clear(&ad_ga); \
|
||||
clear_tv(&adtv); \
|
||||
tv_clear(&adtv); \
|
||||
goto shada_read_next_item_error; \
|
||||
} \
|
||||
tgt = adtv.vval.v_dict; \
|
||||
@ -3474,7 +3474,7 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv,
|
||||
if (msgpack_to_vim(obj, &aetv) == FAIL) { \
|
||||
emsgf(_(READERR(name, "cannot be converted to a VimL list")), \
|
||||
initial_fpos); \
|
||||
clear_tv(&aetv); \
|
||||
tv_clear(&aetv); \
|
||||
goto shada_read_next_item_error; \
|
||||
} \
|
||||
assert(aetv.v_type == VAR_LIST); \
|
||||
@ -3866,7 +3866,7 @@ shada_read_next_item_hist_no_conv:
|
||||
&tgttv,
|
||||
true,
|
||||
0);
|
||||
clear_tv(&entry->data.global_var.value);
|
||||
tv_clear(&entry->data.global_var.value);
|
||||
entry->data.global_var.value = tgttv;
|
||||
}
|
||||
SET_ADDITIONAL_ELEMENTS(unpacked.data.via.array, 2,
|
||||
|
141
src/nvim/spell.c
141
src/nvim/spell.c
@ -2309,10 +2309,11 @@ int captype(char_u *word, char_u *end)
|
||||
for (p = word; !spell_iswordp_nmw(p, curwin); mb_ptr_adv(p))
|
||||
if (end == NULL ? *p == NUL : p >= end)
|
||||
return 0; // only non-word characters, illegal word
|
||||
if (has_mbyte)
|
||||
c = mb_ptr2char_adv(&p);
|
||||
else
|
||||
if (has_mbyte) {
|
||||
c = mb_ptr2char_adv((const char_u **)&p);
|
||||
} else {
|
||||
c = *p++;
|
||||
}
|
||||
firstcap = allcap = SPELL_ISUPPER(c);
|
||||
|
||||
// Need to check all letters to find a word with mixed upper/lower.
|
||||
@ -2607,14 +2608,15 @@ static bool spell_iswordp(char_u *p, win_T *wp)
|
||||
|
||||
// Returns true if "p" points to a word character.
|
||||
// Unlike spell_iswordp() this doesn't check for "midword" characters.
|
||||
bool spell_iswordp_nmw(char_u *p, win_T *wp)
|
||||
bool spell_iswordp_nmw(const char_u *p, win_T *wp)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (has_mbyte) {
|
||||
c = mb_ptr2char(p);
|
||||
if (c > 255)
|
||||
if (c > 255) {
|
||||
return spell_mb_isword_class(mb_get_class(p), wp);
|
||||
}
|
||||
return spelltab.st_isw[c];
|
||||
}
|
||||
return spelltab.st_isw[*p];
|
||||
@ -2675,7 +2677,7 @@ int spell_casefold(char_u *str, int len, char_u *buf, int buflen)
|
||||
buf[outi] = NUL;
|
||||
return FAIL;
|
||||
}
|
||||
c = mb_cptr2char_adv(&p);
|
||||
c = mb_cptr2char_adv((const char_u **)&p);
|
||||
outi += mb_char2bytes(SPELL_TOFOLD(c), buf + outi);
|
||||
}
|
||||
buf[outi] = NUL;
|
||||
@ -2937,7 +2939,7 @@ void spell_suggest(int count)
|
||||
|
||||
// For redo we use a change-word command.
|
||||
ResetRedobuff();
|
||||
AppendToRedobuff((char_u *)"ciw");
|
||||
AppendToRedobuff("ciw");
|
||||
AppendToRedobuffLit(p + c,
|
||||
stp->st_wordlen + sug.su_badlen - stp->st_orglen);
|
||||
AppendCharToRedobuff(ESC);
|
||||
@ -3232,7 +3234,7 @@ static void spell_suggest_expr(suginfo_T *su, char_u *expr)
|
||||
list_T *list;
|
||||
listitem_T *li;
|
||||
int score;
|
||||
char_u *p;
|
||||
const char *p;
|
||||
|
||||
// The work is split up in a few parts to avoid having to export
|
||||
// suginfo_T.
|
||||
@ -3244,11 +3246,12 @@ static void spell_suggest_expr(suginfo_T *su, char_u *expr)
|
||||
if (li->li_tv.v_type == VAR_LIST) {
|
||||
// Get the word and the score from the items.
|
||||
score = get_spellword(li->li_tv.vval.v_list, &p);
|
||||
if (score >= 0 && score <= su->su_maxscore)
|
||||
add_suggestion(su, &su->su_ga, p, su->su_badlen,
|
||||
score, 0, true, su->su_sallang, false);
|
||||
if (score >= 0 && score <= su->su_maxscore) {
|
||||
add_suggestion(su, &su->su_ga, (const char_u *)p, su->su_badlen,
|
||||
score, 0, true, su->su_sallang, false);
|
||||
}
|
||||
}
|
||||
list_unref(list);
|
||||
tv_list_unref(list);
|
||||
}
|
||||
|
||||
// Remove bogus suggestions, sort and truncate at "maxcount".
|
||||
@ -3405,17 +3408,19 @@ void onecap_copy(char_u *word, char_u *wcopy, bool upper)
|
||||
int l;
|
||||
|
||||
p = word;
|
||||
if (has_mbyte)
|
||||
c = mb_cptr2char_adv(&p);
|
||||
else
|
||||
if (has_mbyte) {
|
||||
c = mb_cptr2char_adv((const char_u **)&p);
|
||||
} else {
|
||||
c = *p++;
|
||||
if (upper)
|
||||
}
|
||||
if (upper) {
|
||||
c = SPELL_TOUPPER(c);
|
||||
else
|
||||
} else {
|
||||
c = SPELL_TOFOLD(c);
|
||||
if (has_mbyte)
|
||||
}
|
||||
if (has_mbyte) {
|
||||
l = mb_char2bytes(c, wcopy);
|
||||
else {
|
||||
} else {
|
||||
l = 1;
|
||||
wcopy[0] = c;
|
||||
}
|
||||
@ -3432,10 +3437,11 @@ static void allcap_copy(char_u *word, char_u *wcopy)
|
||||
|
||||
d = wcopy;
|
||||
for (s = word; *s != NUL; ) {
|
||||
if (has_mbyte)
|
||||
c = mb_cptr2char_adv(&s);
|
||||
else
|
||||
if (has_mbyte) {
|
||||
c = mb_cptr2char_adv((const char_u **)&s);
|
||||
} else {
|
||||
c = *s++;
|
||||
}
|
||||
|
||||
if (c == 0xdf) {
|
||||
c = 'S';
|
||||
@ -5616,7 +5622,7 @@ static void
|
||||
add_suggestion (
|
||||
suginfo_T *su,
|
||||
garray_T *gap, // either su_ga or su_sga
|
||||
char_u *goodword,
|
||||
const char_u *goodword,
|
||||
int badlenarg, // len of bad word replaced with "goodword"
|
||||
int score,
|
||||
int altscore,
|
||||
@ -5630,13 +5636,11 @@ add_suggestion (
|
||||
int badlen; // len of bad word changed
|
||||
suggest_T *stp;
|
||||
suggest_T new_sug;
|
||||
int i;
|
||||
char_u *pgood, *pbad;
|
||||
|
||||
// Minimize "badlen" for consistency. Avoids that changing "the the" to
|
||||
// "thee the" is added next to changing the first "the" the "thee".
|
||||
pgood = goodword + STRLEN(goodword);
|
||||
pbad = su->su_badptr + badlenarg;
|
||||
const char_u *pgood = goodword + STRLEN(goodword);
|
||||
char_u *pbad = su->su_badptr + badlenarg;
|
||||
for (;; ) {
|
||||
goodlen = (int)(pgood - goodword);
|
||||
badlen = (int)(pbad - su->su_badptr);
|
||||
@ -5656,9 +5660,10 @@ add_suggestion (
|
||||
// the first "the" to itself.
|
||||
return;
|
||||
|
||||
if (GA_EMPTY(gap))
|
||||
int i;
|
||||
if (GA_EMPTY(gap)) {
|
||||
i = -1;
|
||||
else {
|
||||
} else {
|
||||
// Check if the word is already there. Also check the length that is
|
||||
// being replaced "thes," -> "these" is a different suggestion from
|
||||
// "thes" -> "these".
|
||||
@ -5857,27 +5862,31 @@ cleanup_suggestions (
|
||||
return maxscore;
|
||||
}
|
||||
|
||||
// Soundfold a string, for soundfold().
|
||||
// Result is in allocated memory, NULL for an error.
|
||||
char_u *eval_soundfold(char_u *word)
|
||||
/// Soundfold a string, for soundfold()
|
||||
///
|
||||
/// @param[in] word Word to soundfold.
|
||||
///
|
||||
/// @return [allocated] soundfolded string or NULL in case of error. May return
|
||||
/// copy of the input string if soundfolding is not
|
||||
/// supported by any of the languages in &spellang.
|
||||
char *eval_soundfold(const char *const word)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
langp_T *lp;
|
||||
char_u sound[MAXWLEN];
|
||||
|
||||
if (curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) {
|
||||
// Use the sound-folding of the first language that supports it.
|
||||
for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) {
|
||||
lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
|
||||
for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; lpi++) {
|
||||
langp_T *const lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
|
||||
if (!GA_EMPTY(&lp->lp_slang->sl_sal)) {
|
||||
// soundfold the word
|
||||
spell_soundfold(lp->lp_slang, word, false, sound);
|
||||
return vim_strsave(sound);
|
||||
char_u sound[MAXWLEN];
|
||||
spell_soundfold(lp->lp_slang, (char_u *)word, false, sound);
|
||||
return xstrdup((const char *)sound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No language with sound folding, return word as-is.
|
||||
return vim_strsave(word);
|
||||
return xstrdup(word);
|
||||
}
|
||||
|
||||
/// Turn "inword" into its sound-a-like equivalent in "res[MAXWLEN]".
|
||||
@ -5934,12 +5943,12 @@ static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res)
|
||||
// The sl_sal_first[] table contains the translation for chars up to
|
||||
// 255, sl_sal the rest.
|
||||
for (s = inword; *s != NUL; ) {
|
||||
c = mb_cptr2char_adv(&s);
|
||||
if (enc_utf8 ? utf_class(c) == 0 : ascii_iswhite(c))
|
||||
c = mb_cptr2char_adv((const char_u **)&s);
|
||||
if (enc_utf8 ? utf_class(c) == 0 : ascii_iswhite(c)) {
|
||||
c = ' ';
|
||||
else if (c < 256)
|
||||
} else if (c < 256) {
|
||||
c = slang->sl_sal_first[c];
|
||||
else {
|
||||
} else {
|
||||
ip = ((int **)slang->sl_sal.ga_data)[c & 0xff];
|
||||
if (ip == NULL) // empty list, can't match
|
||||
c = NUL;
|
||||
@ -6224,9 +6233,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
|
||||
int word[MAXWLEN];
|
||||
int wres[MAXWLEN];
|
||||
int l;
|
||||
char_u *s;
|
||||
int *ws;
|
||||
char_u *t;
|
||||
int *pf;
|
||||
int i, j, z;
|
||||
int reslen;
|
||||
@ -6246,9 +6253,9 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
|
||||
// Remove accents, if wanted. We actually remove all non-word characters.
|
||||
// But keep white space.
|
||||
wordlen = 0;
|
||||
for (s = inword; *s != NUL; ) {
|
||||
t = s;
|
||||
c = mb_cptr2char_adv(&s);
|
||||
for (const char_u *s = inword; *s != NUL; ) {
|
||||
const char_u *t = s;
|
||||
c = mb_cptr2char_adv((const char_u **)&s);
|
||||
if (slang->sl_rem_accents) {
|
||||
if (enc_utf8 ? utf_class(c) == 0 : ascii_iswhite(c)) {
|
||||
if (did_white)
|
||||
@ -6257,8 +6264,9 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
|
||||
did_white = true;
|
||||
} else {
|
||||
did_white = false;
|
||||
if (!spell_iswordp_nmw(t, curwin))
|
||||
if (!spell_iswordp_nmw(t, curwin)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
word[wordlen++] = c;
|
||||
@ -6305,7 +6313,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
|
||||
continue;
|
||||
++k;
|
||||
}
|
||||
s = smp[n].sm_rules;
|
||||
char_u *s = smp[n].sm_rules;
|
||||
pri = 5; // default priority
|
||||
|
||||
p0 = *s;
|
||||
@ -6704,25 +6712,30 @@ soundalike_score (
|
||||
// support multi-byte characters.
|
||||
static int spell_edit_score(slang_T *slang, char_u *badword, char_u *goodword)
|
||||
{
|
||||
int *cnt;
|
||||
int badlen, goodlen; // lengths including NUL
|
||||
int *cnt;
|
||||
int j, i;
|
||||
int t;
|
||||
int bc, gc;
|
||||
int pbc, pgc;
|
||||
char_u *p;
|
||||
int wbadword[MAXWLEN];
|
||||
int wgoodword[MAXWLEN];
|
||||
const bool l_has_mbyte = has_mbyte;
|
||||
|
||||
// Lengths with NUL.
|
||||
int badlen;
|
||||
int goodlen;
|
||||
if (l_has_mbyte) {
|
||||
// Get the characters from the multi-byte strings and put them in an
|
||||
// int array for easy access.
|
||||
for (p = badword, badlen = 0; *p != NUL; )
|
||||
badlen = 0;
|
||||
for (const char_u *p = badword; *p != NUL; ) {
|
||||
wbadword[badlen++] = mb_cptr2char_adv(&p);
|
||||
}
|
||||
wbadword[badlen++] = 0;
|
||||
for (p = goodword, goodlen = 0; *p != NUL; )
|
||||
goodlen = 0;
|
||||
for (const char_u *p = goodword; *p != NUL; ) {
|
||||
wgoodword[goodlen++] = mb_cptr2char_adv(&p);
|
||||
}
|
||||
wgoodword[goodlen++] = 0;
|
||||
} else {
|
||||
badlen = (int)STRLEN(badword) + 1;
|
||||
@ -6956,19 +6969,20 @@ static int spell_edit_score_limit_w(slang_T *slang, char_u *badword, char_u *goo
|
||||
int score_off;
|
||||
int minscore;
|
||||
int round;
|
||||
char_u *p;
|
||||
int wbadword[MAXWLEN];
|
||||
int wgoodword[MAXWLEN];
|
||||
|
||||
// Get the characters from the multi-byte strings and put them in an
|
||||
// int array for easy access.
|
||||
bi = 0;
|
||||
for (p = badword; *p != NUL; )
|
||||
for (const char_u *p = badword; *p != NUL; ) {
|
||||
wbadword[bi++] = mb_cptr2char_adv(&p);
|
||||
}
|
||||
wbadword[bi++] = 0;
|
||||
gi = 0;
|
||||
for (p = goodword; *p != NUL; )
|
||||
for (const char_u *p = goodword; *p != NUL; ) {
|
||||
wgoodword[gi++] = mb_cptr2char_adv(&p);
|
||||
}
|
||||
wgoodword[gi++] = 0;
|
||||
|
||||
// The idea is to go from start to end over the words. So long as
|
||||
@ -7134,16 +7148,17 @@ void ex_spelldump(exarg_T *eap)
|
||||
char_u *spl;
|
||||
long dummy;
|
||||
|
||||
if (no_spell_checking(curwin))
|
||||
if (no_spell_checking(curwin)) {
|
||||
return;
|
||||
get_option_value((char_u*)"spl", &dummy, &spl, OPT_LOCAL);
|
||||
}
|
||||
get_option_value((char_u *)"spl", &dummy, &spl, OPT_LOCAL);
|
||||
|
||||
// Create a new empty buffer in a new window.
|
||||
do_cmdline_cmd("new");
|
||||
|
||||
// enable spelling locally in the new window
|
||||
set_option_value((char_u*)"spell", true, (char_u*)"", OPT_LOCAL);
|
||||
set_option_value((char_u*)"spl", dummy, spl, OPT_LOCAL);
|
||||
set_option_value("spell", true, "", OPT_LOCAL);
|
||||
set_option_value("spl", dummy, (char *)spl, OPT_LOCAL);
|
||||
xfree(spl);
|
||||
|
||||
if (!bufempty()) {
|
||||
|
@ -1435,7 +1435,7 @@ static int set_sofo(slang_T *lp, char_u *from, char_u *to)
|
||||
// First count the number of items for each list. Temporarily use
|
||||
// sl_sal_first[] for this.
|
||||
for (p = from, s = to; *p != NUL && *s != NUL; ) {
|
||||
c = mb_cptr2char_adv(&p);
|
||||
c = mb_cptr2char_adv((const char_u **)&p);
|
||||
mb_cptr_adv(s);
|
||||
if (c >= 256)
|
||||
++lp->sl_sal_first[c & 0xff];
|
||||
@ -1455,8 +1455,8 @@ static int set_sofo(slang_T *lp, char_u *from, char_u *to)
|
||||
// list.
|
||||
memset(lp->sl_sal_first, 0, sizeof(salfirst_T) * 256);
|
||||
for (p = from, s = to; *p != NUL && *s != NUL; ) {
|
||||
c = mb_cptr2char_adv(&p);
|
||||
i = mb_cptr2char_adv(&s);
|
||||
c = mb_cptr2char_adv((const char_u **)&p);
|
||||
i = mb_cptr2char_adv((const char_u **)&s);
|
||||
if (c >= 256) {
|
||||
// Append the from-to chars at the end of the list with
|
||||
// the low byte.
|
||||
@ -1542,8 +1542,9 @@ static int *mb_str2wide(char_u *s)
|
||||
int i = 0;
|
||||
|
||||
int *res = xmalloc((mb_charlen(s) + 1) * sizeof(int));
|
||||
for (char_u *p = s; *p != NUL; )
|
||||
res[i++] = mb_ptr2char_adv(&p);
|
||||
for (char_u *p = s; *p != NUL; ) {
|
||||
res[i++] = mb_ptr2char_adv((const char_u **)&p);
|
||||
}
|
||||
res[i] = NUL;
|
||||
|
||||
return res;
|
||||
@ -2486,13 +2487,14 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
|
||||
|
||||
// Check that every character appears only once.
|
||||
for (p = items[1]; *p != NUL; ) {
|
||||
c = mb_ptr2char_adv(&p);
|
||||
c = mb_ptr2char_adv((const char_u **)&p);
|
||||
if ((!GA_EMPTY(&spin->si_map)
|
||||
&& vim_strchr(spin->si_map.ga_data, c)
|
||||
!= NULL)
|
||||
|| vim_strchr(p, c) != NULL)
|
||||
|| vim_strchr(p, c) != NULL) {
|
||||
smsg(_("Duplicate character in MAP in %s line %d"),
|
||||
fname, lnum);
|
||||
}
|
||||
}
|
||||
|
||||
// We simply concatenate all the MAP strings, separated by
|
||||
@ -2717,12 +2719,12 @@ static unsigned get_affitem(int flagtype, char_u **pp)
|
||||
}
|
||||
res = getdigits_int(pp);
|
||||
} else {
|
||||
res = mb_ptr2char_adv(pp);
|
||||
res = mb_ptr2char_adv((const char_u **)pp);
|
||||
if (flagtype == AFT_LONG || (flagtype == AFT_CAPLONG
|
||||
&& res >= 'A' && res <= 'Z')) {
|
||||
if (**pp == NUL)
|
||||
return 0;
|
||||
res = mb_ptr2char_adv(pp) + (res << 16);
|
||||
res = mb_ptr2char_adv((const char_u **)pp) + (res << 16);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
@ -2823,12 +2825,14 @@ static bool flag_in_afflist(int flagtype, char_u *afflist, unsigned flag)
|
||||
case AFT_CAPLONG:
|
||||
case AFT_LONG:
|
||||
for (p = afflist; *p != NUL; ) {
|
||||
n = mb_ptr2char_adv(&p);
|
||||
n = mb_ptr2char_adv((const char_u **)&p);
|
||||
if ((flagtype == AFT_LONG || (n >= 'A' && n <= 'Z'))
|
||||
&& *p != NUL)
|
||||
n = mb_ptr2char_adv(&p) + (n << 16);
|
||||
if (n == flag)
|
||||
&& *p != NUL) {
|
||||
n = mb_ptr2char_adv((const char_u **)&p) + (n << 16);
|
||||
}
|
||||
if (n == flag) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -5436,10 +5440,11 @@ static void init_spellfile(void)
|
||||
fname = LANGP_ENTRY(curwin->w_s->b_langp, 0)
|
||||
->lp_slang->sl_fname;
|
||||
vim_snprintf((char *)buf + l, MAXPATHL - l, ".%s.add",
|
||||
fname != NULL
|
||||
&& strstr((char *)path_tail(fname), ".ascii.") != NULL
|
||||
? (char_u *)"ascii" : spell_enc());
|
||||
set_option_value((char_u *)"spellfile", 0L, buf, OPT_LOCAL);
|
||||
((fname != NULL
|
||||
&& strstr((char *)path_tail(fname), ".ascii.") != NULL)
|
||||
? "ascii"
|
||||
: (const char *)spell_enc()));
|
||||
set_option_value("spellfile", 0L, (const char *)buf, OPT_LOCAL);
|
||||
break;
|
||||
}
|
||||
aspath = false;
|
||||
@ -5465,9 +5470,9 @@ static int set_spell_chartab(char_u *fol, char_u *low, char_u *upp)
|
||||
EMSG(_(e_affform));
|
||||
return FAIL;
|
||||
}
|
||||
f = mb_ptr2char_adv(&pf);
|
||||
l = mb_ptr2char_adv(&pl);
|
||||
u = mb_ptr2char_adv(&pu);
|
||||
f = mb_ptr2char_adv((const char_u **)&pf);
|
||||
l = mb_ptr2char_adv((const char_u **)&pl);
|
||||
u = mb_ptr2char_adv((const char_u **)&pu);
|
||||
// Every character that appears is a word character.
|
||||
if (f < 256)
|
||||
new_st.st_isw[f] = true;
|
||||
@ -5532,7 +5537,7 @@ set_spell_charflags (
|
||||
}
|
||||
|
||||
if (*p != NUL) {
|
||||
c = mb_ptr2char_adv(&p);
|
||||
c = mb_ptr2char_adv((const char_u **)&p);
|
||||
new_st.st_fold[i + 128] = c;
|
||||
if (i + 128 != c && new_st.st_isu[i + 128] && c < 256)
|
||||
new_st.st_upper[c] = i + 128;
|
||||
@ -5619,12 +5624,13 @@ static void set_map_str(slang_T *lp, char_u *map)
|
||||
// "aaa/bbb/ccc/". Fill sl_map_array[c] with the character before c and
|
||||
// before the same slash. For characters above 255 sl_map_hash is used.
|
||||
for (p = map; *p != NUL; ) {
|
||||
c = mb_cptr2char_adv(&p);
|
||||
if (c == '/')
|
||||
c = mb_cptr2char_adv((const char_u **)&p);
|
||||
if (c == '/') {
|
||||
headc = 0;
|
||||
else {
|
||||
if (headc == 0)
|
||||
} else {
|
||||
if (headc == 0) {
|
||||
headc = c;
|
||||
}
|
||||
|
||||
// Characters above 255 don't fit in sl_map_array[], put them in
|
||||
// the hash table. Each entry is the char, a NUL the headchar and
|
||||
|
@ -291,30 +291,33 @@ void vim_strup(char_u *p)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make string "s" all upper-case and return it in allocated memory.
|
||||
* Handles multi-byte characters as well as possible.
|
||||
*/
|
||||
char_u *strup_save(const char_u *orig)
|
||||
/// Make given string all upper-case
|
||||
///
|
||||
/// Handels multi-byte characters as good as possible.
|
||||
///
|
||||
/// @param[in] orig Input string.
|
||||
///
|
||||
/// @return [allocated] upper-cased string.
|
||||
char *strup_save(const char *const orig)
|
||||
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
char_u *res = vim_strsave(orig);
|
||||
char *res = xstrdup(orig);
|
||||
|
||||
char_u *p = res;
|
||||
char *p = res;
|
||||
while (*p != NUL) {
|
||||
int l;
|
||||
|
||||
if (enc_utf8) {
|
||||
int c = utf_ptr2char(p);
|
||||
int c = utf_ptr2char((const char_u *)p);
|
||||
int uc = utf_toupper(c);
|
||||
|
||||
/* Reallocate string when byte count changes. This is rare,
|
||||
* thus it's OK to do another malloc()/free(). */
|
||||
l = utf_ptr2len(p);
|
||||
// Reallocate string when byte count changes. This is rare,
|
||||
// thus it's OK to do another malloc()/free().
|
||||
l = utf_ptr2len((const char_u *)p);
|
||||
int newl = utf_char2len(uc);
|
||||
if (newl != l) {
|
||||
// TODO(philix): use xrealloc() in strup_save()
|
||||
char_u *s = xmalloc(STRLEN(res) + (size_t)(1 + newl - l));
|
||||
char *s = xmalloc(STRLEN(res) + (size_t)(1 + newl - l));
|
||||
memcpy(s, res, (size_t)(p - res));
|
||||
STRCPY(s + (p - res) + newl, p + l);
|
||||
p = s + (p - res);
|
||||
@ -322,12 +325,13 @@ char_u *strup_save(const char_u *orig)
|
||||
res = s;
|
||||
}
|
||||
|
||||
utf_char2bytes(uc, p);
|
||||
utf_char2bytes(uc, (char_u *)p);
|
||||
p += newl;
|
||||
} else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
|
||||
p += l; /* skip multi-byte character */
|
||||
else {
|
||||
*p = (char_u) TOUPPER_LOC(*p); // note that toupper() can be a macro
|
||||
} else if (has_mbyte && (l = (*mb_ptr2len)((const char_u *)p)) > 1) {
|
||||
p += l; // Skip multi-byte character.
|
||||
} else {
|
||||
// note that toupper() can be a macro
|
||||
*p = (char)(uint8_t)TOUPPER_LOC(*p);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
@ -571,8 +575,8 @@ static varnumber_T tv_nr(typval_T *tvs, int *idxp)
|
||||
EMSG(_(e_printf));
|
||||
} else {
|
||||
(*idxp)++;
|
||||
int err = false;
|
||||
n = (varnumber_T)get_tv_number_chk(&tvs[idx], &err);
|
||||
bool err = false;
|
||||
n = tv_get_number_chk(&tvs[idx], &err);
|
||||
if (err) {
|
||||
n = 0;
|
||||
}
|
||||
@ -594,22 +598,21 @@ static varnumber_T tv_nr(typval_T *tvs, int *idxp)
|
||||
/// free "*tofree".
|
||||
///
|
||||
/// @return String value or NULL in case of error.
|
||||
static char *tv_str(typval_T *tvs, int *idxp, char ** const tofree)
|
||||
static const char *tv_str(typval_T *tvs, int *idxp, char **const tofree)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
int idx = *idxp - 1;
|
||||
char *s = NULL;
|
||||
const char *s = NULL;
|
||||
|
||||
if (tvs[idx].v_type == VAR_UNKNOWN) {
|
||||
EMSG(_(e_printf));
|
||||
} else {
|
||||
(*idxp)++;
|
||||
if (tvs[idx].v_type == VAR_STRING || tvs[idx].v_type == VAR_NUMBER) {
|
||||
s = (char *)get_tv_string_chk(&tvs[idx]);
|
||||
s = tv_get_string_chk(&tvs[idx]);
|
||||
*tofree = NULL;
|
||||
} else {
|
||||
s = encode_tv2echo(&tvs[idx], NULL);
|
||||
*tofree = s;
|
||||
s = *tofree = encode_tv2echo(&tvs[idx], NULL);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
@ -949,7 +952,7 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,
|
||||
case 's':
|
||||
case 'S':
|
||||
str_arg = tvs ? tv_str(tvs, &arg_idx, &tofree)
|
||||
: va_arg(ap, char *);
|
||||
: va_arg(ap, const char *);
|
||||
if (!str_arg) {
|
||||
str_arg = "[NULL]";
|
||||
str_arg_l = 6;
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "nvim/types.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "strings.h.generated.h"
|
||||
|
@ -1406,14 +1406,14 @@ static int syn_stack_equal(synstate_T *sp)
|
||||
/* If the pointer is different it can still be the
|
||||
* same text. Compare the strings, ignore case when
|
||||
* the start item has the sp_ic flag set. */
|
||||
if (bsx->matches[j] == NULL
|
||||
|| six->matches[j] == NULL)
|
||||
if (bsx->matches[j] == NULL || six->matches[j] == NULL) {
|
||||
break;
|
||||
if ((SYN_ITEMS(syn_block)[CUR_STATE(i).si_idx]).sp_ic
|
||||
? mb_stricmp(bsx->matches[j],
|
||||
six->matches[j]) != 0
|
||||
: STRCMP(bsx->matches[j], six->matches[j]) != 0)
|
||||
}
|
||||
if (mb_strcmp_ic((SYN_ITEMS(syn_block)[CUR_STATE(i).si_idx]).sp_ic,
|
||||
(const char *)bsx->matches[j],
|
||||
(const char *)six->matches[j]) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j != NSUBEXP)
|
||||
@ -3259,9 +3259,10 @@ static void syn_cmd_clear(exarg_T *eap, int syncing)
|
||||
syntax_sync_clear();
|
||||
else {
|
||||
syntax_clear(curwin->w_s);
|
||||
if (curwin->w_s == &curwin->w_buffer->b_s)
|
||||
do_unlet((char_u *)"b:current_syntax", TRUE);
|
||||
do_unlet((char_u *)"w:current_syntax", TRUE);
|
||||
if (curwin->w_s == &curwin->w_buffer->b_s) {
|
||||
do_unlet(S_LEN("b:current_syntax"), true);
|
||||
}
|
||||
do_unlet(S_LEN("w:current_syntax"), true);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
@ -3337,7 +3338,7 @@ static void syn_cmd_enable(exarg_T *eap, int syncing)
|
||||
{
|
||||
set_internal_string_var((char_u *)"syntax_cmd", (char_u *)"enable");
|
||||
syn_cmd_onoff(eap, "syntax");
|
||||
do_unlet((char_u *)"g:syntax_cmd", TRUE);
|
||||
do_unlet(S_LEN("g:syntax_cmd"), true);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3350,7 +3351,7 @@ static void syn_cmd_reset(exarg_T *eap, int syncing)
|
||||
if (!eap->skip) {
|
||||
set_internal_string_var((char_u *)"syntax_cmd", (char_u *)"reset");
|
||||
do_cmdline_cmd("runtime! syntax/syncolor.vim");
|
||||
do_unlet((char_u *)"g:syntax_cmd", TRUE);
|
||||
do_unlet(S_LEN("g:syntax_cmd"), true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5537,10 +5538,10 @@ void ex_ownsyntax(exarg_T *eap)
|
||||
set_internal_string_var((char_u *)"w:current_syntax", new_value);
|
||||
}
|
||||
|
||||
/* restore value of b:current_syntax */
|
||||
if (old_value == NULL)
|
||||
do_unlet((char_u *)"b:current_syntax", TRUE);
|
||||
else {
|
||||
// Restore value of b:current_syntax.
|
||||
if (old_value == NULL) {
|
||||
do_unlet(S_LEN("b:current_syntax"), true);
|
||||
} else {
|
||||
set_internal_string_var((char_u *)"b:current_syntax", old_value);
|
||||
xfree(old_value);
|
||||
}
|
||||
@ -5573,43 +5574,42 @@ void reset_expand_highlight(void)
|
||||
* Handle command line completion for :match and :echohl command: Add "None"
|
||||
* as highlight group.
|
||||
*/
|
||||
void set_context_in_echohl_cmd(expand_T *xp, char_u *arg)
|
||||
void set_context_in_echohl_cmd(expand_T *xp, const char *arg)
|
||||
{
|
||||
xp->xp_context = EXPAND_HIGHLIGHT;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
include_none = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle command line completion for :syntax command.
|
||||
*/
|
||||
void set_context_in_syntax_cmd(expand_T *xp, char_u *arg)
|
||||
void set_context_in_syntax_cmd(expand_T *xp, const char *arg)
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
/* Default: expand subcommands */
|
||||
// Default: expand subcommands.
|
||||
xp->xp_context = EXPAND_SYNTAX;
|
||||
expand_what = EXP_SUBCMD;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
include_link = 0;
|
||||
include_default = 0;
|
||||
|
||||
/* (part of) subcommand already typed */
|
||||
if (*arg != NUL) {
|
||||
p = skiptowhite(arg);
|
||||
if (*p != NUL) { /* past first word */
|
||||
xp->xp_pattern = skipwhite(p);
|
||||
if (*skiptowhite(xp->xp_pattern) != NUL)
|
||||
const char *p = (const char *)skiptowhite((const char_u *)arg);
|
||||
if (*p != NUL) { // Past first word.
|
||||
xp->xp_pattern = skipwhite((const char_u *)p);
|
||||
if (*skiptowhite(xp->xp_pattern) != NUL) {
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
else if (STRNICMP(arg, "case", p - arg) == 0)
|
||||
} else if (STRNICMP(arg, "case", p - arg) == 0) {
|
||||
expand_what = EXP_CASE;
|
||||
else if ( STRNICMP(arg, "keyword", p - arg) == 0
|
||||
} else if (STRNICMP(arg, "keyword", p - arg) == 0
|
||||
|| STRNICMP(arg, "region", p - arg) == 0
|
||||
|| STRNICMP(arg, "match", p - arg) == 0
|
||||
|| STRNICMP(arg, "list", p - arg) == 0)
|
||||
|| STRNICMP(arg, "list", p - arg) == 0) {
|
||||
xp->xp_context = EXPAND_HIGHLIGHT;
|
||||
else
|
||||
} else {
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6231,7 +6231,7 @@ do_highlight (
|
||||
*/
|
||||
line = linep;
|
||||
if (ends_excmd(*line)) {
|
||||
do_unlet((char_u *)"colors_name", TRUE);
|
||||
do_unlet(S_LEN("colors_name"), true);
|
||||
restore_cterm_colors();
|
||||
|
||||
/*
|
||||
@ -6510,16 +6510,16 @@ do_highlight (
|
||||
if (!ui_rgb_attached()) {
|
||||
must_redraw = CLEAR;
|
||||
if (color >= 0) {
|
||||
if (t_colors < 16)
|
||||
if (t_colors < 16) {
|
||||
i = (color == 0 || color == 4);
|
||||
else
|
||||
} else {
|
||||
i = (color < 7 || color == 8);
|
||||
/* Set the 'background' option if the value is
|
||||
* wrong. */
|
||||
if (i != (*p_bg == 'd'))
|
||||
set_option_value((char_u *)"bg", 0L,
|
||||
i ? (char_u *)"dark"
|
||||
: (char_u *)"light", 0);
|
||||
}
|
||||
// Set the 'background' option if the value is
|
||||
// wrong.
|
||||
if (i != (*p_bg == 'd')) {
|
||||
set_option_value("bg", 0L, (i ? "dark" : "light"), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6930,21 +6930,21 @@ static int highlight_list_arg(int id, int didh, int type, int iarg, char_u *sarg
|
||||
return didh;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "1" if highlight group "id" has attribute "flag".
|
||||
* Return NULL otherwise.
|
||||
*/
|
||||
char_u *
|
||||
highlight_has_attr (
|
||||
int id,
|
||||
int flag,
|
||||
int modec // 'g' for GUI, 'c' for cterm
|
||||
)
|
||||
/// Check whether highlight group has attribute
|
||||
///
|
||||
/// @param[in] id Highilght group to check.
|
||||
/// @param[in] flag Attribute to check.
|
||||
/// @param[in] modec 'g' for GUI, 'c' for term.
|
||||
///
|
||||
/// @return "1" if highlight group has attribute, NULL otherwise.
|
||||
const char *highlight_has_attr(const int id, const int flag, const int modec)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
|
||||
{
|
||||
int attr;
|
||||
|
||||
if (id <= 0 || id > highlight_ga.ga_len)
|
||||
if (id <= 0 || id > highlight_ga.ga_len) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (modec == 'g') {
|
||||
attr = HL_TABLE()[id - 1].sg_gui;
|
||||
@ -6952,39 +6952,42 @@ highlight_has_attr (
|
||||
attr = HL_TABLE()[id - 1].sg_cterm;
|
||||
}
|
||||
|
||||
if (attr & flag)
|
||||
return (char_u *)"1";
|
||||
return NULL;
|
||||
return (attr & flag) ? "1" : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return color name of highlight group "id".
|
||||
*/
|
||||
char_u *
|
||||
highlight_color (
|
||||
int id,
|
||||
char_u *what, /* "font", "fg", "bg", "sp", "fg#", "bg#" or "sp#" */
|
||||
int modec /* 'g' for GUI, 'c' for cterm, 't' for term */
|
||||
)
|
||||
/// Return color name of the given highlight group
|
||||
///
|
||||
/// @param[in] id Highlight group to work with.
|
||||
/// @param[in] what What to return: one of "font", "fg", "bg", "sp", "fg#",
|
||||
/// "bg#" or "sp#".
|
||||
/// @param[in] modec 'g' for GUI, 'c' for cterm and 't' for term.
|
||||
///
|
||||
/// @return color name, possibly in a static buffer. Buffer will be overwritten
|
||||
/// on next highlight_color() call. May return NULL.
|
||||
const char *highlight_color(const int id, const char *const what,
|
||||
const int modec)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
static char_u name[20];
|
||||
static char name[20];
|
||||
int n;
|
||||
int fg = FALSE;
|
||||
int sp = FALSE;
|
||||
int font = FALSE;
|
||||
bool fg = false;
|
||||
bool sp = false;
|
||||
bool font = false;
|
||||
|
||||
if (id <= 0 || id > highlight_ga.ga_len)
|
||||
if (id <= 0 || id > highlight_ga.ga_len) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'g')
|
||||
fg = TRUE;
|
||||
else if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'o'
|
||||
&& TOLOWER_ASC(what[2]) == 'n' && TOLOWER_ASC(what[3]) == 't')
|
||||
font = TRUE;
|
||||
else if (TOLOWER_ASC(what[0]) == 's' && TOLOWER_ASC(what[1]) == 'p')
|
||||
sp = TRUE;
|
||||
else if (!(TOLOWER_ASC(what[0]) == 'b' && TOLOWER_ASC(what[1]) == 'g'))
|
||||
if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'g') {
|
||||
fg = true;
|
||||
} else if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'o'
|
||||
&& TOLOWER_ASC(what[2]) == 'n' && TOLOWER_ASC(what[3]) == 't') {
|
||||
font = true;
|
||||
} else if (TOLOWER_ASC(what[0]) == 's' && TOLOWER_ASC(what[1]) == 'p') {
|
||||
sp = true;
|
||||
} else if (!(TOLOWER_ASC(what[0]) == 'b' && TOLOWER_ASC(what[1]) == 'g')) {
|
||||
return NULL;
|
||||
}
|
||||
if (modec == 'g') {
|
||||
if (what[2] == '#' && ui_rgb_attached()) {
|
||||
if (fg) {
|
||||
@ -6997,19 +7000,20 @@ highlight_color (
|
||||
if (n < 0 || n > 0xffffff) {
|
||||
return NULL;
|
||||
}
|
||||
snprintf((char *)name, sizeof(name), "#%06x", n);
|
||||
snprintf(name, sizeof(name), "#%06x", n);
|
||||
return name;
|
||||
}
|
||||
if (fg) {
|
||||
return HL_TABLE()[id - 1].sg_rgb_fg_name;
|
||||
return (const char *)HL_TABLE()[id - 1].sg_rgb_fg_name;
|
||||
}
|
||||
if (sp) {
|
||||
return HL_TABLE()[id - 1].sg_rgb_sp_name;
|
||||
return (const char *)HL_TABLE()[id - 1].sg_rgb_sp_name;
|
||||
}
|
||||
return HL_TABLE()[id - 1].sg_rgb_bg_name;
|
||||
return (const char *)HL_TABLE()[id - 1].sg_rgb_bg_name;
|
||||
}
|
||||
if (font || sp)
|
||||
if (font || sp) {
|
||||
return NULL;
|
||||
}
|
||||
if (modec == 'c') {
|
||||
if (fg) {
|
||||
n = HL_TABLE()[id - 1].sg_cterm_fg - 1;
|
||||
@ -7019,10 +7023,10 @@ highlight_color (
|
||||
if (n < 0) {
|
||||
return NULL;
|
||||
}
|
||||
snprintf((char *)name, sizeof(name), "%d", n);
|
||||
snprintf(name, sizeof(name), "%d", n);
|
||||
return name;
|
||||
}
|
||||
/* term doesn't have color */
|
||||
// term doesn't have color.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -7113,7 +7117,7 @@ set_hl_attr (
|
||||
* Lookup a highlight group name and return it's ID.
|
||||
* If it is not found, 0 is returned.
|
||||
*/
|
||||
int syn_name2id(char_u *name)
|
||||
int syn_name2id(const char_u *name)
|
||||
{
|
||||
int i;
|
||||
char_u name_u[200];
|
||||
@ -7133,7 +7137,7 @@ int syn_name2id(char_u *name)
|
||||
/*
|
||||
* Return TRUE if highlight group "name" exists.
|
||||
*/
|
||||
int highlight_exists(char_u *name)
|
||||
int highlight_exists(const char_u *name)
|
||||
{
|
||||
return syn_name2id(name) > 0;
|
||||
}
|
||||
@ -7469,41 +7473,41 @@ int highlight_changed(void)
|
||||
/*
|
||||
* Handle command line completion for :highlight command.
|
||||
*/
|
||||
void set_context_in_highlight_cmd(expand_T *xp, char_u *arg)
|
||||
void set_context_in_highlight_cmd(expand_T *xp, const char *arg)
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
/* Default: expand group names */
|
||||
// Default: expand group names.
|
||||
xp->xp_context = EXPAND_HIGHLIGHT;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
include_link = 2;
|
||||
include_default = 1;
|
||||
|
||||
/* (part of) subcommand already typed */
|
||||
if (*arg != NUL) {
|
||||
p = skiptowhite(arg);
|
||||
if (*p != NUL) { /* past "default" or group name */
|
||||
const char *p = (const char *)skiptowhite((const char_u *)arg);
|
||||
if (*p != NUL) { // Past "default" or group name.
|
||||
include_default = 0;
|
||||
if (STRNCMP("default", arg, p - arg) == 0) {
|
||||
arg = skipwhite(p);
|
||||
xp->xp_pattern = arg;
|
||||
p = skiptowhite(arg);
|
||||
if (strncmp("default", arg, p - arg) == 0) {
|
||||
arg = (const char *)skipwhite((const char_u *)p);
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
p = (const char *)skiptowhite((const char_u *)arg);
|
||||
}
|
||||
if (*p != NUL) { /* past group name */
|
||||
include_link = 0;
|
||||
if (arg[1] == 'i' && arg[0] == 'N')
|
||||
if (arg[1] == 'i' && arg[0] == 'N') {
|
||||
highlight_list();
|
||||
if (STRNCMP("link", arg, p - arg) == 0
|
||||
|| STRNCMP("clear", arg, p - arg) == 0) {
|
||||
xp->xp_pattern = skipwhite(p);
|
||||
p = skiptowhite(xp->xp_pattern);
|
||||
if (*p != NUL) { /* past first group name */
|
||||
xp->xp_pattern = skipwhite(p);
|
||||
p = skiptowhite(xp->xp_pattern);
|
||||
}
|
||||
if (strncmp("link", arg, p - arg) == 0
|
||||
|| strncmp("clear", arg, p - arg) == 0) {
|
||||
xp->xp_pattern = skipwhite((const char_u *)p);
|
||||
p = (const char *)skiptowhite(xp->xp_pattern);
|
||||
if (*p != NUL) { // Past first group name.
|
||||
xp->xp_pattern = skipwhite((const char_u *)p);
|
||||
p = (const char *)skiptowhite(xp->xp_pattern);
|
||||
}
|
||||
}
|
||||
if (*p != NUL) /* past group name(s) */
|
||||
if (*p != NUL) { // Past group name(s).
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -674,7 +674,7 @@ do_tag (
|
||||
|
||||
fname = xmalloc(MAXPATHL + 1);
|
||||
cmd = xmalloc(CMDBUFFSIZE + 1);
|
||||
list = list_alloc();
|
||||
list = tv_list_alloc();
|
||||
|
||||
for (i = 0; i < num_matches; ++i) {
|
||||
int len, cmd_len;
|
||||
@ -773,20 +773,21 @@ do_tag (
|
||||
cmd[len] = NUL;
|
||||
}
|
||||
|
||||
dict = dict_alloc();
|
||||
list_append_dict(list, dict);
|
||||
dict = tv_dict_alloc();
|
||||
tv_list_append_dict(list, dict);
|
||||
|
||||
dict_add_nr_str(dict, "text", 0L, tag_name);
|
||||
dict_add_nr_str(dict, "filename", 0L, fname);
|
||||
dict_add_nr_str(dict, "lnum", lnum, NULL);
|
||||
if (lnum == 0)
|
||||
dict_add_nr_str(dict, "pattern", 0L, cmd);
|
||||
tv_dict_add_str(dict, S_LEN("text"), (const char *)tag_name);
|
||||
tv_dict_add_str(dict, S_LEN("filename"), (const char *)fname);
|
||||
tv_dict_add_nr(dict, S_LEN("lnum"), lnum);
|
||||
if (lnum == 0) {
|
||||
tv_dict_add_str(dict, S_LEN("pattern"), (const char *)cmd);
|
||||
}
|
||||
}
|
||||
|
||||
vim_snprintf((char *)IObuff, IOSIZE, "ltag %s", tag);
|
||||
set_errorlist(curwin, list, ' ', IObuff, NULL);
|
||||
|
||||
list_free(list);
|
||||
tv_list_free(list);
|
||||
xfree(fname);
|
||||
xfree(cmd);
|
||||
|
||||
@ -2203,7 +2204,7 @@ parse_tag_line (
|
||||
* Return TRUE if it is a static tag and adjust *tagname to the real tag.
|
||||
* Return FALSE if it is not a static tag.
|
||||
*/
|
||||
static int test_for_static(tagptrs_T *tagp)
|
||||
static bool test_for_static(tagptrs_T *tagp)
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
@ -2768,8 +2769,8 @@ add_tag_field (
|
||||
int len = 0;
|
||||
int retval;
|
||||
|
||||
/* check that the field name doesn't exist yet */
|
||||
if (dict_find(dict, (char_u *)field_name, -1) != NULL) {
|
||||
// Check that the field name doesn't exist yet.
|
||||
if (tv_dict_find(dict, field_name, -1) != NULL) {
|
||||
if (p_verbose > 0) {
|
||||
verbose_enter();
|
||||
smsg(_("Duplicate field name: %s"), field_name);
|
||||
@ -2790,7 +2791,8 @@ add_tag_field (
|
||||
STRLCPY(buf, start, len + 1);
|
||||
}
|
||||
buf[len] = NUL;
|
||||
retval = dict_add_nr_str(dict, field_name, 0L, buf);
|
||||
retval = tv_dict_add_str(dict, field_name, STRLEN(field_name),
|
||||
(const char *)buf);
|
||||
xfree(buf);
|
||||
return retval;
|
||||
}
|
||||
@ -2806,7 +2808,7 @@ int get_tags(list_T *list, char_u *pat)
|
||||
char_u *full_fname;
|
||||
dict_T *dict;
|
||||
tagptrs_T tp;
|
||||
long is_static;
|
||||
bool is_static;
|
||||
|
||||
ret = find_tags(pat, &num_matches, &matches,
|
||||
TAG_REGEXP | TAG_NOIC, (int)MAXCOL, NULL);
|
||||
@ -2824,19 +2826,18 @@ int get_tags(list_T *list, char_u *pat)
|
||||
if (STRNCMP(tp.tagname, "!_TAG_", 6) == 0)
|
||||
continue;
|
||||
|
||||
dict = dict_alloc();
|
||||
list_append_dict(list, dict);
|
||||
dict = tv_dict_alloc();
|
||||
tv_list_append_dict(list, dict);
|
||||
|
||||
full_fname = tag_full_fname(&tp);
|
||||
if (add_tag_field(dict, "name", tp.tagname, tp.tagname_end) == FAIL
|
||||
|| add_tag_field(dict, "filename", full_fname,
|
||||
NULL) == FAIL
|
||||
|| add_tag_field(dict, "cmd", tp.command,
|
||||
tp.command_end) == FAIL
|
||||
|| add_tag_field(dict, "filename", full_fname, NULL) == FAIL
|
||||
|| add_tag_field(dict, "cmd", tp.command, tp.command_end) == FAIL
|
||||
|| add_tag_field(dict, "kind", tp.tagkind,
|
||||
tp.tagkind ? tp.tagkind_end : NULL) == FAIL
|
||||
|| dict_add_nr_str(dict, "static", is_static, NULL) == FAIL)
|
||||
tp.tagkind ? tp.tagkind_end : NULL) == FAIL
|
||||
|| tv_dict_add_nr(dict, S_LEN("static"), is_static) == FAIL) {
|
||||
ret = FAIL;
|
||||
}
|
||||
|
||||
xfree(full_fname);
|
||||
|
||||
|
@ -226,17 +226,17 @@ Terminal *terminal_open(TerminalOptions opts)
|
||||
rv->invalid_start = 0;
|
||||
rv->invalid_end = opts.height;
|
||||
refresh_screen(rv, curbuf);
|
||||
set_option_value((uint8_t *)"buftype", 0, (uint8_t *)"terminal", OPT_LOCAL);
|
||||
set_option_value("buftype", 0, "terminal", OPT_LOCAL);
|
||||
|
||||
// Default settings for terminal buffers
|
||||
curbuf->b_p_ma = false; // 'nomodifiable'
|
||||
curbuf->b_p_ul = -1; // 'undolevels'
|
||||
curbuf->b_p_scbk = p_scbk; // 'scrollback'
|
||||
curbuf->b_p_tw = 0; // 'textwidth'
|
||||
set_option_value((uint8_t *)"wrap", false, NULL, OPT_LOCAL);
|
||||
set_option_value((uint8_t *)"number", false, NULL, OPT_LOCAL);
|
||||
set_option_value((uint8_t *)"relativenumber", false, NULL, OPT_LOCAL);
|
||||
set_option_value((uint8_t *)"list", false, NULL, OPT_LOCAL);
|
||||
set_option_value("wrap", false, NULL, OPT_LOCAL);
|
||||
set_option_value("number", false, NULL, OPT_LOCAL);
|
||||
set_option_value("relativenumber", false, NULL, OPT_LOCAL);
|
||||
set_option_value("list", false, NULL, OPT_LOCAL);
|
||||
buf_set_term_title(curbuf, (char *)curbuf->b_ffname);
|
||||
RESET_BINDING(curwin);
|
||||
// Reset cursor in current window.
|
||||
|
@ -1015,7 +1015,7 @@ static const char *tui_tk_ti_getstr(const char *name, const char *value,
|
||||
ILOG("libtermkey:kdch1=%s", value);
|
||||
// Vim: "If <BS> and <DEL> are now the same, redefine <DEL>."
|
||||
if (stty_erase != NULL && value != NULL && strcmp(stty_erase, value) == 0) {
|
||||
return stty_erase[0] == DEL ? (char *)CTRL_H_STR : (char *)DEL_STR;
|
||||
return stty_erase[0] == DEL ? CTRL_H_STR : DEL_STR;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,6 +82,7 @@
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/undo.h"
|
||||
#include "nvim/macros.h"
|
||||
#include "nvim/cursor.h"
|
||||
#include "nvim/edit.h"
|
||||
#include "nvim/eval.h"
|
||||
@ -317,7 +318,7 @@ static long get_undolevel(void)
|
||||
static inline void zero_fmark_additional_data(fmark_T *fmarks)
|
||||
{
|
||||
for (size_t i = 0; i < NMARKS; i++) {
|
||||
dict_unref(fmarks[i].additional_data);
|
||||
tv_dict_unref(fmarks[i].additional_data);
|
||||
fmarks[i].additional_data = NULL;
|
||||
}
|
||||
}
|
||||
@ -1080,7 +1081,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
|
||||
*/
|
||||
perm = 0600;
|
||||
if (buf->b_ffname != NULL) {
|
||||
perm = os_getperm(buf->b_ffname);
|
||||
perm = os_getperm((const char *)buf->b_ffname);
|
||||
if (perm < 0) {
|
||||
perm = 0600;
|
||||
}
|
||||
@ -1139,7 +1140,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
|
||||
EMSG2(_(e_not_open), file_name);
|
||||
goto theend;
|
||||
}
|
||||
(void)os_setperm((char_u *)file_name, perm);
|
||||
(void)os_setperm(file_name, perm);
|
||||
if (p_verbose > 0) {
|
||||
verbose_enter();
|
||||
smsg(_("Writing undo file: %s"), file_name);
|
||||
@ -1164,7 +1165,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
|
||||
&& os_fileinfo(file_name, &file_info_new)
|
||||
&& file_info_old.stat.st_gid != file_info_new.stat.st_gid
|
||||
&& os_fchown(fd, (uv_uid_t)-1, (uv_gid_t)file_info_old.stat.st_gid)) {
|
||||
os_setperm((char_u *)file_name, (perm & 0707) | ((perm & 07) << 3));
|
||||
os_setperm(file_name, (perm & 0707) | ((perm & 07) << 3));
|
||||
}
|
||||
# ifdef HAVE_SELINUX
|
||||
if (buf->b_ffname != NULL)
|
||||
@ -2941,25 +2942,28 @@ void u_eval_tree(u_header_T *first_uhp, list_T *list)
|
||||
dict_T *dict;
|
||||
|
||||
while (uhp != NULL) {
|
||||
dict = dict_alloc();
|
||||
dict_add_nr_str(dict, "seq", uhp->uh_seq, NULL);
|
||||
dict_add_nr_str(dict, "time", (long)uhp->uh_time, NULL);
|
||||
if (uhp == curbuf->b_u_newhead)
|
||||
dict_add_nr_str(dict, "newhead", 1, NULL);
|
||||
if (uhp == curbuf->b_u_curhead)
|
||||
dict_add_nr_str(dict, "curhead", 1, NULL);
|
||||
if (uhp->uh_save_nr > 0)
|
||||
dict_add_nr_str(dict, "save", uhp->uh_save_nr, NULL);
|
||||
|
||||
if (uhp->uh_alt_next.ptr != NULL) {
|
||||
list_T *alt_list = list_alloc();
|
||||
|
||||
/* Recursive call to add alternate undo tree. */
|
||||
u_eval_tree(uhp->uh_alt_next.ptr, alt_list);
|
||||
dict_add_list(dict, "alt", alt_list);
|
||||
dict = tv_dict_alloc();
|
||||
tv_dict_add_nr(dict, S_LEN("seq"), (varnumber_T)uhp->uh_seq);
|
||||
tv_dict_add_nr(dict, S_LEN("time"), (varnumber_T)uhp->uh_time);
|
||||
if (uhp == curbuf->b_u_newhead) {
|
||||
tv_dict_add_nr(dict, S_LEN("newhead"), 1);
|
||||
}
|
||||
if (uhp == curbuf->b_u_curhead) {
|
||||
tv_dict_add_nr(dict, S_LEN("curhead"), 1);
|
||||
}
|
||||
if (uhp->uh_save_nr > 0) {
|
||||
tv_dict_add_nr(dict, S_LEN("save"), (varnumber_T)uhp->uh_save_nr);
|
||||
}
|
||||
|
||||
list_append_dict(list, dict);
|
||||
if (uhp->uh_alt_next.ptr != NULL) {
|
||||
list_T *alt_list = tv_list_alloc();
|
||||
|
||||
// Recursive call to add alternate undo tree.
|
||||
u_eval_tree(uhp->uh_alt_next.ptr, alt_list);
|
||||
tv_dict_add_list(dict, S_LEN("alt"), alt_list);
|
||||
}
|
||||
|
||||
tv_list_append_dict(list, dict);
|
||||
uhp = uhp->uh_prev.ptr;
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ static char *features[] = {
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
static int included_patches[] = {
|
||||
static const int included_patches[] = {
|
||||
// 2367,NA
|
||||
// 2366 NA
|
||||
// 2365 NA
|
||||
@ -2461,10 +2461,10 @@ static char *(extra_patches[]) = {
|
||||
/// @param version Version string like "1.3.42"
|
||||
///
|
||||
/// @return true if Nvim is at or above the version.
|
||||
bool has_nvim_version(char *version_str)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
bool has_nvim_version(const char *const version_str)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
char *p = version_str;
|
||||
const char *p = version_str;
|
||||
int major = 0;
|
||||
int minor = 0;
|
||||
int patch = 0;
|
||||
@ -2473,7 +2473,7 @@ bool has_nvim_version(char *version_str)
|
||||
return false;
|
||||
}
|
||||
major = atoi(p);
|
||||
p = strchr(p, '.'); // Find the next dot.
|
||||
p = strchr(p, '.'); // Find the next dot.
|
||||
|
||||
if (p) {
|
||||
p++; // Advance past the dot.
|
||||
@ -2481,7 +2481,7 @@ bool has_nvim_version(char *version_str)
|
||||
return false;
|
||||
}
|
||||
minor = atoi(p);
|
||||
p = strchr(p, '.');
|
||||
p = strchr(p, '.');
|
||||
if (p) {
|
||||
p++;
|
||||
if (!ascii_isdigit(*p)) {
|
||||
|
@ -30,7 +30,7 @@ Error: configure did not run properly.Check auto/config.log.
|
||||
#include "nvim/os/os_defs.h" /* bring lots of system header files */
|
||||
|
||||
/// length of a buffer to store a number in ASCII (64 bits binary + NUL)
|
||||
#define NUMBUFLEN 65
|
||||
enum { NUMBUFLEN = 65 };
|
||||
|
||||
// flags for vim_str2nr()
|
||||
#define STR2NR_BIN 1
|
||||
@ -51,22 +51,7 @@ Error: configure did not run properly.Check auto/config.log.
|
||||
|
||||
/* ================ end of the header file puzzle =============== */
|
||||
|
||||
#ifdef HAVE_WORKING_LIBINTL
|
||||
# include <libintl.h>
|
||||
# define _(x) gettext((char *)(x))
|
||||
// XXX do we actually need this?
|
||||
# ifdef gettext_noop
|
||||
# define N_(x) gettext_noop(x)
|
||||
# else
|
||||
# define N_(x) x
|
||||
# endif
|
||||
#else
|
||||
# define _(x) ((char *)(x))
|
||||
# define N_(x) x
|
||||
# define bindtextdomain(x, y) /* empty */
|
||||
# define bind_textdomain_codeset(x, y) /* empty */
|
||||
# define textdomain(x) /* empty */
|
||||
#endif
|
||||
#include "nvim/gettext.h"
|
||||
|
||||
/* special attribute addition: Put message in history */
|
||||
#define MSG_HIST 0x1000
|
||||
@ -109,11 +94,14 @@ Error: configure did not run properly.Check auto/config.log.
|
||||
// all mode bits used for mapping
|
||||
#define MAP_ALL_MODES (0x3f | SELECTMODE | TERM_FOCUS)
|
||||
|
||||
/* directions */
|
||||
#define FORWARD 1
|
||||
#define BACKWARD (-1)
|
||||
#define FORWARD_FILE 3
|
||||
#define BACKWARD_FILE (-3)
|
||||
/// Directions.
|
||||
typedef enum {
|
||||
kDirectionNotSet = 0,
|
||||
FORWARD = 1,
|
||||
BACKWARD = (-1),
|
||||
FORWARD_FILE = 3,
|
||||
BACKWARD_FILE = (-3),
|
||||
} Direction;
|
||||
|
||||
/* return values for functions */
|
||||
#if !(defined(OK) && (OK == 1))
|
||||
@ -282,15 +270,22 @@ enum {
|
||||
#define SHOWCMD_COLS 10 /* columns needed by shown command */
|
||||
#define STL_MAX_ITEM 80 /* max nr of %<flag> in statusline */
|
||||
|
||||
/*
|
||||
* fnamecmp() is used to compare file names.
|
||||
* On some systems case in a file name does not matter, on others it does.
|
||||
* (this does not account for maximum name lengths and things like "../dir",
|
||||
* thus it is not 100% accurate!)
|
||||
*/
|
||||
#define fnamecmp(x, y) vim_fnamecmp((char_u *)(x), (char_u *)(y))
|
||||
#define fnamencmp(x, y, n) vim_fnamencmp((char_u *)(x), (char_u *)(y), \
|
||||
(size_t)(n))
|
||||
/// Compare file names
|
||||
///
|
||||
/// On some systems case in a file name does not matter, on others it does.
|
||||
///
|
||||
/// @note Does not account for maximum name lengths and things like "../dir",
|
||||
/// thus it is not 100% accurate. OS may also use different algorythm for
|
||||
/// case-insensitive comparison.
|
||||
///
|
||||
/// @param[in] x First file name to compare.
|
||||
/// @param[in] y Second file name to compare.
|
||||
///
|
||||
/// @return 0 for equal file names, non-zero otherwise.
|
||||
#define fnamecmp(x, y) path_fnamecmp((const char *)(x), (const char *)(y))
|
||||
#define fnamencmp(x, y, n) path_fnamencmp((const char *)(x), \
|
||||
(const char *)(y), \
|
||||
(size_t)(n))
|
||||
|
||||
/*
|
||||
* Enums need a typecast to be used as array index (for Ultrix).
|
||||
|
@ -2983,8 +2983,8 @@ static tabpage_T *alloc_tabpage(void)
|
||||
tp->handle = ++last_tp_handle;
|
||||
handle_register_tabpage(tp);
|
||||
|
||||
/* init t: variables */
|
||||
tp->tp_vars = dict_alloc();
|
||||
// Init t: variables.
|
||||
tp->tp_vars = tv_dict_alloc();
|
||||
init_var_dict(tp->tp_vars, &tp->tp_winvar, VAR_SCOPE);
|
||||
tp->tp_diff_invalid = TRUE;
|
||||
tp->tp_ch_used = p_ch;
|
||||
@ -3811,8 +3811,8 @@ static win_T *win_alloc(win_T *after, int hidden)
|
||||
new_wp->handle = ++last_win_id;
|
||||
handle_register_window(new_wp);
|
||||
|
||||
/* init w: variables */
|
||||
new_wp->w_vars = dict_alloc();
|
||||
// Init w: variables.
|
||||
new_wp->w_vars = tv_dict_alloc();
|
||||
init_var_dict(new_wp->w_vars, &new_wp->w_winvar, VAR_SCOPE);
|
||||
|
||||
/* Don't execute autocommands while the window is not properly
|
||||
@ -5504,9 +5504,9 @@ void restore_buffer(bufref_T *save_curbuf)
|
||||
// Optionally, a desired ID 'id' can be specified (greater than or equal to 1).
|
||||
// If no particular ID is desired, -1 must be specified for 'id'.
|
||||
// Return ID of added match, -1 on failure.
|
||||
int match_add(win_T *wp, char_u *grp, char_u *pat,
|
||||
int match_add(win_T *wp, const char *const grp, const char *const pat,
|
||||
int prio, int id, list_T *pos_list,
|
||||
char_u *conceal_char)
|
||||
const char *const conceal_char)
|
||||
{
|
||||
matchitem_T *cur;
|
||||
matchitem_T *prev;
|
||||
@ -5534,11 +5534,11 @@ int match_add(win_T *wp, char_u *grp, char_u *pat,
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
if ((hlg_id = syn_namen2id(grp, (int)STRLEN(grp))) == 0) {
|
||||
if ((hlg_id = syn_name2id((const char_u *)grp)) == 0) {
|
||||
EMSG2(_(e_nogroup), grp);
|
||||
return -1;
|
||||
}
|
||||
if (pat != NULL && (regprog = vim_regcomp(pat, RE_MAGIC)) == NULL) {
|
||||
if (pat != NULL && (regprog = vim_regcomp((char_u *)pat, RE_MAGIC)) == NULL) {
|
||||
EMSG2(_(e_invarg2), pat);
|
||||
return -1;
|
||||
}
|
||||
@ -5557,14 +5557,14 @@ int match_add(win_T *wp, char_u *grp, char_u *pat,
|
||||
m = xcalloc(1, sizeof(matchitem_T));
|
||||
m->id = id;
|
||||
m->priority = prio;
|
||||
m->pattern = pat == NULL ? NULL: vim_strsave(pat);
|
||||
m->pattern = pat == NULL ? NULL: (char_u *)xstrdup(pat);
|
||||
m->hlg_id = hlg_id;
|
||||
m->match.regprog = regprog;
|
||||
m->match.rmm_ic = FALSE;
|
||||
m->match.rmm_maxcol = 0;
|
||||
m->conceal_char = 0;
|
||||
if (conceal_char != NULL) {
|
||||
m->conceal_char = (*mb_ptr2char)(conceal_char);
|
||||
m->conceal_char = (*mb_ptr2char)((const char_u *)conceal_char);
|
||||
}
|
||||
|
||||
// Set up position matches
|
||||
@ -5582,7 +5582,7 @@ int match_add(win_T *wp, char_u *grp, char_u *pat,
|
||||
int len = 1;
|
||||
list_T *subl;
|
||||
listitem_T *subli;
|
||||
int error = false;
|
||||
bool error = false;
|
||||
|
||||
if (li->li_tv.v_type == VAR_LIST) {
|
||||
subl = li->li_tv.vval.v_list;
|
||||
@ -5593,8 +5593,8 @@ int match_add(win_T *wp, char_u *grp, char_u *pat,
|
||||
if (subli == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
lnum = get_tv_number_chk(&subli->li_tv, &error);
|
||||
if (error == true) {
|
||||
lnum = tv_get_number_chk(&subli->li_tv, &error);
|
||||
if (error) {
|
||||
goto fail;
|
||||
}
|
||||
if (lnum == 0) {
|
||||
@ -5604,13 +5604,14 @@ int match_add(win_T *wp, char_u *grp, char_u *pat,
|
||||
m->pos.pos[i].lnum = lnum;
|
||||
subli = subli->li_next;
|
||||
if (subli != NULL) {
|
||||
col = get_tv_number_chk(&subli->li_tv, &error);
|
||||
if (error == true)
|
||||
col = tv_get_number_chk(&subli->li_tv, &error);
|
||||
if (error) {
|
||||
goto fail;
|
||||
}
|
||||
subli = subli->li_next;
|
||||
if (subli != NULL) {
|
||||
len = get_tv_number_chk(&subli->li_tv, &error);
|
||||
if (error == true) {
|
||||
len = tv_get_number_chk(&subli->li_tv, &error);
|
||||
if (error) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
@ -5809,14 +5810,14 @@ int win_getid(typval_T *argvars)
|
||||
if (argvars[0].v_type == VAR_UNKNOWN) {
|
||||
return curwin->handle;
|
||||
}
|
||||
int winnr = get_tv_number(&argvars[0]);
|
||||
int winnr = tv_get_number(&argvars[0]);
|
||||
win_T *wp;
|
||||
if (winnr > 0) {
|
||||
if (argvars[1].v_type == VAR_UNKNOWN) {
|
||||
wp = firstwin;
|
||||
} else {
|
||||
tabpage_T *tp = NULL;
|
||||
int tabnr = get_tv_number(&argvars[1]);
|
||||
int tabnr = tv_get_number(&argvars[1]);
|
||||
FOR_ALL_TABS(tp2) {
|
||||
if (--tabnr == 0) {
|
||||
tp = tp2;
|
||||
@ -5843,7 +5844,7 @@ int win_getid(typval_T *argvars)
|
||||
|
||||
int win_gotoid(typval_T *argvars)
|
||||
{
|
||||
int id = get_tv_number(&argvars[0]);
|
||||
int id = tv_get_number(&argvars[0]);
|
||||
|
||||
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
||||
if (wp->handle == id) {
|
||||
@ -5878,16 +5879,16 @@ void win_id2tabwin(typval_T *argvars, list_T *list)
|
||||
{
|
||||
int winnr = 1;
|
||||
int tabnr = 1;
|
||||
int id = get_tv_number(&argvars[0]);
|
||||
handle_T id = (handle_T)tv_get_number(&argvars[0]);
|
||||
|
||||
win_get_tabwin(id, &tabnr, &winnr);
|
||||
list_append_number(list, tabnr);
|
||||
list_append_number(list, winnr);
|
||||
tv_list_append_number(list, tabnr);
|
||||
tv_list_append_number(list, winnr);
|
||||
}
|
||||
|
||||
win_T * win_id2wp(typval_T *argvars)
|
||||
{
|
||||
int id = get_tv_number(&argvars[0]);
|
||||
int id = tv_get_number(&argvars[0]);
|
||||
|
||||
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
||||
if (wp->handle == id) {
|
||||
@ -5901,7 +5902,7 @@ win_T * win_id2wp(typval_T *argvars)
|
||||
int win_id2win(typval_T *argvars)
|
||||
{
|
||||
int nr = 1;
|
||||
int id = get_tv_number(&argvars[0]);
|
||||
int id = tv_get_number(&argvars[0]);
|
||||
|
||||
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||
if (wp->handle == id) {
|
||||
@ -5914,11 +5915,11 @@ int win_id2win(typval_T *argvars)
|
||||
|
||||
void win_findbuf(typval_T *argvars, list_T *list)
|
||||
{
|
||||
int bufnr = get_tv_number(&argvars[0]);
|
||||
int bufnr = tv_get_number(&argvars[0]);
|
||||
|
||||
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
||||
if (wp->w_buffer->b_fnum == bufnr) {
|
||||
list_append_number(list, wp->handle);
|
||||
tv_list_append_number(list, wp->handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
302
test/functional/eval/buf_functions_spec.lua
Normal file
302
test/functional/eval/buf_functions_spec.lua
Normal file
@ -0,0 +1,302 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local lfs = require('lfs')
|
||||
|
||||
local eq = helpers.eq
|
||||
local clear = helpers.clear
|
||||
local funcs = helpers.funcs
|
||||
local meths = helpers.meths
|
||||
local command = helpers.command
|
||||
local exc_exec = helpers.exc_exec
|
||||
local bufmeths = helpers.bufmeths
|
||||
local winmeths = helpers.winmeths
|
||||
local curbufmeths = helpers.curbufmeths
|
||||
local curwinmeths = helpers.curwinmeths
|
||||
local curtabmeths = helpers.curtabmeths
|
||||
local get_pathsep = helpers.get_pathsep
|
||||
|
||||
local fname = 'Xtest-functional-eval-buf_functions'
|
||||
local fname2 = fname .. '.2'
|
||||
local dirname = fname .. '.d'
|
||||
|
||||
before_each(clear)
|
||||
|
||||
for _, func in ipairs({'bufname(%s)', 'bufnr(%s)', 'bufwinnr(%s)',
|
||||
'getbufline(%s, 1)', 'getbufvar(%s, "changedtick")',
|
||||
'setbufvar(%s, "f", 0)'}) do
|
||||
local funcname = func:match('%w+')
|
||||
describe(funcname .. '() function', function()
|
||||
it('errors out when receives v:true/v:false/v:null', function()
|
||||
-- Not compatible with Vim: in Vim it always results in buffer not found
|
||||
-- without any error messages.
|
||||
for _, var in ipairs({'v:true', 'v:false', 'v:null'}) do
|
||||
eq('Vim(call):E5300: Expected a Number or a String',
|
||||
exc_exec('call ' .. func:format(var)))
|
||||
end
|
||||
end)
|
||||
it('errors out when receives invalid argument', function()
|
||||
eq('Vim(call):E745: Expected a Number or a String, List found',
|
||||
exc_exec('call ' .. func:format('[]')))
|
||||
eq('Vim(call):E728: Expected a Number or a String, Dictionary found',
|
||||
exc_exec('call ' .. func:format('{}')))
|
||||
eq('Vim(call):E805: Expected a Number or a String, Float found',
|
||||
exc_exec('call ' .. func:format('0.0')))
|
||||
eq('Vim(call):E703: Expected a Number or a String, Funcref found',
|
||||
exc_exec('call ' .. func:format('function("tr")')))
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
describe('bufname() function', function()
|
||||
it('returns empty string when buffer was not found', function()
|
||||
command('file ' .. fname)
|
||||
eq('', funcs.bufname(2))
|
||||
eq('', funcs.bufname('non-existent-buffer'))
|
||||
eq('', funcs.bufname('#'))
|
||||
command('edit ' .. fname2)
|
||||
eq(2, funcs.bufnr('%'))
|
||||
eq('', funcs.bufname('X'))
|
||||
end)
|
||||
before_each(function()
|
||||
lfs.mkdir(dirname)
|
||||
end)
|
||||
after_each(function()
|
||||
lfs.rmdir(dirname)
|
||||
end)
|
||||
it('returns expected buffer name', function()
|
||||
eq('', funcs.bufname('%')) -- Buffer has no name yet
|
||||
command('file ' .. fname)
|
||||
local wd = lfs.currentdir()
|
||||
local sep = get_pathsep()
|
||||
local curdirname = funcs.fnamemodify(wd, ':t')
|
||||
for _, arg in ipairs({'%', 1, 'X', wd}) do
|
||||
eq(fname, funcs.bufname(arg))
|
||||
meths.set_current_dir('..')
|
||||
eq(curdirname .. sep .. fname, funcs.bufname(arg))
|
||||
meths.set_current_dir(curdirname)
|
||||
meths.set_current_dir(dirname)
|
||||
eq(wd .. sep .. fname, funcs.bufname(arg))
|
||||
meths.set_current_dir('..')
|
||||
eq(fname, funcs.bufname(arg))
|
||||
command('enew')
|
||||
end
|
||||
eq('', funcs.bufname('%'))
|
||||
eq('', funcs.bufname('$'))
|
||||
eq(2, funcs.bufnr('%'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('bufnr() function', function()
|
||||
it('returns -1 when buffer was not found', function()
|
||||
command('file ' .. fname)
|
||||
eq(-1, funcs.bufnr(2))
|
||||
eq(-1, funcs.bufnr('non-existent-buffer'))
|
||||
eq(-1, funcs.bufnr('#'))
|
||||
command('edit ' .. fname2)
|
||||
eq(2, funcs.bufnr('%'))
|
||||
eq(-1, funcs.bufnr('X'))
|
||||
end)
|
||||
it('returns expected buffer number', function()
|
||||
eq(1, funcs.bufnr('%'))
|
||||
command('file ' .. fname)
|
||||
local wd = lfs.currentdir()
|
||||
local curdirname = funcs.fnamemodify(wd, ':t')
|
||||
eq(1, funcs.bufnr(fname))
|
||||
eq(1, funcs.bufnr(wd))
|
||||
eq(1, funcs.bufnr(curdirname))
|
||||
eq(1, funcs.bufnr('X'))
|
||||
end)
|
||||
it('returns number of last buffer with "$"', function()
|
||||
eq(1, funcs.bufnr('$'))
|
||||
command('new')
|
||||
eq(2, funcs.bufnr('$'))
|
||||
command('new')
|
||||
eq(3, funcs.bufnr('$'))
|
||||
command('only')
|
||||
eq(3, funcs.bufnr('$'))
|
||||
eq(3, funcs.bufnr('%'))
|
||||
command('buffer 1')
|
||||
eq(3, funcs.bufnr('$'))
|
||||
eq(1, funcs.bufnr('%'))
|
||||
command('bwipeout 2')
|
||||
eq(3, funcs.bufnr('$'))
|
||||
eq(1, funcs.bufnr('%'))
|
||||
command('bwipeout 3')
|
||||
eq(1, funcs.bufnr('$'))
|
||||
eq(1, funcs.bufnr('%'))
|
||||
command('new')
|
||||
eq(4, funcs.bufnr('$'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('bufwinnr() function', function()
|
||||
it('returns -1 when buffer was not found', function()
|
||||
command('file ' .. fname)
|
||||
eq(-1, funcs.bufwinnr(2))
|
||||
eq(-1, funcs.bufwinnr('non-existent-buffer'))
|
||||
eq(-1, funcs.bufwinnr('#'))
|
||||
command('split ' .. fname2) -- It would be OK if there was one window
|
||||
eq(2, funcs.bufnr('%'))
|
||||
eq(-1, funcs.bufwinnr('X'))
|
||||
end)
|
||||
before_each(function()
|
||||
lfs.mkdir(dirname)
|
||||
end)
|
||||
after_each(function()
|
||||
lfs.rmdir(dirname)
|
||||
end)
|
||||
it('returns expected window number', function()
|
||||
eq(1, funcs.bufwinnr('%'))
|
||||
command('file ' .. fname)
|
||||
command('vsplit')
|
||||
command('split ' .. fname2)
|
||||
eq(2, funcs.bufwinnr(fname))
|
||||
eq(1, funcs.bufwinnr(fname2))
|
||||
eq(-1, funcs.bufwinnr(fname:sub(1, #fname - 1)))
|
||||
meths.set_current_dir(dirname)
|
||||
eq(2, funcs.bufwinnr(fname))
|
||||
eq(1, funcs.bufwinnr(fname2))
|
||||
eq(-1, funcs.bufwinnr(fname:sub(1, #fname - 1)))
|
||||
eq(1, funcs.bufwinnr('%'))
|
||||
eq(2, funcs.bufwinnr(1))
|
||||
eq(1, funcs.bufwinnr(2))
|
||||
eq(-1, funcs.bufwinnr(3))
|
||||
eq(1, funcs.bufwinnr('$'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('getbufline() function', function()
|
||||
it('returns empty list when buffer was not found', function()
|
||||
command('file ' .. fname)
|
||||
eq({}, funcs.getbufline(2, 1))
|
||||
eq({}, funcs.getbufline('non-existent-buffer', 1))
|
||||
eq({}, funcs.getbufline('#', 1))
|
||||
command('edit ' .. fname2)
|
||||
eq(2, funcs.bufnr('%'))
|
||||
eq({}, funcs.getbufline('X', 1))
|
||||
end)
|
||||
it('returns empty list when range is invalid', function()
|
||||
eq({}, funcs.getbufline(1, 0))
|
||||
curbufmeths.set_lines(0, 1, false, {'foo', 'bar', 'baz'})
|
||||
eq({}, funcs.getbufline(1, 2, 1))
|
||||
eq({}, funcs.getbufline(1, -10, -20))
|
||||
eq({}, funcs.getbufline(1, -2, -1))
|
||||
eq({}, funcs.getbufline(1, -1, 9999))
|
||||
end)
|
||||
it('returns expected lines', function()
|
||||
meths.set_option('hidden', true)
|
||||
command('file ' .. fname)
|
||||
curbufmeths.set_lines(0, 1, false, {'foo\0', '\0bar', 'baz'})
|
||||
command('edit ' .. fname2)
|
||||
curbufmeths.set_lines(0, 1, false, {'abc\0', '\0def', 'ghi'})
|
||||
eq({'foo\n', '\nbar', 'baz'}, funcs.getbufline(1, 1, 9999))
|
||||
eq({'abc\n', '\ndef', 'ghi'}, funcs.getbufline(2, 1, 9999))
|
||||
eq({'foo\n', '\nbar', 'baz'}, funcs.getbufline(1, 1, '$'))
|
||||
eq({'baz'}, funcs.getbufline(1, '$', '$'))
|
||||
eq({'baz'}, funcs.getbufline(1, '$', 9999))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('getbufvar() function', function()
|
||||
it('returns empty list when buffer was not found', function()
|
||||
command('file ' .. fname)
|
||||
eq('', funcs.getbufvar(2, '&autoindent'))
|
||||
eq('', funcs.getbufvar('non-existent-buffer', '&autoindent'))
|
||||
eq('', funcs.getbufvar('#', '&autoindent'))
|
||||
command('edit ' .. fname2)
|
||||
eq(2, funcs.bufnr('%'))
|
||||
eq('', funcs.getbufvar('X', '&autoindent'))
|
||||
end)
|
||||
it('returns empty list when variable/option/etc was not found', function()
|
||||
command('file ' .. fname)
|
||||
eq('', funcs.getbufvar(1, '&autondent'))
|
||||
eq('', funcs.getbufvar(1, 'changedtic'))
|
||||
end)
|
||||
it('returns expected option value', function()
|
||||
eq(0, funcs.getbufvar(1, '&autoindent'))
|
||||
eq(0, funcs.getbufvar(1, '&l:autoindent'))
|
||||
eq(0, funcs.getbufvar(1, '&g:autoindent'))
|
||||
-- Also works with global-only options
|
||||
eq(0, funcs.getbufvar(1, '&hidden'))
|
||||
eq(0, funcs.getbufvar(1, '&l:hidden'))
|
||||
eq(0, funcs.getbufvar(1, '&g:hidden'))
|
||||
-- Also works with window-local options
|
||||
eq(0, funcs.getbufvar(1, '&number'))
|
||||
eq(0, funcs.getbufvar(1, '&l:number'))
|
||||
eq(0, funcs.getbufvar(1, '&g:number'))
|
||||
command('new')
|
||||
-- But with window-local options it probably does not what you expect
|
||||
curwinmeths.set_option('number', true)
|
||||
-- (note that current window’s buffer is 2, but getbufvar() receives 1)
|
||||
eq(2, bufmeths.get_number(curwinmeths.get_buf()))
|
||||
eq(1, funcs.getbufvar(1, '&number'))
|
||||
eq(1, funcs.getbufvar(1, '&l:number'))
|
||||
-- You can get global value though, if you find this useful.
|
||||
eq(0, funcs.getbufvar(1, '&g:number'))
|
||||
end)
|
||||
it('returns expected variable value', function()
|
||||
eq(2, funcs.getbufvar(1, 'changedtick'))
|
||||
curbufmeths.set_lines(0, 1, false, {'abc\0', '\0def', 'ghi'})
|
||||
eq(3, funcs.getbufvar(1, 'changedtick'))
|
||||
curbufmeths.set_var('test', true)
|
||||
eq(true, funcs.getbufvar(1, 'test'))
|
||||
eq({test=true, changedtick=3}, funcs.getbufvar(1, ''))
|
||||
command('new')
|
||||
eq(3, funcs.getbufvar(1, 'changedtick'))
|
||||
eq(true, funcs.getbufvar(1, 'test'))
|
||||
eq({test=true, changedtick=3}, funcs.getbufvar(1, ''))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('setbufvar() function', function()
|
||||
it('throws the error or ignores the input when buffer was not found', function()
|
||||
command('file ' .. fname)
|
||||
eq(0,
|
||||
exc_exec('call setbufvar(2, "&autoindent", 0)'))
|
||||
eq('Vim(call):E94: No matching buffer for non-existent-buffer',
|
||||
exc_exec('call setbufvar("non-existent-buffer", "&autoindent", 0)'))
|
||||
eq(0,
|
||||
exc_exec('call setbufvar("#", "&autoindent", 0)'))
|
||||
command('edit ' .. fname2)
|
||||
eq(2, funcs.bufnr('%'))
|
||||
eq('Vim(call):E93: More than one match for X',
|
||||
exc_exec('call setbufvar("X", "&autoindent", 0)'))
|
||||
end)
|
||||
it('may set options, including window-local and global values', function()
|
||||
local buf1 = meths.get_current_buf()
|
||||
eq(false, curwinmeths.get_option('number'))
|
||||
command('split')
|
||||
command('new')
|
||||
eq(2, bufmeths.get_number(curwinmeths.get_buf()))
|
||||
funcs.setbufvar(1, '&number', true)
|
||||
local windows = curtabmeths.list_wins()
|
||||
eq(false, winmeths.get_option(windows[1], 'number'))
|
||||
eq(true, winmeths.get_option(windows[2], 'number'))
|
||||
eq(false, winmeths.get_option(windows[3], 'number'))
|
||||
eq(false, winmeths.get_option(meths.get_current_win(), 'number'))
|
||||
|
||||
eq(false, meths.get_option('hidden'))
|
||||
funcs.setbufvar(1, '&hidden', true)
|
||||
eq(true, meths.get_option('hidden'))
|
||||
|
||||
eq(false, bufmeths.get_option(buf1, 'autoindent'))
|
||||
funcs.setbufvar(1, '&autoindent', true)
|
||||
eq(true, bufmeths.get_option(buf1, 'autoindent'))
|
||||
eq('Vim(call):E355: Unknown option: xxx',
|
||||
exc_exec('call setbufvar(1, "&xxx", 0)'))
|
||||
end)
|
||||
it('may set variables', function()
|
||||
local buf1 = meths.get_current_buf()
|
||||
command('split')
|
||||
command('new')
|
||||
eq(2, curbufmeths.get_number())
|
||||
funcs.setbufvar(1, 'number', true)
|
||||
eq(true, bufmeths.get_var(buf1, 'number'))
|
||||
eq('Vim(call):E461: Illegal variable name: b:',
|
||||
exc_exec('call setbufvar(1, "", 0)'))
|
||||
eq(true, bufmeths.get_var(buf1, 'number'))
|
||||
funcs.setbufvar(1, 'changedtick', true)
|
||||
-- eq(true, bufmeths.get_var(buf1, 'changedtick'))
|
||||
eq(2, funcs.getbufvar(1, 'changedtick'))
|
||||
end)
|
||||
end)
|
24
test/functional/eval/container_functions_spec.lua
Normal file
24
test/functional/eval/container_functions_spec.lua
Normal file
@ -0,0 +1,24 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local eq = helpers.eq
|
||||
local eval = helpers.eval
|
||||
local meths = helpers.meths
|
||||
local clear = helpers.clear
|
||||
|
||||
before_each(clear)
|
||||
|
||||
describe('extend()', function()
|
||||
it('suceeds to extend list with itself', function()
|
||||
meths.set_var('l', {1, {}})
|
||||
eq({1, {}, 1, {}}, eval('extend(l, l)'))
|
||||
eq({1, {}, 1, {}}, meths.get_var('l'))
|
||||
|
||||
meths.set_var('l', {1, {}})
|
||||
eq({1, {}, 1, {}}, eval('extend(l, l, 0)'))
|
||||
eq({1, {}, 1, {}}, meths.get_var('l'))
|
||||
|
||||
meths.set_var('l', {1, {}})
|
||||
eq({1, 1, {}, {}}, eval('extend(l, l, 1)'))
|
||||
eq({1, 1, {}, {}}, meths.get_var('l'))
|
||||
end)
|
||||
end)
|
38
test/functional/eval/input_spec.lua
Normal file
38
test/functional/eval/input_spec.lua
Normal file
@ -0,0 +1,38 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
|
||||
local feed = helpers.feed
|
||||
local clear = helpers.clear
|
||||
local command = helpers.command
|
||||
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
screen = Screen.new(25, 5)
|
||||
screen:attach()
|
||||
end)
|
||||
|
||||
describe('input()', function()
|
||||
it('works correctly with multiline prompts', function()
|
||||
feed([[:call input("Test\nFoo")<CR>]])
|
||||
screen:expect([[
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
Test |
|
||||
Foo^ |
|
||||
]], {{bold=true, foreground=Screen.colors.Blue}})
|
||||
end)
|
||||
it('works correctly with multiline prompts and :echohl', function()
|
||||
command('hi Test ctermfg=Red guifg=Red term=bold')
|
||||
feed([[:echohl Test | call input("Test\nFoo")<CR>]])
|
||||
screen:expect([[
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{2:Test} |
|
||||
{2:Foo}^ |
|
||||
]], {{bold=true, foreground=Screen.colors.Blue}, {foreground=Screen.colors.Red}})
|
||||
end)
|
||||
end)
|
61
test/functional/eval/match_functions_spec.lua
Normal file
61
test/functional/eval/match_functions_spec.lua
Normal file
@ -0,0 +1,61 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local eq = helpers.eq
|
||||
local clear = helpers.clear
|
||||
local funcs = helpers.funcs
|
||||
local command = helpers.command
|
||||
|
||||
before_each(clear)
|
||||
|
||||
describe('setmatches()', function()
|
||||
it('correctly handles case when both group and pattern entries are numbers',
|
||||
function()
|
||||
command('hi def link 1 PreProc')
|
||||
eq(0, funcs.setmatches({{group=1, pattern=2, id=3, priority=4}}))
|
||||
eq({{
|
||||
group='1',
|
||||
pattern='2',
|
||||
id=3,
|
||||
priority=4,
|
||||
}}, funcs.getmatches())
|
||||
eq(0, funcs.setmatches({{group=1, pattern=2, id=3, priority=4, conceal=5}}))
|
||||
eq({{
|
||||
group='1',
|
||||
pattern='2',
|
||||
id=3,
|
||||
priority=4,
|
||||
conceal='5',
|
||||
}}, funcs.getmatches())
|
||||
eq(0, funcs.setmatches({{group=1, pos1={2}, pos2={6}, id=3, priority=4, conceal=5}}))
|
||||
eq({{
|
||||
group='1',
|
||||
pos1={2},
|
||||
pos2={6},
|
||||
id=3,
|
||||
priority=4,
|
||||
conceal='5',
|
||||
}}, funcs.getmatches())
|
||||
end)
|
||||
|
||||
it('fails with -1 if highlight group is not defined', function()
|
||||
eq(-1, funcs.setmatches({{group=1, pattern=2, id=3, priority=4}}))
|
||||
eq({}, funcs.getmatches())
|
||||
eq(-1, funcs.setmatches({{group=1, pos1={2}, pos2={6}, id=3, priority=4, conceal=5}}))
|
||||
eq({}, funcs.getmatches())
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('matchadd()', function()
|
||||
it('correctly works when first two arguments and conceal are numbers at once',
|
||||
function()
|
||||
command('hi def link 1 PreProc')
|
||||
eq(4, funcs.matchadd(1, 2, 3, 4, {conceal=5}))
|
||||
eq({{
|
||||
group='1',
|
||||
pattern='2',
|
||||
priority=3,
|
||||
id=4,
|
||||
conceal='5',
|
||||
}}, funcs.getmatches())
|
||||
end)
|
||||
end)
|
51
test/functional/eval/minmax_functions_spec.lua
Normal file
51
test/functional/eval/minmax_functions_spec.lua
Normal file
@ -0,0 +1,51 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local eq = helpers.eq
|
||||
local eval = helpers.eval
|
||||
local clear = helpers.clear
|
||||
local funcs = helpers.funcs
|
||||
local redir_exec = helpers.redir_exec
|
||||
|
||||
before_each(clear)
|
||||
for _, func in ipairs({'min', 'max'}) do
|
||||
describe(func .. '()', function()
|
||||
it('gives a single error message when multiple values failed conversions',
|
||||
function()
|
||||
eq('\nE745: Using a List as a Number\n0',
|
||||
redir_exec('echo ' .. func .. '([-5, [], [], [], 5])'))
|
||||
eq('\nE745: Using a List as a Number\n0',
|
||||
redir_exec('echo ' .. func .. '({1:-5, 2:[], 3:[], 4:[], 5:5})'))
|
||||
for errmsg, errinput in pairs({
|
||||
['E745: Using a List as a Number'] = '[]',
|
||||
['E805: Using a Float as a Number'] = '0.0',
|
||||
['E703: Using a Funcref as a Number'] = 'function("tr")',
|
||||
['E728: Using a Dictionary as a Number'] = '{}',
|
||||
}) do
|
||||
eq('\n' .. errmsg .. '\n0',
|
||||
redir_exec('echo ' .. func .. '([' .. errinput .. '])'))
|
||||
eq('\n' .. errmsg .. '\n0',
|
||||
redir_exec('echo ' .. func .. '({1:' .. errinput .. '})'))
|
||||
end
|
||||
end)
|
||||
it('works with arrays/dictionaries with zero items', function()
|
||||
eq(0, funcs[func]({}))
|
||||
eq(0, eval(func .. '({})'))
|
||||
end)
|
||||
it('works with arrays/dictionaries with one item', function()
|
||||
eq(5, funcs[func]({5}))
|
||||
eq(5, funcs[func]({test=5}))
|
||||
end)
|
||||
it('works with NULL arrays/dictionaries', function()
|
||||
eq(0, eval(func .. '(v:_null_list)'))
|
||||
eq(0, eval(func .. '(v:_null_dict)'))
|
||||
end)
|
||||
it('errors out for invalid types', function()
|
||||
for _, errinput in ipairs({'1', 'v:true', 'v:false', 'v:null',
|
||||
'function("tr")', '""'}) do
|
||||
eq(('\nE712: Argument of %s() must be a List or Dictionary\n0'):format(
|
||||
func),
|
||||
redir_exec('echo ' .. func .. '(' .. errinput .. ')'))
|
||||
end
|
||||
end)
|
||||
end)
|
||||
end
|
138
test/functional/eval/null_spec.lua
Normal file
138
test/functional/eval/null_spec.lua
Normal file
@ -0,0 +1,138 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local curbufmeths = helpers.curbufmeths
|
||||
local redir_exec = helpers.redir_exec
|
||||
local exc_exec = helpers.exc_exec
|
||||
local command = helpers.command
|
||||
local clear = helpers.clear
|
||||
local meths = helpers.meths
|
||||
local funcs = helpers.funcs
|
||||
local eq = helpers.eq
|
||||
|
||||
describe('NULL', function()
|
||||
before_each(function()
|
||||
clear()
|
||||
command('let L = v:_null_list')
|
||||
command('let D = v:_null_dict')
|
||||
command('let S = $XXX_NONEXISTENT_VAR_XXX')
|
||||
end)
|
||||
local tmpfname = 'Xtest-functional-viml-null'
|
||||
after_each(function()
|
||||
os.remove(tmpfname)
|
||||
end)
|
||||
local null_test = function(name, cmd, err)
|
||||
it(name, function()
|
||||
eq(err, exc_exec(cmd))
|
||||
end)
|
||||
end
|
||||
local null_expr_test = function(name, expr, err, val, after)
|
||||
it(name, function()
|
||||
eq((err == 0) and ('') or ('\n' .. err),
|
||||
redir_exec('let g:_var = ' .. expr))
|
||||
if val == nil then
|
||||
eq(0, funcs.exists('g:_var'))
|
||||
else
|
||||
eq(val, meths.get_var('_var'))
|
||||
end
|
||||
if after ~= nil then
|
||||
after()
|
||||
end
|
||||
end)
|
||||
end
|
||||
describe('list', function()
|
||||
-- Incorrect behaviour
|
||||
|
||||
-- FIXME map() should not return 0 without error
|
||||
null_expr_test('does not crash map()', 'map(L, "v:val")', 0, 0)
|
||||
-- FIXME map() should not return 0 without error
|
||||
null_expr_test('does not crash filter()', 'filter(L, "1")', 0, 0)
|
||||
-- FIXME map() should at least return L
|
||||
null_expr_test('makes map() return v:_null_list', 'map(L, "v:val") is# L', 0, 0)
|
||||
-- FIXME filter() should at least return L
|
||||
null_expr_test('makes filter() return v:_null_list', 'map(L, "1") is# L', 0, 0)
|
||||
-- FIXME add() should not return 1 at all
|
||||
null_expr_test('does not crash add()', 'add(L, 0)', 0, 1)
|
||||
null_expr_test('does not crash extend()', 'extend(L, [1])', 'E742: Cannot change value of extend() argument', 0)
|
||||
null_expr_test('does not crash extend() (second position)', 'extend([1], L)', 0, {1})
|
||||
-- FIXME should be accepted by inputlist()
|
||||
null_expr_test('is accepted as an empty list by inputlist()',
|
||||
'[feedkeys("\\n"), inputlist(L)]', 'E686: Argument of inputlist() must be a List', {0, 0})
|
||||
-- FIXME should be accepted by writefile(), return {0, {}}
|
||||
null_expr_test('is accepted as an empty list by writefile()',
|
||||
('[writefile(L, "%s"), readfile("%s")]'):format(tmpfname, tmpfname),
|
||||
'E484: Can\'t open file ' .. tmpfname, {0, {}})
|
||||
-- FIXME should give error message
|
||||
null_expr_test('does not crash remove()', 'remove(L, 0)', 0, 0)
|
||||
-- FIXME should return 0
|
||||
null_expr_test('is accepted by setqflist()', 'setqflist(L)', 0, -1)
|
||||
-- FIXME should return 0
|
||||
null_expr_test('is accepted by setloclist()', 'setloclist(1, L)', 0, -1)
|
||||
-- FIXME should return 0
|
||||
null_expr_test('is accepted by setmatches()', 'setmatches(L)', 0, -1)
|
||||
-- FIXME should return empty list or error out
|
||||
null_expr_test('is accepted by sort()', 'sort(L)', 0, 0)
|
||||
-- FIXME Should return 1
|
||||
null_expr_test('is accepted by sort()', 'sort(L) is L', 0, 0)
|
||||
-- FIXME should not error out
|
||||
null_test('is accepted by :cexpr', 'cexpr L', 'Vim(cexpr):E777: String or List expected')
|
||||
-- FIXME should not error out
|
||||
null_test('is accepted by :lexpr', 'lexpr L', 'Vim(lexpr):E777: String or List expected')
|
||||
null_test('is accepted by :for', 'for x in L|throw x|endfor', 0)
|
||||
|
||||
-- Subjectable behaviour
|
||||
|
||||
-- FIXME Should return 1
|
||||
null_expr_test('is equal to empty list', 'L == []', 0, 0)
|
||||
-- FIXME Should return 1
|
||||
null_expr_test('is equal to empty list (reverse order)', '[] == L', 0, 0)
|
||||
-- FIXME Should return 1
|
||||
null_expr_test('is not locked', 'islocked("v:_null_list")', 0, 0)
|
||||
|
||||
-- Crashes
|
||||
|
||||
-- null_expr_test('does not crash setreg', 'setreg("x", L)', 0, 0)
|
||||
-- null_expr_test('does not crash setline', 'setline(1, L)', 0, 0)
|
||||
-- null_expr_test('does not crash system()', 'system("cat", L)', 0, '')
|
||||
-- null_expr_test('does not crash systemlist()', 'systemlist("cat", L)', 0, {})
|
||||
|
||||
-- Correct behaviour
|
||||
null_expr_test('does not crash append()', 'append(1, L)', 0, 0, function()
|
||||
eq({''}, curbufmeths.get_lines(0, -1, false))
|
||||
end)
|
||||
null_expr_test('is identical to itself', 'L is L', 0, 1)
|
||||
null_expr_test('can be sliced', 'L[:]', 0, {})
|
||||
null_expr_test('can be copied', 'copy(L)', 0, {})
|
||||
null_expr_test('can be deepcopied', 'deepcopy(L)', 0, {})
|
||||
null_expr_test('does not crash when indexed', 'L[1]',
|
||||
'E684: list index out of range: 1\nE15: Invalid expression: L[1]', nil)
|
||||
null_expr_test('does not crash call()', 'call("arglistid", L)', 0, 0)
|
||||
null_expr_test('does not crash col()', 'col(L)', 0, 0)
|
||||
null_expr_test('does not crash virtcol()', 'virtcol(L)', 0, 0)
|
||||
null_expr_test('does not crash line()', 'line(L)', 0, 0)
|
||||
null_expr_test('does not crash count()', 'count(L, 1)', 0, 0)
|
||||
null_expr_test('does not crash cursor()', 'cursor(L)', 'E474: Invalid argument', -1)
|
||||
null_expr_test('is empty', 'empty(L)', 0, 1)
|
||||
null_expr_test('does not crash get()', 'get(L, 1, 10)', 0, 10)
|
||||
null_expr_test('has zero length', 'len(L)', 0, 0)
|
||||
null_expr_test('is accepted as an empty list by max()', 'max(L)', 0, 0)
|
||||
null_expr_test('is accepted as an empty list by min()', 'min(L)', 0, 0)
|
||||
null_expr_test('is stringified correctly', 'string(L)', 0, '[]')
|
||||
null_expr_test('is JSON encoded correctly', 'json_encode(L)', 0, '[]')
|
||||
null_test('does not crash lockvar', 'lockvar! L', 0)
|
||||
null_expr_test('can be added to itself', '(L + L)', 0, {})
|
||||
null_expr_test('can be added to itself', '(L + L) is L', 0, 1)
|
||||
null_expr_test('can be added to non-empty list', '([1] + L)', 0, {1})
|
||||
null_expr_test('can be added to non-empty list (reversed)', '(L + [1])', 0, {1})
|
||||
null_expr_test('is equal to itself', 'L == L', 0, 1)
|
||||
null_expr_test('is not not equal to itself', 'L != L', 0, 0)
|
||||
null_expr_test('counts correctly', 'count([L], L)', 0, 1)
|
||||
end)
|
||||
describe('dict', function()
|
||||
it('does not crash when indexing NULL dict', function()
|
||||
eq('\nE716: Key not present in Dictionary: test\nE15: Invalid expression: v:_null_dict.test',
|
||||
redir_exec('echo v:_null_dict.test'))
|
||||
end)
|
||||
null_expr_test('makes extend error out', 'extend(D, {})', 'E742: Cannot change value of extend() argument', 0)
|
||||
null_expr_test('makes extend do nothing', 'extend({1: 2}, D)', 0, {['1']=2})
|
||||
end)
|
||||
end)
|
41
test/functional/eval/sort_spec.lua
Normal file
41
test/functional/eval/sort_spec.lua
Normal file
@ -0,0 +1,41 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local eq = helpers.eq
|
||||
local NIL = helpers.NIL
|
||||
local eval = helpers.eval
|
||||
local clear = helpers.clear
|
||||
local meths = helpers.meths
|
||||
local funcs = helpers.funcs
|
||||
local command = helpers.command
|
||||
local exc_exec = helpers.exc_exec
|
||||
|
||||
before_each(clear)
|
||||
|
||||
describe('sort()', function()
|
||||
it('errors out when sorting special values', function()
|
||||
eq('Vim(call):E907: Using a special value as a Float',
|
||||
exc_exec('call sort([v:true, v:false], "f")'))
|
||||
end)
|
||||
|
||||
it('sorts “wrong” values between -0.0001 and 0.0001, preserving order',
|
||||
function()
|
||||
meths.set_var('list', {true, false, NIL, {}, {a=42}, 'check',
|
||||
0.0001, -0.0001})
|
||||
command('call insert(g:list, function("tr"))')
|
||||
local error_lines = funcs.split(
|
||||
funcs.execute('silent! call sort(g:list, "f")'), '\n')
|
||||
local errors = {}
|
||||
for _, err in ipairs(error_lines) do
|
||||
errors[err] = true
|
||||
end
|
||||
eq({
|
||||
['E891: Using a Funcref as a Float']=true,
|
||||
['E892: Using a String as a Float']=true,
|
||||
['E893: Using a List as a Float']=true,
|
||||
['E894: Using a Dictionary as a Float']=true,
|
||||
['E907: Using a special value as a Float']=true,
|
||||
}, errors)
|
||||
eq('[-1.0e-4, function(\'tr\'), v:true, v:false, v:null, [], {\'a\': 42}, \'check\', 1.0e-4]',
|
||||
eval('string(g:list)'))
|
||||
end)
|
||||
end)
|
@ -7,7 +7,6 @@ local eval = helpers.eval
|
||||
local exc_exec = helpers.exc_exec
|
||||
local redir_exec = helpers.redir_exec
|
||||
local funcs = helpers.funcs
|
||||
local write_file = helpers.write_file
|
||||
local NIL = helpers.NIL
|
||||
local source = helpers.source
|
||||
local dedent = helpers.dedent
|
||||
@ -105,10 +104,8 @@ describe('string() function', function()
|
||||
end)
|
||||
|
||||
describe('used to represent funcrefs', function()
|
||||
local fname = 'Xtest-functional-eval-string_spec-fref-script.vim'
|
||||
|
||||
before_each(function()
|
||||
write_file(fname, [[
|
||||
source([[
|
||||
function Test1()
|
||||
endfunction
|
||||
|
||||
@ -120,11 +117,6 @@ describe('string() function', function()
|
||||
|
||||
let g:Test2_f = function('s:Test2')
|
||||
]])
|
||||
command('source ' .. fname)
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
os.remove(fname)
|
||||
end)
|
||||
|
||||
it('dumps references to built-in functions', function()
|
||||
|
@ -49,7 +49,7 @@ describe('timers', function()
|
||||
it('works with zero timeout', function()
|
||||
-- timer_start does still not invoke the callback immediately
|
||||
eq(0,eval("[timer_start(0, 'MyHandler', {'repeat': 1000}), g:val][1]"))
|
||||
run(nil, nil, nil, 300)
|
||||
run(nil, nil, nil, 400)
|
||||
eq(1000,eval("g:val"))
|
||||
end)
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user