diff options
Diffstat (limited to '.vim/autoload/node')
-rw-r--r-- | .vim/autoload/node/lib.vim | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/.vim/autoload/node/lib.vim b/.vim/autoload/node/lib.vim new file mode 100644 index 0000000..1c7a8c1 --- /dev/null +++ b/.vim/autoload/node/lib.vim @@ -0,0 +1,153 @@ +let s:ABSPATH = '^/' +let s:RELPATH = '\v^\.\.?(/|$)' +let s:MODULE = '\v^(/|\.\.?(/|$))@!' + +" Damn Netrw can't handle HTTPS at all. It's 2013! Insecure bastard! +let s:CORE_URL_PREFIX = "https://rawgit.com/nodejs/node" +let s:CORE_MODULES = ["_debugger", "_http_agent", "_http_client", + \ "_http_common", "_http_incoming", "_http_outgoing", "_http_server", + \ "_linklist", "_stream_duplex", "_stream_passthrough", "_stream_readable", + \ "_stream_transform", "_stream_writable", "_tls_legacy", "_tls_wrap", + \ "assert", "buffer", "child_process", "cluster", "console", "constants", + \ "crypto", "dgram", "dns", "domain", "events", "freelist", "fs", "http", + \ "https", "module", "net", "node", "os", "path", "punycode", "querystring", + \ "readline", "repl", "smalloc", "stream", "string_decoder", "sys", + \ "timers", "tls", "tty", "url", "util", "vm", "zlib"] + +function! node#lib#find(name, from) + if index(s:CORE_MODULES, a:name) != -1 + let l:version = node#lib#version() + let l:version = empty(l:version) ? "master" : "v" . l:version + let l:dir = a:name == "node" ? "src" : "lib" + let l:url = get(g:, "node_repository_url", s:CORE_URL_PREFIX) + return l:url ."/". l:version ."/". l:dir ."/". a:name .".js" + endif + + let l:path = s:resolve(s:absolutize(a:name, a:from)) + if !empty(path) | return fnamemodify(resolve(path), ":.") | endif +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:absolutize(name, from) + if a:name =~# s:ABSPATH + return a:name + elseif a:name =~# s:RELPATH + let dir = isdirectory(a:from) ? a:from : fnamemodify(a:from, ":h") + return dir . "/" . a:name + else + return b:node_root . "/node_modules/" . a:name + endif +endfunction + +function! s:resolve(path) + " Node checks for files *before* directories, so see if the path does not + " end with a slash or dots and try to match it as a file. + if a:path !~# '\v/(\.\.?/?)?$' + let path_with_suffix = s:resolveSuffix(a:path) + if !empty(path_with_suffix) | return path_with_suffix | endif + endif + + if isdirectory(a:path) | return s:resolveFromDirectory(a:path) | endif +endfunction + +function! s:resolveFromDirectory(path) + " Node.js checks for package.json in every directory, not just the + " module's parent. According to: + " http://nodejs.org/api/modules.html#modules_all_together + if filereadable(a:path . "/package.json") + " Turns out, even though Node says it does not support directories in + " main, it does. + " NOTE: If package.json's main is empty or refers to a non-existent file, + " ./index.js is still tried. + let main = s:mainFromPackage(a:path . "/package.json") + + if !empty(main) && main != "" + let path = s:resolve(a:path . "/" . main) + if !empty(path) | return path | endif + endif + endif + + " We need to check for ./index.js's existence here rather than leave it to + " the caller, because otherwise we can't distinguish if this ./index was + " from the directory defaulting to ./index.js or it was the package.json + " which referred to ./index, which in itself could mean both ./index.js and + " ./index/index.js. + return s:resolveSuffix(a:path . "/index") +endfunction + +function! s:mainFromPackage(path) + for line in readfile(a:path) + if line !~# '"main"\s*:' | continue | endif + return matchstr(line, '"main"\s*:\s*"\zs[^"]\+\ze"') + endfor +endfunction + +function! s:resolveSuffix(path) + for suffix in s:uniq([""] + g:node#suffixesadd + split(&l:suffixesadd, ",")) + let path = a:path . suffix + if filereadable(path) | return path | endif + endfor +endfunction + +let s:GLOB_WILDIGNORE = 1 + +function! node#lib#glob(name) + let matches = [] + + if empty(a:name) + let matches += s:CORE_MODULES + endif + + if empty(a:name) || a:name =~# s:MODULE + let root = b:node_root . "/node_modules" + let matches += s:glob(empty(a:name) ? root : root . "/" . a:name, root) + endif + + if a:name =~# s:ABSPATH + let matches += s:glob(a:name, 0) + endif + + if empty(a:name) || a:name =~# s:RELPATH + let root = b:node_root + let relatives = s:glob(empty(a:name) ? root : root . "/" . a:name, root) + + "call map(relatives, "substitute(v:val, '^\./\./', './', '')") + if empty(a:name) | call map(relatives, "'./' . v:val") | endif + call filter(relatives, "v:val !~# '^\\.//*node_modules/$'") + + let matches += relatives + endif + + return matches +endfunction + +function! s:glob(path, stripPrefix) + " Remove a single trailing slash because we're adding one with the glob. + let path = substitute(a:path, '/$', "", "") + " Glob() got the ability to return a list only in Vim 7.3.465. Using split + " for compatibility. + let list = split(glob(fnameescape(path)."/*", s:GLOB_WILDIGNORE), "\n") + + " Add slashes to directories, like /bin/ls. + call map(list, "v:val . (isdirectory(v:val) ? '/' : '')") + + if !empty(a:stripPrefix) + " Counting and removing bytes intentionally as there's no substr function + " that takes character count, only bytes. + let prefix_length = len(a:stripPrefix) + 1 + return map(list, "strpart(v:val, prefix_length)") + endif + + return list +endfunction + +function! s:uniq(list) + let list = reverse(copy(a:list)) + return reverse(filter(list, "index(list, v:val, v:key + 1) == -1")) +endfunction |