mirror of
https://github.com/neovim/neovim.git
synced 2025-09-28 05:58:33 +00:00
refactor: move some mapping-related code to a separate file (#19061)
This marks the following Vim patches as ported: vim-patch:8.1.1785: map functionality mixed with character input Problem: Map functionality mixed with character input. Solution: Move the map functionality to a separate file. (Yegappan Lakshmanan, closes vim/vim#4740) Graduate the +localmap feature.b66bab381c
vim-patch:8.2.3643: header for source file is outdated Problem: Header for source file is outdated. Solution: Make the header more accurate. (closes vim/vim#9186)a3f83feb63
Also cherry-pick a change for <unique> mappings from patch 8.2.0807. Rename map_clear_mode() to do_mapclear().
This commit is contained in:
@@ -51,6 +51,7 @@
|
||||
#include "nvim/indent_c.h"
|
||||
#include "nvim/keycodes.h"
|
||||
#include "nvim/macros.h"
|
||||
#include "nvim/mapping.h"
|
||||
#include "nvim/mbyte.h"
|
||||
#include "nvim/memfile.h"
|
||||
#include "nvim/memline.h"
|
||||
@@ -7062,175 +7063,6 @@ static int wc_use_keyname(char_u *varp, long *wcp)
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Any character has an equivalent 'langmap' character. This is used for
|
||||
/// keyboards that have a special language mode that sends characters above
|
||||
/// 128 (although other characters can be translated too). The "to" field is a
|
||||
/// Vim command character. This avoids having to switch the keyboard back to
|
||||
/// ASCII mode when leaving Insert mode.
|
||||
///
|
||||
/// langmap_mapchar[] maps any of 256 chars to an ASCII char used for Vim
|
||||
/// commands.
|
||||
/// langmap_mapga.ga_data is a sorted table of langmap_entry_T.
|
||||
/// This does the same as langmap_mapchar[] for characters >= 256.
|
||||
///
|
||||
/// With multi-byte support use growarray for 'langmap' chars >= 256
|
||||
typedef struct {
|
||||
int from;
|
||||
int to;
|
||||
} langmap_entry_T;
|
||||
|
||||
static garray_T langmap_mapga = GA_EMPTY_INIT_VALUE;
|
||||
|
||||
/// Search for an entry in "langmap_mapga" for "from". If found set the "to"
|
||||
/// field. If not found insert a new entry at the appropriate location.
|
||||
static void langmap_set_entry(int from, int to)
|
||||
{
|
||||
langmap_entry_T *entries = (langmap_entry_T *)(langmap_mapga.ga_data);
|
||||
unsigned int a = 0;
|
||||
assert(langmap_mapga.ga_len >= 0);
|
||||
unsigned int b = (unsigned int)langmap_mapga.ga_len;
|
||||
|
||||
// Do a binary search for an existing entry.
|
||||
while (a != b) {
|
||||
unsigned int i = (a + b) / 2;
|
||||
int d = entries[i].from - from;
|
||||
|
||||
if (d == 0) {
|
||||
entries[i].to = to;
|
||||
return;
|
||||
}
|
||||
if (d < 0) {
|
||||
a = i + 1;
|
||||
} else {
|
||||
b = i;
|
||||
}
|
||||
}
|
||||
|
||||
ga_grow(&langmap_mapga, 1);
|
||||
|
||||
// insert new entry at position "a"
|
||||
entries = (langmap_entry_T *)(langmap_mapga.ga_data) + a;
|
||||
memmove(entries + 1, entries,
|
||||
((unsigned int)langmap_mapga.ga_len - a) * sizeof(langmap_entry_T));
|
||||
langmap_mapga.ga_len++;
|
||||
entries[0].from = from;
|
||||
entries[0].to = to;
|
||||
}
|
||||
|
||||
/// Apply 'langmap' to multi-byte character "c" and return the result.
|
||||
int langmap_adjust_mb(int c)
|
||||
{
|
||||
langmap_entry_T *entries = (langmap_entry_T *)(langmap_mapga.ga_data);
|
||||
int a = 0;
|
||||
int b = langmap_mapga.ga_len;
|
||||
|
||||
while (a != b) {
|
||||
int i = (a + b) / 2;
|
||||
int d = entries[i].from - c;
|
||||
|
||||
if (d == 0) {
|
||||
return entries[i].to; // found matching entry
|
||||
}
|
||||
if (d < 0) {
|
||||
a = i + 1;
|
||||
} else {
|
||||
b = i;
|
||||
}
|
||||
}
|
||||
return c; // no entry found, return "c" unmodified
|
||||
}
|
||||
|
||||
static void langmap_init(void)
|
||||
{
|
||||
for (int i = 0; i < 256; i++) {
|
||||
langmap_mapchar[i] = (char_u)i; // we init with a one-to-one map
|
||||
}
|
||||
ga_init(&langmap_mapga, sizeof(langmap_entry_T), 8);
|
||||
}
|
||||
|
||||
/// Called when langmap option is set; the language map can be
|
||||
/// changed at any time!
|
||||
static void langmap_set(void)
|
||||
{
|
||||
char_u *p;
|
||||
char_u *p2;
|
||||
int from, to;
|
||||
|
||||
ga_clear(&langmap_mapga); // clear the previous map first
|
||||
langmap_init(); // back to one-to-one map
|
||||
|
||||
for (p = p_langmap; p[0] != NUL;) {
|
||||
for (p2 = p; p2[0] != NUL && p2[0] != ',' && p2[0] != ';';
|
||||
MB_PTR_ADV(p2)) {
|
||||
if (p2[0] == '\\' && p2[1] != NUL) {
|
||||
p2++;
|
||||
}
|
||||
}
|
||||
if (p2[0] == ';') {
|
||||
p2++; // abcd;ABCD form, p2 points to A
|
||||
} else {
|
||||
p2 = NULL; // aAbBcCdD form, p2 is NULL
|
||||
}
|
||||
while (p[0]) {
|
||||
if (p[0] == ',') {
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
if (p[0] == '\\' && p[1] != NUL) {
|
||||
p++;
|
||||
}
|
||||
from = utf_ptr2char((char *)p);
|
||||
to = NUL;
|
||||
if (p2 == NULL) {
|
||||
MB_PTR_ADV(p);
|
||||
if (p[0] != ',') {
|
||||
if (p[0] == '\\') {
|
||||
p++;
|
||||
}
|
||||
to = utf_ptr2char((char *)p);
|
||||
}
|
||||
} else {
|
||||
if (p2[0] != ',') {
|
||||
if (p2[0] == '\\') {
|
||||
p2++;
|
||||
}
|
||||
to = utf_ptr2char((char *)p2);
|
||||
}
|
||||
}
|
||||
if (to == NUL) {
|
||||
semsg(_("E357: 'langmap': Matching character missing for %s"),
|
||||
transchar(from));
|
||||
return;
|
||||
}
|
||||
|
||||
if (from >= 256) {
|
||||
langmap_set_entry(from, to);
|
||||
} else {
|
||||
assert(to <= UCHAR_MAX);
|
||||
langmap_mapchar[from & 255] = (char_u)to;
|
||||
}
|
||||
|
||||
// Advance to next pair
|
||||
MB_PTR_ADV(p);
|
||||
if (p2 != NULL) {
|
||||
MB_PTR_ADV(p2);
|
||||
if (*p == ';') {
|
||||
p = p2;
|
||||
if (p[0] != NUL) {
|
||||
if (p[0] != ',') {
|
||||
semsg(_("E358: 'langmap': Extra characters after semicolon: %s"),
|
||||
p);
|
||||
return;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return true if format option 'x' is in effect.
|
||||
/// Take care of no formatting when 'paste' is set.
|
||||
bool has_format_option(int x)
|
||||
|
Reference in New Issue
Block a user