diff --git a/autoload/SpaceVim/health/environment.vim b/autoload/SpaceVim/health/environment.vim index 512a24557..7053ba9f4 100644 --- a/autoload/SpaceVim/health/environment.vim +++ b/autoload/SpaceVim/health/environment.vim @@ -11,7 +11,7 @@ function! SpaceVim#health#environment#check() abort " for getting the progpath of current vim. call add(result, 'Current progpath: ' . v:progname . '(' . get(v:, 'progpath', '') . ')') call add(result, 'version: ' . v:version) - call add(result, 'OS: ' . SpaceVim#api#import('system').name) + call add(result, 'OS: ' . SpaceVim#api#import('system').name()) call add(result, '[shell, shellcmdflag, shellslash]: ' . string([&shell, &shellcmdflag, &shellslash])) return result endfunction diff --git a/autoload/SpaceVim/logger.vim b/autoload/SpaceVim/logger.vim index fe6c9353d..b6048f781 100644 --- a/autoload/SpaceVim/logger.vim +++ b/autoload/SpaceVim/logger.vim @@ -6,143 +6,192 @@ " License: GPLv3 "============================================================================= -let s:LOGGER = SpaceVim#api#import('logger') +if get(g:, 'spacevim_use_lua', 0) + function! SpaceVim#logger#info(msg) abort + lua require("spacevim.logger").info( + \ require("spacevim").eval("a:msg") + \ ) + endfunction -call s:LOGGER.set_name('SpaceVim') -call s:LOGGER.set_level(get(g:, 'spacevim_debug_level', 1)) -call s:LOGGER.set_silent(1) -call s:LOGGER.set_verbose(1) - -function! SpaceVim#logger#info(msg) abort - - call s:LOGGER.info(a:msg) - -endfunction - -function! SpaceVim#logger#warn(msg, ...) abort - let issilent = get(a:000, 0, 1) - call s:LOGGER.warn(a:msg, issilent) -endfunction + function! SpaceVim#logger#warn(msg, ...) abort + let issilent = get(a:000, 0, 1) + lua require("spacevim.logger").warn( + \ require("spacevim").eval("a:msg"), + \ require("spacevim").eval("issilent") + \ ) + endfunction -function! SpaceVim#logger#error(msg) abort + function! SpaceVim#logger#error(msg) abort + lua require("spacevim.logger").error( + \ require("spacevim").eval("a:msg") + \ ) + endfunction - call s:LOGGER.error(a:msg) + function! SpaceVim#logger#debug(msg) abort + lua require("spacevim.logger").debug( + \ require("spacevim").eval("a:msg") + \ ) + endfunction -endfunction - -function! SpaceVim#logger#viewRuntimeLog() abort - let info = "### SpaceVim runtime log :\n\n" - let info .= "```log\n" - - let info .= s:LOGGER.view(s:LOGGER.level) - - let info .= "\n```\n" - tabnew +setl\ nobuflisted - nnoremap q :tabclose! - for msg in split(info, "\n") - call append(line('$'), msg) - endfor - normal! "_dd - setl nomodifiable - setl buftype=nofile - setl filetype=markdown - call s:syntax_extra() -endfunction + function! SpaceVim#logger#viewRuntimeLog() abort + lua require("spacevim.logger").viewRuntimeLog() + endfunction -function! SpaceVim#logger#viewLog(...) abort - let info = "
SpaceVim debug information \n\n" - let info .= "### SpaceVim options :\n\n" - let info .= "```toml\n" - let info .= join(SpaceVim#options#list(), "\n") - let info .= "\n```\n" - let info .= "\n\n" + function! SpaceVim#logger#viewLog(...) abort + let bang = get(a:000, 0, 0) + return luaeval('require("spacevim.logger").viewLog(require("spacevim").eval("bang"))') + endfunction - let info .= "### SpaceVim layers :\n\n" - let info .= SpaceVim#layers#report() - let info .= "\n\n" + function! SpaceVim#logger#setLevel(level) abort + lua require("spacevim.logger").setLevel(require("spacevim").eval("a:level")) + endfunction - let info .= "### SpaceVim Health checking :\n\n" - let info .= SpaceVim#health#report() - let info .= "\n\n" + function! SpaceVim#logger#setOutput(file) abort + lua require("spacevim.logger").setOutput(require("spacevim").eval("a:file")) + endfunction - let info .= "### SpaceVim runtime log :\n\n" - let info .= "```log\n" + function! SpaceVim#logger#derive(name) abort + return luaeval('require("spacevim.logger").derive(require("spacevim").eval("a:name"))') + endfunction +else + let s:LOGGER = SpaceVim#api#import('logger') - let info .= s:LOGGER.view(s:LOGGER.level) + call s:LOGGER.set_name('SpaceVim') + call s:LOGGER.set_level(get(g:, 'spacevim_debug_level', 1)) + call s:LOGGER.set_silent(1) + call s:LOGGER.set_verbose(1) - let info .= "\n```\n
\n\n" - if a:0 > 0 - if a:1 == 1 - tabnew +setl\ nobuflisted - nnoremap q :bd! - for msg in split(info, "\n") - call append(line('$'), msg) - endfor - normal! "_dd - setl nomodifiable - setl buftype=nofile - setl filetype=markdown + function! SpaceVim#logger#info(msg) abort + + call s:LOGGER.info(a:msg) + + endfunction + + function! SpaceVim#logger#warn(msg, ...) abort + let issilent = get(a:000, 0, 1) + call s:LOGGER.warn(a:msg, issilent) + endfunction + + + function! SpaceVim#logger#error(msg) abort + + call s:LOGGER.error(a:msg) + + endfunction + + function! SpaceVim#logger#viewRuntimeLog() abort + let info = "### SpaceVim runtime log :\n\n" + let info .= "```log\n" + + let info .= s:LOGGER.view(s:LOGGER.level) + + let info .= "\n```\n" + tabnew +setl\ nobuflisted + nnoremap q :tabclose! + for msg in split(info, "\n") + call append(line('$'), msg) + endfor + normal! "_dd + setl nomodifiable + setl buftype=nofile + endfunction + + + function! SpaceVim#logger#viewLog(...) abort + let info = "
SpaceVim debug information \n\n" + let info .= "### SpaceVim options :\n\n" + let info .= "```toml\n" + let info .= join(SpaceVim#options#list(), "\n") + let info .= "\n```\n" + let info .= "\n\n" + + let info .= "### SpaceVim layers :\n\n" + let info .= SpaceVim#layers#report() + let info .= "\n\n" + + let info .= "### SpaceVim Health checking :\n\n" + let info .= SpaceVim#health#report() + let info .= "\n\n" + + let info .= "### SpaceVim runtime log :\n\n" + let info .= "```log\n" + + let info .= s:LOGGER.view(s:LOGGER.level) + + let info .= "\n```\n
\n\n" + if a:0 > 0 + if a:1 == 1 + tabnew +setl\ nobuflisted + nnoremap q :bd! + for msg in split(info, "\n") + call append(line('$'), msg) + endfor + normal! "_dd + setl nomodifiable + setl buftype=nofile + setl filetype=markdown + else + echo info + endif else - echo info + return info endif - else - return info - endif -endfunction + endfunction -function! s:syntax_extra() abort - call matchadd('ErrorMsg','.*[\sError\s\].*') - call matchadd('WarningMsg','.*[\sWarn\s\].*') -endfunction + function! s:syntax_extra() abort + call matchadd('ErrorMsg','.*[\sError\s\].*') + call matchadd('WarningMsg','.*[\sWarn\s\].*') + endfunction -"" -" @public -" Set debug level of SpaceVim. Default is 1. -" -" 1 : log all messages -" -" 2 : log warning and error messages -" -" 3 : log error messages only -function! SpaceVim#logger#setLevel(level) abort - call s:LOGGER.set_level(a:level) -endfunction + "" + " @public + " Set debug level of SpaceVim. Default is 1. + " + " 1 : log all messages + " + " 2 : log warning and error messages + " + " 3 : log error messages only + function! SpaceVim#logger#setLevel(level) abort + call s:LOGGER.set_level(a:level) + endfunction -"" -" @public -" Set the log output file of SpaceVim. Default is empty. -function! SpaceVim#logger#setOutput(file) abort - call s:LOGGER.set_file(a:file) -endfunction + "" + " @public + " Set the log output file of SpaceVim. Default is empty. + function! SpaceVim#logger#setOutput(file) abort + call s:LOGGER.set_file(a:file) + endfunction -" derive a logger for built-in plugins -" [ name ] [11:31:26] [ Info ] log message here + " derive a logger for built-in plugins + " [ name ] [11:31:26] [ Info ] log message here -let s:derive = {} -let s:derive.origin_name = s:LOGGER.get_name() + let s:derive = {} + let s:derive.origin_name = s:LOGGER.get_name() -function! s:derive.info(msg) abort - call s:LOGGER.set_name(self.derive_name) - call s:LOGGER.info(a:msg) - call s:LOGGER.set_name(self.origin_name) -endfunction + function! s:derive.info(msg) abort + call s:LOGGER.set_name(self.derive_name) + call s:LOGGER.info(a:msg) + call s:LOGGER.set_name(self.origin_name) + endfunction -function! s:derive.warn(msg) abort - call s:LOGGER.set_name(self.derive_name) - call s:LOGGER.warn(a:msg) - call s:LOGGER.set_name(self.origin_name) -endfunction + function! s:derive.warn(msg) abort + call s:LOGGER.set_name(self.derive_name) + call s:LOGGER.warn(a:msg) + call s:LOGGER.set_name(self.origin_name) + endfunction -function! s:derive.error(msg) abort - call s:LOGGER.set_name(self.derive_name) - call s:LOGGER.error(a:msg) - call s:LOGGER.set_name(self.origin_name) -endfunction + function! s:derive.error(msg) abort + call s:LOGGER.set_name(self.derive_name) + call s:LOGGER.error(a:msg) + call s:LOGGER.set_name(self.origin_name) + endfunction -function! SpaceVim#logger#derive(name) abort - let s:derive.derive_name = printf('%' . strdisplaywidth(s:LOGGER.get_name()) . 'S', a:name) - return deepcopy(s:derive) -endfunction + function! SpaceVim#logger#derive(name) abort + let s:derive.derive_name = printf('%' . strdisplaywidth(s:LOGGER.get_name()) . 'S', a:name) + return deepcopy(s:derive) + endfunction +endif diff --git a/autoload/SpaceVim/plugins/a.vim b/autoload/SpaceVim/plugins/a.vim index 209f3c34c..ab0f8e6a7 100644 --- a/autoload/SpaceVim/plugins/a.vim +++ b/autoload/SpaceVim/plugins/a.vim @@ -11,223 +11,254 @@ set cpo&vim scriptencoding utf-8 -" Load SpaceVim API +if get(g:, 'spacevim_use_lua', 0) + function! SpaceVim#plugins#a#alt(request_parse, ...) abort + lua require("spacevim.plugin.a").alt( + \ require("spacevim").eval("a:request_parse"), + \ require("spacevim").eval("a:000") + \ ) + endfunction + function! SpaceVim#plugins#a#set_config_name(path, name) abort + lua require("spacevim.plugin.a").set_config_name( + \ require("spacevim").eval("a:path"), + \ require("spacevim").eval("a:name") + \ ) + endfunction + function! SpaceVim#plugins#a#getConfigPath() abort + return luaeval('require("spacevim.plugin.a").getConfigPath()') + endfunction + function! SpaceVim#plugins#a#complete(ArgLead, CmdLine, CursorPos) abort + return luaeval('require("spacevim.plugin.a").complete(' + \ .'require("spacevim").eval("a:ArgLead"),' + \ .'require("spacevim").eval("a:CmdLine"),' + \ .'require("spacevim").eval("a:CursorPos"))') + endfunction + function! SpaceVim#plugins#a#get_alt(file, conf_path, request_parse,...) abort + let type = get(a:000, 0, 'alternate') + return luaeval('require("spacevim.plugin.a").get_alt(' + \ . 'require("spacevim").eval("a:file"),' + \ . 'require("spacevim").eval("a:conf_path"),' + \ . 'require("spacevim").eval("a:request_parse"),' + \ . 'require("spacevim").eval("type"))') + endfunction +else + " Load SpaceVim API -let s:CMP = SpaceVim#api#import('vim#compatible') -let s:JSON = SpaceVim#api#import('data#json') -let s:FILE = SpaceVim#api#import('file') -let s:LOGGER =SpaceVim#logger#derive('a.vim') + let s:CMP = SpaceVim#api#import('vim#compatible') + let s:JSON = SpaceVim#api#import('data#json') + let s:FILE = SpaceVim#api#import('file') + let s:LOGGER =SpaceVim#logger#derive('a.vim') -" local value -" -" s:alternate_conf define which file should be loaded as alternate -" file configuration for current project, This is a directory -let s:alternate_conf = { - \ '_' : '.project_alt.json' - \ } -let s:cache_path = s:FILE.unify_path(g:spacevim_data_dir, ':p') . 'SpaceVim/a.json' - - -" this is for saving the project configuration information. Use the path of -" the project_alt.json file as the key. -let s:project_config = {} - - -" saving cache - -function! s:cache() abort - call writefile([s:JSON.json_encode(s:project_config)], s:FILE.unify_path(s:cache_path, ':p')) -endfunction - -function! s:load_cache() abort - call s:LOGGER.info('Try to load alt cache from: ' . s:cache_path) - let cache_context = join(readfile(s:cache_path, ''), '') - if !empty(cache_context) - let s:project_config = s:JSON.json_decode(cache_context) - endif -endfunction - -" when this function is called, the project_config file name is changed, and -" the project_config info is cleared. -function! SpaceVim#plugins#a#set_config_name(path, name) abort - let s:alternate_conf[a:path] = a:name -endfunction -function! s:get_project_config(conf_file) abort - call s:LOGGER.info('read context from: '. a:conf_file) - let context = join(readfile(a:conf_file), "\n") - let conf = s:JSON.json_decode(context) - if type(conf) !=# type({}) - " in Old vim we get E706 - " Variable type mismatch for conf, so we need to unlet conf first - " ref: patch-7.4.1546 - " https://github.com/vim/vim/commit/f6f32c38bf3319144a84a01a154c8c91939e7acf - unlet conf - let conf = {} - endif - let root = s:FILE.unify_path(a:conf_file, ':p:h') - return { - \ 'root' : root, - \ 'config' : conf - \ } -endfunction - -function! SpaceVim#plugins#a#alt(request_parse,...) abort - let type = get(a:000, 0, 'alternate') - if !exists('b:alternate_file_config') - let conf_file_path = SpaceVim#plugins#a#getConfigPath() - let file = s:FILE.unify_path(bufname('%'), ':.') - let alt = SpaceVim#plugins#a#get_alt(file, conf_file_path, a:request_parse, type) - else - endif - if !empty(alt) - exe 'e ' . alt - else - echo 'failed to find alternate file!' - endif -endfunction - - -" the parse function should only accept one argv -" the alt_config_json -" -" @todo Rewrite alternate file parse -" parse function is written in vim script, and it is too slow, -" we are going to rewrite this function in other language. -" asynchronous parse should be supported. -function! s:parse(alt_config_json) abort - call s:LOGGER.info('Start to parse alternate files for: ' . a:alt_config_json.root) - let s:project_config[a:alt_config_json.root] = {} - " @question why need sory() - " if we have two key docs/*.md and docs/cn/*.md - " with the first key, we can also find files in - " docs/cn/ directory, for example docs/cn/index.md - " and the alt file will be - " docs/cn/cn/index.md. this should be overrided by login in - " docs/cn/*.md + " local value " - " so we need to use sort, and make sure `docs/cn/*.md` is parsed after - " docs/*.md - for key in sort(keys(a:alt_config_json.config)) - call s:LOGGER.info('start parse key:' . key) - let searchpath = key - if match(searchpath, '/\*') - let searchpath = substitute(searchpath, '*', '**/*', 'g') + " s:alternate_conf define which file should be loaded as alternate + " file configuration for current project, This is a directory + let s:alternate_conf = { + \ '_' : '.project_alt.json' + \ } + let s:cache_path = s:FILE.unify_path(g:spacevim_data_dir, ':p') . 'SpaceVim/a.json' + + + " this is for saving the project configuration information. Use the path of + " the project_alt.json file as the key. + let s:project_config = {} + + + " saving cache + + function! s:cache() abort + call writefile([s:JSON.json_encode(s:project_config)], s:FILE.unify_path(s:cache_path, ':p')) + endfunction + + function! s:load_cache() abort + call s:LOGGER.info('Try to load alt cache from: ' . s:cache_path) + let cache_context = join(readfile(s:cache_path, ''), '') + if !empty(cache_context) + let s:project_config = s:JSON.json_decode(cache_context) endif - call s:LOGGER.info('run globpath for: '. searchpath) - for file in s:CMP.globpath('.', searchpath) - let file = s:FILE.unify_path(file, ':.') - let s:project_config[a:alt_config_json.root][file] = {} - if has_key(a:alt_config_json.config, file) - for type in keys(a:alt_config_json.config[file]) - let s:project_config[a:alt_config_json.root][file][type] = a:alt_config_json.config[file][type] - endfor + endfunction + + " when this function is called, the project_config file name is changed, and + " the project_config info is cleared. + function! s:get_project_config(conf_file) abort + call s:LOGGER.info('read context from: '. a:conf_file) + let context = join(readfile(a:conf_file), "\n") + let conf = s:JSON.json_decode(context) + if type(conf) !=# type({}) + " in Old vim we get E706 + " Variable type mismatch for conf, so we need to unlet conf first + " ref: patch-7.4.1546 + " https://github.com/vim/vim/commit/f6f32c38bf3319144a84a01a154c8c91939e7acf + unlet conf + let conf = {} + endif + let root = s:FILE.unify_path(a:conf_file, ':p:h') + return { + \ 'root' : root, + \ 'config' : conf + \ } + endfunction + + function! SpaceVim#plugins#a#alt(request_parse,...) abort + let type = get(a:000, 0, 'alternate') + if !exists('b:alternate_file_config') + let conf_file_path = SpaceVim#plugins#a#getConfigPath() + let file = s:FILE.unify_path(bufname('%'), ':.') + let alt = SpaceVim#plugins#a#get_alt(file, conf_file_path, a:request_parse, type) + if !empty(alt) + exe 'e ' . alt else - for type in keys(a:alt_config_json.config[key]) - let begin_end = split(key, '*') - if len(begin_end) == 2 - let s:project_config[a:alt_config_json.root][file][type] = - \ s:get_type_path( - \ begin_end, - \ file, - \ a:alt_config_json.config[key][type] - \ ) - endif - endfor + echo 'failed to find alternate file!' endif - endfor - endfor - call s:LOGGER.info('Paser done, try to cache alternate info') - call s:cache() -endfunction + endif + endfunction + function! SpaceVim#plugins#a#set_config_name(path, name) abort + let s:alternate_conf[a:path] = a:name + endfunction + function! SpaceVim#plugins#a#getConfigPath() abort + return s:FILE.unify_path(get(s:alternate_conf, getcwd(), s:alternate_conf['_']), ':p') + endfunction -function! s:get_type_path(a, f, b) abort - let begin_len = strlen(a:a[0]) - let end_len = strlen(a:a[1]) - return substitute(a:b, '{}', a:f[begin_len : (end_len+1) * -1], 'g') -endfunction -function! s:is_config_changed(conf_path) abort - if getftime(a:conf_path) > getftime(s:cache_path) - call s:LOGGER.info('alt config file (' - \ . a:conf_path - \ . ') has been changed, parse required!') - return 1 - endif -endfunction + " @vimlint(EVL103, 1, a:ArgLead) + " @vimlint(EVL103, 1, a:CmdLine) + " @vimlint(EVL103, 1, a:CursorPos) + function! SpaceVim#plugins#a#complete(ArgLead, CmdLine, CursorPos) abort + let file = s:FILE.unify_path(bufname('%'), ':.') + let conf_file_path = SpaceVim#plugins#a#getConfigPath() + let alt_config_json = s:get_project_config(conf_file_path) -function! SpaceVim#plugins#a#get_alt(file, conf_path, request_parse,...) abort - call s:LOGGER.info('getting alt file for:' . a:file) - call s:LOGGER.info(' > type: ' . get(a:000, 0, 'alternate')) - call s:LOGGER.info(' > parse: ' . a:request_parse) - call s:LOGGER.info(' > config: ' . a:conf_path) - " @question when should the cache be loaded? - " if the local value s:project_config do not has the key a:conf_path - " and the file a:conf_path has not been updated since last cache - " and no request_parse specified - let alt_config_json = s:get_project_config(a:conf_path) - if !has_key(s:project_config, alt_config_json.root) - \ && !s:is_config_changed(a:conf_path) - \ && !a:request_parse - " config file has been cached since last update. - " so no need to parse the config for current config file - " just load the cache - call s:load_cache() + call SpaceVim#plugins#a#get_alt(file, conf_file_path, 0) + try + let a = s:project_config[alt_config_json.root][file] + catch + let a = {} + endtry + return join(keys(a), "\n") + endfunction + function! SpaceVim#plugins#a#get_alt(file, conf_path, request_parse,...) abort + call s:LOGGER.info('getting alt file for:' . a:file) + call s:LOGGER.info(' > type: ' . get(a:000, 0, 'alternate')) + call s:LOGGER.info(' > parse: ' . a:request_parse) + call s:LOGGER.info(' > config: ' . a:conf_path) + " @question when should the cache be loaded? + " if the local value s:project_config do not has the key a:conf_path + " and the file a:conf_path has not been updated since last cache + " and no request_parse specified + let alt_config_json = s:get_project_config(a:conf_path) if !has_key(s:project_config, alt_config_json.root) - \ || !has_key(s:project_config[alt_config_json.root], a:file) + \ && !s:is_config_changed(a:conf_path) + \ && !a:request_parse + " config file has been cached since last update. + " so no need to parse the config for current config file + " just load the cache + call s:load_cache() + if !has_key(s:project_config, alt_config_json.root) + \ || !has_key(s:project_config[alt_config_json.root], a:file) + call s:parse(alt_config_json) + endif + else call s:parse(alt_config_json) endif - else - call s:parse(alt_config_json) - endif - " try - " This will throw error in vim7.4.629 and 7.4.052 - " @quection why can not catch the errors? - " return s:project_config[alt_config_json.root][a:file][get(a:000, 0, 'alternate')] - " catch - " return '' - " endtry - if has_key(s:project_config, alt_config_json.root) - \ && has_key(s:project_config[alt_config_json.root], a:file) - \ && has_key(s:project_config[alt_config_json.root][a:file], get(a:000, 0, 'alternate')) - return s:project_config[alt_config_json.root][a:file][get(a:000, 0, 'alternate')] - else - return '' - endif -endfunction - -" @vimlint(EVL103, 1, a:file) -function! s:get_alternate(file) abort - -endfunction -" @vimlint(EVL103, 0, a:file) + " try + " This will throw error in vim7.4.629 and 7.4.052 + " @quection why can not catch the errors? + " return s:project_config[alt_config_json.root][a:file][get(a:000, 0, 'alternate')] + " catch + " return '' + " endtry + if has_key(s:project_config, alt_config_json.root) + \ && has_key(s:project_config[alt_config_json.root], a:file) + \ && has_key(s:project_config[alt_config_json.root][a:file], get(a:000, 0, 'alternate')) + return s:project_config[alt_config_json.root][a:file][get(a:000, 0, 'alternate')] + else + return '' + endif + endfunction -function! SpaceVim#plugins#a#getConfigPath() abort - return s:FILE.unify_path(get(s:alternate_conf, getcwd(), s:alternate_conf['_']), ':p') -endfunction + " the parse function should only accept one argv + " the alt_config_json + " + " @todo Rewrite alternate file parse + " parse function is written in vim script, and it is too slow, + " we are going to rewrite this function in other language. + " asynchronous parse should be supported. + function! s:parse(alt_config_json) abort + call s:LOGGER.info('Start to parse alternate files for: ' . a:alt_config_json.root) + let s:project_config[a:alt_config_json.root] = {} + " @question why need sory() + " if we have two key docs/*.md and docs/cn/*.md + " with the first key, we can also find files in + " docs/cn/ directory, for example docs/cn/index.md + " and the alt file will be + " docs/cn/cn/index.md. this should be overrided by login in + " docs/cn/*.md + " + " so we need to use sort, and make sure `docs/cn/*.md` is parsed after + " docs/*.md + for key in sort(keys(a:alt_config_json.config)) + call s:LOGGER.info('start parse key:' . key) + let searchpath = key + if match(searchpath, '/\*') + let searchpath = substitute(searchpath, '*', '**/*', 'g') + endif + call s:LOGGER.info('run globpath for: '. searchpath) + for file in s:CMP.globpath('.', searchpath) + let file = s:FILE.unify_path(file, ':.') + let s:project_config[a:alt_config_json.root][file] = {} + if has_key(a:alt_config_json.config, file) + for type in keys(a:alt_config_json.config[file]) + let s:project_config[a:alt_config_json.root][file][type] = a:alt_config_json.config[file][type] + endfor + else + for type in keys(a:alt_config_json.config[key]) + let begin_end = split(key, '*') + if len(begin_end) == 2 + let s:project_config[a:alt_config_json.root][file][type] = + \ s:get_type_path( + \ begin_end, + \ file, + \ a:alt_config_json.config[key][type] + \ ) + endif + endfor + endif + endfor + endfor + call s:LOGGER.info('Paser done, try to cache alternate info') + call s:cache() + endfunction + + function! s:get_type_path(a, f, b) abort + let begin_len = strlen(a:a[0]) + let end_len = strlen(a:a[1]) + return substitute(a:b, '{}', a:f[begin_len : (end_len+1) * -1], 'g') + endfunction + + function! s:is_config_changed(conf_path) abort + if getftime(a:conf_path) > getftime(s:cache_path) + call s:LOGGER.info('alt config file (' + \ . a:conf_path + \ . ') has been changed, parse required!') + return 1 + endif + endfunction -" @vimlint(EVL103, 1, a:ArgLead) -" @vimlint(EVL103, 1, a:CmdLine) -" @vimlint(EVL103, 1, a:CursorPos) -function! SpaceVim#plugins#a#complete(ArgLead, CmdLine, CursorPos) abort - let file = s:FILE.unify_path(bufname('%'), ':.') - let conf_file_path = SpaceVim#plugins#a#getConfigPath() - let alt_config_json = s:get_project_config(conf_file_path) + " @vimlint(EVL103, 1, a:file) + function! s:get_alternate(file) abort - call SpaceVim#plugins#a#get_alt(file, conf_file_path, 0) - try - let a = s:project_config[alt_config_json.root][file] - catch - let a = {} - endtry - return join(keys(a), "\n") -endfunction -" @vimlint(EVL103, 0, a:ArgLead) -" @vimlint(EVL103, 0, a:CmdLine) -" @vimlint(EVL103, 0, a:CursorPos) + endfunction + " @vimlint(EVL103, 0, a:file) + + " @vimlint(EVL103, 0, a:ArgLead) + " @vimlint(EVL103, 0, a:CmdLine) + " @vimlint(EVL103, 0, a:CursorPos) + +endif let &cpo = s:save_cpo unlet s:save_cpo diff --git a/docs/api/logger.md b/docs/api/logger.md index f37392e4f..ee2815a81 100644 --- a/docs/api/logger.md +++ b/docs/api/logger.md @@ -17,13 +17,18 @@ description: "logger API provides some basic functions for log message when crea `logger` API provides some functions to create logger for plugin. - ## Functions -| name | description | -| --------------- | ------------------------------ | -| `set_name(str)` | set the name of current logger | - +| name | description | +| --------------------- | --------------------------------- | +| `set_name(string)` | set the name of current logger | +| `set_silent(0 or 1)` | enable/disable silent mode | +| `set_verbose(number)` | set the verbose level | +| `set_level(number)` | set the logger level | +| `error(string)` | log error message | +| `warn(string)` | log string only when `level <= 2` | +| `info(string)` | log string only when `level <= 1` | +| `debug(string)` | log string only when `level <= 0` | ## Usage diff --git a/lua/spacevim/api/data/json.lua b/lua/spacevim/api/data/json.lua new file mode 100644 index 000000000..64dcd5bc2 --- /dev/null +++ b/lua/spacevim/api/data/json.lua @@ -0,0 +1,42 @@ +local M = {} + +if vim.fn == nil then + fn = require('spacevim').fn +else + fn = vim.fn +end + +-- M._vim = require('spacevim.api').import('vim') +-- M._iconv = require('spacevim.api').import('iconv') + +function M._json_null() + return nil +end + +function M._json_true() + return true +end + +function M._json_false() + return false +end + + +if fn.exists('*json_decode') then + function M.json_decode(json) + if json == '' then + return '' + end + return fn.json_decode(json) + end +else +end + +if fn.exists('*json_encode') then + function M.json_encode(val) + return fn.json_encode(val) + end +else +end + +return M diff --git a/lua/spacevim/api/logger.lua b/lua/spacevim/api/logger.lua index b98d9751e..4525c9160 100644 --- a/lua/spacevim/api/logger.lua +++ b/lua/spacevim/api/logger.lua @@ -16,7 +16,12 @@ local M = { ['temp'] = {}, } -local levels = {'Info', 'Warn', 'Error'} + +-- 0 : log debug, info, warn, error messages +-- 1 : log info, warn, error messages +-- 2 : log warn, error messages +-- 3 : log error messages +M.levels = {'Info', 'Warn', 'Error', 'Debug'} function M.set_silent(sl) M.silent = sl @@ -30,9 +35,25 @@ function M.set_level(l) M.level = l end -function M.error(msg) +function M._build_msg(msg, l) + msg = msg or '' local time = fn.strftime('%H:%M:%S') - local log = '[ ' .. M.name .. ' ] [' .. time .. '] [ ' .. levels[1] .. ' ] ' .. msg + local log = '[ ' .. M.name .. ' ] [' .. time .. '] [ ' .. M.levels[l] .. ' ] ' .. msg + return log +end + +function M.debug(msg) + if M.level <= 0 then + local log = M._build_msg(msg, 4) + if M.silent == 0 and M.verbose >= 4 then + cmd('echom "' .. log .. '"') + end + M.write(log) + end +end + +function M.error(msg) + local log = M._build_msg(msg, 3) if M.silent == 0 and M.verbose >= 1 then cmd('echohl Error') cmd('echom "' .. log .. '"') @@ -58,8 +79,7 @@ end function M.warn(msg, ...) if M.level <= 2 then - local time = fn.strftime('%H:%M:%S') - local log = '[ ' .. M.name .. ' ] [' .. time .. '] [ ' .. levels[1] .. ' ] ' .. msg + local log = M._build_msg(msg, 2) if (M.silent == 0 and M.verbose >= 2) or select(1, ...) == 1 then cmd('echohl WarningMsg') cmd('echom "' .. log .. '"') @@ -67,13 +87,11 @@ function M.warn(msg, ...) end M.write(log) end - end function M.info(msg) if M.level <= 1 then - local time = fn.strftime('%H:%M:%S') - local log = '[ ' .. M.name .. ' ] [' .. time .. '] [ ' .. levels[1] .. ' ] ' .. msg + local log = M._build_msg(msg, 1) if M.silent == 0 and M.verbose >= 3 then cmd('echom "' .. log .. '"') end @@ -82,27 +100,34 @@ function M.info(msg) end function M.view(l) - local info = '' - local logs = '' - if fn.filereadable(M.file) == 1 then - logs = fn.readfile(M.file, '') - info = info .. fn.join(fn.filter(logs, 'self._comp(v:val, a:l)'), "\n") - else - info = info .. '[ ' .. M.name .. ' ] : logger file ' .. M.file - .. ' does not exists, only log for current process will be shown!' - .. "\n" - for key, value in pairs(M.temp) do - if M._comp(value, l) == 1 then - info = info .. value .. "\n" - end - end - end - return info - + local info = '' + local logs = '' + if fn.filereadable(M.file) == 1 then + logs = fn.readfile(M.file, '') + info = info .. fn.join(fn.filter(logs, 'self._comp(v:val, a:l)'), "\n") + else + info = info .. '[ ' .. M.name .. ' ] : logger file ' .. M.file + .. ' does not exists, only log for current process will be shown!' + .. "\n" + for key, value in pairs(M.temp) do + if M._comp(value, l) == 1 then + info = info .. value .. "\n" + end + end + end + return info + end -function M._comp(a, b) - +function M._comp(msg, l) + -- if a:msg =~# '\[ ' . self.name . ' \] \[\d\d\:\d\d\:\d\d\] \[ ' + if string.find(msg, M.levels[2]) ~= nil then + return 1 + elseif string.find(msg, M.levels[1]) ~= nil then + if l > 2 then return 0 else return 1 end + else + if l > 1 then return 0 else return 1 end + end end function M.set_name(name) diff --git a/lua/spacevim/logger.lua b/lua/spacevim/logger.lua index dc3c3cd89..b080c8908 100644 --- a/lua/spacevim/logger.lua +++ b/lua/spacevim/logger.lua @@ -2,6 +2,7 @@ local M = {} local logger = require('spacevim.api').import('logger') local cmd = require('spacevim').cmd +local call = require('spacevim').call local fn = nil if vim.fn == nil then fn = require('spacevim').fn @@ -28,6 +29,10 @@ function M.error(msg) logger.error(msg) end +function M.debug(msg) + logger.debug(msg) +end + function M.setLevel(level) logger.set_level(level) end @@ -37,46 +42,81 @@ function M.setOutput(file) end function M.viewRuntimeLog() - local info = "### SpaceVim runtime log :\n\n" - .. "```log\n" - .. logger.view(logger.level) - .. "\n```\n" - cmd('tabnew') - cmd('setl nobuflisted') - cmd('nnoremap q :tabclose!') - -- put info into buffer - fn.append(0, fn.split(info, "\n")) - cmd('setl nomodifiable') - cmd('setl buftype=nofile') - cmd('setl filetype=markdown') - M.syntax_extra() + local info = "### SpaceVim runtime log :\n\n" + .. "```log\n" + .. logger.view(logger.level) + .. "\n```\n" + cmd('tabnew') + cmd('setl nobuflisted') + cmd('nnoremap q :tabclose!') + -- put info into buffer + fn.append(0, fn.split(info, "\n")) + cmd('setl nomodifiable') + cmd('setl buftype=nofile') + -- cmd('setl filetype=markdown') + -- M.syntax_extra() +end + +function M.viewLog(bang) + local info = "
SpaceVim debug information \n\n" + .. "### SpaceVim options :\n\n" + .. "```toml\n" + .. fn.join(call('SpaceVim#options#list'), "\n") + .. "\n```\n" + .. "\n\n" + .. "### SpaceVim layers :\n\n" + .. call('SpaceVim#layers#report') + .. "\n\n" + .. "### SpaceVim Health checking :\n\n" + .. call('SpaceVim#health#report') + .. "\n\n" + .. "### SpaceVim runtime log :\n\n" + .. "```log\n" + .. logger.view(logger.level) + .. "\n```\n
\n\n" + if bang == 1 then + cmd('tabnew') + cmd('setl nobuflisted') + cmd('nnoremap q :tabclose!') + -- put info into buffer + fn.append(0, fn.split(info, "\n")) + cmd('setl nomodifiable') + cmd('setl buftype=nofile') + cmd('setl filetype=markdown') + end + return info end function M.syntax_extra() - fn.matchadd('ErrorMsg','.*[\\sError\\s\\].*') - fn.matchadd('WarningMsg','.*[\\sWarn\\s\\].*') + fn.matchadd('ErrorMsg','.*[\\sError\\s\\].*') + fn.matchadd('WarningMsg','.*[\\sWarn\\s\\].*') end function M.derive(name) local derive = {} derive['origin_name'] = logger.get_name() - function derive.info() - logger.set_name(self.derive_name) + function derive.info(msg) + logger.set_name(derive.derive_name) logger.info(msg) - logger.set_name(self.origin_name) + logger.set_name(derive.origin_name) end - function derive.warn() - logger.set_name(self.derive_name) + function derive.warn(msg) + logger.set_name(derive.derive_name) logger.warn(msg) - logger.set_name(self.origin_name) + logger.set_name(derive.origin_name) end - function derive.error() - logger.set_name(self.derive_name) + function derive.error(msg) + logger.set_name(derive.derive_name) logger.error(msg) - logger.set_name(self.origin_name) + logger.set_name(derive.origin_name) end + function derive.debug(msg) + logger.set_name(derive.derive_name) + logger.debug(msg) + logger.set_name(derive.origin_name) + end derive['derive_name'] = fn.printf('%' .. fn.strdisplaywidth(logger.get_name()) .. 'S', name) return derive end diff --git a/lua/spacevim/plugin/a.lua b/lua/spacevim/plugin/a.lua new file mode 100644 index 000000000..6c17bff74 --- /dev/null +++ b/lua/spacevim/plugin/a.lua @@ -0,0 +1,206 @@ +local M = {} +local sp = require('spacevim') +local cmp = require('spacevim.api').import('vim.compatible') +local cmd = require('spacevim').cmd +local sp_file = require('spacevim.api').import('file') +local sp_json = require('spacevim.api').import('data.json') +local logger = require('spacevim.logger').derive('a.vim') + +local alternate_conf = {} +alternate_conf['_'] = '.project_alt.json' + +local cache_path = sp_file.unify_path(sp.eval('g:spacevim_data_dir'), ':p') .. 'SpaceVim/a.json' + + +local project_config = {} + +local function cache() + fn.writefile({sp_json.json_encode(project_config)}, sp_file.unify_path(cache_path, ':p')) +end + +local function get_type_path(a, f, b) + logger.debug('get_type_path') + logger.debug(fn.string(a)) + logger.debug(f) + logger.debug(b) + local begin_len = fn.strlen(a[1]) + local end_len = fn.strlen(a[2]) + local r = fn.substitute(b, '{}', string.sub(f, begin_len + 1, (end_len+1) * -1), 'g') + logger.debug(r) + return r +end + + +local function load_cache() + logger.info('Try to load alt cache from:' .. cache_path) + local cache_context = fn.join(fn.readfile(cache_path, ''), '') + if cache_context ~= '' then + project_config = sp_json.json_decode(cache_context) + end +end + +function M.set_config_name(path, name) + alternate_conf[path] = name +end + +function M.alt(request_parse, ...) + local arg={...} + local type = 'alternate' + local alt = nil + if fn.exists('b:alternate_file_config') ~= 1 then + local conf_file_path = M.getConfigPath() + local file = sp_file.unify_path(fn.bufname('%'), ':.') + alt = M.get_alt(file, conf_file_path, request_parse, type) + end + logger.debug('alt is:' .. alt) + if alt ~= nil and alt ~= '' then + cmd('e ' .. alt) + else + print('failed to find alternate file!') + end +end + +local function get_project_config(conf_file) + logger.info('read context from:' .. conf_file) + local context = fn.join(fn.readfile(conf_file), "\n") + local conf = sp_json.json_decode(context) + logger.debug(context) + if type(conf) ~= type({}) then + conf = {} + end + local root = sp_file.unify_path(conf_file, ':p:h') + return { + ['root'] = root, + ['config'] = conf + } +end + +-- we need to sort the keys in config +-- + +local function _keys(val) + local new_keys = {} + for k,v in pairs(val) do + table.insert(new_keys, k) + end + return new_keys +end +local function _comp(a, b) + if (string.match(a, '*') == '*' + and string.match(b, '*') == '*') + then + return #a < #b + elseif string.match(a, '*') == '*' then + return true + elseif string.match(b, '*') == '*' then + return false + else + local _, al = string.gsub(a, "/", "") + local _, bl = string.gsub(b, "/", "") + return al < bl + end + +end + +local function parse(alt_config_json) + logger.debug('Start to parse alternate file for:' .. alt_config_json.root) + project_config[alt_config_json.root] = {} + local keys = _keys(alt_config_json.config) + table.sort(keys, _comp) + for _, key in pairs(keys) do + logger.info('start parse key:' .. key) + local searchpath = key + if string.match(searchpath, '*') == '*' then + searchpath = string.gsub(searchpath, '*', '**/*') + end + logger.info('run globpath for: '.. searchpath) + for _,file in pairs(cmp.globpath('.', searchpath)) do + file = sp_file.unify_path(file, ':.') + logger.debug(file) + project_config[alt_config_json.root][file] = {} + if alt_config_json.config[file] ~= nil then + for type, type_v in pairs(alt_config_json.config[file]) do + project_config[alt_config_json.root][file][type] = type_v + end + else + for a_type, _ in pairs(alt_config_json.config[key]) do + local begin_end = fn.split(key, '*') + if #begin_end == 2 then + project_config[alt_config_json.root][file][a_type] = + get_type_path( + begin_end, + file, + alt_config_json.config[key][a_type] + ) + end + end + end + end + end + logger.info('Paser done, try to cache alternate info') + cache() +end + +local function is_config_changed(conf_path) + if fn.getftime(conf_path) > fn.getftime(cache_path) then + logger.info('alt config file(' + .. conf_path + .. ')') + return 1 + end +end + +function M.get_alt(file, conf_path, request_parse, a_type) + logger.info('getting alt file for:' .. file) + logger.info(' > type: ' .. a_type) + logger.info(' > parse: ' .. request_parse) + logger.info(' > config: ' .. conf_path) + alt_config_json = get_project_config(conf_path) + if project_config[alt_config_json.root] == nil + and is_config_changed(conf_path) == 0 + and request_parse == 0 then + load_cache() + if project_config[alt_config_json.root] == nil + or project_config[alt_config_json.root][file] == nil then + parse(alt_config_json) + end + else + parse(alt_config_json) + end + if project_config[alt_config_json.root] ~= nil + and project_config[alt_config_json.root][file] ~= nil + and project_config[alt_config_json.root][file][a_type] ~= nil then + return project_config[alt_config_json.root][file][a_type] + else + return '' + end +end + +function M.getConfigPath() + logger.debug('getConfigPath') + local pwd = fn.getcwd() + logger.debug(pwd) + local p = alternate_conf['_'] + logger.debug(p) + if alternate_conf[pwd] ~= nil then + p = alternate_conf[pwd] + end + return sp_file.unify_path(p, ':p') +end + +function M.complete(arglead, cmdline, cursorpos) + local file = sp_file.unify_path(fn.bufname('%'), ':.') + local conf_file_path = M.getConfigPath() + local alt_config_json = get_project_config(conf_file_path) + + M.get_alt(file, conf_file_path, 0, '') + local a = project_config[alt_config_json.root][file] + if a ~= nil then + return fn.join(fn.keys(a), "\n") + else + return '' + end +end + +return M + diff --git a/test/lua/api/data/json.vader b/test/lua/api/data/json.vader new file mode 100644 index 000000000..972fb07eb --- /dev/null +++ b/test/lua/api/data/json.vader @@ -0,0 +1,9 @@ +Execute ( SpaceVim lua api: data.json ): + if get(g:, 'spacevim_use_lua', 0) + let cmp = SpaceVim#api#import('vim#compatible') + lua spacevim_json = require('spacevim.api').import('data.json') + lua context = '{"java" : "hello world"}' + AssertEqual cmp.luaeval('spacevim_json.json_decode(context).java'), 'hello world' + AssertEqual cmp.luaeval("spacevim_json.json_decode(spacevim_json.json_encode({['foo'] = 'zaa'}))"), {'foo' : 'zaa'} + endif + diff --git a/test/lua/api/file.vader b/test/lua/api/file.vader index 0867bf366..ac41f8455 100644 --- a/test/lua/api/file.vader +++ b/test/lua/api/file.vader @@ -9,12 +9,16 @@ Execute ( SpaceVim lua api: file.unify_path(path, ...) ): let file = SpaceVim#api#import('file') let cmp = SpaceVim#api#import('vim#compatible') lua spacevim_file = require('spacevim.api').import('file') + lua cmp = require('spacevim.api').import('vim.compatible') + lua fn = require('spacevim').fn AssertEqual cmp.luaeval('spacevim_file.unify_path(".SpaceVim.d/init.vim", ":p")'), \ file.unify_path(".SpaceVim.d/init.vim", ":p") AssertEqual cmp.luaeval('spacevim_file.unify_path("~/.SpaceVim.d/", ":p")'), \ file.unify_path("~/.SpaceVim.d/", ":p") AssertEqual cmp.luaeval('spacevim_file.unify_path("autoload", ":p")'), \ file.unify_path("autoload", ":p") + AssertEqual cmp.luaeval('spacevim_file.unify_path(fn.bufname("%"), ":.")'), + \ file.unify_path(bufname("%"), ":.") Execute ( SpaceVim lua api: file.path_to_fname(path) ): let file = SpaceVim#api#import('file') diff --git a/test/lua/logger.vader b/test/lua/logger.vader index 36bff2787..3e5c26780 100644 --- a/test/lua/logger.vader +++ b/test/lua/logger.vader @@ -3,17 +3,3 @@ Execute ( SpaceVim lua api: logger ): lua spacevim_logger = require('spacevim.api').import('logger') lua spacevim_logger.set_name('TestLog') AssertEqual cmp.luaeval('spacevim_logger.name'), 'TestLog' - lua spacevim_logger.info('info test') - lua spacevim_logger.warn('info test') - lua spacevim_logger.error('info test') - AssertEqual cmp.luaeval('#spacevim_logger.temp'), 3 - lua spacevim_logger.set_level(2) - lua spacevim_logger.info('info test') - lua spacevim_logger.warn('info test') - lua spacevim_logger.error('info test') - AssertEqual cmp.luaeval('#spacevim_logger.temp'), 5 - lua spacevim_logger.set_level(3) - lua spacevim_logger.info('info test') - lua spacevim_logger.warn('info test') - lua spacevim_logger.error('info test') - AssertEqual cmp.luaeval('#spacevim_logger.temp'), 6