mirror of
				https://github.com/kepler155c/opus
				synced 2025-10-30 23:23:03 +00:00 
			
		
		
		
	debugger support
This commit is contained in:
		| @@ -7,47 +7,47 @@ local shell = _ENV.shell | |||||||
| local URL = 'https://raw.githubusercontent.com/kepler155c/opus/%s/.opus_version' | local URL = 'https://raw.githubusercontent.com/kepler155c/opus/%s/.opus_version' | ||||||
|  |  | ||||||
| if fs.exists('.opus_version') then | if fs.exists('.opus_version') then | ||||||
|     local f = fs.open('.opus_version', 'r') | 	local f = fs.open('.opus_version', 'r') | ||||||
|     local date = f.readLine() | 	local date = f.readLine() | ||||||
|     f.close() | 	f.close() | ||||||
|     date = type(date) == 'string' and Util.split(date)[1] | 	date = type(date) == 'string' and Util.split(date)[1] | ||||||
|  |  | ||||||
|     local today = os.date('%j') | 	local today = os.date('%j') | ||||||
|     local config = Config.load('version', { | 	local config = Config.load('version', { | ||||||
|         packages = date, | 		packages = date, | ||||||
|         checked = today, | 		checked = today, | ||||||
|     }) | 	}) | ||||||
|  |  | ||||||
|     -- check if packages need an update | 	-- check if packages need an update | ||||||
|     if date ~= config.packages then | 	if date ~= config.packages then | ||||||
|         config.packages = date | 		config.packages = date | ||||||
|         Config.update('version', config) | 		Config.update('version', config) | ||||||
|         print('Updating packages') | 		print('Updating packages') | ||||||
|         shell.run('package updateall') | 		shell.run('package updateall') | ||||||
|         os.reboot() | 		os.reboot() | ||||||
|     end | 	end | ||||||
|  |  | ||||||
|     if type(date) == 'string' and #date > 0 then | 	if type(date) == 'string' and #date > 0 then | ||||||
|         if config.checked ~= today then | 		if config.checked ~= today then | ||||||
|             config.checked = today | 			config.checked = today | ||||||
|             Config.update('version', config) | 			Config.update('version', config) | ||||||
|             print('Checking for new version') | 			print('Checking for new version') | ||||||
|             pcall(function() | 			pcall(function() | ||||||
|                 local c = Util.httpGet(string.format(URL, _G.OPUS_BRANCH)) | 				local c = Util.httpGet(string.format(URL, _G.OPUS_BRANCH)) | ||||||
|                 if c then | 				if c then | ||||||
|                     local lines = Util.split(c) | 					local lines = Util.split(c) | ||||||
|                     local revdate = table.remove(lines, 1) | 					local revdate = table.remove(lines, 1) | ||||||
|                     if date ~= revdate and config.skip ~= revdate then | 					if date ~= revdate and config.skip ~= revdate then | ||||||
|                         config.current = revdate | 						config.current = revdate | ||||||
|                         config.details = table.concat(lines, '\n') | 						config.details = table.concat(lines, '\n') | ||||||
|                         Config.update('version', config) | 						Config.update('version', config) | ||||||
|                         print('New version available') | 						print('New version available') | ||||||
|                         if _ENV.multishell then | 						if _ENV.multishell then | ||||||
|                             shell.openForegroundTab('sys/apps/Version.lua') | 							shell.openForegroundTab('sys/apps/Version.lua') | ||||||
|                         end | 						end | ||||||
|                     end | 					end | ||||||
|                 end | 				end | ||||||
|             end) | 			end) | ||||||
|         end | 		end | ||||||
|     end | 	end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -1,5 +1,20 @@ | |||||||
| local fs = _G.fs | local fs = _G.fs | ||||||
|  |  | ||||||
|  | -- override bios function to include the actual filename | ||||||
|  | function _G.loadfile(filename, env) | ||||||
|  |     -- Support the previous `loadfile(filename, env)` form instead. | ||||||
|  |     if type(mode) == "table" and env == nil then | ||||||
|  |         mode, env = nil, mode | ||||||
|  |     end | ||||||
|  |  | ||||||
|  |     local file = fs.open(filename, "r") | ||||||
|  |     if not file then return nil, "File not found" end | ||||||
|  |  | ||||||
|  |     local func, err = load(file.readAll(), '@' .. filename, mode, env) | ||||||
|  |     file.close() | ||||||
|  |     return func, err | ||||||
|  | end | ||||||
|  |  | ||||||
| local sandboxEnv = setmetatable({ }, { __index = _G }) | local sandboxEnv = setmetatable({ }, { __index = _G }) | ||||||
| for k,v in pairs(_ENV) do | for k,v in pairs(_ENV) do | ||||||
| 	sandboxEnv[k] = v | 	sandboxEnv[k] = v | ||||||
|   | |||||||
| @@ -42,5 +42,5 @@ end | |||||||
|  |  | ||||||
| -- non-standard - will raise error instead | -- non-standard - will raise error instead | ||||||
| os.exit = function(code) | os.exit = function(code) | ||||||
| 	error('Terminated with ' .. code) | 	error(code) | ||||||
| end | end | ||||||
|   | |||||||
| @@ -7,41 +7,41 @@ local sub   = string.sub | |||||||
| -- https://rosettacode.org/wiki/Jaro_distance (ported to lua) | -- https://rosettacode.org/wiki/Jaro_distance (ported to lua) | ||||||
| return function(s1, s2) | return function(s1, s2) | ||||||
| 	local l1, l2 = #s1, #s2; | 	local l1, l2 = #s1, #s2; | ||||||
|     if l1 == 0 then | 	if l1 == 0 then | ||||||
| 		return l2 == 0 and 1.0 or 0.0 | 		return l2 == 0 and 1.0 or 0.0 | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	local match_distance = max(floor(max(l1, l2) / 2) - 1, 0) | 	local match_distance = max(floor(max(l1, l2) / 2) - 1, 0) | ||||||
|     local s1_matches = { } | 	local s1_matches = { } | ||||||
|     local s2_matches = { } | 	local s2_matches = { } | ||||||
|     local matches = 0 | 	local matches = 0 | ||||||
|  |  | ||||||
| 	for i = 1, l1 do | 	for i = 1, l1 do | ||||||
|         local _end = min(i + match_distance + 1, l2) | 		local _end = min(i + match_distance + 1, l2) | ||||||
| 		for k = max(1, i - match_distance), _end do | 		for k = max(1, i - match_distance), _end do | ||||||
|             if not s2_matches[k] and sub(s1, i, i) == sub(s2, k, k) then | 			if not s2_matches[k] and sub(s1, i, i) == sub(s2, k, k) then | ||||||
|                 s1_matches[i] = true | 				s1_matches[i] = true | ||||||
|                 s2_matches[k] = true | 				s2_matches[k] = true | ||||||
|                 matches = matches + 1 | 				matches = matches + 1 | ||||||
|                 break | 				break | ||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
|     if matches == 0 then | 	if matches == 0 then | ||||||
| 		return 0.0 | 		return 0.0 | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
|     local t = 0.0 | 	local t = 0.0 | ||||||
|     local k = 1 | 	local k = 1 | ||||||
| 	for i = 1, l1 do | 	for i = 1, l1 do | ||||||
|         if s1_matches[i] then | 		if s1_matches[i] then | ||||||
| 			while not s2_matches[k] do | 			while not s2_matches[k] do | ||||||
| 				k = k + 1 | 				k = k + 1 | ||||||
| 			end | 			end | ||||||
| 			if sub(s1, i, i) ~= sub(s2, k, k) then | 			if sub(s1, i, i) ~= sub(s2, k, k) then | ||||||
| 				t = t + 0.5 | 				t = t + 0.5 | ||||||
| 			end | 			end | ||||||
|             k = k + 1 | 			k = k + 1 | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| @@ -51,6 +51,6 @@ return function(s1, s2) | |||||||
| 		b = b + .5 | 		b = b + .5 | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
|     local m = matches | 	local m = matches | ||||||
|     return (m / l1 + m / l2 + (m - t) / m) / 3.0 + b | 	return (m / l1 + m / l2 + (m - t) / m) / 3.0 + b | ||||||
| end | end | ||||||
|   | |||||||
| @@ -12,6 +12,10 @@ local function traceback(x) | |||||||
| 		return x | 		return x | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
|  | 	if x and x:match(':%d+: 0$') then | ||||||
|  | 		return x | ||||||
|  | 	end | ||||||
|  |  | ||||||
| 	if debug_traceback then | 	if debug_traceback then | ||||||
| 		-- The parens are important, as they prevent a tail call occuring, meaning | 		-- The parens are important, as they prevent a tail call occuring, meaning | ||||||
| 		-- the stack level is preserved. This ensures the code behaves identically | 		-- the stack level is preserved. This ensures the code behaves identically | ||||||
| @@ -65,7 +69,7 @@ local function trim_traceback(stack) | |||||||
| 	local t = { } | 	local t = { } | ||||||
| 	for _, line in pairs(trace) do | 	for _, line in pairs(trace) do | ||||||
| 		if not matchesFilter(line) then | 		if not matchesFilter(line) then | ||||||
| 			line = line:gsub("in function", "in") | 			line = line:gsub("in function", "in"):gsub('%w+/', '') | ||||||
| 			table.insert(t, line) | 			table.insert(t, line) | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| @@ -84,9 +88,15 @@ return function (fn, ...) | |||||||
| 	if not res[1] and res[2] ~= nil then | 	if not res[1] and res[2] ~= nil then | ||||||
| 		local err, trace = trim_traceback(res[2]) | 		local err, trace = trim_traceback(res[2]) | ||||||
|  |  | ||||||
| 		_G._syslog('\n' .. err .. '\n' .. 'stack traceback:') | 		if #trace > 0 then | ||||||
| 		for _, v in ipairs(trace) do | 			_G._syslog('\n' .. err .. '\n' .. 'stack traceback:') | ||||||
| 			_G._syslog(v) | 			for _, v in ipairs(trace) do | ||||||
|  | 				_G._syslog(v) | ||||||
|  | 			end | ||||||
|  | 		end | ||||||
|  |  | ||||||
|  | 		if err:match(':%d+: 0$') then | ||||||
|  | 			return true | ||||||
| 		end | 		end | ||||||
|  |  | ||||||
| 		return res[1], err, trace | 		return res[1], err, trace | ||||||
|   | |||||||
							
								
								
									
										107
									
								
								sys/modules/opus/ui/components/QuickSelect.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								sys/modules/opus/ui/components/QuickSelect.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,107 @@ | |||||||
