1
0
Fork 0
mirror of synced 2024-06-30 20:41:09 -04:00
ultimate-vim/sources_non_forked/vim-node/autoload/node/lib.vim
2014-06-13 21:52:19 +08:00

152 lines
5.1 KiB
VimL

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 = "http://rawgit.com/joyent/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"
return s:CORE_URL_PREFIX ."/". l:version ."/". l:dir ."/". a:name .".js"
endif
return s:resolve(s:absolutize(a:name, a:from))
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