mirror of
https://github.com/neovim/neovim.git
synced 2025-10-18 15:51:50 +00:00
Merge #6947 from ZyX-I/consistent-get_keymap
This commit is contained in:
@@ -12117,9 +12117,11 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
|
|||||||
xfree(keys_buf);
|
xfree(keys_buf);
|
||||||
|
|
||||||
if (!get_dict) {
|
if (!get_dict) {
|
||||||
/* Return a string. */
|
// Return a string.
|
||||||
if (rhs != NULL)
|
if (rhs != NULL) {
|
||||||
rettv->vval.v_string = str2special_save(rhs, FALSE);
|
rettv->vval.v_string = (char_u *)str2special_save(
|
||||||
|
(const char *)rhs, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
tv_dict_alloc_ret(rettv);
|
tv_dict_alloc_ret(rettv);
|
||||||
@@ -12154,7 +12156,8 @@ void mapblock_fill_dict(dict_T *const dict,
|
|||||||
bool compatible)
|
bool compatible)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
char_u *lhs = str2special_save(mp->m_keys, true);
|
char *const lhs = str2special_save((const char *)mp->m_keys,
|
||||||
|
compatible, !compatible);
|
||||||
char *const mapmode = map_mode_to_chars(mp->m_mode);
|
char *const mapmode = map_mode_to_chars(mp->m_mode);
|
||||||
varnumber_T noremap_value;
|
varnumber_T noremap_value;
|
||||||
|
|
||||||
@@ -12168,18 +12171,21 @@ void mapblock_fill_dict(dict_T *const dict,
|
|||||||
noremap_value = mp->m_noremap == REMAP_SCRIPT ? 2 : !!mp->m_noremap;
|
noremap_value = mp->m_noremap == REMAP_SCRIPT ? 2 : !!mp->m_noremap;
|
||||||
}
|
}
|
||||||
|
|
||||||
tv_dict_add_str(dict, S_LEN("lhs"), (const char *)lhs);
|
if (compatible) {
|
||||||
tv_dict_add_str(dict, S_LEN("rhs"), (const char *)mp->m_orig_str);
|
tv_dict_add_str(dict, S_LEN("rhs"), (const char *)mp->m_orig_str);
|
||||||
|
} else {
|
||||||
|
tv_dict_add_allocated_str(dict, S_LEN("rhs"),
|
||||||
|
str2special_save((const char *)mp->m_str, false,
|
||||||
|
true));
|
||||||
|
}
|
||||||
|
tv_dict_add_allocated_str(dict, S_LEN("lhs"), lhs);
|
||||||
tv_dict_add_nr(dict, S_LEN("noremap"), noremap_value);
|
tv_dict_add_nr(dict, S_LEN("noremap"), noremap_value);
|
||||||
tv_dict_add_nr(dict, S_LEN("expr"), mp->m_expr ? 1 : 0);
|
tv_dict_add_nr(dict, S_LEN("expr"), mp->m_expr ? 1 : 0);
|
||||||
tv_dict_add_nr(dict, S_LEN("silent"), mp->m_silent ? 1 : 0);
|
tv_dict_add_nr(dict, S_LEN("silent"), mp->m_silent ? 1 : 0);
|
||||||
tv_dict_add_nr(dict, S_LEN("sid"), (varnumber_T)mp->m_script_ID);
|
tv_dict_add_nr(dict, S_LEN("sid"), (varnumber_T)mp->m_script_ID);
|
||||||
tv_dict_add_nr(dict, S_LEN("buffer"), (varnumber_T)buffer_value);
|
tv_dict_add_nr(dict, S_LEN("buffer"), (varnumber_T)buffer_value);
|
||||||
tv_dict_add_nr(dict, S_LEN("nowait"), mp->m_nowait ? 1 : 0);
|
tv_dict_add_nr(dict, S_LEN("nowait"), mp->m_nowait ? 1 : 0);
|
||||||
tv_dict_add_str(dict, S_LEN("mode"), mapmode);
|
tv_dict_add_allocated_str(dict, S_LEN("mode"), mapmode);
|
||||||
|
|
||||||
xfree(lhs);
|
|
||||||
xfree(mapmode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -1386,12 +1386,33 @@ int tv_dict_add_str(dict_T *const d,
|
|||||||
const char *const key, const size_t key_len,
|
const char *const key, const size_t key_len,
|
||||||
const char *const val)
|
const char *const val)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
|
{
|
||||||
|
return tv_dict_add_allocated_str(d, key, key_len, xstrdup(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a string entry to dictionary
|
||||||
|
///
|
||||||
|
/// Unlike tv_dict_add_str() saves val to the new dictionary item in place of
|
||||||
|
/// creating a new copy.
|
||||||
|
///
|
||||||
|
/// @warning String will be freed even in case addition fails.
|
||||||
|
///
|
||||||
|
/// @param[out] d Dictionary to add entry to.
|
||||||
|
/// @param[in] key Key to add.
|
||||||
|
/// @param[in] key_len Key length.
|
||||||
|
/// @param[in] val String to add.
|
||||||
|
///
|
||||||
|
/// @return OK in case of success, FAIL when key already exists.
|
||||||
|
int tv_dict_add_allocated_str(dict_T *const d,
|
||||||
|
const char *const key, const size_t key_len,
|
||||||
|
char *const val)
|
||||||
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
dictitem_T *const item = tv_dict_item_alloc_len(key, key_len);
|
dictitem_T *const item = tv_dict_item_alloc_len(key, key_len);
|
||||||
|
|
||||||
item->di_tv.v_lock = VAR_UNLOCKED;
|
item->di_tv.v_lock = VAR_UNLOCKED;
|
||||||
item->di_tv.v_type = VAR_STRING;
|
item->di_tv.v_type = VAR_STRING;
|
||||||
item->di_tv.vval.v_string = (char_u *)xstrdup(val);
|
item->di_tv.vval.v_string = (char_u *)val;
|
||||||
if (tv_dict_add(d, item) == FAIL) {
|
if (tv_dict_add(d, item) == FAIL) {
|
||||||
tv_dict_item_free(item);
|
tv_dict_item_free(item);
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
@@ -1806,7 +1806,7 @@ static int vgetorpeek(int advance)
|
|||||||
* <M-a> and then changing 'encoding'. Beware
|
* <M-a> and then changing 'encoding'. Beware
|
||||||
* that 0x80 is escaped. */
|
* that 0x80 is escaped. */
|
||||||
char_u *p1 = mp->m_keys;
|
char_u *p1 = mp->m_keys;
|
||||||
char_u *p2 = mb_unescape(&p1);
|
char_u *p2 = (char_u *)mb_unescape((const char **)&p1);
|
||||||
|
|
||||||
if (has_mbyte && p2 != NULL && MB_BYTE2LEN(c1) > MB_PTR2LEN(p2))
|
if (has_mbyte && p2 != NULL && MB_BYTE2LEN(c1) > MB_PTR2LEN(p2))
|
||||||
mlen = 0;
|
mlen = 0;
|
||||||
@@ -3999,12 +3999,10 @@ int put_escstr(FILE *fd, char_u *strstart, int what)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; *str != NUL; ++str) {
|
for (; *str != NUL; str++) {
|
||||||
char_u *p;
|
// Check for a multi-byte character, which may contain escaped
|
||||||
|
// K_SPECIAL and CSI bytes.
|
||||||
/* Check for a multi-byte character, which may contain escaped
|
const char *p = mb_unescape((const char **)&str);
|
||||||
* K_SPECIAL and CSI bytes */
|
|
||||||
p = mb_unescape(&str);
|
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
while (*p != NUL)
|
while (*p != NUL)
|
||||||
if (fputc(*p++, fd) < 0)
|
if (fputc(*p++, fd) < 0)
|
||||||
|
@@ -1739,53 +1739,56 @@ int mb_charlen_len(char_u *str, int len)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Try to unescape a multibyte character
|
||||||
* Try to un-escape a multi-byte character.
|
///
|
||||||
* Used for the "to" and "from" part of a mapping.
|
/// Used for the rhs and lhs of the mappings.
|
||||||
* Return the un-escaped string if it is a multi-byte character, and advance
|
///
|
||||||
* "pp" to just after the bytes that formed it.
|
/// @param[in,out] pp String to unescape. Is advanced to just after the bytes
|
||||||
* Return NULL if no multi-byte char was found.
|
/// that form a multibyte character.
|
||||||
*/
|
///
|
||||||
char_u * mb_unescape(char_u **pp)
|
/// @return Unescaped string if it is a multibyte character, NULL if no
|
||||||
|
/// multibyte character was found. Returns a static buffer, always one
|
||||||
|
/// and the same.
|
||||||
|
const char *mb_unescape(const char **const pp)
|
||||||
|
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
static char_u buf[6];
|
static char buf[6];
|
||||||
int n;
|
size_t buf_idx = 0;
|
||||||
int m = 0;
|
uint8_t *str = (uint8_t *)(*pp);
|
||||||
char_u *str = *pp;
|
|
||||||
|
|
||||||
/* Must translate K_SPECIAL KS_SPECIAL KE_FILLER to K_SPECIAL and CSI
|
// Must translate K_SPECIAL KS_SPECIAL KE_FILLER to K_SPECIAL and CSI
|
||||||
* KS_EXTRA KE_CSI to CSI.
|
// KS_EXTRA KE_CSI to CSI.
|
||||||
* Maximum length of a utf-8 character is 4 bytes. */
|
// Maximum length of a utf-8 character is 4 bytes.
|
||||||
for (n = 0; str[n] != NUL && m < 4; ++n) {
|
for (size_t str_idx = 0; str[str_idx] != NUL && buf_idx < 4; str_idx++) {
|
||||||
if (str[n] == K_SPECIAL
|
if (str[str_idx] == K_SPECIAL
|
||||||
&& str[n + 1] == KS_SPECIAL
|
&& str[str_idx + 1] == KS_SPECIAL
|
||||||
&& str[n + 2] == KE_FILLER) {
|
&& str[str_idx + 2] == KE_FILLER) {
|
||||||
buf[m++] = K_SPECIAL;
|
buf[buf_idx++] = (char)K_SPECIAL;
|
||||||
n += 2;
|
str_idx += 2;
|
||||||
} else if ((str[n] == K_SPECIAL
|
} else if ((str[str_idx] == K_SPECIAL)
|
||||||
)
|
&& str[str_idx + 1] == KS_EXTRA
|
||||||
&& str[n + 1] == KS_EXTRA
|
&& str[str_idx + 2] == KE_CSI) {
|
||||||
&& str[n + 2] == (int)KE_CSI) {
|
buf[buf_idx++] = (char)CSI;
|
||||||
buf[m++] = CSI;
|
str_idx += 2;
|
||||||
n += 2;
|
} else if (str[str_idx] == K_SPECIAL) {
|
||||||
} else if (str[n] == K_SPECIAL
|
break; // A special key can't be a multibyte char.
|
||||||
)
|
} else {
|
||||||
break; /* a special key can't be a multibyte char */
|
buf[buf_idx++] = (char)str[str_idx];
|
||||||
else
|
}
|
||||||
buf[m++] = str[n];
|
buf[buf_idx] = NUL;
|
||||||
buf[m] = NUL;
|
|
||||||
|
|
||||||
/* Return a multi-byte character if it's found. An illegal sequence
|
// Return a multi-byte character if it's found. An illegal sequence
|
||||||
* will result in a 1 here. */
|
// will result in a 1 here.
|
||||||
if ((*mb_ptr2len)(buf) > 1) {
|
if (utf_ptr2len((const char_u *)buf) > 1) {
|
||||||
*pp = str + n + 1;
|
*pp = (const char *)str + buf_idx + 1;
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bail out quickly for ASCII. */
|
// Bail out quickly for ASCII.
|
||||||
if (buf[0] < 128)
|
if ((uint8_t)buf[0] < 128) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1269,7 +1269,7 @@ msg_outtrans_special (
|
|||||||
string = "<Space>";
|
string = "<Space>";
|
||||||
str++;
|
str++;
|
||||||
} else {
|
} else {
|
||||||
string = (const char *)str2special((char_u **)&str, from);
|
string = str2special((const char **)&str, from, false);
|
||||||
}
|
}
|
||||||
const int len = vim_strsize((char_u *)string);
|
const int len = vim_strsize((char_u *)string);
|
||||||
// Highlight special keys
|
// Highlight special keys
|
||||||
@@ -1281,108 +1281,125 @@ msg_outtrans_special (
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Convert string, replacing key codes with printables
|
||||||
* Return the lhs or rhs of a mapping, with the key codes turned into printable
|
///
|
||||||
* strings, in an allocated string.
|
/// Used for lhs or rhs of mappings.
|
||||||
*/
|
///
|
||||||
char_u *
|
/// @param[in] str String to convert.
|
||||||
str2special_save (
|
/// @param[in] replace_spaces Convert spaces into `<Space>`, normally used fo
|
||||||
char_u *str,
|
/// lhs, but not rhs.
|
||||||
int is_lhs /* TRUE for lhs, FALSE for rhs */
|
/// @param[in] replace_lt Convert `<` into `<lt>`.
|
||||||
)
|
///
|
||||||
|
/// @return [allocated] Converted string.
|
||||||
|
char *str2special_save(const char *const str, const bool replace_spaces,
|
||||||
|
const bool replace_lt)
|
||||||
|
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC
|
||||||
|
FUNC_ATTR_NONNULL_RET
|
||||||
{
|
{
|
||||||
garray_T ga;
|
garray_T ga;
|
||||||
char_u *p = str;
|
|
||||||
|
|
||||||
ga_init(&ga, 1, 40);
|
ga_init(&ga, 1, 40);
|
||||||
while (*p != NUL)
|
|
||||||
ga_concat(&ga, str2special(&p, is_lhs));
|
const char *p = str;
|
||||||
|
while (*p != NUL) {
|
||||||
|
ga_concat(&ga, (const char_u *)str2special(&p, replace_spaces, replace_lt));
|
||||||
|
}
|
||||||
ga_append(&ga, NUL);
|
ga_append(&ga, NUL);
|
||||||
return (char_u *)ga.ga_data;
|
return (char *)ga.ga_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Convert character, replacing key one key code with printable representation
|
||||||
* Return the printable string for the key codes at "*sp".
|
///
|
||||||
* Used for translating the lhs or rhs of a mapping to printable chars.
|
/// @param[in,out] sp String to convert. Is advanced to the next key code.
|
||||||
* Advances "sp" to the next code.
|
/// @param[in] replace_spaces Convert spaces into <Space>, normally used for
|
||||||
*/
|
/// lhs, but not rhs.
|
||||||
char_u *
|
/// @param[in] replace_lt Convert `<` into `<lt>`.
|
||||||
str2special (
|
///
|
||||||
char_u **sp,
|
/// @return Converted key code, in a static buffer. Buffer is always one and the
|
||||||
int from /* TRUE for lhs of mapping */
|
/// same, so save converted string somewhere before running str2special
|
||||||
)
|
/// for the second time.
|
||||||
|
const char *str2special(const char **const sp, const bool replace_spaces,
|
||||||
|
const bool replace_lt)
|
||||||
|
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET
|
||||||
{
|
{
|
||||||
int c;
|
static char buf[7];
|
||||||
static char_u buf[7];
|
|
||||||
char_u *str = *sp;
|
|
||||||
int modifiers = 0;
|
|
||||||
int special = FALSE;
|
|
||||||
|
|
||||||
if (has_mbyte) {
|
// Try to un-escape a multi-byte character. Return the un-escaped
|
||||||
char_u *p;
|
// string if it is a multi-byte character.
|
||||||
|
const char *const p = mb_unescape(sp);
|
||||||
/* Try to un-escape a multi-byte character. Return the un-escaped
|
if (p != NULL) {
|
||||||
* string if it is a multi-byte character. */
|
|
||||||
p = mb_unescape(sp);
|
|
||||||
if (p != NULL)
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = *str;
|
const char *str = *sp;
|
||||||
|
int c = (uint8_t)(*str);
|
||||||
|
int modifiers = 0;
|
||||||
|
bool special = false;
|
||||||
if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) {
|
if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) {
|
||||||
if (str[1] == KS_MODIFIER) {
|
if ((uint8_t)str[1] == KS_MODIFIER) {
|
||||||
modifiers = str[2];
|
modifiers = (uint8_t)str[2];
|
||||||
str += 3;
|
str += 3;
|
||||||
c = *str;
|
c = (uint8_t)(*str);
|
||||||
}
|
}
|
||||||
if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) {
|
if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) {
|
||||||
c = TO_SPECIAL(str[1], str[2]);
|
c = TO_SPECIAL((uint8_t)str[1], (uint8_t)str[2]);
|
||||||
str += 2;
|
str += 2;
|
||||||
if (c == KS_ZERO) /* display <Nul> as ^@ or <Nul> */
|
if (c == KS_ZERO) { // display <Nul> as ^@ or <Nul>
|
||||||
c = NUL;
|
c = NUL;
|
||||||
}
|
}
|
||||||
if (IS_SPECIAL(c) || modifiers) /* special key */
|
}
|
||||||
special = TRUE;
|
if (IS_SPECIAL(c) || modifiers) { // Special key.
|
||||||
|
special = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_mbyte && !IS_SPECIAL(c)) {
|
if (!IS_SPECIAL(c)) {
|
||||||
int len = (*mb_ptr2len)(str);
|
const int len = utf_ptr2len((const char_u *)str);
|
||||||
|
|
||||||
/* For multi-byte characters check for an illegal byte. */
|
// Check for an illegal byte.
|
||||||
if (has_mbyte && MB_BYTE2LEN(*str) > len) {
|
if (MB_BYTE2LEN((uint8_t)(*str)) > len) {
|
||||||
transchar_nonprint(buf, c);
|
transchar_nonprint((char_u *)buf, c);
|
||||||
*sp = str + 1;
|
*sp = str + 1;
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
/* Since 'special' is TRUE the multi-byte character 'c' will be
|
// Since 'special' is TRUE the multi-byte character 'c' will be
|
||||||
* processed by get_special_key_name() */
|
// processed by get_special_key_name().
|
||||||
c = (*mb_ptr2char)(str);
|
c = utf_ptr2char((const char_u *)str);
|
||||||
*sp = str + len;
|
*sp = str + len;
|
||||||
} else
|
} else {
|
||||||
*sp = str + 1;
|
*sp = str + 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Make unprintable characters in <> form, also <M-Space> and <Tab>.
|
// Make unprintable characters in <> form, also <M-Space> and <Tab>.
|
||||||
* Use <Space> only for lhs of a mapping. */
|
if (special
|
||||||
if (special || char2cells(c) > 1 || (from && c == ' '))
|
|| char2cells(c) > 1
|
||||||
return get_special_key_name(c, modifiers);
|
|| (replace_spaces && c == ' ')
|
||||||
|
|| (replace_lt && c == '<')) {
|
||||||
|
return (const char *)get_special_key_name(c, modifiers);
|
||||||
|
}
|
||||||
buf[0] = c;
|
buf[0] = c;
|
||||||
buf[1] = NUL;
|
buf[1] = NUL;
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Convert string, replacing key codes with printables
|
||||||
* Translate a key sequence into special key names.
|
///
|
||||||
*/
|
/// @param[in] str String to convert.
|
||||||
void str2specialbuf(char_u *sp, char_u *buf, int len)
|
/// @param[out] buf Buffer to save results to.
|
||||||
|
/// @param[in] len Buffer length.
|
||||||
|
void str2specialbuf(const char *sp, char *buf, size_t len)
|
||||||
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
char_u *s;
|
|
||||||
|
|
||||||
*buf = NUL;
|
|
||||||
while (*sp) {
|
while (*sp) {
|
||||||
s = str2special(&sp, FALSE);
|
const char *s = str2special(&sp, false, false);
|
||||||
if ((int)(STRLEN(s) + STRLEN(buf)) < len)
|
const size_t s_len = strlen(s);
|
||||||
STRCAT(buf, s);
|
if (s_len <= len) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
memcpy(buf, s, s_len);
|
||||||
|
buf += s_len;
|
||||||
|
len -= s_len;
|
||||||
|
}
|
||||||
|
*buf = NUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -5175,9 +5175,13 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, int e
|
|||||||
* CTRL-V or backslash */
|
* CTRL-V or backslash */
|
||||||
if (valuep == &p_pt) {
|
if (valuep == &p_pt) {
|
||||||
s = *valuep;
|
s = *valuep;
|
||||||
while (*s != NUL)
|
while (*s != NUL) {
|
||||||
if (put_escstr(fd, str2special(&s, FALSE), 2) == FAIL)
|
if (put_escstr(fd, (char_u *)str2special((const char **)&s, false,
|
||||||
|
false), 2)
|
||||||
|
== FAIL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (expand) {
|
} else if (expand) {
|
||||||
buf = xmalloc(MAXPATHL);
|
buf = xmalloc(MAXPATHL);
|
||||||
home_replace(NULL, *valuep, buf, MAXPATHL, FALSE);
|
home_replace(NULL, *valuep, buf, MAXPATHL, FALSE);
|
||||||
@@ -6173,16 +6177,17 @@ option_value2string (
|
|||||||
}
|
}
|
||||||
} else { // P_STRING
|
} else { // P_STRING
|
||||||
varp = *(char_u **)(varp);
|
varp = *(char_u **)(varp);
|
||||||
if (varp == NULL) /* just in case */
|
if (varp == NULL) { // Just in case.
|
||||||
NameBuff[0] = NUL;
|
NameBuff[0] = NUL;
|
||||||
else if (opp->flags & P_EXPAND)
|
} else if (opp->flags & P_EXPAND) {
|
||||||
home_replace(NULL, varp, NameBuff, MAXPATHL, FALSE);
|
home_replace(NULL, varp, NameBuff, MAXPATHL, false);
|
||||||
/* Translate 'pastetoggle' into special key names */
|
// Translate 'pastetoggle' into special key names.
|
||||||
else if ((char_u **)opp->var == &p_pt)
|
} else if ((char_u **)opp->var == &p_pt) {
|
||||||
str2specialbuf(p_pt, NameBuff, MAXPATHL);
|
str2specialbuf((const char *)p_pt, (char *)NameBuff, MAXPATHL);
|
||||||
else
|
} else {
|
||||||
STRLCPY(NameBuff, varp, MAXPATHL);
|
STRLCPY(NameBuff, varp, MAXPATHL);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
local helpers = require('test.functional.helpers')(after_each)
|
local helpers = require('test.functional.helpers')(after_each)
|
||||||
|
local global_helpers = require('test.helpers')
|
||||||
|
|
||||||
local clear = helpers.clear
|
local clear = helpers.clear
|
||||||
local command = helpers.command
|
local command = helpers.command
|
||||||
local curbufmeths = helpers.curbufmeths
|
local curbufmeths = helpers.curbufmeths
|
||||||
@@ -8,13 +9,7 @@ local funcs = helpers.funcs
|
|||||||
local meths = helpers.meths
|
local meths = helpers.meths
|
||||||
local source = helpers.source
|
local source = helpers.source
|
||||||
|
|
||||||
local function local_copy(t)
|
local shallowcopy = global_helpers.shallowcopy
|
||||||
local copy = {}
|
|
||||||
for k,v in pairs(t) do
|
|
||||||
copy[k] = v
|
|
||||||
end
|
|
||||||
return copy
|
|
||||||
end
|
|
||||||
|
|
||||||
describe('get_keymap', function()
|
describe('get_keymap', function()
|
||||||
before_each(clear)
|
before_each(clear)
|
||||||
@@ -50,7 +45,7 @@ describe('get_keymap', function()
|
|||||||
|
|
||||||
-- Add another mapping
|
-- Add another mapping
|
||||||
command('nnoremap foo_longer bar_longer')
|
command('nnoremap foo_longer bar_longer')
|
||||||
local foolong_bar_map_table = local_copy(foo_bar_map_table)
|
local foolong_bar_map_table = shallowcopy(foo_bar_map_table)
|
||||||
foolong_bar_map_table['lhs'] = 'foo_longer'
|
foolong_bar_map_table['lhs'] = 'foo_longer'
|
||||||
foolong_bar_map_table['rhs'] = 'bar_longer'
|
foolong_bar_map_table['rhs'] = 'bar_longer'
|
||||||
|
|
||||||
@@ -72,7 +67,7 @@ describe('get_keymap', function()
|
|||||||
|
|
||||||
command('inoremap foo bar')
|
command('inoremap foo bar')
|
||||||
-- The table will be the same except for the mode
|
-- The table will be the same except for the mode
|
||||||
local insert_table = local_copy(foo_bar_map_table)
|
local insert_table = shallowcopy(foo_bar_map_table)
|
||||||
insert_table['mode'] = 'i'
|
insert_table['mode'] = 'i'
|
||||||
|
|
||||||
eq({insert_table}, meths.get_keymap('i'))
|
eq({insert_table}, meths.get_keymap('i'))
|
||||||
@@ -81,11 +76,11 @@ describe('get_keymap', function()
|
|||||||
it('considers scope', function()
|
it('considers scope', function()
|
||||||
-- change the map slightly
|
-- change the map slightly
|
||||||
command('nnoremap foo_longer bar_longer')
|
command('nnoremap foo_longer bar_longer')
|
||||||
local foolong_bar_map_table = local_copy(foo_bar_map_table)
|
local foolong_bar_map_table = shallowcopy(foo_bar_map_table)
|
||||||
foolong_bar_map_table['lhs'] = 'foo_longer'
|
foolong_bar_map_table['lhs'] = 'foo_longer'
|
||||||
foolong_bar_map_table['rhs'] = 'bar_longer'
|
foolong_bar_map_table['rhs'] = 'bar_longer'
|
||||||
|
|
||||||
local buffer_table = local_copy(foo_bar_map_table)
|
local buffer_table = shallowcopy(foo_bar_map_table)
|
||||||
buffer_table['buffer'] = 1
|
buffer_table['buffer'] = 1
|
||||||
|
|
||||||
command('nnoremap <buffer> foo bar')
|
command('nnoremap <buffer> foo bar')
|
||||||
@@ -98,7 +93,7 @@ describe('get_keymap', function()
|
|||||||
it('considers scope for overlapping maps', function()
|
it('considers scope for overlapping maps', function()
|
||||||
command('nnoremap foo bar')
|
command('nnoremap foo bar')
|
||||||
|
|
||||||
local buffer_table = local_copy(foo_bar_map_table)
|
local buffer_table = shallowcopy(foo_bar_map_table)
|
||||||
buffer_table['buffer'] = 1
|
buffer_table['buffer'] = 1
|
||||||
|
|
||||||
command('nnoremap <buffer> foo bar')
|
command('nnoremap <buffer> foo bar')
|
||||||
@@ -121,7 +116,7 @@ describe('get_keymap', function()
|
|||||||
|
|
||||||
command('nnoremap <buffer> foo bar')
|
command('nnoremap <buffer> foo bar')
|
||||||
-- Final buffer will have buffer mappings
|
-- Final buffer will have buffer mappings
|
||||||
local buffer_table = local_copy(foo_bar_map_table)
|
local buffer_table = shallowcopy(foo_bar_map_table)
|
||||||
buffer_table['buffer'] = final_buffer
|
buffer_table['buffer'] = final_buffer
|
||||||
eq({buffer_table}, meths.buf_get_keymap(final_buffer, 'n'))
|
eq({buffer_table}, meths.buf_get_keymap(final_buffer, 'n'))
|
||||||
eq({buffer_table}, meths.buf_get_keymap(0, 'n'))
|
eq({buffer_table}, meths.buf_get_keymap(0, 'n'))
|
||||||
@@ -243,4 +238,75 @@ describe('get_keymap', function()
|
|||||||
eq('<F12>', meths.get_keymap('n')[1]['lhs'])
|
eq('<F12>', meths.get_keymap('n')[1]['lhs'])
|
||||||
eq(':let g:maparg_test_var = 1<CR>', meths.get_keymap('n')[1]['rhs'])
|
eq(':let g:maparg_test_var = 1<CR>', meths.get_keymap('n')[1]['rhs'])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('works correctly despite various &cpo settings', function()
|
||||||
|
local cpo_table = {
|
||||||
|
silent=0,
|
||||||
|
expr=0,
|
||||||
|
sid=0,
|
||||||
|
buffer=0,
|
||||||
|
nowait=0,
|
||||||
|
noremap=1,
|
||||||
|
}
|
||||||
|
local function cpomap(lhs, rhs, mode)
|
||||||
|
local ret = shallowcopy(cpo_table)
|
||||||
|
ret.lhs = lhs
|
||||||
|
ret.rhs = rhs
|
||||||
|
ret.mode = mode
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
command('set cpo-=< cpo+=B')
|
||||||
|
command('nnoremap \\<C-a><C-a><LT>C-a>\\ \\<C-b><C-b><LT>C-b>\\')
|
||||||
|
command('nnoremap <special> \\<C-c><C-c><LT>C-c>\\ \\<C-d><C-d><LT>C-d>\\')
|
||||||
|
|
||||||
|
command('set cpo+=B<')
|
||||||
|
command('xnoremap \\<C-a><C-a><LT>C-a>\\ \\<C-b><C-b><LT>C-b>\\')
|
||||||
|
command('xnoremap <special> \\<C-c><C-c><LT>C-c>\\ \\<C-d><C-d><LT>C-d>\\')
|
||||||
|
|
||||||
|
command('set cpo-=B<')
|
||||||
|
command('snoremap \\<C-a><C-a><LT>C-a>\\ \\<C-b><C-b><LT>C-b>\\')
|
||||||
|
command('snoremap <special> \\<C-c><C-c><LT>C-c>\\ \\<C-d><C-d><LT>C-d>\\')
|
||||||
|
|
||||||
|
command('set cpo-=B cpo+=<')
|
||||||
|
command('onoremap \\<C-a><C-a><LT>C-a>\\ \\<C-b><C-b><LT>C-b>\\')
|
||||||
|
command('onoremap <special> \\<C-c><C-c><LT>C-c>\\ \\<C-d><C-d><LT>C-d>\\')
|
||||||
|
|
||||||
|
for _, cmd in ipairs({
|
||||||
|
'set cpo-=B cpo+=<',
|
||||||
|
'set cpo-=B<',
|
||||||
|
'set cpo+=B<',
|
||||||
|
'set cpo-=< cpo+=B',
|
||||||
|
}) do
|
||||||
|
command(cmd)
|
||||||
|
eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'n'),
|
||||||
|
cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'n')},
|
||||||
|
meths.get_keymap('n'))
|
||||||
|
eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'x'),
|
||||||
|
cpomap('\\<lt>C-a><lt>C-a><lt>LT>C-a>\\', '\\<lt>C-b><lt>C-b><lt>LT>C-b>\\', 'x')},
|
||||||
|
meths.get_keymap('x'))
|
||||||
|
eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 's'),
|
||||||
|
cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 's')},
|
||||||
|
meths.get_keymap('s'))
|
||||||
|
eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 'o'),
|
||||||
|
cpomap('<lt>C-a><lt>C-a><lt>LT>C-a> ', '<lt>C-b><lt>C-b><lt>LT>C-b>', 'o')},
|
||||||
|
meths.get_keymap('o'))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('always uses space for space and bar for bar', function()
|
||||||
|
local space_table = {
|
||||||
|
lhs='| |',
|
||||||
|
rhs='| |',
|
||||||
|
mode='n',
|
||||||
|
silent=0,
|
||||||
|
expr=0,
|
||||||
|
sid=0,
|
||||||
|
buffer=0,
|
||||||
|
nowait=0,
|
||||||
|
noremap=1,
|
||||||
|
}
|
||||||
|
command('nnoremap \\|<Char-0x20><Char-32><Space><Bar> \\|<Char-0x20><Char-32><Space> <Bar>')
|
||||||
|
eq({space_table}, meths.get_keymap('n'))
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
@@ -1948,8 +1948,8 @@ describe('typval.c', function()
|
|||||||
eq(OK, lib.tv_dict_add_str(d, 'testt', 3, 'TEST'))
|
eq(OK, lib.tv_dict_add_str(d, 'testt', 3, 'TEST'))
|
||||||
local dis = dict_items(d)
|
local dis = dict_items(d)
|
||||||
alloc_log:check({
|
alloc_log:check({
|
||||||
|
a.str(dis.tes.di_tv.vval.v_string, 'TEST'),
|
||||||
a.di(dis.tes, 'tes'),
|
a.di(dis.tes, 'tes'),
|
||||||
a.str(dis.tes.di_tv.vval.v_string, 'TEST')
|
|
||||||
})
|
})
|
||||||
eq({test=10, tes='TEST'}, dct2tbl(d))
|
eq({test=10, tes='TEST'}, dct2tbl(d))
|
||||||
eq(FAIL, check_emsg(function() return lib.tv_dict_add_str(d, 'testt', 3, 'TEST') end,
|
eq(FAIL, check_emsg(function() return lib.tv_dict_add_str(d, 'testt', 3, 'TEST') end,
|
||||||
@@ -1963,6 +1963,38 @@ describe('typval.c', function()
|
|||||||
alloc_log:check({})
|
alloc_log:check({})
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
describe('allocated_str()', function()
|
||||||
|
itp('works', function()
|
||||||
|
local d = dict({test=10})
|
||||||
|
eq({test=10}, dct2tbl(d))
|
||||||
|
alloc_log:clear()
|
||||||
|
local s1 = lib.xstrdup('TEST')
|
||||||
|
local s2 = lib.xstrdup('TEST')
|
||||||
|
local s3 = lib.xstrdup('TEST')
|
||||||
|
alloc_log:check({
|
||||||
|
a.str(s1, 'TEST'),
|
||||||
|
a.str(s2, 'TEST'),
|
||||||
|
a.str(s3, 'TEST'),
|
||||||
|
})
|
||||||
|
eq(OK, lib.tv_dict_add_allocated_str(d, 'testt', 3, s1))
|
||||||
|
local dis = dict_items(d)
|
||||||
|
alloc_log:check({
|
||||||
|
a.di(dis.tes, 'tes'),
|
||||||
|
})
|
||||||
|
eq({test=10, tes='TEST'}, dct2tbl(d))
|
||||||
|
eq(FAIL, check_emsg(function() return lib.tv_dict_add_allocated_str(d, 'testt', 3, s2) end,
|
||||||
|
'E685: Internal error: hash_add()'))
|
||||||
|
alloc_log:clear()
|
||||||
|
lib.emsg_skip = lib.emsg_skip + 1
|
||||||
|
eq(FAIL, check_emsg(function() return lib.tv_dict_add_allocated_str(d, 'testt', 3, s3) end,
|
||||||
|
nil))
|
||||||
|
lib.emsg_skip = lib.emsg_skip - 1
|
||||||
|
alloc_log:clear_tmp_allocs()
|
||||||
|
alloc_log:check({
|
||||||
|
a.freed(s3),
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
describe('clear()', function()
|
describe('clear()', function()
|
||||||
itp('works', function()
|
itp('works', function()
|
||||||
@@ -1975,7 +2007,7 @@ describe('typval.c', function()
|
|||||||
local dis = dict_items(d)
|
local dis = dict_items(d)
|
||||||
local di = dis.TES
|
local di = dis.TES
|
||||||
local di_s = di.di_tv.vval.v_string
|
local di_s = di.di_tv.vval.v_string
|
||||||
alloc_log:check({a.di(di), a.str(di_s)})
|
alloc_log:check({a.str(di_s), a.di(di)})
|
||||||
eq({TES='tEsT'}, dct2tbl(d))
|
eq({TES='tEsT'}, dct2tbl(d))
|
||||||
lib.tv_dict_clear(d)
|
lib.tv_dict_clear(d)
|
||||||
alloc_log:check({a.freed(di_s), a.freed(di)})
|
alloc_log:check({a.freed(di_s), a.freed(di)})
|
||||||
|
Reference in New Issue
Block a user