local separators = " ()[],-+*/=<>" local function split_by_last_separator(s) for i = #s, 1, -1 do local c = s:sub(i, i) if separators:find(c, 1, true) then if i == #s then -- Separador al final return s, "" end -- Separador en medio return s:sub(1, i), s:sub(i + 1) end end -- Sin separadores return "", s end local function split_by_last_dot(s) local last = s:match(".*()%.") -- devuelve la posición DESPUÉS del último punto if not last then -- No hay puntos: primera parte = cadena completa, segunda = "" return "", s end -- Si el punto está al final, la segunda parte es "" if last > #s then return s, "" end -- Primera parte incluye el punto local first = s:sub(1, last - 1) local second = s:sub(last+1) return first, second end function get_by_path(path) local current = _G for segment in path:gmatch("[^%.]+") do if type(current) ~= "table" then return nil end current = current[segment] if current == nil then --print("get_by_path: " ..segment.." es nil") return nil end end --print("get_by_path: ok") return current end function entries_starting_with(s, t) if not t then return nil end local result = {} for k, v in pairs(t) do if type(k) == "string" and k:sub(1, #s) == s then result[#result+1] = k end end return result end console = { command = "", history = {}, history_pos = 0, cursor = 50, autocomplete_list = {}, autocomplete_prefix = "", autocomplete_index = 1, } local me = console function me.enable() app.push(me.update) me.command = "" end function me.update() surf.target(0) draw.rrectf(0, 92, 160, 108, 4, 1) draw.rrect(0, 92, 160, 108, 4, 13) draw.text(">", 2, 96, 13) draw.text(me.command, 6, 96, 13) if me.autocomplete_list and #me.autocomplete_list>0 then --local num = math.min(5, #me.autocomplete_list) --local base_y = 92-num*7 --draw.rectf(3+#me.command*4, base_y, 80, num*7, 1) --draw.rect(3+#me.command*4, base_y, 80, num*7, 13) --for i=1,num do -- draw.text(me.autocomplete_list[i], 6+#me.command*4, base_y+i*7, 13) --end local sufix = me.autocomplete_list[me.autocomplete_index]:sub(#me.autocomplete_prefix+1) draw.text(sufix, 6+#me.command*4, 96, 6) end if me.cursor > 24 then draw.text("_", 6+#me.command*4, 96, 13) end me.cursor = me.cursor - 1 if me.cursor == 0 then me.cursor = 50 end if key.press(key.ESCAPE) then app.pop() return end local should_update = false if #me.history>0 then if key.press(key.UP) and me.history_pos > 1 then me.history_pos = me.history_pos - 1 me.command = me.history[me.history_pos] should_update = true elseif key.press(key.DOWN) and me.history_pos < #me.history then me.history_pos = me.history_pos + 1 me.command = me.history[me.history_pos] should_update = true end end local k = key.press() if k ~= key.UNKNOWN then should_update = true if k >= key.A and k <= key.Z then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. string.char(k+61) else me.command = me.command .. string.char(k+93) end elseif k == key.N0 then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. '=' elseif key.down(key.RALT) then me.command = me.command .. '}' else me.command = me.command .. '0' end elseif k == key.N1 then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. '!' elseif key.down(key.RALT) then me.command = me.command .. '|' else me.command = me.command .. '1' end elseif k == key.N2 then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. '"' elseif key.down(key.RALT) then me.command = me.command .. '@' else me.command = me.command .. '2' end elseif k == key.N3 then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. '·' elseif key.down(key.RALT) then me.command = me.command .. '#' else me.command = me.command .. '3' end elseif k == key.N4 then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. '$' elseif key.down(key.RALT) then me.command = me.command .. '~' else me.command = me.command .. '4' end elseif k == key.N5 then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. '%' elseif key.down(key.RALT) then me.command = me.command .. ' ' else me.command = me.command .. '5' end elseif k == key.N6 then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. '&' elseif key.down(key.RALT) then me.command = me.command .. ' ' else me.command = me.command .. '6' end elseif k == key.N7 then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. '/' elseif key.down(key.RALT) then me.command = me.command .. ' ' else me.command = me.command .. '7' end elseif k == key.N8 then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. '(' elseif key.down(key.RALT) then me.command = me.command .. ' ' else me.command = me.command .. '8' end elseif k == key.N9 then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. ')' elseif key.down(key.RALT) then me.command = me.command .. ' ' else me.command = me.command .. '9' end elseif k == key.PERIOD then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. ':' else me.command = me.command .. '.' end elseif k == key.COMMA then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. ';' else me.command = me.command .. ',' end elseif k == key.GRAVE then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. ' ' elseif key.down(key.RALT) then me.command = me.command .. '\\' else me.command = me.command .. ' ' end elseif k == key.EQUALS then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. '¿' else me.command = me.command .. '¡' end elseif k == key.SLASH then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. '_' elseif key.down(key.RALT) then me.command = me.command .. ' ' else me.command = me.command .. '-' end elseif k == key.APOSTROPHE then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. '"' elseif key.down(key.RALT) then me.command = me.command .. '{' else me.command = me.command .. '\'' end elseif k == key.SEMICOLON then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. 'Ñ' elseif key.down(key.RALT) then me.command = me.command .. ' ' else me.command = me.command .. 'ñ' end elseif k == key.BACKSLASH then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. 'Ç' elseif key.down(key.RALT) then me.command = me.command .. '}' else me.command = me.command .. 'ç' end elseif k == key.RIGHTBRACKET then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. '*' elseif key.down(key.RALT) then me.command = me.command .. ']' else me.command = me.command .. '+' end elseif k == key.LEFTBRACKET then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. '^' elseif key.down(key.RALT) then me.command = me.command .. '[' else me.command = me.command .. '`' end elseif k == key.NONUSBACKSLASH then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. '>' elseif key.down(key.RALT) then me.command = me.command .. ' ' else me.command = me.command .. '<' end elseif k == key.MINUS then if key.down(key.LSHIFT) or key.down(key.RSHIFT) then me.command = me.command .. '?' else me.command = me.command .. '\'' end elseif k == key.SPACE then me.command = me.command .. ' ' elseif k == key.BACKSPACE then me.command = me.command:sub(1, #me.command - 1) elseif k == key.TAB then local sufix = me.autocomplete_list[me.autocomplete_index]:sub(#me.autocomplete_prefix+1) me.command = me.command .. sufix elseif k == key.RETURN then table.insert(me.history, me.command) me.history_pos = #me.history+1 local f,err = load(me.command) if not f then print("Error al compilar:", err) else print(f()) app.pop() end end end if should_update then local a, b = split_by_last_separator(me.command) if b ~= "" then local ba, bb = split_by_last_dot(b) me.autocomplete_prefix = bb if ba ~= "" then me.autocomplete_list = entries_starting_with(bb, get_by_path(ba)) --print(bb..":"..ba) --print(#me.autocomplete_list) else me.autocomplete_list = entries_starting_with(bb, _G) --print(bb..":".."golbal") --print(#me.autocomplete_list) end else me.autocomplete_prefix = "" me.autocomplete_list = entries_starting_with("", _G) --print(""..":".."golbal") --print(#me.autocomplete_list) end end end