diff --git a/autoload/SpaceVim/api/vim/compatible.vim b/autoload/SpaceVim/api/vim/compatible.vim index 7b6e3bb55..72978430c 100644 --- a/autoload/SpaceVim/api/vim/compatible.vim +++ b/autoload/SpaceVim/api/vim/compatible.vim @@ -193,7 +193,7 @@ if has('patch-7.4.279') endfunction else function! s:self.globpath(dir, expr) abort - return split(globpath(a:dir, a:expr), '\n') + return split(globpath(a:dir, a:expr), "\n") endfunction endif diff --git a/docs/api/file.md b/docs/api/file.md index 95fd3ca20..8b541b07e 100644 --- a/docs/api/file.md +++ b/docs/api/file.md @@ -10,6 +10,7 @@ description: "file API provides some basic functions and values for current os." - [values](#values) - [functions](#functions) +- [Usage](#usage) @@ -30,3 +31,21 @@ description: "file API provides some basic functions and values for current os." | `read(file)` | read message from file | | `ls(dir, if_file_only)` | list files and directorys in specific directory | | `updateFiles(files)` | update the contents of all files | + +## Usage + +This api can be used in both vim script and lua script. + +**vim script:** + +```vim +let s:FILE = SpaceVim#api#import('file') +echom S:FILE.separator +``` + +**lua script:** + +```lua +local file_api = require('spacevim.api').import('file') +print(file_api.separator) +``` diff --git a/lua/spacevim.lua b/lua/spacevim.lua index a1e74575e..070cda58b 100644 --- a/lua/spacevim.lua +++ b/lua/spacevim.lua @@ -23,6 +23,21 @@ end -- there is no want to call viml function in old vim and neovim +local function build_argv(...) + local str = '' + for index, value in ipairs(...) do + if str ~= '' then + str = str .. ',' + end + if type(value) == 'string' then + str = str .. '"' .. value .. '"' + elseif type(value) == 'number' then + str = str .. value + end + end + return str +end + function M.call(funcname, ...) if vim.call ~= nil then return vim.call(funcname, ...) @@ -30,6 +45,9 @@ function M.call(funcname, ...) if vim.api ~= nil then return vim.api.nvim_call_function(funcname, {...}) else + -- call not call vim script function in lua + vim.command('let g:lua_rst = ' .. funcname .. '(' .. build_argv({...}) .. ')') + return M.eval('g:lua_rst') end end end diff --git a/lua/spacevim/api.lua b/lua/spacevim/api.lua index c046670bb..3668137d7 100644 --- a/lua/spacevim/api.lua +++ b/lua/spacevim/api.lua @@ -1,6 +1,4 @@ local api = {} - - function api.import(name) return require('spacevim.api.' .. name) end diff --git a/lua/spacevim/api/file.lua b/lua/spacevim/api/file.lua new file mode 100644 index 000000000..3eb46c926 --- /dev/null +++ b/lua/spacevim/api/file.lua @@ -0,0 +1,276 @@ +local M = {} + +local system = require('spacevim.api').import('system') +local fn = nil + +if vim.fn == nil then + fn = require('spacevim').fn +else + fn = vim.fn +end + +if system.isWindows then + M.separator = '\\' + M.pathSeparator = ';' +else + M.separator = '/' + M.pathSeparator = ':' +end + +local file_node_extensions = { + ['styl'] = '', + ['scss'] = '', + ['htm'] = '', + ['html'] = '', + ['erb'] = '', + ['slim'] = '', + ['ejs'] = '', + ['wxml'] = '', + ['css'] = '', + ['less'] = '', + ['wxss'] = '', + ['md'] = '', + ['markdown'] = '', + ['json'] = '', + ['js'] = '', + ['jsx'] = '', + ['rb'] = '', + ['php'] = '', + ['py'] = '', + ['pyc'] = '', + ['pyo'] = '', + ['pyd'] = '', + ['coffee'] = '', + ['mustache'] = '', + ['hbs'] = '', + ['conf'] = '', + ['ini'] = '', + ['yml'] = '', + ['bat'] = '', + ['jpg'] = '', + ['jpeg'] = '', + ['bmp'] = '', + ['png'] = '', + ['gif'] = '', + ['ico'] = '', + ['twig'] = '', + ['cpp'] = '', + ['c++'] = '', + ['cxx'] = '', + ['cc'] = '', + ['cp'] = '', + ['c'] = '', + ['hs'] = '', + ['lhs'] = '', + ['lua'] = '', + ['java'] = '', + ['sh'] = '', + ['fish'] = '', + ['ml'] = 'λ', + ['mli'] = 'λ', + ['diff'] = '', + ['db'] = '', + ['sql'] = '', + ['dump'] = '', + ['clj'] = '', + ['cljc'] = '', + ['cljs'] = '', + ['edn'] = '', + ['scala'] = '', + ['go'] = '', + ['dart'] = '', + ['xul'] = '', + ['sln'] = '', + ['suo'] = '', + ['pl'] = '', + ['pm'] = '', + ['t'] = '', + ['rss'] = '', + ['f#'] = '', + ['fsscript'] = '', + ['fsx'] = '', + ['fs'] = '', + ['fsi'] = '', + ['rs'] = '', + ['rlib'] = '', + ['d'] = '', + ['erl'] = '', + ['hrl'] = '', + ['vim'] = '', + ['ai'] = '', + ['psd'] = '', + ['psb'] = '', + ['ts'] = '', + ['tsx'] = '', + ['jl'] = '', + ['ex'] = '', + ['exs'] = '', + ['eex'] = '', + ['leex'] = '' +} + +local file_node_exact_matches = { + ['exact-match-case-sensitive-1.txt'] = 'X1', + ['exact-match-case-sensitive-2'] = 'X2', + ['gruntfile.coffee'] = '', + ['gruntfile.js'] = '', + ['gruntfile.ls'] = '', + ['gulpfile.coffee'] = '', + ['gulpfile.js'] = '', + ['gulpfile.ls'] = '', + ['dropbox'] = '', + ['.ds_store'] = '', + ['.gitconfig'] = '', + ['.gitignore'] = '', + ['.bashrc'] = '', + ['.bashprofile'] = '', + ['favicon.ico'] = '', + ['license'] = '', + ['node_modules'] = '', + ['react.jsx'] = '', + ['Procfile'] = '', + ['.vimrc'] = '', + ['mix.lock'] = '', +} + +local file_node_pattern_matches = { + ['.*jquery.*\\.js$'] = '', + ['.*angular.*\\.js$'] = '', + ['.*backbone.*\\.js$'] = '', + ['.*require.*\\.js$'] = '', + ['.*materialize.*\\.js$'] = '', + ['.*materialize.*\\.css$'] = '', + ['.*mootools.*\\.js$'] = '' +} + +function M.fticon(path) + local file = fn.fnamemodify(path, ':t') + if file_node_exact_matches[file] ~= nil then + return file_node_exact_matches[file] + end + for k,v in ipairs(file_node_pattern_matches) do + if fn.match(file, k) ~= -1 then + return v + end + end + local ext = fn.fnamemodify(file, ':e') + if file_node_extensions[ext] ~= nil then + return file_node_extensions[ext] + else + return '' + end +end + +function M.read(path) + if fn.filereadable(path) then + return fn.readfile(path, '') + else + return '' + end +end + +function M.write(msg, fname) + local flags + if fn.filereadable(fname) == 1 then + flags = 'a' + else + flags = '' + end + fn.writefile({msg}, fname, flags) +end + +function M.override(msg, fname) + local flags + if fn.filereadable(fname) == 1 then + flags = 'b' + else + flags = '' + end + fn.writefile({msg}, fname, flags) +end + +function M.read(fname) + if fn.filereadable(fname) == 1 then + return fn.readfile(fname, '') + else + return '' + end +end + +function M.unify_path(_path, ...) + local mod = select('1', ...) + if mod == nil then + mod = ':p' + end + local path = fn.fnamemodify(_path, mod .. ':gs?[\\\\/]?/?') + if fn.isdirectory(path) == 1 and string.sub(path, -1) ~= '/' then + return path .. '/' + elseif string.sub(_path, -1) == '/' and string.sub(path, -1) ~= '/' then + return path .. '/' + else + return path + end +end + +function M.path_to_fname(path) + return fn.substitute(M.unify_path(path), '[\\/:;.]', '_', 'g') +end + + + +function M.findfile(what, where, ...) + -- let old_suffixesadd = &suffixesadd + -- let &suffixesadd = '' + local count = select('1', ...) + if count == nil then + count = 0 + end + + local file = '' + + if fn.filereadable(where) == 1 and fn.isdirectory(where) == 0 then + path = fn.fnamemodify(where, ':h') + else + path = where + end + if count > 0 then + file = fn.findfile(what, fn.escape(path, ' ') .. ';', count) + elseif #{...} == 0 then + file = fn.findfile(what, fn.escape(path, ' ') .. ';') + elseif count == 0 then + file = fn.findfile(what, fn.escape(path, ' ') .. ';', -1) + else + file = fn.get(fn.findfile(what, fn.escape(path, ' ') .. ';', -1), count, '') + end + -- let &suffixesadd = old_suffixesadd + return file +end + +function M.finddir(what, where, ...) + -- let old_suffixesadd = &suffixesadd + -- let &suffixesadd = '' + local count = select('1', ...) + if count == nil then + count = 0 + end + local path = '' + local file = '' + if fn.filereadable(where) == 1 and fn.isdirectory(where) == 0 then + path = fn.fnamemodify(where, ':h') + else + path = where + end + if count > 0 then + file = fn.finddir(what, fn.escape(path, ' ') .. ';', count) + elseif #{...} == 0 then + file = fn.finddir(what, fn.escape(path, ' ') .. ';') + elseif count == 0 then + file = fn.finddir(what, fn.escape(path, ' ') .. ';', -1) + else + file = fn.get(fn.finddir(what, fn.escape(path, ' ') .. ';', -1), count, '') + end + -- let &suffixesadd = old_suffixesadd + return file +end + +return M diff --git a/lua/spacevim/api/vim/compatible.lua b/lua/spacevim/api/vim/compatible.lua new file mode 100644 index 000000000..a4001c90e --- /dev/null +++ b/lua/spacevim/api/vim/compatible.lua @@ -0,0 +1,41 @@ +local M = {} + +local system = require('spacevim.api').import('system') +local fn = nil +local has = nil + +if vim.fn == nil then + fn = require('spacevim').fn +else + fn = vim.fn +end + +if vim.api == nil then + has = require('spacevim').has +else + if vim.fn ~= nil then + has = vim.fn.has + else + has = require('spacevim').has + end +end + +local has_cache = {} + +function M.has(feature) + if has_cache[feature] ~= nil then + return has_cache[feature] + end +end + +if has('patch-7.4.279') then + function M.globpath(dir, expr) + return fn.globpath(dir, expr, 1, 1) + end +else + function M.globpath(dir, expr) + return fn.split(fn.globpath(dir, expr), "\n") + end +end + +return M diff --git a/test/api/file.vader b/test/api/file.vader index 6ba7f94ff..38795add2 100644 --- a/test/api/file.vader +++ b/test/api/file.vader @@ -1,5 +1,4 @@ Execute ( SpaceVim api: file.fticon ): - let &encoding = 'utf-8' let g:spacevim_filetype_icons = {} let file = SpaceVim#api#import('file') AssertEqual file.fticon('foo.md'), '' diff --git a/test/lua/api/file.vader b/test/lua/api/file.vader new file mode 100644 index 000000000..0867bf366 --- /dev/null +++ b/test/lua/api/file.vader @@ -0,0 +1,35 @@ +Execute ( SpaceVim lua api: file.fticon(ft) ): + let file = SpaceVim#api#import('file') + let cmp = SpaceVim#api#import('vim#compatible') + lua spacevim_file = require('spacevim.api').import('file') + AssertEqual cmp.luaeval('spacevim_file.fticon("foo.md")'), file.fticon('foo.md') + AssertEqual cmp.luaeval('spacevim_file.fticon("foo.mdxx")'), file.fticon('foo.mdxx') + +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') + 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") + +Execute ( SpaceVim lua api: file.path_to_fname(path) ): + let file = SpaceVim#api#import('file') + let cmp = SpaceVim#api#import('vim#compatible') + lua spacevim_file = require('spacevim.api').import('file') + AssertEqual cmp.luaeval('spacevim_file.path_to_fname(".SpaceVim.d/init.vim")'), + \ file.path_to_fname('.SpaceVim.d/init.vim') + +Execute ( SpaceVim lua api: file.findfile(what, where, ...) ): + let file = SpaceVim#api#import('file') + let cmp = SpaceVim#api#import('vim#compatible') + lua spacevim_file = require('spacevim.api').import('file') + lua if vim.fn == nil then fn = require('spacevim').fn else fn = vim.fn end + AssertEqual cmp.luaeval('spacevim_file.finddir("doc/", fn.fnamemodify("bundle/dein.vim/autoload/dein.vim", ":p:."))'), + \ file.finddir("doc/", fnamemodify("bundle/dein.vim/autoload/dein.vim", ":p:.")) + AssertEqual cmp.luaeval('spacevim_file.unify_path(spacevim_file.findfile("vimrc", "bundle/dein.vim/autoload/dein.vim"), ":.")'), + \ file.unify_path(file.findfile("vimrc", "bundle/dein.vim/autoload/dein.vim"), ":.") + lua spacevim_file = nil