local progress = require 'progress' local lang = require 'language' local await = require 'await' local files = require 'files' local config = require 'config.config' local client = require 'client' local util = require 'utility' local furi = require 'file-uri' local pub = require 'pub' ---@class workspace.loading ---@field scp scope ---@field _bar progress ---@field _stash function[] ---@field _refs uri[] ---@field _cache table ---@field _sets function[] ---@field _removed boolean local mt = {} mt.__index = mt mt._loadLock = false mt.read = 0 mt.max = 0 mt.preload = 0 function mt:__close() self:remove() end function mt:update() self._bar:setMessage(('%d/%d'):format(self.read, self.max)) self._bar:setPercentage(self.read / self.max * 100.0) end ---@param uri uri function mt:checkMaxPreload(uri) local max = config.get(uri, 'Lua.workspace.maxPreload') if self.preload <= max then return true end if self.scp:get 'hasHintedMaxPreload' then return false end self.scp:set('hasHintedMaxPreload', true) client.requestMessage('Info' , lang.script('MWS_MAX_PRELOAD', max) , { lang.script('WINDOW_INCREASE_UPPER_LIMIT'), } , function (_, index) if index == 1 then client.setConfig { { key = 'Lua.workspace.maxPreload', uri = self.scp.uri, action = 'set', value = max + math.max(1000, max), } } end end ) return false end ---@param uri uri ---@param libraryUri? uri ---@async function mt:loadFile(uri, libraryUri) if files.isLua(uri) then if not libraryUri then self.preload = self.preload + 1 if not self:checkMaxPreload(uri) then return end end self.max = self.max + 1 self:update() ---@async self._stash[#self._stash+1] = function () if files.getFile(uri) then self.read = self.read + 1 self:update() if not self._cache[uri] then files.addRef(uri) end self._cache[uri] = true log.debug(('Skip loaded file: %s'):format(uri)) else local content = pub.awaitTask('loadFile', furi.decode(uri)) self.read = self.read + 1 self:update() if not content then return end log.debug(('Preload file at: %s , size = %.3f KB'):format(uri, #content / 1024.0)) --await.wait(function (waker) -- self._sets[#self._sets+1] = waker --end) files.setText(uri, content, false) if COMPILECORES then files.compileStateAsync(uri, function (state) end) else files.compileState(uri) end if not self._cache[uri] then files.addRef(uri) end self._cache[uri] = true end if libraryUri then log.debug('++++As library of:', libraryUri) end end elseif files.isDll(uri) then self.max = self.max + 1 self:update() ---@async self._stash[#self._stash+1] = function () if files.getFile(uri) then self.read = self.read + 1 self:update() if not self._cache[uri] then files.addRef(uri) end self._cache[uri] = true log.debug(('Skip loaded file: %s'):format(uri)) else local content = pub.awaitTask('loadFile', furi.decode(uri)) self.read = self.read + 1 self:update() if not content then return end log.debug(('Preload dll at: %s , size = %.3f KB'):format(uri, #content / 1024.0)) --await.wait(function (waker) -- self._sets[#self._sets+1] = waker --end) files.saveDll(uri, content) if not self._cache[uri] then files.addRef(uri) end self._cache[uri] = true end if libraryUri then log.debug('++++As library of:', libraryUri) end end end await.delay() end ---@async function mt:loadAll(fileName) local startClock = os.clock() log.info('Load files from disk:', fileName) while self.read < self.max do self:update() local loader = table.remove(self._stash) if loader then await.call(loader) await.delay() else await.sleep(0.1) end end local loadedClock = os.clock() log.info(('Loaded files takes [%.3f] sec: %s'):format(loadedClock - startClock, fileName)) self._bar:remove() self._bar = progress.create(self.scp.uri, lang.script('WORKSPACE_LOADING', self.scp.uri), 0) for i, set in ipairs(self._sets) do await.delay() set() self.read = i self:update() end log.info(('Compile files takes [%.3f] sec: %s'):format(os.clock() - loadedClock, fileName)) log.info('Loaded finish:', fileName) end function mt:remove() if self._removed then return end self._removed = true self._bar:remove() end function mt:isRemoved() return self._removed == true end ---@class workspace.loading.manager local m = {} ---@type table m._loadings = setmetatable({}, { __mode = 'k' }) ---@return workspace.loading function m.create(scp) local loading = setmetatable({ scp = scp, _bar = progress.create(scp.uri, lang.script('WORKSPACE_LOADING', scp.uri), 0.5), _stash = {}, _cache = {}, _sets = {}, }, mt) m._loadings[loading] = true return loading end function m.count() local num = 0 for ld in pairs(m._loadings) do if ld:isRemoved() then m._loadings[ld] = nil else num = num + 1 end end return num end return m