Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch E2Helper & Wire's Text Editor to a partly modular/mode system #3127

Merged
merged 7 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 113 additions & 95 deletions lua/wire/client/e2helper.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
--[[
Expression 2 Helper for Expression 2
-HP- (and tomylobo, though he breaks a lot ^^)
Divran made CPU support
Divran made the original CPU support
Fasteroid made the "from" column
]] --

Expand All @@ -12,50 +12,53 @@ E2Helper.Descriptions = {}
include("e2descriptions.lua")

-------------------------------
---- CPU support
E2Helper.CPUDescriptions = {}
E2Helper.CPUTable = {}
E2Helper.CurrentMode = true -- E2/CPU. True = E2, false = CPU

local function AddCPUDesc(FuncName, Args, Desc, Platform, Type)
table.insert(E2Helper.CPUTable, { [1] = FuncName, [2] = Args, [3] = Platform, [4] = Type })
E2Helper.CPUDescriptions[FuncName] = Desc
end

if CPULib then
-- Add help on all opcodes
for _, instruction in ipairs(CPULib.InstructionTable) do
if (instruction.Mnemonic ~= "RESERVED") and
(not instruction.Obsolete) then
local instructionArgs = instruction.Operand1
if instruction.Operand2 ~= "" then
instructionArgs = instructionArgs .. ", " .. instruction.Operand2
end

AddCPUDesc(instruction.Mnemonic,
instructionArgs,
instruction.Reference,
instruction.Set,
instruction.Opcode)
end
---- Extension / Mode Switching Support
E2Helper.Modes = {}
E2Helper.CurrentMode = "E2" -- Key for accessing mode.

function E2Helper:RegisterMode(name)
if self.Modes[name] then
-- Don't overwrite a previously existing mode if possible
-- If an addon really wants to do so, they have access to the E2Helper mode table.
return false
else
-- Name is available, return a table to be set up by caller.
local ModeTable = {
Descriptions = {}, -- Item descriptions
Items = {}, -- Items
-- There should be a ModeSetup function here taking the E2Helper table as an argument.
-- Optionally, as well, a ModeSwitch function, taking the E2Helper as an argument.
-- Will be called on switch, before the new mode's ModeSetup, used for teardown if necessary.
}
self.Modes[name] = ModeTable
return ModeTable
end
end

-- Which tables are we going to use?
local function CurrentDescs()
if E2Helper.CurrentMode == true then
return E2Helper.Descriptions
else
return E2Helper.CPUDescriptions
end
return E2Helper.Modes[E2Helper.CurrentMode].Descriptions
end

local function CurrentTable()
if E2Helper.CurrentMode == true then
return wire_expression2_funcs
else
return E2Helper.CPUTable
return E2Helper.Modes[E2Helper.CurrentMode].Items
end

function E2Helper:SetMode(key)
local mode = self.Modes[key or false]
local curMode = self.Modes[self.CurrentMode]
if mode then
if curMode.ModeSwitch then
curMode.ModeSwitch(self) -- For teardown of previous setup if needed.
end
self.CurrentMode = key
if mode.ModeSetup then
mode.ModeSetup(self)
end
self.Update()
return true
end
return false -- No mode.
end

-------------------------------
Expand Down Expand Up @@ -105,6 +108,37 @@ local function getdesc(name, args)
return CurrentDescs()[string.format("%s(%s)", name, args)] or CurrentDescs()[name]
end

-- Register the E2 mode, this shouldn't need be done twice because it indexes global for its info
local E2Mode = E2Helper:RegisterMode("E2")
if E2Mode then
local E2ModeMetatable = {
__index = function(self,key)
if key == "Items" then return wire_expression2_funcs end
if key == "Descriptions" then return E2Helper.Descriptions end
return nil
end
}
E2Mode.Items = nil
E2Mode.Descriptions = nil
-- The metatable is needed because storing a ref to wire_expression2_funcs
-- and then causing e2 to reload (like changing extensions) doesn't update the ref
-- or something like that, it causes e2helper to access nil values.
setmetatable(E2Mode,E2ModeMetatable)
E2Mode.ModeSetup = function(E2HelperPanel)
E2HelperPanel.FunctionColumn:SetName("Function")
E2HelperPanel.FunctionColumn:SetWidth(126)
E2HelperPanel.FromColumn:SetName("From")
E2HelperPanel.FromColumn:SetWidth(80)
E2HelperPanel.TakesColumn:SetName("Takes")
E2HelperPanel.TakesColumn:SetWidth(60)
E2HelperPanel.ReturnsColumn:SetName("Returns")
E2HelperPanel.ReturnsColumn:SetWidth(60)
E2HelperPanel.CostColumn:SetName("Cost")
E2HelperPanel.CostColumn:SetWidth(40)
end

