1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-23 17:50:04 +08:00

Rewrite plugin a.vim in lua (#4390)

This commit is contained in:
Wang Shidong 2021-08-15 19:06:48 +08:00 committed by GitHub
parent 8f742f30a2
commit 81e58fdd78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 782 additions and 385 deletions

View File

@ -11,7 +11,7 @@ function! SpaceVim#health#environment#check() abort
" for getting the progpath of current vim. " for getting the progpath of current vim.
call add(result, 'Current progpath: ' . v:progname . '(' . get(v:, 'progpath', '') . ')') call add(result, 'Current progpath: ' . v:progname . '(' . get(v:, 'progpath', '') . ')')
call add(result, 'version: ' . v:version) 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])) call add(result, '[shell, shellcmdflag, shellslash]: ' . string([&shell, &shellcmdflag, &shellslash]))
return result return result
endfunction endfunction

View File

@ -6,143 +6,192 @@
" License: GPLv3 " 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') function! SpaceVim#logger#warn(msg, ...) abort
call s:LOGGER.set_level(get(g:, 'spacevim_debug_level', 1)) let issilent = get(a:000, 0, 1)
call s:LOGGER.set_silent(1) lua require("spacevim.logger").warn(
call s:LOGGER.set_verbose(1) \ require("spacevim").eval("a:msg"),
\ require("spacevim").eval("issilent")
function! SpaceVim#logger#info(msg) abort \ )
endfunction
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 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
lua require("spacevim.logger").viewRuntimeLog()
function! SpaceVim#logger#viewRuntimeLog() abort endfunction
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 <buffer><silent> q :tabclose!<CR>
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#viewLog(...) abort function! SpaceVim#logger#viewLog(...) abort
let info = "<details><summary> SpaceVim debug information </summary>\n\n" let bang = get(a:000, 0, 0)
let info .= "### SpaceVim options :\n\n" return luaeval('require("spacevim.logger").viewLog(require("spacevim").eval("bang"))')
let info .= "```toml\n" endfunction
let info .= join(SpaceVim#options#list(), "\n")
let info .= "\n```\n"
let info .= "\n\n"
let info .= "### SpaceVim layers :\n\n" function! SpaceVim#logger#setLevel(level) abort
let info .= SpaceVim#layers#report() lua require("spacevim.logger").setLevel(require("spacevim").eval("a:level"))
let info .= "\n\n" endfunction
let info .= "### SpaceVim Health checking :\n\n" function! SpaceVim#logger#setOutput(file) abort
let info .= SpaceVim#health#report() lua require("spacevim.logger").setOutput(require("spacevim").eval("a:file"))
let info .= "\n\n" endfunction
let info .= "### SpaceVim runtime log :\n\n" function! SpaceVim#logger#derive(name) abort
let info .= "```log\n" 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</details>\n\n" function! SpaceVim#logger#info(msg) abort
if a:0 > 0
if a:1 == 1 call s:LOGGER.info(a:msg)
tabnew +setl\ nobuflisted
nnoremap <buffer><silent> q :bd!<CR> endfunction
for msg in split(info, "\n")
call append(line('$'), msg) function! SpaceVim#logger#warn(msg, ...) abort
endfor let issilent = get(a:000, 0, 1)
normal! "_dd call s:LOGGER.warn(a:msg, issilent)
setl nomodifiable endfunction
setl buftype=nofile
setl filetype=markdown
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 <buffer><silent> q :tabclose!<CR>
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 = "<details><summary> SpaceVim debug information </summary>\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</details>\n\n"
if a:0 > 0
if a:1 == 1
tabnew +setl\ nobuflisted
nnoremap <buffer><silent> q :bd!<CR>
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 else
echo info return info
endif endif
else endfunction
return info
endif
endfunction
function! s:syntax_extra() abort function! s:syntax_extra() abort
call matchadd('ErrorMsg','.*[\sError\s\].*') call matchadd('ErrorMsg','.*[\sError\s\].*')
call matchadd('WarningMsg','.*[\sWarn\s\].*') call matchadd('WarningMsg','.*[\sWarn\s\].*')
endfunction endfunction
"" ""
" @public " @public
" Set debug level of SpaceVim. Default is 1. " Set debug level of SpaceVim. Default is 1.
" "
" 1 : log all messages " 1 : log all messages
" "
" 2 : log warning and error messages " 2 : log warning and error messages
" "
" 3 : log error messages only " 3 : log error messages only
function! SpaceVim#logger#setLevel(level) abort function! SpaceVim#logger#setLevel(level) abort
call s:LOGGER.set_level(a:level) call s:LOGGER.set_level(a:level)
endfunction endfunction
"" ""
" @public " @public
" Set the log output file of SpaceVim. Default is empty. " Set the log output file of SpaceVim. Default is empty.
function! SpaceVim#logger#setOutput(file) abort function! SpaceVim#logger#setOutput(file) abort
call s:LOGGER.set_file(a:file) call s:LOGGER.set_file(a:file)
endfunction endfunction
" derive a logger for built-in plugins " derive a logger for built-in plugins
" [ name ] [11:31:26] [ Info ] log message here " [ name ] [11:31:26] [ Info ] log message here
let s:derive = {} let s:derive = {}
let s:derive.origin_name = s:LOGGER.get_name() let s:derive.origin_name = s:LOGGER.get_name()
function! s:derive.info(msg) abort function! s:derive.info(msg) abort
call s:LOGGER.set_name(self.derive_name) call s:LOGGER.set_name(self.derive_name)
call s:LOGGER.info(a:msg) call s:LOGGER.info(a:msg)
call s:LOGGER.set_name(self.origin_name) call s:LOGGER.set_name(self.origin_name)
endfunction endfunction
function! s:derive.warn(msg) abort function! s:derive.warn(msg) abort
call s:LOGGER.set_name(self.derive_name) call s:LOGGER.set_name(self.derive_name)
call s:LOGGER.warn(a:msg) call s:LOGGER.warn(a:msg)
call s:LOGGER.set_name(self.origin_name) call s:LOGGER.set_name(self.origin_name)
endfunction endfunction
function! s:derive.error(msg) abort function! s:derive.error(msg) abort
call s:LOGGER.set_name(self.derive_name) call s:LOGGER.set_name(self.derive_name)
call s:LOGGER.error(a:msg) call s:LOGGER.error(a:msg)
call s:LOGGER.set_name(self.origin_name) call s:LOGGER.set_name(self.origin_name)
endfunction endfunction
function! SpaceVim#logger#derive(name) abort function! SpaceVim#logger#derive(name) abort
let s:derive.derive_name = printf('%' . strdisplaywidth(s:LOGGER.get_name()) . 'S', a:name) let s:derive.derive_name = printf('%' . strdisplaywidth(s:LOGGER.get_name()) . 'S', a:name)
return deepcopy(s:derive) return deepcopy(s:derive)
endfunction endfunction
endif

View File

@ -11,223 +11,254 @@ set cpo&vim
scriptencoding utf-8 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:CMP = SpaceVim#api#import('vim#compatible')
let s:JSON = SpaceVim#api#import('data#json') let s:JSON = SpaceVim#api#import('data#json')
let s:FILE = SpaceVim#api#import('file') let s:FILE = SpaceVim#api#import('file')
let s:LOGGER =SpaceVim#logger#derive('a.vim') let s:LOGGER =SpaceVim#logger#derive('a.vim')
" local value " 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
" "
" so we need to use sort, and make sure `docs/cn/*.md` is parsed after " s:alternate_conf define which file should be loaded as alternate
" docs/*.md " file configuration for current project, This is a directory
for key in sort(keys(a:alt_config_json.config)) let s:alternate_conf = {
call s:LOGGER.info('start parse key:' . key) \ '_' : '.project_alt.json'
let searchpath = key \ }
if match(searchpath, '/\*') let s:cache_path = s:FILE.unify_path(g:spacevim_data_dir, ':p') . 'SpaceVim/a.json'
let searchpath = substitute(searchpath, '*', '**/*', 'g')
" 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 endif
call s:LOGGER.info('run globpath for: '. searchpath) endfunction
for file in s:CMP.globpath('.', searchpath)
let file = s:FILE.unify_path(file, ':.') " when this function is called, the project_config file name is changed, and
let s:project_config[a:alt_config_json.root][file] = {} " the project_config info is cleared.
if has_key(a:alt_config_json.config, file) function! s:get_project_config(conf_file) abort
for type in keys(a:alt_config_json.config[file]) call s:LOGGER.info('read context from: '. a:conf_file)
let s:project_config[a:alt_config_json.root][file][type] = a:alt_config_json.config[file][type] let context = join(readfile(a:conf_file), "\n")
endfor 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 else
for type in keys(a:alt_config_json.config[key]) echo 'failed to find alternate file!'
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 endif
endfor endif
endfor endfunction
call s:LOGGER.info('Paser done, try to cache alternate info') function! SpaceVim#plugins#a#set_config_name(path, name) abort
call s:cache() let s:alternate_conf[a:path] = a:name
endfunction 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 " @vimlint(EVL103, 1, a:ArgLead)
if getftime(a:conf_path) > getftime(s:cache_path) " @vimlint(EVL103, 1, a:CmdLine)
call s:LOGGER.info('alt config file (' " @vimlint(EVL103, 1, a:CursorPos)
\ . a:conf_path function! SpaceVim#plugins#a#complete(ArgLead, CmdLine, CursorPos) abort
\ . ') has been changed, parse required!') let file = s:FILE.unify_path(bufname('%'), ':.')
return 1 let conf_file_path = SpaceVim#plugins#a#getConfigPath()
endif let alt_config_json = s:get_project_config(conf_file_path)
endfunction
function! SpaceVim#plugins#a#get_alt(file, conf_path, request_parse,...) abort call SpaceVim#plugins#a#get_alt(file, conf_file_path, 0)
call s:LOGGER.info('getting alt file for:' . a:file) try
call s:LOGGER.info(' > type: ' . get(a:000, 0, 'alternate')) let a = s:project_config[alt_config_json.root][file]
call s:LOGGER.info(' > parse: ' . a:request_parse) catch
call s:LOGGER.info(' > config: ' . a:conf_path) let a = {}
" @question when should the cache be loaded? endtry
" if the local value s:project_config do not has the key a:conf_path return join(keys(a), "\n")
" and the file a:conf_path has not been updated since last cache endfunction
" and no request_parse specified function! SpaceVim#plugins#a#get_alt(file, conf_path, request_parse,...) abort
let alt_config_json = s:get_project_config(a:conf_path) call s:LOGGER.info('getting alt file for:' . a:file)
if !has_key(s:project_config, alt_config_json.root) call s:LOGGER.info(' > type: ' . get(a:000, 0, 'alternate'))
\ && !s:is_config_changed(a:conf_path) call s:LOGGER.info(' > parse: ' . a:request_parse)
\ && !a:request_parse call s:LOGGER.info(' > config: ' . a:conf_path)
" config file has been cached since last update. " @question when should the cache be loaded?
" so no need to parse the config for current config file " if the local value s:project_config do not has the key a:conf_path
" just load the cache " and the file a:conf_path has not been updated since last cache
call s:load_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) 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) call s:parse(alt_config_json)
endif endif
else " try
call s:parse(alt_config_json) " This will throw error in vim7.4.629 and 7.4.052
endif " @quection why can not catch the errors?
" try " return s:project_config[alt_config_json.root][a:file][get(a:000, 0, 'alternate')]
" This will throw error in vim7.4.629 and 7.4.052 " catch
" @quection why can not catch the errors? " return ''
" return s:project_config[alt_config_json.root][a:file][get(a:000, 0, 'alternate')] " endtry
" catch if has_key(s:project_config, alt_config_json.root)
" return '' \ && has_key(s:project_config[alt_config_json.root], a:file)
" endtry \ && has_key(s:project_config[alt_config_json.root][a:file], get(a:000, 0, 'alternate'))
if has_key(s:project_config, alt_config_json.root) return s:project_config[alt_config_json.root][a:file][get(a:000, 0, 'alternate')]
\ && has_key(s:project_config[alt_config_json.root], a:file) else
\ && has_key(s:project_config[alt_config_json.root][a:file], get(a:000, 0, 'alternate')) return ''
return s:project_config[alt_config_json.root][a:file][get(a:000, 0, 'alternate')] endif
else endfunction
return ''
endif
endfunction
" @vimlint(EVL103, 1, a:file)
function! s:get_alternate(file) abort
endfunction
" @vimlint(EVL103, 0, a:file)
function! SpaceVim#plugins#a#getConfigPath() abort " the parse function should only accept one argv
return s:FILE.unify_path(get(s:alternate_conf, getcwd(), s:alternate_conf['_']), ':p') " the alt_config_json
endfunction "
" @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:file)
" @vimlint(EVL103, 1, a:CmdLine) function! s:get_alternate(file) abort
" @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)
call SpaceVim#plugins#a#get_alt(file, conf_file_path, 0) endfunction
try " @vimlint(EVL103, 0, a:file)
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)
" @vimlint(EVL103, 0, a:ArgLead)
" @vimlint(EVL103, 0, a:CmdLine)
" @vimlint(EVL103, 0, a:CursorPos)
endif
let &cpo = s:save_cpo let &cpo = s:save_cpo
unlet s:save_cpo unlet s:save_cpo

