Skip to content

Lua: Allow reading and setting the current console input line

Zackhasacat requested to merge zackhasacat/openmw:console_command into master

This MR allows lua scripts to read and set the console input line, enabling them to do things like autocomplete.

ui.getConsoleInput() will return the console's input, but only if in lua mode, and the console window is open.

Here is a demonstration script. For brevity's sake, it will not actually teleport the player, only autocomplete the line.

getConsoleInput() returns string, not string_view, because that's how it's stored in the UI. I tried converting it but it did not work well.

coctest_p.lua
--
local ui = require("openmw.ui")
local input = require("openmw.input")
local cellNames = nil

local function getCellsThatStartWith(txt)
    local ret = {}
    for index, value in ipairs(cellNames) do
        if string.sub(value, 1, #txt):lower() == txt:lower() then
            table.insert(ret, value)
        end
    end
    return ret
end
local tabCount = 1
local originalLine = nil
local function getEntry(tbl, position)
    local length = #tbl
    if position > length then
        return tbl[length]
    else
        return tbl[position]
    end
end
local function sortStrings(list)
    local size = #list
    local swapped = true

    while swapped do
        swapped = false

        for i = 1, size - 1 do
            if list[i] > list[i + 1] then
                list[i], list[i + 1] = list[i + 1], list[i]
                swapped = true
            end
        end

        size = size - 1
    end
end
local function onKeyPress(key)
    if key.code == input.KEY.Tab then
        local cline = ui.getConsoleInput()
        --Above line returns a valid string only if the console is open, and in lua mode.
        print(cline)
        if cline and cline ~= "" then
            if string.sub(cline, 1, 3) == "coc" then
                local searchString = string.sub(cline, 5) -- Remove "coc " from the start
                if (originalLine == nil) then
                    originalLine = searchString
                end
                local valid = getCellsThatStartWith(originalLine)
                sortStrings(valid)
                if (key.withShift and tabCount > 1) then
                    tabCount = tabCount - 1
                    ui.showMessage("Shift Tab Press")
                end
                if next(valid) and valid[1] ~= cline then
                    local nline = getEntry(valid, tabCount)
                    ui.setConsoleInput("coc " .. nline)
                end
                if (not key.withShift and #valid > tabCount) then
                    tabCount = tabCount + 1
                    ui.showMessage("Tab Press")
                end
            end
        else
            ui.showMessage("UI Nil")
        end
    elseif key.code == input.KEY.Enter then
        tabCount = 1
        originalLine = nil
    elseif key.code == input.KEY.Backspace then
        tabCount = 1
        originalLine = nil
    end
end


return {
    eventHandlers = {
        recieveCellNames = function(c)
            cellNames = c--takes a table of cell names from a global script
        end
    },
    engineHandlers = {
        onKeyPress = onKeyPress
    }
}
coctest_g.lua
--
local world = require("openmw.world")
local types = require("openmw.types")
local function sendData()
    local player = nil
    for index, act in ipairs(world.activeActors) do
        if act.type == types.Player then
            player = act
            break
        end
    end
    local cellNames = {}
    for i, cell in ipairs(world.cells) do
        if (cell.name ~= nil and cell.name ~= "") then
            table.insert(cellNames, cell.name)
        end
    end
    player:sendEvent("recieveCellNames", cellNames)
end



return {
    engineHandlers = {
        onPlayerAdded = sendData,
        onLoad = sendData
    }
}
coctest.omwscripts
--
PLAYER:scripts/coctest_p.lua
GLOBAL:scripts/coctest_g.lua
Edited by Zackhasacat

Merge request reports