mirror of
https://github.com/gryf/.vim.git
synced 2025-12-18 12:00:30 +01:00
Added omnicompletion and indentation for javascript (including node.js).
Added Windows configuration.
This commit is contained in:
File diff suppressed because one or more lines are too long
296
bundle/git_vim-nodejs-complete/after/autoload/nodejscomplete.vim
Normal file
296
bundle/git_vim-nodejs-complete/after/autoload/nodejscomplete.vim
Normal file
@@ -0,0 +1,296 @@
|
||||
" Vim completion script
|
||||
" Language: Javascript(node)
|
||||
" Maintainer: Lin Zhang ( myhere.2009 AT gmail DOT com )
|
||||
" Last Change: 2012-8-18 1:32:00
|
||||
|
||||
" save current dir
|
||||
let s:nodejs_doc_file = expand('<sfile>:p:h') . '/nodejs-doc.vim'
|
||||
|
||||
function! nodejscomplete#CompleteJS(findstart, base)
|
||||
if a:findstart
|
||||
if exists('g:node_usejscomplete') && g:node_usejscomplete
|
||||
let start = jscomplete#CompleteJS(a:findstart, a:base)
|
||||
else
|
||||
let start = javascriptcomplete#CompleteJS(a:findstart, a:base)
|
||||
endif
|
||||
|
||||
" complete context
|
||||
let line = getline('.')
|
||||
let b:nodecompl_context = line[0:start-1]
|
||||
"Decho 'start: ' . start
|
||||
return start
|
||||
else
|
||||
let nodeCompl = s:findNodeComplete(a:base)
|
||||
if exists('g:node_usejscomplete') && g:node_usejscomplete
|
||||
let jsCompl = jscomplete#CompleteJS(a:findstart, a:base)
|
||||
else
|
||||
let jsCompl = javascriptcomplete#CompleteJS(a:findstart, a:base)
|
||||
endif
|
||||
|
||||
return nodeCompl + jsCompl
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
" complete node's build-in module
|
||||
function! s:findNodeComplete(base)
|
||||
" get complete context
|
||||
let context = b:nodecompl_context
|
||||
unlet b:nodecompl_context
|
||||
|
||||
"Decho 'context: ' . context
|
||||
"Decho 'base: ' . a:base
|
||||
|
||||
let ret = []
|
||||
|
||||
" get object name
|
||||
let obj_name = matchstr(context, '\k\+\ze\.$')
|
||||
|
||||
if (len(obj_name) == 0) " variable complete
|
||||
let ret = s:getVariableComplete(context, a:base)
|
||||
else " module complete
|
||||
"Decho 'obj_name: ' . obj_name
|
||||
|
||||
" get variable declared line number
|
||||
let decl_line = search(obj_name . '\s*=\s*require\s*(.\{-})', 'bn')
|
||||
"Decho 'decl_line: ' . decl_line
|
||||
|
||||
if (decl_line == 0)
|
||||
" maybe a global module
|
||||
let ret = s:getModuleComplete(obj_name, a:base, 'globals')
|
||||
else
|
||||
" find the node module name
|
||||
let mod_name = matchstr(getline(decl_line), obj_name . '\s*=\s*require\s*(\s*\([''"]\)\zs.\{-}\ze\(\1\)\s*)')
|
||||
|
||||
if exists('mod_name')
|
||||
let ret = s:getModuleComplete(mod_name, a:base, 'modules')
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:getModuleComplete(mod_name, prop_name, type)
|
||||
"Decho 'mod_name: ' . a:mod_name
|
||||
"Decho 'prop_name: ' . a:prop_name
|
||||
"Decho 'type: ' . a:type
|
||||
|
||||
call s:loadNodeDocData()
|
||||
|
||||
let ret = []
|
||||
let mods = {}
|
||||
let mod = []
|
||||
|
||||
if (has_key(g:nodejs_complete_data, a:type))
|
||||
let mods = g:nodejs_complete_data[a:type]
|
||||
endif
|
||||
|
||||
if (has_key(mods, a:mod_name))
|
||||
let mod = mods[a:mod_name]
|
||||
endif
|
||||
|
||||
" no prop_name suplied
|
||||
if (len(a:prop_name) == 0)
|
||||
let ret = mod
|
||||
else
|
||||
" filter properties with prop_name
|
||||
let ret = filter(copy(mod), 'v:val["word"] =~# "' . a:prop_name . '"')
|
||||
endif
|
||||
"Decho string(ret)
|
||||
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:getVariableComplete(context, var_name)
|
||||
"Decho 'var_name: ' . a:var_name
|
||||
|
||||
" complete require's arguments
|
||||
let matched = matchlist(a:context, 'require\s*(\s*\%(\([''"]\)\(\.\{1,2}.*\)\=\)\=$')
|
||||
if (len(matched) > 0)
|
||||
"Decho 'require: ' . string(matched)
|
||||
|
||||
if (len(matched[2]) > 0) " complete -> require('./
|
||||
let mod_names = s:getModuleInCurrentDir(a:context, a:var_name, matched)
|
||||
else
|
||||
let mod_names = s:getModuleNames()
|
||||
|
||||
if (len(matched[1]) == 0) " complete -> require(
|
||||
call map(mod_names, '"''" . v:val . "'')"')
|
||||
elseif (len(a:var_name) == 0) " complete -> require('
|
||||
call map(mod_names, 'v:val . "' . escape(matched[1], '"') . ')"')
|
||||
else " complete -> require('ti
|
||||
let mod_names = filter(mod_names, 'v:val =~# "^' . a:var_name . '"')
|
||||
call map(mod_names, 'v:val . "' . escape(matched[1], '"') . ')"')
|
||||
endif
|
||||
endif
|
||||
|
||||
return mod_names
|
||||
endif
|
||||
|
||||
" complete global variables
|
||||
let vars = []
|
||||
if (len(a:var_name) == 0)
|
||||
return vars
|
||||
endif
|
||||
|
||||
call s:loadNodeDocData()
|
||||
|
||||
if (has_key(g:nodejs_complete_data, 'vars'))
|
||||
let vars = g:nodejs_complete_data.vars
|
||||
endif
|
||||
|
||||
let ret = filter(copy(vars), 'v:val["word"] =~# "^' . a:var_name . '"')
|
||||
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! s:getModuleInCurrentDir(context, var_name, matched)
|
||||
let mod_names = []
|
||||
let path = a:matched[2] . a:var_name
|
||||
|
||||
" typed as require('..
|
||||
" complete as require('../
|
||||
" cause the latter one is more common
|
||||
let compl_prefix = ''
|
||||
if (path =~# '\.\.$')
|
||||
let compl_prefix = '/'
|
||||
let path = path . compl_prefix
|
||||
endif
|
||||
|
||||
"Decho 'path: ' . path
|
||||
|
||||
let current_dir = expand('%:p:h')
|
||||
let glob_path = current_dir . '/' . path . '*'
|
||||
let files = s:fuzglob(glob_path)
|
||||
"Decho 'glob: ' . glob_path
|
||||
"Decho 'current dir files: ' . string(files)
|
||||
for file in files
|
||||
" not '.' and '..'
|
||||
if ((isdirectory(file) ) || file =~? '\.json$\|\.js$')
|
||||
let mod_file = file
|
||||
" directory
|
||||
if (file !~? '\.json$\|\.js$')
|
||||
let mod_file = mod_file . '/'
|
||||
endif
|
||||
|
||||
" get complete word
|
||||
let mod_file = substitute(mod_file, '\', '/', 'g')
|
||||
let start = len(glob_path) - 1 " substract character '*'
|
||||
let compl_infix = strpart(mod_file, start)
|
||||
"Decho 'idx: ' . start
|
||||
"Decho 'compl_infix: ' . compl_infix
|
||||
"Decho 'relative file: ' . mod_file
|
||||
|
||||
let mod_name = compl_prefix . a:var_name . compl_infix
|
||||
" file module, not a directory
|
||||
if (compl_infix !~# '/$')
|
||||
let mod_name = mod_name . a:matched[1] . ')'
|
||||
endif
|
||||
|
||||
"Decho 'mod_name: ' . mod_name
|
||||
call add(mod_names, mod_name)
|
||||
endif
|
||||
endfor
|
||||
|
||||
"Decho 'relative path: ' . path
|
||||
|
||||
return mod_names
|
||||
endfunction
|
||||
|
||||
function! s:getModuleNames()
|
||||
call s:loadNodeDocData()
|
||||
|
||||
let mod_names = []
|
||||
|
||||
" build-in module name
|
||||
if (has_key(g:nodejs_complete_data, 'modules'))
|
||||
let mod_names = keys(g:nodejs_complete_data.modules)
|
||||
endif
|
||||
|
||||
|
||||
" find module in 'module_dir' folder
|
||||
if (!exists('b:npm_module_names'))
|
||||
let current_dir = expand('%:p:h')
|
||||
|
||||
let b:npm_module_names = s:getModuleNamesInNode_modulesFolder(current_dir)
|
||||
endif
|
||||
|
||||
let mod_names = mod_names + b:npm_module_names
|
||||
|
||||
return sort(mod_names)
|
||||
endfunction
|
||||
|
||||
function! s:getModuleNamesInNode_modulesFolder(current_dir)
|
||||
" ensure platform coincidence
|
||||
let base_dir = substitute(a:current_dir, '\', '/', 'g')
|
||||
"Decho 'base_dir: ' . base_dir
|
||||
|
||||
let ret = []
|
||||
|
||||
let parts = split(base_dir, '/', 1)
|
||||
"Decho 'parts: ' . string(parts)
|
||||
let idx = 0
|
||||
let len = len(parts)
|
||||
let sub_parts = []
|
||||
while idx < len
|
||||
let sub_parts = add(sub_parts, parts[idx])
|
||||
let module_dir = join(sub_parts, '/') . '/node_modules'
|
||||
"Decho 'directory: ' . module_dir
|
||||
|
||||
if (isdirectory(module_dir))
|
||||
let files = s:fuzglob(module_dir . '/*')
|
||||
"Decho 'node_module files: ' . string(files)
|
||||
for file in files
|
||||
if (isdirectory(file) || file =~? '\.json$\|\.js$')
|
||||
let mod_name = matchstr(file, '[^/\\]\+$')
|
||||
let ret = add(ret, mod_name)
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
|
||||
let idx = idx + 1
|
||||
endwhile
|
||||
|
||||
"Decho 'npm modules: ' . string(ret)
|
||||
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! s:loadNodeDocData()
|
||||
" load node module data
|
||||
if (!exists('g:nodejs_complete_data'))
|
||||
" load data from external file
|
||||
let filename = s:nodejs_doc_file
|
||||
"Decho 'filename: ' . filename
|
||||
if (filereadable(filename))
|
||||
"Decho 'readable'
|
||||
execute 'so ' . filename
|
||||
"Decho string(g:nodejs_complete_data)
|
||||
else
|
||||
"Decho 'not readable'
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" copied from FuzzyFinder/autoload/fuf.vim
|
||||
" returns list of paths.
|
||||
" An argument for glob() is normalized in order to avoid a bug on Windows.
|
||||
function! s:fuzglob(expr)
|
||||
" Substitutes "\", because on Windows, "**\" doesn't include ".\",
|
||||
" but "**/" include "./". I don't know why.
|
||||
return split(glob(substitute(a:expr, '\', '/', 'g')), "\n")
|
||||
endfunction
|
||||
|
||||
|
||||
"
|
||||
" use plugin Decho(https://github.com/vim-scripts/Decho) for debug
|
||||
"
|
||||
" turn off debug mode
|
||||
" :%s;^\(\s*\)\(Decho\);\1"\2;g
|
||||
"
|
||||
" turn on debug mode
|
||||
" :%s;^\(\s*\)"\(Decho\);\1\2;g
|
||||
"
|
||||
@@ -0,0 +1,283 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* @author: Lin Zhang ( myhere.2009 AT gmail DOT com )
|
||||
* @fileoverview: This script for auto-generate nodejs-doc.vim
|
||||
*/
|
||||
|
||||
var util = require('util'),
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
os = require('os'),
|
||||
emitter = new (require('events')).EventEmitter();
|
||||
|
||||
init();
|
||||
|
||||
function init() {
|
||||
initEvents();
|
||||
|
||||
initLoading();
|
||||
|
||||
getNodejsDoc();
|
||||
}
|
||||
|
||||
function initEvents() {
|
||||
// uncatched exception
|
||||
process.on('uncaughtException', function(err) {
|
||||
clearLoading();
|
||||
|
||||
console.error('Error: ' + err.stack);
|
||||
});
|
||||
|
||||
emitter.on('vimscript/done', function(message) {
|
||||
clearLoading();
|
||||
console.log(message);
|
||||
console.log('Done!');
|
||||
});
|
||||
}
|
||||
|
||||
function initLoading() {
|
||||
var chars = [
|
||||
'-',
|
||||
'\\',
|
||||
'|',
|
||||
'/'
|
||||
];
|
||||
|
||||
var index = 0,
|
||||
total = chars.length;
|
||||
|
||||
initLoading.timer = setInterval(function() {
|
||||
index = ++index % total;
|
||||
|
||||
var c = chars[index];
|
||||
|
||||
// clear console
|
||||
// @see: https://groups.google.com/forum/?fromgroups#!topic/nodejs/i-oqYFVty5I
|
||||
process.stdout.write('\033[2J\033[0;0H');
|
||||
console.log('please wait:');
|
||||
console.log(c);
|
||||
}, 200);
|
||||
}
|
||||
function clearLoading() {
|
||||
clearInterval(initLoading.timer);
|
||||
}
|
||||
|
||||
function getNodejsDoc() {
|
||||
var http = require('http');
|
||||
|
||||
var req = http.get('http://nodejs.org/api/all.json', function(res){
|
||||
var chunks = [];
|
||||
|
||||
res.on('data', function(chunk) {
|
||||
chunks.push(chunk);
|
||||
});
|
||||
|
||||
res.on('end', function() {
|
||||
var buf = Buffer.concat(chunks),
|
||||
body = buf.toString('utf-8');
|
||||
|
||||
extract2VimScript(body);
|
||||
});
|
||||
}).on('error', function(e) {
|
||||
console.error('problem with request: ' + e.message);
|
||||
});
|
||||
}
|
||||
|
||||
function extract2VimScript(body) {
|
||||
// for debug
|
||||
fs.writeFileSync('./nodejs-doc-all.json', body);
|
||||
var json = JSON.parse(body),
|
||||
vimObject;
|
||||
|
||||
var _globals = sortModuleByName(mergeObject(getModInfo(json.globals), getModInfo(json.vars))),
|
||||
_moduels = sortModuleByName(getModInfo(json.modules)),
|
||||
_vars = (getVarInfo(json.vars)).concat(getVarInfo(json.globals)).sort(sortCompleteWord);
|
||||
|
||||
vimObject = {
|
||||
'globals': _globals,
|
||||
'modules': _moduels,
|
||||
'vars': _vars
|
||||
};
|
||||
|
||||
|
||||
var filename = path.join(__dirname, 'nodejs-doc.vim'),
|
||||
comment = '" this file is auto created by "' + __filename + '", please do not edit it yourself!',
|
||||
content = 'let g:nodejs_complete_data = ' + JSON.stringify(vimObject),
|
||||
|
||||
content = comment + os.EOL + content;
|
||||
|
||||
fs.writeFile(filename, content, function(err) {
|
||||
emitter.emit('vimscript/done', 'write file to "' + filename + '" complete.');
|
||||
});
|
||||
|
||||
// for debug
|
||||
fs.writeFileSync(filename + '.js', JSON.stringify(vimObject, null, 2));
|
||||
}
|
||||
|
||||
function getModInfo(mods) {
|
||||
var ret = {};
|
||||
if (!util.isArray(mods)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
mods.forEach(function(mod) {
|
||||
var list = [];
|
||||
|
||||
// methods
|
||||
var methods = mod.methods || [];
|
||||
methods.forEach(function(method) {
|
||||
var item = {};
|
||||
if (method.type == 'method') {
|
||||
item.word = method.name + '(';
|
||||
item.info = method.textRaw;
|
||||
item.kind = 'f'
|
||||
|
||||
list.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
// properties
|
||||
var properties = mod.properties || [];
|
||||
properties.forEach(function(property) {
|
||||
var item = {};
|
||||
item.word = property.name;
|
||||
item.kind = 'm'
|
||||
|
||||
list.push(item);
|
||||
});
|
||||
|
||||
// if empty
|
||||
if (list.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// sort items
|
||||
list = list.sort(sortCompleteWord);
|
||||
|
||||
|
||||
// module name
|
||||
var mod_name = mod.name;
|
||||
// invalid module name like 'tls_(ssl)'
|
||||
// then guess the module name from textRaw 'TLS (SSL)'
|
||||
if ((/[^_a-z\d\$]/i).test(mod_name)) {
|
||||
var textRaw = mod.textRaw;
|
||||
var matched = textRaw.match(/^[_a-z\d\$]+/i);
|
||||
if (matched) {
|
||||
var mod_name_len = matched[0].length;
|
||||
mod_name = mod_name.substr(0, mod_name_len);
|
||||
}
|
||||
}
|
||||
|
||||
ret[mod_name] = list;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function getVarInfo(vars) {
|
||||
var ret = [];
|
||||
if (!util.isArray(vars)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
vars.forEach(function(_var) {
|
||||
// if var is a function
|
||||
if ((/\([^\(\)]*\)\s*$/).test(_var.textRaw)) {
|
||||
ret.push({
|
||||
word: _var.name + '(',
|
||||
info: _var.textRaw,
|
||||
kind: 'f'
|
||||
});
|
||||
} else {
|
||||
ret.push({
|
||||
word: _var.name,
|
||||
kind: 'v'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// sort
|
||||
ret = ret.sort(sortCompleteWord);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// helpers
|
||||
/**
|
||||
* @param {Object}
|
||||
*/
|
||||
function sortModuleByName(mods) {
|
||||
var keys = Object.keys(mods);
|
||||
// sort
|
||||
keys.sort();
|
||||
|
||||
var ret = {};
|
||||
keys.forEach(function(k) {
|
||||
ret[k] = mods[k];
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object}
|
||||
* @param {Object}
|
||||
*/
|
||||
function sortCompleteWord(a, b) {
|
||||
var a_w = a.word.toLowerCase(),
|
||||
b_w = b.word.toLowerCase();
|
||||
|
||||
return a_w < b_w ? -1 : (a_w > b_w ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc merge Object
|
||||
* @arguemnts: {Object}
|
||||
*
|
||||
* @return: return the new merged Object
|
||||
*/
|
||||
function mergeObject() {
|
||||
var ret = {},
|
||||
args = Array.prototype.slice.call(arguments);
|
||||
|
||||
args.forEach(function(obj) {
|
||||
for (var p in obj) {
|
||||
if (obj.hasOwnProperty(p)) {
|
||||
ret[p] = obj[p];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*************** code below for test ***************
|
||||
|
||||
// require complete
|
||||
var fs = req
|
||||
var http = require(
|
||||
var util = require('u
|
||||
var m1 = require('..
|
||||
var m1 = require('../
|
||||
var m2 = require('../auto
|
||||
var m4 = require('.
|
||||
var m3 = require('./
|
||||
var m3 = require('./node
|
||||
|
||||
|
||||
// module methdo complete
|
||||
var fs = require('fs');
|
||||
fs.
|
||||
fs.writ
|
||||
|
||||
|
||||
// global variable complete
|
||||
var filename = __
|
||||
mo
|
||||
cons
|
||||
console.l
|
||||
|
||||
***************************************************/
|
||||
@@ -0,0 +1,3 @@
|
||||
if exists('&ofu')
|
||||
setlocal omnifunc=nodejscomplete#CompleteJS
|
||||
endif
|
||||
Reference in New Issue
Block a user