From 522d89f18ec5298998dda1128017c75b58866473 Mon Sep 17 00:00:00 2001 From: Damian Monogue <3660+demonnic@users.noreply.github.com> Date: Mon, 17 Apr 2023 15:16:21 -0400 Subject: [PATCH] Collection of updates (#59) * Add reverse fill option for text gauges * ldoc change * Use better getValueAt, do not discard string.gsub return to appease linter * Add updateHook option to SUG to allow for modifying the gauge based on values * Fix error when wrapping strings with newlines already present. Add 'truncate' option to cut the string to length if it is longer than the width setting. Add headerTitle to display column header with same look as title. forceHeaderSeparator to show the column header separator even if normal row separators are turned off. Add missing setters for tablemaker. Make tablemaker auto update on changes when autoupdate is turned on. * Bump version * Try using 4.17.2 as the mudlet version for now in github actions. --- .github/workflows/ci.yml | 1 + mfile | 2 +- src/resources/demontools.lua | 29 +----- src/resources/echofile.lua | 10 +- src/resources/ftext.lua | 177 +++++++++++++++++++++++++++++++++-- src/resources/mdkversion.txt | 2 +- src/resources/sug.lua | 50 +++++----- src/resources/textgauge.lua | 22 ++++- 8 files changed, 224 insertions(+), 69 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 676bc6b..6244795 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,3 +28,4 @@ jobs: uses: demonnic/test-in-mudlet@v1.2 with: pretestPackage: ${{ github.workspace }}/build/MDK.mpackage + mudletVersion: Mudlet-4.17.2 diff --git a/mfile b/mfile index 55c6c75..0358132 100644 --- a/mfile +++ b/mfile @@ -1,6 +1,6 @@ { "package": "MDK", - "version": "2.8.3", + "version": "2.8.4", "author": "Demonnic", "title": "Collection of useful objects/classes", "icon": "computer.png", diff --git a/src/resources/demontools.lua b/src/resources/demontools.lua index 49cac61..defcb4a 100644 --- a/src/resources/demontools.lua +++ b/src/resources/demontools.lua @@ -93,32 +93,11 @@ local htmlHeaderPattern = [=[ ]=] --- internal function, recursively digs for a value within subtables if possible -local function digForValue(dataFrom, tableTo) - if dataFrom == nil or table.size(tableTo) == 0 then - return dataFrom - else - local newData = dataFrom[tableTo[1]] - table.remove(tableTo, 1) - return digForValue(newData, tableTo) - end -end - -- Internal function, used to turn a string variable name into a value local function getValueAt(accessString) - if accessString == "" then - return nil - end - local tempTable = accessString:split("%.") - local accessTable = {} - for i, v in ipairs(tempTable) do - if tonumber(v) then - accessTable[i] = tonumber(v) - else - accessTable[i] = v - end - end - return digForValue(_G, accessTable) + local ok, err = pcall(loadstring("return " .. tostring(accessString))) + if ok then return err end + return nil, err end -- internal sorting function, sorts first by hue, then luminosity, then value @@ -832,7 +811,7 @@ function string.tocolor(self) local strTable = {} local part1 = {} local part2 = {} - self:gsub(".", function(c) + _ = self:gsub(".", function(c) table.insert(strTable, c) end) for index, value in ipairs(strTable) do diff --git a/src/resources/echofile.lua b/src/resources/echofile.lua index 56e378e..dc77cd4 100644 --- a/src/resources/echofile.lua +++ b/src/resources/echofile.lua @@ -1,9 +1,9 @@ --- set of functions for echoing files to things. Uses a slightly hacked up version of f-strings for interpolation/templating ----@module echofile ----@author Damian Monogue ----@copyright 2021 Damian Monogue ----@copyright 2016 Hisham Muhammad (https://github.com/hishamhm/f-strings/blob/master/LICENSE) ----@license MIT, see LICENSE.lua +-- @module echofile +-- @author Damian Monogue +-- @copyright 2021 Damian Monogue +-- @copyright 2016 Hisham Muhammad (https://github.com/hishamhm/f-strings/blob/master/LICENSE) +-- @license MIT, see LICENSE.lua local echofile = {} -- following functions fiddled with from https://github.com/hishamhm/f-strings/blob/master/F.lua and https://hisham.hm/2016/01/04/string-interpolation-in-lua/ diff --git a/src/resources/ftext.lua b/src/resources/ftext.lua index 8fce254..6a1cbe8 100644 --- a/src/resources/ftext.lua +++ b/src/resources/ftext.lua @@ -107,6 +107,11 @@ function ftext.xwrap(text, limit, type) table.insert(lines, take) table.insert(strLines, take) end + if leave == "\n" then + table.insert(lines, leave) + table.insert(strLines, leave) + leave = "" + end end end end @@ -189,12 +194,25 @@ end -- Should the endcap be reversed on the right? IE [[ becomes ]] -- true -- +-- truncate +-- Cut the string to width. Is superceded by wrap being true. +-- false +-- -- -- function ftext.fText(str, opts) local options = ftext.fixFormatOptions(str, opts) if options.wrap and (options.strLen > options.effWidth) then - local wrapped = ftext.xwrap(str, options.effWidth, options.formatType) + local wrapped = "" + if str:find("\n") then + for _,line in ipairs(str:split("\n")) do + local newline = "\n" + if _ == 1 then newline = "" end + wrapped = wrapped .. newline .. ftext.xwrap(line, options.effWidth, options.formatType) + end + else + wrapped = ftext.xwrap(str, options.effWidth, options.formatType) + end local lines = wrapped:split("\n") local formatted = {} options.fixed = false @@ -225,6 +243,9 @@ function ftext.fixFormatOptions(str, opts) if options.wrap == nil then options.wrap = true end -- wrap by default. + if options.truncate == nil then + options.truncate = false + end -- do not truncate by default options.formatType = options.formatType or "" -- by default, no color formatting. options.width = options.width or 80 -- default 80 width options.cap = options.cap or "" -- no cap by default @@ -294,6 +315,12 @@ end -- internal function, processes a single line of the wrapped string. function ftext.fLine(str, opts) local options = ftext.fixFormatOptions(str, opts) + local truncate, strLen, width = options.truncate, options.strLen, options.width + if truncate and strLen > width then + local wrapped = ftext.xwrap(str, options.effWidth, options.formatType) + local lines = wrapped:split("\n") + str = lines[1] + end local leftCap = options.leftCap local rightCap = options.rightCap local leftPadLen = options.leftPadLen @@ -638,13 +665,23 @@ function TextFormatter:setNoGap(noGap) self.options.noGap = noGap end +--- Enables truncation (cutting to length). You still need to ensure wrap is disabled, as it supercedes. +function TextFormatter:enableTruncate() + self.options.truncate = true +end + +--- Disables truncation (cutting to length). You still need to ensure wrap is enabled if you want it to wrap. +function TextFormatter:disableTruncate() + self.options.truncate = false +end + --- Format a string based on the stored options -- @tparam string str The string to format function TextFormatter:format(str) return ftext.fText(str, self.options) end ---- Creates and returns a new TextFormatter. For valid options, please see https://github.com/demonnic/fText/wiki/fText +--- Creates and returns a new TextFormatter. -- @tparam table options the options for the text formatter to use when running format() --

Table of options -- @@ -716,6 +753,10 @@ end -- -- -- +-- +-- +-- +-- -- --
Should the endcap be reversed on the right? IE [[ becomes ]]true
truncateCut the string to width. Is superceded by wrap being true.false
-- @usage @@ -766,6 +807,9 @@ local TableMaker = { autoEcho = false, title = "", printTitle = false, + headerTitle = false, + forceHeaderSeparator = false, + autoEchoConsole = "main", } function TableMaker:checkPosition(position, func) @@ -1058,6 +1102,8 @@ function TableMaker:echo(message, echoType, ...) end if consoleType == "string" then console = self.autoEchoConsole + elseif consoleType == "nil" then + console = "main" else console = self.autoEchoConsole.name end @@ -1202,8 +1248,9 @@ function TableMaker:makeHeader() for _, v in ipairs(self.columns) do table.insert(columnEntries, v:format(v.options.name)) end - local divWithNewlines = string.format("\n%s", self:createRowDivider()) - columnHeaders = string.format("\n%s%s%s%s", ec, table.concat(columnEntries, sep), ec, self.separateRows and divWithNewlines or '') + local divWithNewlines = self.headerTitle and header or self:createRowDivider() + divWithNewlines = "\n" .. divWithNewlines + columnHeaders = string.format("\n%s%s%s%s", ec, table.concat(columnEntries, sep), ec, (self.separateRows or self.forceHeaderSeparator) and divWithNewlines or '') end local title = self:makeTitle(totalWidth, header) header = string.format("%s%s%s", header, title, columnHeaders) @@ -1231,39 +1278,139 @@ function TableMaker:createRowDivider() end --- set the title of the table +-- @tparam string title The title of the table. function TableMaker:setTitle(title) self.title = title + if self.autoEcho then self:assemble() end +end + +--- set the rowSeparator for the table +-- @tparam string char The row separator to use +function TableMaker:setRowSeparator(char) + self.rowSeparator = char + if self.autoEcho then self:assemble() end +end + +--- set the edgeCharacter for the table +-- @tparam string char The edge character to use +function TableMaker:setEdgeCharacter(char) + self.edgeCharacter = char + if self.autoEcho then self:assemble() end +end + +--- set the foot character for the table +-- @tparam string char The foot character to use +function TableMaker:setFootCharacter(char) + self.footCharacter = char + if self.autoEcho then self:assemble() end +end + +--- set the head character for the table +-- @tparam string char The head character to use +function TableMaker:setHeadCharacter(char) + self.headCharacter = char + if self.autoEcho then self:assemble() end +end + +--- set the column separator character for the table +-- @tparam string char The separator character to use +function TableMaker:setSeparator(char) + self.separator = char + if self.autoEcho then self:assemble() end +end + +--- set the title color for the table +-- @tparam string color The title color to use. Should match the color type of the tablemaker (cecho by default) +function TableMaker:setTitleColor(color) + self.titleColor = color + if self.autoEcho then self:assemble() end +end + +--- set the title color for the table +-- @tparam string color The separator color to use. Should match the color type of the tablemaker (cecho by default) +function TableMaker:setSeparatorColor(color) + self.separatorColor = color + if self.autoEcho then self:assemble() end +end + +--- set the title color for the table +-- @tparam string color The frame color to use. Should match the color type of the tablemaker (cecho by default) +function TableMaker:setFrameColor(color) + self.frameColor = color + if self.autoEcho then self:assemble() end +end + +--- Force a separator between the header and first row, even if the row separator is disabled for the overall table +function TableMaker:enableForceHeaderSeparator() + self.forceHeaderSeparator = true + if self.autoEcho then self:assemble() end +end + +--- Do not force a separator between the header and first row, even if the row separator is disabled for the overall table +function TableMaker:disableForceHeaderSeparator() + self.forceHeaderSeparator = false + if self.autoEcho then self:assemble() end +end + +--- Enable using the title separator for the column headers as well +function TableMaker:enableHeaderTitle() + self.headerTitle = true + if self.autoEcho then self:assemble() end +end + +--- Disable using the title separator for the column headers as well +function TableMaker:disableHeaderTitle() + self.headerTitle = false + if self.autoEcho then self:assemble() end end --- enable printing the title of the table function TableMaker:enablePrintTitle() self.printTitle = true + if self.autoEcho then self:assemble() end end ---- enable printing the title of the table +--- disable printing the title of the table function TableMaker:disablePrintTitle() self.printTitle = false + if self.autoEcho then self:assemble() end +end + +--- enable printing of the column headers +function TableMaker:enablePrintHeaders() + self.printHeaders = true + if self.autoEcho then self:assemble() end +end + +--- disable printing of the column headers +function TableMaker:disablePrintHeaders() + self.printHeaders = false + if self.autoEcho then self:assemble() end end --- enable printing the separator line between rows function TableMaker:enableRowSeparator() self.separateRows = true + if self.autoEcho then self:assemble() end end --- enable printing the separator line between rows function TableMaker:disableRowSeparator() self.separateRows = false + if self.autoEcho then self:assemble() end end --- enables making cells which incorporate insertLink/insertPopup function TableMaker:enablePopups() self.autoEcho = true self.allowPopups = true + if self.autoEcho then self:assemble() end end --- enables autoEcho so that when assemble is called it echos automatically function TableMaker:enableAutoEcho() self.autoEcho = true + self:assemble() end --- disables autoecho. Cannot be used if allowPopups is set @@ -1278,6 +1425,7 @@ end --- Enables automatically clearing the miniconsole we echo to function TableMaker:enableAutoClear() self.autoClear = true + if self.autoEcho then self:assemble() end end --- Disables automatically clearing the miniconsole we echo to @@ -1294,12 +1442,13 @@ function TableMaker:setAutoEchoConsole(console) end local consoleType = type(console) if consoleType ~= "string" and consoleType ~= "table" then - error(funcName .. " ArgumentError: console as string or Geyser.MiniConsole expected, got " .. consoleType) - elseif consoleType == "table" and console.type ~= "miniConsole" then + error(funcName .. " ArgumentError: console as string or a Geyser MiniConsole or UserWindow expected, got " .. consoleType) + elseif consoleType == "table" and not (console.type == "miniConsole" or console.type == "userwindow") then error(funcName .. " ArgumentError: console received was a table and may be a Geyser object, but console.type is not miniConsole, it is " .. console.type) end self.autoEchoConsole = console + if self.autoEcho then self:assemble() end end --- Assemble the table. If autoEcho is enabled/set to true, will automatically echo. Otherwise, returns the formatted string to echo the table @@ -1356,8 +1505,8 @@ function TableMaker:textAssemble() return sheet end ---- Creates and returns a new TableMaker. See https://github.com/demonnic/fText/wiki/TableMaker for valid entries to the options table. --- see https://github.com/demonnic/tempwiki/wiki/fText%3A-TableMaker%3A-Examples for usage +--- Creates and returns a new TableMaker. +-- see https://github.com/demonnic/MDK/wiki/fText%3A-TableMaker%3A-Examples for usage -- @tparam table options table of options for the TableMaker object --

Table of new options -- @@ -1455,6 +1604,16 @@ end -- -- -- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- -- --
Should we print the title of the table at the very tip-top?false
headerTitleUse the same separator for the column headers as the title/top, rather than the row separatorformatColor
forceHeaderSeparatorForce a separator between the column headers and the first row, even if rowSeparator is false.false
function TableMaker:new(options) diff --git a/src/resources/mdkversion.txt b/src/resources/mdkversion.txt index 9f8d8a9..2701a22 100644 --- a/src/resources/mdkversion.txt +++ b/src/resources/mdkversion.txt @@ -1 +1 @@ -2.8.3 +2.8.4 diff --git a/src/resources/sug.lua b/src/resources/sug.lua index 2624aff..ea99c90 100644 --- a/src/resources/sug.lua +++ b/src/resources/sug.lua @@ -15,33 +15,11 @@ local SUG = { strict = true, } --- ========== Copied from demontools.lua in order to cut the dependency for just this small functionality ========== --- internal function, recursively digs for a value within subtables if possible -local function digForValue(dataFrom, tableTo) - if dataFrom == nil or table.size(tableTo) == 0 then - return dataFrom - else - local newData = dataFrom[tableTo[1]] - table.remove(tableTo, 1) - return digForValue(newData, tableTo) - end -end - -- Internal function, used to turn a string variable name into a value local function getValueAt(accessString) - if accessString == "" then - return nil - end - local tempTable = accessString:split("%.") - local accessTable = {} - for i, v in ipairs(tempTable) do - if tonumber(v) then - accessTable[i] = tonumber(v) - else - accessTable[i] = v - end - end - return digForValue(_G, accessTable) + local ok, err = pcall(loadstring("return " .. tostring(accessString))) + if ok then return err end + return nil, err end -- ========== End section copied from demontools.lua @@ -95,6 +73,11 @@ end -- The name of an event to listen for to perform an update. Can be run alongside or instead of the timer updates. Empty string to turn off -- "" -- +-- +-- updateHook +-- A function which is run each time the gauge updates. Should take 3 arguments, the gauge itself, current value, and max value. You can return new current and max values to be used, for example `return 34, 120` would cause the gauge to use 34 for current and 120 for max regardless of what the variables it reads say. +-- +-- -- -- @param container The Geyser container for this gauge -- @usage @@ -194,6 +177,16 @@ function SUG:setTextTemplate(template) self:update() end +--- Set the updateHook function which is run just prior to the gauge updating +-- @tparam function func The function which will be called when the gauge updates. It should take 3 arguments, the gauge itself, the current value, and the max value. If you wish to override the current or max values used for the gauge, you can return new current and max values, like `return newCurrent newMax` +function SUG:setUpdateHook(func) + local funcType = type(func) + if funcType ~= "function" then + return nil, "setUpdateHook only takes functions, no strings or anything like that. You passed in: " .. funcType + end + self.updateHook = func +end + --- Stops the Self Updating Gauge from updating function SUG:stop() self.active = false @@ -241,6 +234,13 @@ function SUG:update() self.name, self.currentVariable, self.maxVariable)) end end + if self.updateHook and type(self.updateHook) == "function" then + local ok, newcur, newmax = pcall(self.updateHook, self, current, max) + if ok and newcur then + current = newcur + max = newmax and newmax or self.defaultMax + end + end local text = self.textTemplate local percent = math.floor((current / max * 100) + 0.5) text = text:gsub("|c", current) diff --git a/src/resources/textgauge.lua b/src/resources/textgauge.lua index b2637bc..05c34c3 100644 --- a/src/resources/textgauge.lua +++ b/src/resources/textgauge.lua @@ -171,6 +171,16 @@ function TextGauge:setPercentSymbolColor(color) self.percentSymbolColor = color end +--- Enables reversing the fill direction (right to left instead of the usual left to right) +function TextGauge:enableReverse() + self.reverse = true +end + +--- Disables reversing the fill direction (go back to the usual left to right) +function TextGauge:disableReverse() + self.reverse = false +end + --- Enables showing the percent value of the gauge function TextGauge:enableShowPercent() self.showPercent = true @@ -306,9 +316,15 @@ function TextGauge:setValue(current, max) if value >= 200 and self.showPercent then overflowWidth = overflowWidth - 1 end - return string.format("%s%s%s%s%s%s%s%s%s%s%s", overflowColor, string.rep(overflowCharacter, overflowWidth), fillColor, - string.rep(fillCharacter, fillWidth), resetColor, emptyColor, string.rep(emptyCharacter, emptyWidth), resetColor, - percentString, percentSymbolString, resetColor) + local result = "" + if self.reverse then + result = string.format("%s%s%s%s%s%s%s%s%s%s%s", emptyColor, string.rep(emptyCharacter, emptyWidth), resetColor,fillColor, string.rep(fillCharacter, fillWidth), resetColor, overflowColor, string.rep(overflowCharacter, overflowWidth), resetColor, percentString, percentSymbolString, resetColor) + else + result = string.format("%s%s%s%s%s%s%s%s%s%s%s", overflowColor, string.rep(overflowCharacter, overflowWidth), fillColor, + string.rep(fillCharacter, fillWidth), resetColor, emptyColor, string.rep(emptyCharacter, emptyWidth), resetColor, + percentString, percentSymbolString, resetColor) + end + return result end --- Synonym for setValue