diff --git a/.gitignore b/.gitignore index ec2481e..fc3fcd3 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ tags # Persistent undo [._]*.un~ +# Plug +plugged + diff --git a/autoload/tui.vim b/autoload/tui.vim index 7091642..8c22455 100644 --- a/autoload/tui.vim +++ b/autoload/tui.vim @@ -2,6 +2,11 @@ vim9script export def Init(tui_home: string) tui#core#cached#Set("tui.home", tui_home) + # 加载插件 + tui#core#plug#Init(expand(tui_home .. "/plugged")) + # 加载模块 tui#core#layer#Init(expand(tui_home .. "/layers")) + # 加载插件 + tui#core#plug#Hook() enddef diff --git a/autoload/tui/core/plug.vim b/autoload/tui/core/plug.vim new file mode 100644 index 0000000..50a8425 --- /dev/null +++ b/autoload/tui/core/plug.vim @@ -0,0 +1,188 @@ +vim9script + +# tui_plug: { +# home: 'xxx', +# registed: { +# plug_id: { +# id: 'xxx/yyy', +# deps: [], +# path: '/path/to/plug/installed' +# } +# }, +# enabled: [], +# disabled: [] +# } + +export def Init(plug_home: string = v:none) + if !tui#core#cached#Has("tui.plug.home") + # 初始化插件路径 + const tui_home = tui#core#cached#Get("tui.home") + var tui_plug_home = plug_home + if empty(tui_plug_home) || empty(split(tui_plug_home)) + tui_plug_home = tui#util#path#Join(tui_home, "plugged") + endif + tui#core#cached#Set("tui.plug.home", tui_plug_home) + # 初始化插件缓存 + tui#core#cached#Set('tui.plug.registed', {}) + tui#core#cached#Set('tui.plug.enabled', []) + tui#core#cached#Set('tui.plug.disabled', []) + endif +enddef + +export def IsPlugRegisted(plug_id: string): bool + assert_true(!empty(plug_id) && !empty(split(plug_id))) + + var tui_plug_registed = tui#core#cached#Get('tui.plug.registed', {}) + return has_key(tui_plug_registed, plug_id) +enddef + +export def IsPlugEnabled(plug_id: string): bool + assert_true(!empty(plug_id) && !empty(split(plug_id))) + + var tui_plug_registed = tui#core#cached#Get('tui.plug.registed', {}) + var tui_plug_enabled = tui#core#cached#Get('tui.plug.enabled', []) + return has_key(tui_plug_registed, plug_id) && index(tui_plug_enabled, plug_id) >= 0 +enddef + +export def GetPlug(plug_id: string): dict + assert_true(!empty(plug_id) && !empty(split(plug_id))) + + var tui_plug_registed = tui#core#cached#Get('tui.plug.registed', {}) + return tui_plug_registed[plug_id] +enddef + + +export def Regist(plug_id: string, plug_options: dict = {}) + assert_true(!empty(plug_id) && !empty(split(plug_id))) + + if IsPlugRegisted(plug_id) + return + endif + + var tui_plug_registed = tui#core#cached#Get('tui.plug.registed', {}) + var plug_info = Parse(plug_id, plug_options) + var plug_deps = [] + for plug_dep_info in plug_info['deps'] + var plug_dep_id = plug_dep_info['id'] + if !has_key(tui_plug_registed, plug_dep_id) + tui_plug_registed[plug_dep_id] = plug_dep_info + endif + add(plug_deps, plug_dep_id) + endfor + plug_info['deps'] = plug_deps + + tui_plug_registed[plug_id] = plug_info + tui#core#cached#Set('tui.plug.registed', tui_plug_registed) +enddef + +def Parse(plug_id: string, plug_options: dict = {}): dict + assert_true(!empty(plug_id) && !empty(split(plug_id))) + if IsPlugRegisted(plug_id) + return GetPlug(plug_id) + endif + + var plug_info = {} + # id: string + plug_info['id'] = plug_id + # path: string + const plug_path = tui#util#path#Join(tui#core#cached#Get('tui.plug.home'), split(plug_id, '/')[-1]) + plug_info['path'] = plug_path + # enabled: bool / func + var plug_enabled = v:true + if has_key(plug_options, 'enabled') + var Tmp_plug_enabled = plug_options['enabled'] + + assert_true(type(Tmp_plug_enabled) == v:t_number || type(Tmp_plug_enabled) == v:t_bool || type(Tmp_plug_enabled) == v:t_func) + if type(Tmp_plug_enabled) == v:t_number + assert_true(Tmp_plug_enabled == 0 || Tmp_plug_enabled == 1) + if Tmp_plug_enabled != 1 + plug_enabled = v:false + endif + elseif type(Tmp_plug_enabled) == v:t_bool + plug_enabled = Tmp_plug_enabled + else + plug_enabled = Tmp_plug_enabled() + endif + endif + plug_info['enabled'] = plug_enabled + # config: func + if has_key(plug_options, 'config') + assert_true(type(plug_options['config']) == v:t_func) + plug_info['config'] = plug_options['config'] + endif + # deps + var plug_deps = [] + if has_key(plug_options, 'deps') + var tmp_plug_deps = plug_options['deps'] + assert_true(type(tmp_plug_deps) == v:t_list) + for tmp_plug_dep in tmp_plug_deps + assert_true(type(tmp_plug_dep) == v:t_string || type(tmp_plug_dep) == v:t_dict) + + if type(tmp_plug_dep) == v:t_string + var tmp_plug_dep_id = tmp_plug_dep + var tmp_plug_dep_info = Parse(tmp_plug_dep_id, {}) + add(plug_deps, tmp_plug_dep_info) + else + assert_true(has_key(tmp_plug_dep, 'id')) + var tmp_plug_dep_id = tmp_plug_dep['id'] + var tmp_plug_dep_info = Parse(tmp_plug_dep_id, tmp_plug_dep) + add(plug_deps, tmp_plug_dep_info) + endif + endfor + endif + plug_info['deps'] = plug_deps + + return plug_info +enddef + +export def Hook() + var tui_plug_registed = tui#core#cached#Get('tui.plug.registed', {}) + var tui_plug_enabled = tui#core#cached#Get('tui.plug.enabled', []) + var tui_plug_disabled = tui#core#cached#Get('tui.plug.disabled', []) + + for plug_id in keys(tui_plug_registed) + var plug_info = tui_plug_registed[plug_id] + + if Hook_loading(plug_id, plug_info) + if index(tui_plug_enabled, plug_id) == -1 + add(tui_plug_enabled, plug_id) + endif + else + if index(tui_plug_disabled, plug_id) == -1 + add(tui_plug_disabled, plug_id) + endif + endif + endfor + + tui#core#cached#Set('tui.plug.enabled', tui_plug_enabled) + tui#core#cached#Set('tui.plug.disabled', tui_plug_disabled) +enddef + +def Hook_loading(plug_id: string, plug_info: dict): bool + var plug_path = plug_info['path'] + var plug_enabled = plug_info['enabled'] + + if !plug_enabled || !isdirectory(plug_path) + return v:false + endif + + var dep_loaded = v:true + for plug_dep_id in plug_info['deps'] + var plug_dep = GetPlug(plug_dep_id) + if !Hook_loading(plug_dep_id, plug_dep) + dep_loaded = v:false + break + endif + endfor + + if dep_loaded + execute('set rtp+=' .. plug_path) + if has_key(plug_info, 'config') + plug_info['config']() + endif + endif + + return dep_loaded +enddef + + diff --git a/autoload/tui/util/osinfo.vim b/autoload/tui/util/osinfo.vim new file mode 100644 index 0000000..1f13309 --- /dev/null +++ b/autoload/tui/util/osinfo.vim @@ -0,0 +1,13 @@ +vim9script + +export def IsOsWindows(): bool + return has('win32') +enddef + +export def GetFileSeparator(): string + return IsOsWindows() ? '\' : '/' +enddef + +export def GetLineSeparator(): string + return IsOsWindows() ? "\r\n" : "\n" +enddef diff --git a/autoload/tui/util/path.vim b/autoload/tui/util/path.vim new file mode 100644 index 0000000..4a4e227 --- /dev/null +++ b/autoload/tui/util/path.vim @@ -0,0 +1,22 @@ +vim9script + +import autoload "tui/util/osinfo.vim" + +export def GetFileSeparator(): string + return osinfo.GetFileSeparator() +enddef + +export def Normalize(path: string): string + assert_true(!empty(path) && !empty(split(path))) + + const path_joined = join(filter(split(path, '[/\\]'), '!empty(split(v:val))'), GetFileSeparator()) + return expand(match(path, '^[/\\]') != -1 ? (GetFileSeparator() .. path_joined) : path_joined) +enddef + +export def Join(parent: string, ...subs: list): string + assert_true(!empty(parent) && !empty(split(parent))) + + const path_joined = join(extend([parent], subs), GetFileSeparator()) + return Normalize(path_joined) +enddef + diff --git a/layers/init.vim b/layers/init.vim index d120988..355869c 100644 --- a/layers/init.vim +++ b/layers/init.vim @@ -2,4 +2,4 @@ vim9script TuiLayer base -# TuiLayer plug +TuiLayer plug diff --git a/layers/plug/colorscheme.vim b/layers/plug/colorscheme.vim new file mode 100644 index 0000000..6c67d70 --- /dev/null +++ b/layers/plug/colorscheme.vim @@ -0,0 +1,4 @@ +vim9script + +tui#core#plug#Regist('flazz/vim-colorschemes') + diff --git a/layers/plug/init.vim b/layers/plug/init.vim new file mode 100644 index 0000000..83f5759 --- /dev/null +++ b/layers/plug/init.vim @@ -0,0 +1,6 @@ +vim9script + +TuiLayer plug.colorscheme + +TuiLayer plug.nerdtree + diff --git a/layers/plug/nerdtree.vim b/layers/plug/nerdtree.vim new file mode 100644 index 0000000..4bf83aa --- /dev/null +++ b/layers/plug/nerdtree.vim @@ -0,0 +1,13 @@ +vim9script + +tui#core#plug#Regist('preservim/nerdtree', { + deps: [ + 'ryanoasis/vim-devicons', + 'tiagofumo/vim-nerdtree-syntax-highlight', + ], + config: () => { + final g:NERDTreeFileLines = 1 + nnoremap vf :NERDTreeToggle + } +}) +