end

function E2Helper.Create(reset)

E2Helper.Frame = vgui.Create("DFrame")
Expand Down Expand Up @@ -139,14 +173,25 @@ function E2Helper.Create(reset)
E2Helper.ResultFrame:SetPos(5, 60)
E2Helper.ResultFrame:SetSize(330, 240)
E2Helper.ResultFrame:SetMultiSelect(false)
E2Helper.ResultFrame:AddColumn("Function"):SetWidth(126)
E2Helper.FromColumn = E2Helper.ResultFrame:AddColumn("From")
E2Helper.FromColumn:SetWidth(80)
E2Helper.ResultFrame:AddColumn("Takes"):SetWidth(60)
E2Helper.ReturnsColumn = E2Helper.ResultFrame:AddColumn("Returns")
E2Helper.ReturnsColumn:SetWidth(60)
E2Helper.CostColumn = E2Helper.ResultFrame:AddColumn("Cost")
E2Helper.CostColumn:SetWidth(40)
-- Default 5 columns, accessable by index here for more modularity.
E2Helper.Columns = {
E2Helper.ResultFrame:AddColumn("Function"),
E2Helper.ResultFrame:AddColumn("From"),
E2Helper.ResultFrame:AddColumn("Takes"),
E2Helper.ResultFrame:AddColumn("Returns"),
E2Helper.ResultFrame:AddColumn("Cost"),
}
E2Helper.Columns[1]:SetWidth(126)
E2Helper.Columns[2]:SetWidth(80)
E2Helper.Columns[3]:SetWidth(60)
E2Helper.Columns[4]:SetWidth(60)
E2Helper.Columns[5]:SetWidth(40)
-- Name keys for backwards compatibility
E2Helper.FunctionColumn = E2Helper.Columns[1]
E2Helper.FromColumn = E2Helper.Columns[2]
E2Helper.TakesColumn = E2Helper.Columns[3]
E2Helper.ReturnsColumn = E2Helper.Columns[4]
E2Helper.CostColumn = E2Helper.Columns[5]

function E2Helper.ResultFrame:OnClickLine(line)
self:ClearSelection()
Expand Down Expand Up @@ -239,32 +284,21 @@ function E2Helper.Create(reset)
E2Helper.MaxLabel:SetText("Max results:")
E2Helper.MaxLabel:SizeToContents()

E2Helper.E2Mode = vgui.Create("DCheckBoxLabel", E2Helper.Frame)
E2Helper.E2Mode:SetPos(90, 384)
E2Helper.E2Mode:SetText("E2")
E2Helper.E2Mode:SetValue(true)
E2Helper.E2Mode:SizeToContents()
function E2Helper.E2Mode.Button:Toggle()
self:SetValue(true)
E2Helper.CurrentMode = true
E2Helper.CPUMode:SetValue(false)
E2Helper.CostColumn:SetName("Cost")
E2Helper.ReturnsColumn:SetName("Returns")
E2Helper.Update()
E2Helper.ModeSelect = vgui.Create("DComboBox", E2Helper.Frame)
E2Helper.ModeSelect:SetPos(90, 384)
local modecount = 0
for k,_ in pairs(E2Helper.Modes) do
modecount = modecount + 1
E2Helper.ModeSelect:AddChoice(k)
end

E2Helper.CPUMode = vgui.Create("DCheckBoxLabel", E2Helper.Frame)
E2Helper.CPUMode:SetPos(90, 404)
E2Helper.CPUMode:SetText("CPU/GPU")
E2Helper.CPUMode:SetValue(false)
E2Helper.CPUMode:SizeToContents()
function E2Helper.CPUMode.Button:Toggle()
self:SetValue(true)
E2Helper.CurrentMode = false
E2Helper.E2Mode:SetValue(false)
E2Helper.CostColumn:SetName("Opcode")
E2Helper.ReturnsColumn:SetName("Platform")
E2Helper.Update()
if modecount < 2 then
-- If we don't have enough modes it's pointless to display this I think.
E2Helper.ModeSelect:Hide()
else
E2Helper.ModeSelect:Show()
end
function E2Helper.ModeSelect:OnSelect(ind,value,data)
E2Helper:SetMode(value)
end

E2Helper.NameEntry.OnTextChanged = delayed(0.1, E2Helper.Update)
Expand Down Expand Up @@ -293,7 +327,7 @@ function E2Helper.Create(reset)
end

function E2Helper.GetFunctionSyntax(func, args, rets)
if E2Helper.CurrentMode == true then
if E2Helper.CurrentMode == "E2" then
local signature = func .. "(" .. args .. ")"
local ret = E2Lib.generate_signature(signature, rets, wire_expression2_funcs[signature].argnames)
if rets ~= "" then ret = ret:sub(1, 1):upper() .. ret:sub(2) end
Expand All @@ -309,6 +343,7 @@ function E2Helper.Update()
cookie_update()

E2Helper.ResultFrame:Clear()
E2Helper.ModeSelect:SetValue(E2Helper.CurrentMode)

local search_name, search_from, search_args, search_rets = E2Helper.NameEntry:GetValue():lower(), E2Helper.FromEntry:GetValue():lower(), E2Helper.ParamEntry:GetValue():lower(), E2Helper.ReturnEntry:GetValue():lower()
local count = 0
Expand All @@ -317,7 +352,7 @@ function E2Helper.Update()

-- add E2 constants
E2Helper.constants = {}
if E2Helper.CurrentMode == true then
if E2Helper.CurrentMode == "E2" then
for k, v in pairs(wire_expression2_constants) do
-- constants have no arguments and no cost
local name, args, rets, cost = k, nil, v.type, 0
Expand All @@ -332,7 +367,7 @@ function E2Helper.Update()

if count < maxcount then
for _, v in pairs(CurrentTable()) do
if E2Helper.CurrentMode == true then
if E2Helper.CurrentMode == "E2" then
local from, signature, rets, cost = v.extension, v[1], v[2], v[4]
local name, args = string.match(signature, "^([^(]+)%(([^)]*)%)$")

Expand All @@ -347,11 +382,12 @@ function E2Helper.Update()
if count >= maxcount then break end
end
else
local funcname, args, forwhat, functype = unpack(v)
if (funcname:lower():find(search_name, 1, true) and
local funcname, extension, args, forwhat, functype = unpack(v)
if funcname:lower():find(search_name, 1, true) and
extension:lower():find(search_from, 1, true) and
args:lower():find(search_args, 1, true) and
forwhat:lower():find(search_rets, 1, true)) then
local line = E2Helper.ResultFrame:AddLine(funcname, "", args, forwhat, functype) -- TODO: make this column useful for CPU/GPU
forwhat:lower():find(search_rets, 1, true) then
local line = E2Helper.ResultFrame:AddLine(funcname, extension, args, forwhat, functype)
if tooltip then line:SetTooltip(funcname .. " " .. args) end
count = count + 1
if count >= maxcount then break end
Expand Down Expand Up @@ -379,23 +415,6 @@ function E2Helper.Show(searchtext)
end
end

function E2Helper.UseE2(nEditorType)
E2Helper.CurrentMode = false
E2Helper.E2Mode:Toggle()
local val = E2Helper.ReturnEntry:GetValue()
if val and (val == "CPU" or val == "GPU") then E2Helper.ReturnEntry:SetText("") end
E2Helper.CostColumn:SetName("Cost")
E2Helper.ReturnsColumn:SetName("Returns")
end

function E2Helper.UseCPU(nEditorType)
E2Helper.CurrentMode = true
E2Helper.CPUMode:Toggle()
E2Helper.CostColumn:SetName("Type")
E2Helper.ReturnsColumn:SetName("For What")
E2Helper.ReturnEntry:SetText(nEditorType)
end

local delayed_cookie_update = delayed(1, cookie_update)

local lastw, lasth
Expand All @@ -417,8 +436,7 @@ function E2Helper.Resize()
E2Helper.DescriptionEntry:SetPos(orig.DescriptionEntry[1], orig.DescriptionEntry[2] + changeh)
E2Helper.DescriptionEntry:SetSize(orig.DescriptionEntry[3] + changew, orig.DescriptionEntry[4])
E2Helper.ResultFrame:SetSize(orig.ResultFrame[3] + changew, orig.ResultFrame[4] + changeh)
E2Helper.E2Mode:SetPos(orig.E2Mode[1], orig.E2Mode[2] + changeh)
E2Helper.CPUMode:SetPos(orig.CPUMode[1], orig.CPUMode[2] + changeh)
E2Helper.ModeSelect:SetPos(orig.ModeSelect[1] + changew, orig.ModeSelect[2] + changeh)

E2Helper.NameEntry:SetSize(orig.NameEntry[3] + changew * 0.25, orig.NameEntry[4])
E2Helper.FromEntry:SetPos(orig.FromEntry[1] + changew * 0.25, orig.FromEntry[2])
Expand Down
8 changes: 7 additions & 1 deletion lua/wire/client/text_editor/modes/e2.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ local string_sub = string.sub
local string_gmatch = string.gmatch
local string_gsub = string.gsub

local EDITOR = {}
local EDITOR = {
UseValidator = true,
Validator = function(editor,source,file)
return E2Lib.Validate(source)
end,
UseSoundBrowser = true,
}

local function istype(tp)
return wire_expression_types[tp:upper()] or tp == "number"
Expand Down
Loading
Loading