View File

@ -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. `logger` API provides some functions to create logger for plugin.
## Functions ## Functions
| name | description | | name | description |
| --------------- | ------------------------------ | | --------------------- | --------------------------------- |
| `set_name(str)` | set the name of current logger | | `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 ## Usage

View File

@ -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

View File

@ -16,7 +16,12 @@ local M = {
['temp'] = {}, ['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) function M.set_silent(sl)
M.silent = sl M.silent = sl
@ -30,9 +35,25 @@ function M.set_level(l)
M.level = l M.level = l
end end
function M.error(msg) function M._build_msg(msg, l)
msg = msg or ''
local time = fn.strftime('%H:%M:%S') 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 if M.silent == 0 and M.verbose >= 1 then
cmd('echohl Error') cmd('echohl Error')
cmd('echom "' .. log .. '"') cmd('echom "' .. log .. '"')
@ -58,8 +79,7 @@ end
function M.warn(msg, ...) function M.warn(msg, ...)
if M.level <= 2 then if M.level <= 2 then
local time = fn.strftime('%H:%M:%S') local log = M._build_msg(msg, 2)
local log = '[ ' .. M.name .. ' ] [' .. time .. '] [ ' .. levels[1] .. ' ] ' .. msg
if (M.silent == 0 and M.verbose >= 2) or select(1, ...) == 1 then if (M.silent == 0 and M.verbose >= 2) or select(1, ...) == 1 then
cmd('echohl WarningMsg') cmd('echohl WarningMsg')
cmd('echom "' .. log .. '"') cmd('echom "' .. log .. '"')
@ -67,13 +87,11 @@ function M.warn(msg, ...)
end end
M.write(log) M.write(log)
end end
end end
function M.info(msg) function M.info(msg)
if M.level <= 1 then if M.level <= 1 then
local time = fn.strftime('%H:%M:%S') local log = M._build_msg(msg, 1)
local log = '[ ' .. M.name .. ' ] [' .. time .. '] [ ' .. levels[1] .. ' ] ' .. msg
if M.silent == 0 and M.verbose >= 3 then if M.silent == 0 and M.verbose >= 3 then
cmd('echom "' .. log .. '"') cmd('echom "' .. log .. '"')
end end
@ -82,27 +100,34 @@ function M.info(msg)
end end
function M.view(l) function M.view(l)
local info = '' local info = ''
local logs = '' local logs = ''
if fn.filereadable(M.file) == 1 then if fn.filereadable(M.file) == 1 then
logs = fn.readfile(M.file, '') logs = fn.readfile(M.file, '')
info = info .. fn.join(fn.filter(logs, 'self._comp(v:val, a:l)'), "\n") info = info .. fn.join(fn.filter(logs, 'self._comp(v:val, a:l)'), "\n")
else else
info = info .. '[ ' .. M.name .. ' ] : logger file ' .. M.file info = info .. '[ ' .. M.name .. ' ] : logger file ' .. M.file
.. ' does not exists, only log for current process will be shown!' .. ' does not exists, only log for current process will be shown!'
.. "\n" .. "\n"
for key, value in pairs(M.temp) do for key, value in pairs(M.temp) do
if M._comp(value, l) == 1 then if M._comp(value, l) == 1 then
info = info .. value .. "\n" info = info .. value .. "\n"
end end
end end
end end
return info return info
end 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 end
function M.set_name(name) function M.set_name(name)

View File

@ -2,6 +2,7 @@ local M = {}
local logger = require('spacevim.api').import('logger') local logger = require('spacevim.api').import('logger')
local cmd = require('spacevim').cmd local cmd = require('spacevim').cmd
local call = require('spacevim').call
local fn = nil local fn = nil
if vim.fn == nil then if vim.fn == nil then
fn = require('spacevim').fn fn = require('spacevim').fn
@ -28,6 +29,10 @@ function M.error(msg)
logger.error(msg) logger.error(msg)
end end
function M.debug(msg)
logger.debug(msg)
end
function M.setLevel(level) function M.setLevel(level)
logger.set_level(level) logger.set_level(level)
end end
@ -37,46 +42,81 @@ function M.setOutput(file)
end end
function M.viewRuntimeLog() function M.viewRuntimeLog()
local info = "### SpaceVim runtime log :\n\n" local info = "### SpaceVim runtime log :\n\n"
.. "```log\n" .. "```log\n"
.. logger.view(logger.level) .. logger.view(logger.level)
.. "\n```\n" .. "\n```\n"
cmd('tabnew') cmd('tabnew')
cmd('setl nobuflisted') cmd('setl nobuflisted')
cmd('nnoremap <buffer><silent> q :tabclose!<CR>') cmd('nnoremap <buffer><silent> q :tabclose!<CR>')
-- put info into buffer -- put info into buffer
fn.append(0, fn.split(info, "\n")) fn.append(0, fn.split(info, "\n"))
cmd('setl nomodifiable') cmd('setl nomodifiable')
cmd('setl buftype=nofile') cmd('setl buftype=nofile')
cmd('setl filetype=markdown') -- cmd('setl filetype=markdown')
M.syntax_extra() -- M.syntax_extra()
end
function M.viewLog(bang)
local info = "<details><summary> SpaceVim debug information </summary>\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</details>\n\n"
if bang == 1 then
cmd('tabnew')
cmd('setl nobuflisted')
cmd('nnoremap <buffer><silent> q :tabclose!<CR>')
-- 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 end
function M.syntax_extra() function M.syntax_extra()
fn.matchadd('ErrorMsg','.*[\\sError\\s\\].*') fn.matchadd('ErrorMsg','.*[\\sError\\s\\].*')
fn.matchadd('WarningMsg','.*[\\sWarn\\s\\].*') fn.matchadd('WarningMsg','.*[\\sWarn\\s\\].*')
end end
function M.derive(name) function M.derive(name)
local derive = {} local derive = {}
derive['origin_name'] = logger.get_name() derive['origin_name'] = logger.get_name()
function derive.info() function derive.info(msg)
logger.set_name(self.derive_name) logger.set_name(derive.derive_name)
logger.info(msg) logger.info(msg)
logger.set_name(self.origin_name) logger.set_name(derive.origin_name)
end end
function derive.warn() function derive.warn(msg)
logger.set_name(self.derive_name) logger.set_name(derive.derive_name)
logger.warn(msg) logger.warn(msg)
logger.set_name(self.origin_name) logger.set_name(derive.origin_name)
end end
function derive.error() function derive.error(msg)
logger.set_name(self.derive_name) logger.set_name(derive.derive_name)
logger.error(msg) logger.error(msg)
logger.set_name(self.origin_name) logger.set_name(derive.origin_name)
end 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) derive['derive_name'] = fn.printf('%' .. fn.strdisplaywidth(logger.get_name()) .. 'S', name)
return derive return derive
end end

206
lua/spacevim/plugin/a.lua Normal file
View File

@ -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

View File

@ -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

View File

@ -9,12 +9,16 @@ Execute ( SpaceVim lua api: file.unify_path(path, ...) ):
let file = SpaceVim#api#import('file') let file = SpaceVim#api#import('file')
let cmp = SpaceVim#api#import('vim#compatible') let cmp = SpaceVim#api#import('vim#compatible')
lua spacevim_file = require('spacevim.api').import('file') 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")'), AssertEqual cmp.luaeval('spacevim_file.unify_path(".SpaceVim.d/init.vim", ":p")'),
\ 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")'), AssertEqual cmp.luaeval('spacevim_file.unify_path("~/.SpaceVim.d/", ":p")'),
\ file.unify_path("~/.SpaceVim.d/", ":p") \ file.unify_path("~/.SpaceVim.d/", ":p")
AssertEqual cmp.luaeval('spacevim_file.unify_path("autoload", ":p")'), AssertEqual cmp.luaeval('spacevim_file.unify_path("autoload", ":p")'),
\ 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) ): Execute ( SpaceVim lua api: file.path_to_fname(path) ):
let file = SpaceVim#api#import('file') let file = SpaceVim#api#import('file')

View File

@ -3,17 +3,3 @@ Execute ( SpaceVim lua api: logger ):
lua spacevim_logger = require('spacevim.api').import('logger') lua spacevim_logger = require('spacevim.api').import('logger')
lua spacevim_logger.set_name('TestLog') lua spacevim_logger.set_name('TestLog')
AssertEqual cmp.luaeval('spacevim_logger.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