Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Dictionary-function elements within the description dictionary #209

Merged
merged 1 commit into from
Jun 7, 2022

Conversation

rene-descartes2021
Copy link
Collaborator

@rene-descartes2021 rene-descartes2021 commented May 25, 2022

In writing a C# layer for space-vim, I wanted to overlap/replace/augment the '+lsp' key mappings.

EDIT2: For example, in space-vim the hotkey sequence ' lgd' is '+lsp/+goto/definition' using the existing '+lsp' keymappings using the LSP Client as configured in space-vim, but in *.cs files ' lgd' should use OmniSharp-vim (in the C# space-vim layer) to do the same. OmniSharp-vim isn't an LSP Client (it doesn't use the language server protocol (LSP)) but does many of the same things with a language server, so it makes sense to use the same hotkeys.

The most convenient way I thought to do this was to use a dictionary-function as an element within the vim-which-key description dictionary (see :help dictionary-function). May have pros/cons compared to the technique of BufEnter/BufLeave in #132 and perhaps #48.

The dictionary-function can return a different mapping depending on e.g. the &filetype.

Example:

" <space-vim>/layers/+lang/csharp/config.vim

" nickspoons/omnisharp-vim: {
  " A `Dictionary-function` containing vim-which-key mappings
  function! s:SetOmnisharpHotkeysInWhichkey()
    let s:keep_lsp_mapping = get(s:, 'keep_lsp_mapping', deepcopy(g:spacevim#map#leader#desc['l']))

    let l:omnisharp_map = {
    \ 'name': '+omnisharp',
    \ '.': ['<Plug>(omnisharp_code_action_repeat)', 'repeat'],
    \ 'a': ['<Plug>(omnisharp_code_actions)'      , 'code-action'],
    \ 'c': ['<Plug>(omnisharp_global_code_check)' , 'global-code-check'],
    \ 'f': ['<Plug>(omnisharp_code_format)'       , 'formatting'],
    "\ 'h': ['spacevim#lang#util#Hover()'         , 'hover'],
    \ 'h': ['<Plug>(omnisharp_signature_help)'    , 'hover'],
    \ 'H': ['<Plug>(omnisharp_highlight)'         , 'highlight'],
    \ 'r': ['<Plug>(omnisharp_find_usages)'       , 'references'],
    \ 'R': ['<Plug>(omnisharp_rename)'            , 'rename'],
    "\ 's': ['spacevim#lang#util#DocumentSymbol()', 'document-symbol'],
    \ 's': ['<Plug>(omnisharp_documentation)'     , 'document-symbol'],
    "\ 'S': ['spacevim#lang#util#WorkspaceSymbol()', 'workspace-symbol'],
    \ 'S': ['<Plug>(omnisharp_find_symbol)'       , 'workspace-symbol'],
    \ 'g': {
      \ 'name': '+goto',
      \ 'd': ['<Plug>(omnisharp_go_to_definition)', 'definition'],
      \ 't': ['<Plug>(omnisharp_find_type)'       , 'type-definition'],
      \ 'i': ['<Plug>(omnisharp_find_implementations)', 'implementation'],
      \ 's': ['<Plug>(omnisharp_find_symbol)'     , 'symbol'],
      \ },
    \ 'p': {
      \ 'name': '+preview',
      \ 'd': ['<Plug>(omnisharp_preview_definition)'     , 'definition'],
      \ 'i': ['<Plug>(omnisharp_preview_implementations)', 'implementation'],
      \ },
    \ 'b': {
      \ 'name': '+build',
      \ 'p': ['<Plug>(omnisharp_build_project)'      , 'build-project'],
      \ 's': ['<Plug>(omnisharp_build_solution)'     , 'build-solution'],
      \ 'd': ['<Plug>(omnisharp_debug_project)'      , 'debug-project'],
      \ 'v': ['<Plug>(omnisharp_create_debug_config)', 'create-vimspector-config'],
      \ },
    \ }

    if &filetype ==# 'cs'
      return l:omnisharp_map
    else
      return s:keep_lsp_mapping
    endif
  endfunction

  " Integrate OmniSharp hotkeys with vim-which-key
  if spacevim#load('which-key')
    let s:leader = g:spacevim#map#leader#desc
    let s:leader['l'] = function('s:SetOmnisharpHotkeysInWhichkey')
  endif
" }

EDIT: Very simple changes in vim-which-key. V had to be capitalized so as lower-case variable names can't refer to a funcref. And if V was a funcref it had to be called with V() and the result of that dictionary-function assigned to the right location in s:runtime for processing (calculating layout and etc).

TODO: I can put a simpler example in the wiki and make a new FAQ entry in the README.md.

@liuchengxu
Copy link
Owner

TODO: I can put a simpler example in the wiki and make a new FAQ entry in the README.md.

That can be really great!

@rene-descartes2021 Thanks for the PR! Looks pretty good to me!

autoload/which_key.vim Outdated Show resolved Hide resolved
@rene-descartes2021 rene-descartes2021 force-pushed the dict-funcref branch 2 times, most recently from 65fe2a0 to 7d17e03 Compare June 6, 2022 21:39
@rene-descartes2021
Copy link
Collaborator Author

Ok a smaller example would be:

set nocompatible

call plug#begin('~/.vim/plugged')
Plug 'liuchengxu/vim-which-key'
call plug#end()

let mapleader = "\<Space>"

nnoremap <silent> <leader>      :<c-u>WhichKey '<Space>'<CR>
nnoremap <silent> <localleader> :<c-u>WhichKey  ','<CR>

call which_key#register('<Space>', "g:which_key_map")

let g:which_key_map = {}

let g:which_key_map.c = { 'name' : '+coc' }
let g:which_key_map.c.g = { 'name' : '+goto'}
let g:which_key_map.c.g.d = [ '<Plug>(coc-definition)', "coc-definition"]

let g:which_key_map.g = {'name': '+git'}
let g:which_key_map.g = ['Gstatus', 'git-status']


" ~/.vim/ftplugin/cs.vim
" A `Dictionary-function` containing vim-which-key mappings
function! s:MyHotkeyDictionaryFunction()
  let s:keep_lsp_mapping = get(s:, 'keep_lsp_mapping', deepcopy(g:which_key_map['g']))

  if &filetype ==# 'cs'
    let l:key_map = {
    \ 'name': '+goto',
    \ 'd': ['<Plug>(omnisharp_go_to_definition)', 'definition'],
    \ 'f': {
      \ 'name': '+find',
      \ 't': ['<Plug>(omnisharp_find_type)'       , 'type-definition'],
      \ 'i': ['<Plug>(omnisharp_find_implementations)', 'implementation'],
      \ 's': ['<Plug>(omnisharp_find_symbol)'     , 'symbol'],
      \ },
    \ }
    return l:key_map
  else
    return s:keep_lsp_mapping
  endif
endfunction

" Integrate dictionary-function with dictionary used in earlier which_key#register()
let s:leader = g:which_key_map
let s:leader['g'] = function('s:MyHotkeyDictionaryFunction')

I can't edit the wiki, don't have permission, so I added an entry in the README.md FAQ.

@liuchengxu liuchengxu merged commit d7d451d into liuchengxu:master Jun 7, 2022
@liuchengxu
Copy link
Owner

Merged, thank you! And now you can edit the wiki @rene-descartes2021 :D

@rene-descartes2021 rene-descartes2021 deleted the dict-funcref branch June 16, 2022 18:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants