neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

node.vim (4520B)


      1 if exists('g:loaded_node_provider')
      2  finish
      3 endif
      4 let g:loaded_node_provider = 0
      5 
      6 function! s:is_minimum_version(version, min_version) abort
      7  if empty(a:version)
      8    let nodejs_version = get(split(system(['node', '-v']), "\n"), 0, '')
      9    if v:shell_error || nodejs_version[0] !=# 'v'
     10      return 0
     11    endif
     12  else
     13    let nodejs_version = a:version
     14  endif
     15  " Remove surrounding junk.  Example: 'v4.12.0' => '4.12.0'
     16  let nodejs_version = matchstr(nodejs_version, '\(\d\.\?\)\+')
     17  " [major, minor, patch]
     18  return !v:lua.vim.version.lt(nodejs_version, a:min_version)
     19 endfunction
     20 
     21 let s:NodeHandler = {
     22 \ 'stdout_buffered': v:true,
     23 \ 'result': ''
     24 \ }
     25 function! s:NodeHandler.on_exit(job_id, data, event) abort
     26  let bin_dir = join(get(self, 'stdout', []), '')
     27  let entry_point = bin_dir . self.entry_point
     28  let self.result = filereadable(entry_point) ? entry_point : ''
     29 endfunction
     30 
     31 " Support for --inspect-brk requires node 6.12+ or 7.6+ or 8+
     32 " Return 1 if it is supported
     33 " Return 0 otherwise
     34 function! provider#node#can_inspect() abort
     35  if !executable('node')
     36    return 0
     37  endif
     38  let ver = get(split(system(['node', '-v']), "\n"), 0, '')
     39  if v:shell_error || ver[0] !=# 'v'
     40    return 0
     41  endif
     42  return (ver[1] ==# '6' && s:is_minimum_version(ver, '6.12.0'))
     43    \ || s:is_minimum_version(ver, '7.6.0')
     44 endfunction
     45 
     46 function! provider#node#Detect() abort
     47  let minver = '6.0.0'
     48  if exists('g:node_host_prog')
     49    return [expand(g:node_host_prog, v:true), '']
     50  endif
     51  if !executable('node')
     52    return ['', 'node not found (or not executable)']
     53  endif
     54  if !s:is_minimum_version(v:null, minver)
     55    return ['', printf('node version %s not found', minver)]
     56  endif
     57 
     58  let npm_opts = {}
     59  if executable('npm')
     60    let npm_opts = deepcopy(s:NodeHandler)
     61    let npm_opts.entry_point = '/neovim/bin/cli.js'
     62    let npm_opts.job_id = jobstart('npm --loglevel silent root -g', npm_opts)
     63  endif
     64 
     65  let yarn_opts = {}
     66  if executable('yarn')
     67    let yarn_opts = deepcopy(s:NodeHandler)
     68    let yarn_opts.entry_point = '/node_modules/neovim/bin/cli.js'
     69    " `yarn global dir` is slow (> 250ms), try the default path first
     70    " https://github.com/yarnpkg/yarn/issues/2049#issuecomment-263183768
     71    let yarn_config_dir = has('win32') ? '/AppData/Local/Yarn/Data' : '/.config/yarn'
     72    let yarn_default_path = $HOME . yarn_config_dir . '/global/' . yarn_opts.entry_point
     73    if filereadable(yarn_default_path)
     74      return [yarn_default_path, '']
     75    endif
     76    let yarn_opts.job_id = jobstart('yarn global dir', yarn_opts)
     77  endif
     78 
     79  let pnpm_opts = {}
     80  if executable('pnpm')
     81    let pnpm_opts = deepcopy(s:NodeHandler)
     82    let pnpm_opts.entry_point = '/neovim/bin/cli.js'
     83    let pnpm_opts.job_id = jobstart('pnpm --loglevel silent root -g', pnpm_opts)
     84  endif
     85 
     86  " npm returns the directory faster, so let's check that first
     87  if !empty(npm_opts)
     88    let result = jobwait([npm_opts.job_id])
     89    if result[0] == 0 && npm_opts.result != ''
     90      return [npm_opts.result, '']
     91    endif
     92  endif
     93 
     94  if !empty(yarn_opts)
     95    let result = jobwait([yarn_opts.job_id])
     96    if result[0] == 0 && yarn_opts.result != ''
     97      return [yarn_opts.result, '']
     98    endif
     99  endif
    100 
    101  if !empty(pnpm_opts)
    102    let result = jobwait([pnpm_opts.job_id])
    103    if result[0] == 0 && pnpm_opts.result != ''
    104      return [pnpm_opts.result, '']
    105    endif
    106  endif
    107 
    108  return ['', 'failed to detect node']
    109 endfunction
    110 
    111 function! provider#node#Prog() abort
    112  return s:prog
    113 endfunction
    114 
    115 function! provider#node#Require(host) abort
    116  if s:err != ''
    117    echoerr s:err
    118    return
    119  endif
    120 
    121  let args = ['node']
    122 
    123  if !empty($NVIM_NODE_HOST_DEBUG) && provider#node#can_inspect()
    124    call add(args, '--inspect-brk')
    125  endif
    126 
    127  call add(args, provider#node#Prog())
    128 
    129  return provider#Poll(args, a:host.orig_name, '$NVIM_NODE_LOG_FILE')
    130 endfunction
    131 
    132 function! provider#node#Call(method, args) abort
    133  if s:err != ''
    134    echoerr s:err
    135    return
    136  endif
    137 
    138  if !exists('s:host')
    139    try
    140      let s:host = remote#host#Require('node')
    141    catch
    142      let s:err = v:exception
    143      echohl WarningMsg
    144      echomsg v:exception
    145      echohl None
    146      return
    147    endtry
    148  endif
    149  return call('rpcrequest', insert(insert(a:args, 'node_'.a:method), s:host))
    150 endfunction
    151 
    152 
    153 let s:err = ''
    154 let [s:prog, s:_] = provider#node#Detect()
    155 let g:loaded_node_provider = empty(s:prog) ? 0 : 2
    156 
    157 if g:loaded_node_provider != 2
    158  let s:err = 'Cannot find the "neovim" node package. Try :checkhealth'
    159 endif
    160 
    161 call remote#host#RegisterPlugin('node-provider', 'node', [])