local available_modes = { normal_visual_select_operator_pending = '', N = '', normal = 'n', n = 'n', insert = 'i', i = 'i', visual = 'x', x = 'x', visual_select = 'v', v = 'v', select = 's', s = 's', operator_pending = 'o', o = 'o', ['!'] = '!', insert_command_line = '!', command_line = 'c', c = 'c', terminal = 't', t = 't', } local bind = function ( self, map ) vim.validate( 'map', map, 'table' ) vim.validate( 'map.keys', map.keys, { 'string', 'table' } ) vim.validate( 'map.command', map.command, { 'function', 'string' } ) local keys = map.keys local command = map.command map.options = map.options or {} if map.category and map.description then map.description = map.category .. ': ' .. map.description end local options = vim.tbl_extend( 'keep', map.options, { silent = true, desc = map.description, buf = map.buffer, remap = map.remap, } ) if vim.tbl_isempty( self.modes ) then self.modes[1] = available_modes.normal_visual_select_operator_pending end local modes = self.modes if type( keys ) == 'table' then for _, key in ipairs( keys ) do vim.keymap.set( modes, key, command, options ) end else vim.keymap.set( modes, keys, command, options ) end self.modes = {} return function () local delete_options = options.buf and { buf = options.buf } or {} if type( keys ) == 'table' then for _, key in ipairs( keys ) do vim.keymap.del( modes, key, delete_options ) end else vim.keymap.del( modes, keys, delete_options ) end end end local add_mode = function ( self, key ) local new_mode = available_modes[key] if new_mode == nil then error( 'unknown keymap mode requested: ' .. key ) end if not vim.tbl_contains( self.modes, new_mode ) then table.insert( self.modes, new_mode ) end return self end --- @overload fun(map:table): function local map = setmetatable( { modes = {}, }, { __index = add_mode, __newindex = function ( ... ) error( 'Assignments are not supported for std.map.\n' .. vim.inspect( ... ), 2 ) end, __call = bind, } ) return map