From efdf2e611fa2c639b4000764a4ca65b5e5a3950a Mon Sep 17 00:00:00 2001 From: "Charles-P. Clermont" Date: Wed, 4 Apr 2018 11:33:53 -0400 Subject: [PATCH 1/6] Add support for NODE_PATH and mimic node.js module resolution --- autoload/node.vim | 20 +++--- autoload/node/lib.vim | 154 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 132 insertions(+), 42 deletions(-) diff --git a/autoload/node.vim b/autoload/node.vim index 3954e4c..c020e3a 100644 --- a/autoload/node.vim +++ b/autoload/node.vim @@ -6,18 +6,18 @@ function! node#initialize(root) let b:node_root = a:root command! -bar -bang -nargs=1 -buffer -complete=customlist,s:complete Nedit - \ exe s:nedit(, bufname("%"), "edit") + \ exe s:nedit(, expand('%:p'), "edit") command! -bar -bang -nargs=1 -buffer -complete=customlist,s:complete Nopen - \ exe s:nopen(, bufname("%"), "edit") + \ exe s:nopen(, expand('%:p'), "edit") nnoremap NodeGotoFile - \ :call edit(expand(""), bufname("%")) + \ :call edit(expand(""), expand('%:p')) nnoremap NodeSplitGotoFile - \ :call edit(expand(""), bufname("%"), "split") + \ :call edit(expand(""), expand('%:p'), "split") nnoremap NodeVSplitGotoFile - \ :call edit(expand(""), bufname("%"), "vsplit") + \ :call edit(expand(""), expand('%:p'), "vsplit") nnoremap NodeTabGotoFile - \ :call edit(expand(""), bufname("%"), "tab split") + \ :call edit(expand(""), expand('%:p'), "tab split") silent doautocmd User Node endfunction @@ -30,7 +30,7 @@ function! node#javascript() setlocal path-=/usr/include let &l:suffixesadd .= "," . join(g:node#suffixesadd, ",") let &l:include = '\= 0, +" a. if PARTS[I] = "node_modules" CONTINUE +" b. DIR = path join(PARTS[0 .. I] + "node_modules") +" c. DIRS = DIRS + DIR +" d. let I = I - 1 +" 5. return DIRS +function! s:nodeModulePaths(start) + let parts = split(a:start, '/') + + " We want to keep the leading slash of an absolute path + if a:start =~# s:ABSPATH + let parts[0] = '/' . parts[0] + endif + + let i = len(parts) - 1 + let dirs = [] + while i >= 0 + if parts[i] == 'node_modules' | continue | endif + let dir = join(parts[0:i] + ['node_modules'], '/') + let dirs += [dir] + let i = i - 1 + endwhile + + " Add support for NODE_PATH + let NODE_PATH = $NODE_PATH + if !empty(NODE_PATH) + let dirs += [NODE_PATH] + endif + + return dirs +endfunction + +function! s:getModulePath(name, from) + if a:name =~# s:ABSPATH + return a:name + elseif a:name =~# s:RELPATH + let dir = isdirectory(a:from) ? a:from : s:dirname(a:from) + return dir . "/" . a:name + endif +endfunction + +function! s:dirname(path) + return fnamemodify(a:path, ':h') +endfunction + +function! node#lib#version() + if exists("b:node_version") | return b:node_version | endif + if !executable("node") | let b:node_version = "" | return | endif + let b:node_version = matchstr(system("node --version"), '^v\?\zs[0-9.]\+') + return b:node_version endfunction function! s:mainFromPackage(path) From 4b26392d3362aec321725a3ab629b01fae0a878b Mon Sep 17 00:00:00 2001 From: "Charles-P. Clermont" Date: Wed, 4 Apr 2018 11:38:15 -0400 Subject: [PATCH 2/6] Add .editorconfig and fixup mixed indentation --- .editorconfig | 15 ++++++ autoload/node/lib.vim | 122 +++++++++++++++++++++--------------------- 2 files changed, 76 insertions(+), 61 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..92a11b9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +#Config helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + +[*] +indent_style = tab +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/autoload/node/lib.vim b/autoload/node/lib.vim index 2591556..3ccd2c0 100644 --- a/autoload/node/lib.vim +++ b/autoload/node/lib.vim @@ -19,13 +19,13 @@ let s:CORE_MODULES = ["_debugger", "_http_agent", "_http_client", " " require(a:name) from module at path a:from " 1. If a:name is a core module, -" a. return the core module -" b. STOP +" a. return the core module +" b. STOP " 2. If a:name begins with '/' -" a. set a:from to be the filesystem root +" a. set a:from to be the filesystem root " 3. If a:name begins with './' or '/' or '../' -" a. LOAD_AS_FILE(a:from + a:name) -" b. LOAD_AS_DIRECTORY(a:from + a:name) +" a. LOAD_AS_FILE(a:from + a:name) +" b. LOAD_AS_DIRECTORY(a:from + a:name) " 4. LOAD_NODE_MODULES(a:name, dirname(a:from)) " 5. THROW "not found" function! node#lib#find(name, from) @@ -36,24 +36,24 @@ function! node#lib#find(name, from) return s:CORE_URL_PREFIX ."/". l:version ."/". l:dir ."/". a:name .".js" endif - let request = s:getModulePath(a:name, a:from) - if !empty(request) - let asFile = s:loadAsFile(request) - if !empty(asFile) | return asFile | endif + let request = s:getModulePath(a:name, a:from) + if !empty(request) + let asFile = s:loadAsFile(request) + if !empty(asFile) | return asFile | endif - let asDirectory = s:loadAsDirectory(request) - if !empty(asDirectory) | return asDirectory | endif - endif + let asDirectory = s:loadAsDirectory(request) + if !empty(asDirectory) | return asDirectory | endif + endif - let asNodeModule = s:loadNodeModules(a:name, s:dirname(a:from)) + let asNodeModule = s:loadNodeModules(a:name, s:dirname(a:from)) if !empty(asNodeModule) | return asNodeModule | endif endfunction " LOAD_AS_FILE(X) -" 1. If X is a file, load X as JavaScript text. STOP -" 2. If X.js is a file, load X.js as JavaScript text. STOP -" 3. If X.json is a file, parse X.json to a JavaScript Object. STOP -" 4. If X.node is a file, load X.node as binary addon. STOP +" 1. If X is a file, load X as JavaScript text. STOP +" 2. If X.js is a file, load X.js as JavaScript text. STOP +" 3. If X.json is a file, parse X.json to a JavaScript Object. STOP +" 4. If X.node is a file, load X.node as binary addon. STOP function! s:loadAsFile(path) if a:path !~# '\v/(\.\.?/?)?$' let path_with_suffix = s:resolveSuffix(a:path) @@ -62,19 +62,19 @@ function! s:loadAsFile(path) endfunction " LOAD_INDEX(X) -" 1. If X/index.js is a file, load X/index.js as JavaScript text. STOP +" 1. If X/index.js is a file, load X/index.js as JavaScript text. STOP " 2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP -" 3. If X/index.node is a file, load X/index.node as binary addon. STOP +" 3. If X/index.node is a file, load X/index.node as binary addon. STOP function! s:loadIndex(path) return s:resolveSuffix(a:path . "/index") endfunction " LOAD_AS_DIRECTORY(X) " 1. If X/package.json is a file, -" a. Parse X/package.json, and look for "main" field. -" b. let M = X + (json main field) -" c. LOAD_AS_FILE(M) -" d. LOAD_INDEX(M) +" a. Parse X/package.json, and look for "main" field. +" b. let M = X + (json main field) +" c. LOAD_AS_FILE(M) +" d. LOAD_INDEX(M) " 2. LOAD_INDEX(X) function! s:loadAsDirectory(path) " Node.js checks for package.json in every directory, not just the @@ -89,10 +89,10 @@ function! s:loadAsDirectory(path) if !empty(main) && main != "" let path = a:path . "/" . main - let asFile = s:loadAsFile(path) + let asFile = s:loadAsFile(path) if !empty(asFile) | return asFile | endif - let asIndex = s:loadIndex(path) + let asIndex = s:loadIndex(path) if !empty(asIndex) | return asIndex | endif endif endif @@ -103,18 +103,18 @@ endfunction " LOAD_NODE_MODULES(X, START) " 1. let DIRS=NODE_MODULES_PATHS(START) " 2. for each DIR in DIRS: -" a. LOAD_AS_FILE(DIR/X) -" b. LOAD_AS_DIRECTORY(DIR/X) +" a. LOAD_AS_FILE(DIR/X) +" b. LOAD_AS_DIRECTORY(DIR/X) function! s:loadNodeModules(x, start) - let dirs = s:nodeModulePaths(a:start) - for dir in dirs + let dirs = s:nodeModulePaths(a:start) + for dir in dirs let path = dir . "/" . a:x - let asFile = s:loadAsFile(path) + let asFile = s:loadAsFile(path) if !empty(asFile) | return asFile | endif - let asDirectory = s:loadAsDirectory(path) + let asDirectory = s:loadAsDirectory(path) if !empty(asDirectory) | return asDirectory | endif - endfor + endfor endfunction " NODE_MODULES_PATHS(START) @@ -122,35 +122,35 @@ endfunction " 2. let I = count of PARTS - 1 " 3. let DIRS = [] " 4. while I >= 0, -" a. if PARTS[I] = "node_modules" CONTINUE -" b. DIR = path join(PARTS[0 .. I] + "node_modules") -" c. DIRS = DIRS + DIR -" d. let I = I - 1 +" a. if PARTS[I] = "node_modules" CONTINUE +" b. DIR = path join(PARTS[0 .. I] + "node_modules") +" c. DIRS = DIRS + DIR +" d. let I = I - 1 " 5. return DIRS function! s:nodeModulePaths(start) - let parts = split(a:start, '/') - - " We want to keep the leading slash of an absolute path - if a:start =~# s:ABSPATH - let parts[0] = '/' . parts[0] - endif - - let i = len(parts) - 1 - let dirs = [] - while i >= 0 - if parts[i] == 'node_modules' | continue | endif - let dir = join(parts[0:i] + ['node_modules'], '/') - let dirs += [dir] - let i = i - 1 - endwhile - - " Add support for NODE_PATH - let NODE_PATH = $NODE_PATH - if !empty(NODE_PATH) - let dirs += [NODE_PATH] - endif - - return dirs + let parts = split(a:start, '/') + + " We want to keep the leading slash of an absolute path + if a:start =~# s:ABSPATH + let parts[0] = '/' . parts[0] + endif + + let i = len(parts) - 1 + let dirs = [] + while i >= 0 + if parts[i] == 'node_modules' | continue | endif + let dir = join(parts[0:i] + ['node_modules'], '/') + let dirs += [dir] + let i = i - 1 + endwhile + + " Add support for NODE_PATH + let NODE_PATH = $NODE_PATH + if !empty(NODE_PATH) + let dirs += [NODE_PATH] + endif + + return dirs endfunction function! s:getModulePath(name, from) @@ -159,11 +159,11 @@ function! s:getModulePath(name, from) elseif a:name =~# s:RELPATH let dir = isdirectory(a:from) ? a:from : s:dirname(a:from) return dir . "/" . a:name - endif + endif endfunction function! s:dirname(path) - return fnamemodify(a:path, ':h') + return fnamemodify(a:path, ':h') endfunction function! node#lib#version() From cc0f516f19650cc5a81a486bce188dc6c7791699 Mon Sep 17 00:00:00 2001 From: "Charles-P. Clermont" Date: Wed, 4 Apr 2018 11:46:12 -0400 Subject: [PATCH 3/6] Add support for g:vim_node#node_path --- autoload/node/lib.vim | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/autoload/node/lib.vim b/autoload/node/lib.vim index 3ccd2c0..7b887ab 100644 --- a/autoload/node/lib.vim +++ b/autoload/node/lib.vim @@ -150,6 +150,11 @@ function! s:nodeModulePaths(start) let dirs += [NODE_PATH] endif + " Add support for configured NODE_PATH + if !empty(g:vim_node#node_path) + let dirs += g:vim_node#node_path + endif + return dirs endfunction From cf5474921287cc884656f09616d08f774587afcf Mon Sep 17 00:00:00 2001 From: "Charles-P. Clermont" Date: Wed, 4 Apr 2018 11:46:59 -0400 Subject: [PATCH 4/6] Update README --- README.md | 7 +++++++ autoload/node.vim | 2 -- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7d63374..3903add 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,13 @@ autocmd User Node \ endif ``` +#### Want to resolve modules with a custom NODE_PATH? + +```vim +let g:vim_node#node_path = [$HOME.'/project/src', '/absolute/path'] +``` + +Or you can also start vim with the `NODE_PATH` environment variable set. License ------- diff --git a/autoload/node.vim b/autoload/node.vim index c020e3a..bc8171f 100644 --- a/autoload/node.vim +++ b/autoload/node.vim @@ -50,8 +50,6 @@ function! s:edit(name, from, ...) if empty(a:name) | return | endif let dir = isdirectory(a:from) ? a:from : fnamemodify(a:from, ":h") let command = a:0 == 1 ? a:1 : "edit" - - " If just a plain filename with no directory part, check if it exists: let path = node#lib#find(a:name, dir) if empty(path) From 911d0f510dbf0bb301e02b89bab7711341f24091 Mon Sep 17 00:00:00 2001 From: "Charles-P. Clermont" Date: Mon, 2 Sep 2019 12:43:53 -0400 Subject: [PATCH 5/6] Add suffix variable config --- autoload/node.vim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/autoload/node.vim b/autoload/node.vim index bc8171f..8b226f3 100644 --- a/autoload/node.vim +++ b/autoload/node.vim @@ -1,6 +1,8 @@ " Vim by default sets the filetype to JavaScript for the following suffices. " And, yes, it has .jsx there. -let node#suffixesadd = [".js", ".json", ".es", ".jsx"] +if !exists("node#suffixesadd") + let node#suffixesadd = [".js", ".json", ".es", ".jsx"] +endif function! node#initialize(root) let b:node_root = a:root From e83a52a718356ad1a271474ded6a20908be9926b Mon Sep 17 00:00:00 2001 From: "Charles-P. Clermont" Date: Mon, 2 Sep 2019 12:43:58 -0400 Subject: [PATCH 6/6] Resolve simlinks --- autoload/node/lib.vim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/autoload/node/lib.vim b/autoload/node/lib.vim index 7b887ab..0a6000a 100644 --- a/autoload/node/lib.vim +++ b/autoload/node/lib.vim @@ -39,14 +39,14 @@ function! node#lib#find(name, from) let request = s:getModulePath(a:name, a:from) if !empty(request) let asFile = s:loadAsFile(request) - if !empty(asFile) | return asFile | endif + if !empty(asFile) | return resolve(asFile) | endif let asDirectory = s:loadAsDirectory(request) - if !empty(asDirectory) | return asDirectory | endif + if !empty(asDirectory) | return resolve(asDirectory) | endif endif let asNodeModule = s:loadNodeModules(a:name, s:dirname(a:from)) - if !empty(asNodeModule) | return asNodeModule | endif + if !empty(asNodeModule) | return resolve(asNodeModule) | endif endfunction " LOAD_AS_FILE(X)