|  | local class = require('opus.class') | ||||||
|  | local fuzzy = require('opus.fuzzy') | ||||||
|  | local UI    = require('opus.ui') | ||||||
|  |  | ||||||
|  | local fs      = _G.fs | ||||||
|  | local _insert = table.insert | ||||||
|  |  | ||||||
|  | UI.QuickSelect = class(UI.Window) | ||||||
|  | UI.QuickSelect.defaults = { | ||||||
|  | 	UIElement = 'QuickSelect', | ||||||
|  | } | ||||||
|  | function UI.QuickSelect:postInit() | ||||||
|  | 	self.filterEntry = UI.TextEntry { | ||||||
|  | 		x = 2, y = 2, ex = -2, | ||||||
|  | 		shadowText = 'File name', | ||||||
|  | 		accelerators = { | ||||||
|  | 			[ 'enter' ] = 'accept', | ||||||
|  | 			[ 'up' ] = 'grid_up', | ||||||
|  | 			[ 'down' ] = 'grid_down', | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	self.grid = UI.ScrollingGrid { | ||||||
|  | 		x = 2, y = 3, ex = -2, ey = -4, | ||||||
|  | 		disableHeader = true, | ||||||
|  | 		columns = { | ||||||
|  | 			{ key = 'name' }, | ||||||
|  | 			{ key = 'dir', textColor = 'lightGray' }, | ||||||
|  | 		}, | ||||||
|  | 		accelerators = { | ||||||
|  | 			grid_select = 'accept', | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	self.cancel = UI.Button { | ||||||
|  | 		x = -9, y = -2, | ||||||
|  | 		text = 'Cancel', | ||||||
|  | 		event = 'select_cancel', | ||||||
|  | 	} | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function UI.QuickSelect:draw() | ||||||
|  | 	self:fillArea(1, 1, self.width, self.height, string.rep('\127', self.width), 'black', 'gray') | ||||||
|  | 	self:drawChildren() | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function UI.QuickSelect:applyFilter(filter) | ||||||
|  | 	if filter then | ||||||
|  | 		filter = filter:lower() | ||||||
|  | 		self.grid.sortColumn = 'score' | ||||||
|  |  | ||||||
|  | 		for _,v in pairs(self.grid.values) do | ||||||
|  | 			v.score = -fuzzy(v.lname, filter) | ||||||
|  | 		end | ||||||
|  | 	else | ||||||
|  | 		self.grid.sortColumn = 'lname' | ||||||
|  | 	end | ||||||
|  |  | ||||||
|  | 	self.grid:update() | ||||||
|  | 	self.grid:setIndex(1) | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function UI.QuickSelect:enable() | ||||||
|  | 	self.grid.values = { } | ||||||
|  | 	local function recurse(dir) | ||||||
|  | 		local files = fs.list(dir) | ||||||
|  | 		for _,f in ipairs(files) do | ||||||
|  | 			local fullName = fs.combine(dir, f) | ||||||
|  | 			if fs.native.isDir(fullName) then -- skip virtual dirs | ||||||
|  | 				if f ~= '.git' then recurse(fullName) end | ||||||
|  | 			else | ||||||
|  | 				_insert(self.grid.values, { | ||||||
|  | 					name = f, | ||||||
|  | 					dir = dir, | ||||||
|  | 					lname = f:lower(), | ||||||
|  | 					fullName = fullName, | ||||||
|  | 				}) | ||||||
|  | 			end | ||||||
|  | 		end | ||||||
|  | 	end | ||||||
|  | 	recurse('') | ||||||
|  | 	self:applyFilter() | ||||||
|  | 	self.filterEntry:reset() | ||||||
|  | 	UI.Window.enable(self) | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function UI.QuickSelect:eventHandler(event) | ||||||
|  | 	if event.type == 'grid_up' then | ||||||
|  | 		self.grid:emit({ type = 'scroll_up' }) | ||||||
|  | 		return true | ||||||
|  |  | ||||||
|  | 	elseif event.type == 'grid_down' then | ||||||
|  | 		self.grid:emit({ type = 'scroll_down' }) | ||||||
|  | 		return true | ||||||
|  |  | ||||||
|  | 	elseif event.type == 'accept' then | ||||||
|  | 		local sel = self.grid:getSelected() | ||||||
|  | 		if sel then | ||||||
|  | 			self:emit({ type = 'select_file', file = sel.fullName, element = self }) | ||||||
|  | 		end | ||||||
|  | 		return true | ||||||
|  |  | ||||||
|  | 	elseif event.type == 'text_change' then | ||||||
|  | 		self:applyFilter(event.text) | ||||||
|  | 		self.grid:draw() | ||||||
|  | 		return true | ||||||
|  |  | ||||||
|  | 	end | ||||||
|  | end | ||||||
		Reference in New Issue
	
	Block a user
	 kepler155c@gmail.com
					kepler155c@gmail.com