|
09-09-16, 10:36 PM | #1 |
string.gsub questions
I am rewriting LibAboutPanel by Ackis to add some features, and this isn't new news to some people. However, I have hit some stumbling blocks.
In the attached picture, you will see under Version that the repository keyword is still visible, and should have been replaced. Also, under Email, it says "Unknown" yet the ToC does have a value. And last, for whatever reason, the display is changing "https:" to "http:" and I don't know why. Linked first is my ToC, then the code for the library. I am using the AboutOptionsTable() API from the library. Code:
## Interface: 70000 ## Title: SmartRes2 ## Notes: Co-ordinated targetless Party and Raid wipe recovery. Evolved ## Notes-ruRU: @localization(locale="ruRU", key="Notes", namespace="ToC")@ ## Notes-deDE: @localization(locale="deDE", key="Notes", namespace="ToC")@ ## Notes-koKR: @localization(locale="koKR", key="Notes", namespace="ToC")@ ## Notes-esMX: @localization(locale="esMX", key="Notes", namespace="ToC")@ ## Notes-esES: @localization(locale="esES", key="Notes", namespace="ToC")@ ## Notes-ptBR: @localization(locale="ptBR", key="Notes", namespace="ToC")@ ## Notes-zhCN: @localization(locale="zhCN", key="Notes", namespace="ToC")@ ## Notes-zhTW: @localization(locale="zhTW", key="Notes", namespace="ToC")@ ## Notes-itIT: @localization(locale="itIT", key="Notes", namespace="ToC")@ ## Notes-frFR: @localization(locale="frFR", key="Notes", namespace="ToC")@ ## Version: @project-version@ ## X-Project-Revision: @project-revision@ ## Author: Myrroddin of Knights of the Storm ## X-Author-Server: Llane US ## X-Author-Faction: Alliance ## X-Email: psvander at gmail dot com ## X-Category: Raid, Party, Healer, Priest, Shaman, Paladin, Druid, Monk ## SavedVariables: SmartRes2DB ## X-Localizations: enUS, frFR, deDE, esES, esMX, ruRU, zhCN, koKR, zhTW, ptBR, itIT ## X-Website: https://mods.curse.com/addons/wow/smartres2 ## X-Credits: Jerry, Onaforeignshore, Morgalm, Torhal, and the original SmartRes team! ## X-License: (c) 2009 - 2016, Paul "Myrroddin" Vandersypen. All Rights Reserved Code:
--[[ Whom is doing what with this library $Date: $ $Revision: $ $Author: $ $URL: $ $Id: $ $Header: $ ]]-- local lib = LibStub:NewLibrary("LibAboutPanel-2.0", "$Revision: 1 $") if not lib then return -- no upgrade necessary end -- handy fuction to create Title Case ----------- -- string.gsub(string, "(%a)([%w_']*)", TitleCase) local function TitleCase(first, rest) return first:upper() .. rest:lower() end -- localization --------------------------------- local function defaultTranslations(L, key) -- no translation for the key -- so it becomes its own translation return key end local L = setmetatable({}, {__index = defaultTranslations }) if GetLocale() == "koKR" then --@localization(locale="koKR", format="lua_additive_table")@ elseif GetLocale() == "frFR" then --@localization(locale="frFR", format="lua_additive_table")@ elseif GetLocale() == "deDE" then --@localization(locale="deDE", format="lua_additive_table")@ elseif GetLocale() == "ruRU" then --@localization(locale="ruRU", format="lua_additive_table")@ elseif GetLocale() == "zhTW" then --@localization(locale="zhTW", format="lua_additive_table")@ elseif GetLocale() == "zhCN" then --@localization(locale="zhCN", format="lua_additive_table")@ elseif GetLocale() == "itIT" then --@localization(locale="itIT", format="lua_additive_table")@ elseif GetLocale() == "ptBR" then --@localization(locale="ptBR", format="lua_additive_table")@ elseif GetLocale() == "esES" or GetLocale() == "esMX" then --@localization(locale="esES", format="lua_additive_table")@ end -- per AddOn options ---------------------------- local aboutTable = {} -- LibAboutPanel stuff -------------------------- local editbox = CreateFrame("EditBox", nil, UIParent) editbox:Hide() editbox:SetAutoFocus(true) editbox:SetHeight(32) editbox:SetFontObject("GameFontHighlightSmall") lib.editbox = editbox local left = editbox:CreateTexture(nil, "BACKGROUND") left:SetWidth(8) left:SetHeight(20) left:SetPoint("LEFT", -5, 0) left:SetTexture("Interface\\Common\\Common-Input-Border") left:SetTexCoord(0, 0.0625, 0, 0.625) local right = editbox:CreateTexture(nil, "BACKGROUND") right:SetWidth(8) right:SetHeight(20) right:SetPoint("RIGHT", 0, 0) right:SetTexture("Interface\\Common\\Common-Input-Border") right:SetTexCoord(0.9375, 1, 0, 0.625) local center = editbox:CreateTexture(nil, "BACKGROUND") center:SetHeight(20) center:SetPoint("RIGHT", right, "LEFT", 0, 0) center:SetPoint("LEFT", left, "RIGHT", 0, 0) center:SetTexture("Interface\\Common\\Common-Input-Border") center:SetTexCoord(0.0625, 0.9375, 0, 0.625) editbox:SetScript("OnEscapePressed", editbox.ClearFocus) editbox:SetScript("OnEnterPressed", editbox.ClearFocus) editbox:SetScript("OnEditFocusLost", editbox.Hide) editbox:SetScript("OnEditFocusGained", editbox.HighlightText) editbox:SetScript("OnTextChanged", function(self) self:SetText(self:GetParent().val) self:HighlightText() end) local function OpenEditbox(self) editbox:SetText(self.val) editbox:SetParent(self) editbox:SetPoint("LEFT", self) editbox:SetPoint("RIGHT", self) editbox:Show() end local fields = { "Version", "Author", "X-Category", "X-License", "X-Email", "X-Website", "X-Credits", "X-Localizations" } local haseditbox = { ["X-Website"] = true, ["X-Email"] = true } local function HideTooltip() GameTooltip:Hide() end local function ShowTooltip(self) GameTooltip:SetOwner(self, "ANCHOR_TOPRIGHT") GameTooltip:SetText(L["Click and press Ctrl-C to copy"]) end -- embedded functions beginning of file code lib.embeds = lib.embeds or {} local mixins = { "CreateAboutPanel", "AboutOptionsTable" } --- Embeds lib on target AddOn -- So you can call LibStub("LibAboutPanel-2.0"):Embed(myAddOn) -- @param target AddOn table in which to embed -- @usage -- local AddOnName, AddOn = ... -- LibStub("LibAboutPanel-2.0"):Embed(AddOn) -- -- **OR**, if using Ace3 -- -- you do not explicitly call :Embed -- local MyAddOn = LibStub("AceAddon-3.0"):NewAddon("MyAddOn", "LibAboutPanel-2.0") function lib:Embed(target) for k, v in pairs(mixins) do target[v] = self[v] end self.embeds[target] = true return target end --- Create a new About panel -- @paramsig AddOn[, parent] -- @param AddOn name of which you are attaching the panel. String -- @param parent AddOn name in Interface Options. String or nil -- If parent is provided, panel will be under [+] -- otherwise the panel will be a normal AddOn category -- @return frame To do as you wish -- @usage local aboutFrame = MyAddOn:CreateAboutPanel("MyAddOn", "MyAddOn") -- -- OR -- MyAddOn:CreateAboutPanel("MyAddOn", "MyAddOn") function lib:CreateAboutPanel(AddOn, parent) -- Remove spaces from AddOn because GetMetadata doesn't like those local gsubName = gsub(AddOn, " ", "") local about = CreateFrame("Frame", nil, UIParent) about.name = not parent and gsubName or L["About"] about.parent = parent about.AddOnName = gsubName about:Hide() about:SetScript("OnShow", OnShow) -- about.refresh = function() OnShow() end InterfaceOptions_AddCategory(about) return about end --- Creates a table of an AddOn's ToC fields -- see http://www.wowace.com/addons/ace3/pages/api/ace-config-3-0/ -- @param AddOn name string whose ToC you want parsed -- @return aboutTable suitable for use with AceConfig-3.0 -- @usage -- assuming options is your top-level table -- local options = {} -- put your regular stuff here -- options.args.aboutTable = MyAddOn:AboutOptionsTable("MyAddOn") -- options.args.aboutTable.order = 100 -- use any number in the hierarchy -- LibStub("AceConfig-3.0"):RegisterOptionsTable("MyAddOn", options) function lib:AboutOptionsTable(AddOn) assert(LibStub("AceConfig-3.0"), "LibAboutPanel-2.0 API 'AboutOptionsTable' requires AceConfig-3.0", 2) aboutTable[AddOn] = aboutTable[AddOn] or { order = 10, name = L["About"], type = "group", args = { title = { order = 10, name = "|cffe6cc80" .. AddOn .. "|r", type = "description", fontSize = "large" }, blank = { order = 20, name = "", type = "description" }, notes = { order = 30, name = function() local notefield = "Notes" if GetLocale() ~= "enUS" then notefield = notefield .. "-" .. GetLocale() end local notes = GetAddOnMetadata(AddOn, notefield) return "|cffe6cc80" .. L["Notes"] .. ": |r" .. notes end, type = "description", fontSize = "medium" }, blank2 = { order = 40, name = "", type = "description" }, author = { order = 50, name = function() local author = GetAddOnMetadata(AddOn, "Author") author = string.gsub(author, "(%a)([%w_']*)", TitleCase) local authorservername = GetAddOnMetadata(AddOn, "X-Author-Server") authorservername = string.gsub(authorservername, "(%a)([%w_']*)", TitleCase) local authorfaction = GetAddOnMetadata(AddOn, "X-Author-Faction") authorfaction = string.gsub(authorfaction, "(%a)([%w_']*)", TitleCase) authorfaction = string.gsub(authorfaction, "Alliance", FACTION_ALLIANCE) authorfaction = string.gsub(authorfaction, "Horde", FACTION_HORDE) if authorservername and authorfaction then author = string.format(L["%s on the %s realm (%s)"], author, authorservername, authorfaction) elseif authorservername and not authorfaction then author = string.format(L["%s on the %s realm"], author, authorservername) elseif not authorservername and authorfaction then author = (author .. "( " .. authorfaction .. ")") else author = author -- redundancy check end return "|cffe6cc80" .. L["Author"] .. ": |r".. author end, type = "description" }, version = { order = 60, name = function() local addonversion = GetAddOnMetadata(AddOn, "Version") -- replace repository keywords addonversion = string.gsub(addonversion, "@project-version@", L["Repository"]) -- Curse addonversion = string.gsub(addonversion, "wowi:revision", L["Repository"]) -- WoWInterface return "|cffe6cc80" .. L["Version"] .. ": |r" .. addonversion end, type = "description" }, license = { order = 70, name = function() local copyright = GetAddOnMetadata(AddOn, "X-License") or UNKNOWN -- replace with © if applicable copyright = string.gsub(copyright, "Copyright", "©") copyright = string.gsub(copyright, "copyright", "©") copyright = string.gsub(copyright, "(C)", "©") copyright = string.gsub(copyright, "(c)", "©") copyright = string.gsub(copyright, "All Rights Reserved", L["All Rights Reserved"]) return "|cffe6cc80" .. L["License"] .. ": |r" .. copyright end, type = "description" }, localizations = { order = 80, name = function() local localizations = GetAddOnMetadata(AddOn, "X-Localizations") or UNKNOWN -- replace with global strings localizations = string.gsub(localizations, "enUS", LFG_LIST_LANGUAGE_ENUS) localizations = string.gsub(localizations, "frFR", LFG_LIST_LANGUAGE_FRFR) localizations = string.gsub(localizations, "deDE", LFG_LIST_LANGUAGE_DEDE) localizations = string.gsub(localizations, "esES", LFG_LIST_LANGUAGE_ESES) localizations = string.gsub(localizations, "esMX", LFG_LIST_LANGUAGE_ESMX) localizations = string.gsub(localizations, "koKR", LFG_LIST_LANGUAGE_KOKR) localizations = string.gsub(localizations, "itIT", LFG_LIST_LANGUAGE_ITIT) localizations = string.gsub(localizations, "ptBR", LFG_LIST_LANGUAGE_PTBR) localizations = string.gsub(localizations, "ruRU", LFG_LIST_LANGUAGE_RURU) localizations = string.gsub(localizations, "zhCN", LFG_LIST_LANGUAGE_ZHCN) localizations = string.gsub(localizations, "zhTW", LFG_LIST_LANGUAGE_ZHTW) return "|cffe6cc80" .. L["Localizations"] .. ": |r" .. localizations end, type = "description" }, credits = { order = 90, name = function() return "|cffe6cc80" .. L["Credits"] .. ": |r" .. GetAddOnMetadata(AddOn, "X-Credits") or UNKNOWN end, type = "description" }, website = { order = 100, name = "|cffe6cc80" .. L["Website"] .. ": |r", desc = L["Click and press Ctrl-C to copy"], type = "input", get = function() local website = GetAddOnMetadata(AddOn, "X-Website") or UNKNOWN return (haseditbox["X-Website"] and "|cff77ccff" or "") .. website end, width = "full" }, email = { order = 110, name = "|cffe6cc80" .. L["Email"] .. ": |r", desc = L["Click and press Ctrl-C to copy"], get = function() local eMail = GetAddOnMetadata(AddOn, "X-Email") or UNKNOWN eMail = string.gsub(eMail, " at ", "@") eMail = string.gsub(eMail, " dot ", ".") return (haseditbox["X-Email"] and "|cff77ccff" or "") .. eMail end, type = "input", width = "full" } } } return aboutTable[AddOn] end local function OnShow(frame) -- Get the localized version of notes if it exists or fall back to the English one. local notefield = "Notes" if GetLocale() ~= "enUS" then notefield = notefield .. "-" .. GetLocale() end local notes = GetAddOnMetadata(frame.AddOnName, notefield) -- main title about.name or L["About"] ------ local title = frame.about_title if not title then title = frame:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge") frame.about_title = title end title:SetPoint("TOPLEFT", 16, -16) title:SetText(frame.parent and (frame.parent .. " - " .. L["About"]) or frame.name) -- ToC Notes field -------------------------- if not frame.about_subtitle then frame.about_subtitle = frame:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall") end local subtitle = frame.about_subtitle subtitle:SetHeight(32) subtitle:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -8) subtitle:SetPoint("RIGHT", frame, -32, 0) subtitle:SetNonSpaceWrap(true) subtitle:SetJustifyH("LEFT") subtitle:SetJustifyV("TOP") subtitle:SetText(notes) local anchor for i = 1, #fields do local field = fields[i] local value = GetAddOnMetadata(frame.AddOnName, field) if value then local title = frame[field .. "_title"] if not title then title = frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall") frame[field .. "_title"] = title end title:SetWidth(80) if not anchor then title:SetPoint("TOPLEFT", subtitle, "BOTTOMLEFT", -2, -12) else title:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, -10) end title:SetJustifyH("RIGHT") title:SetJustifyV("TOP") -- fix for display -- first strip "X-" from field -- then TitleCase field local fixed_field = field:gsub("X%-", "") fixed_field = string.gsub(fixed_field, "(%a)([%w_']*)", TitleCase) title:SetText(L[fixed_field]) local detail = frame[field .. "_detail"] if not detail then detail = frame:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall") frame[field .. "_detail"] = detail end detail:SetPoint("TOPLEFT", title, "TOPRIGHT", 4, 0) detail:SetPoint("RIGHT", frame, -16, 0) detail:SetJustifyH("LEFT") detail:SetJustifyV("TOP") if field == "Author" then local authorservername = GetAddOnMetadata(frame.AddOnName, "X-Author-Server") -- Title Case server authorservername = string.gsub(authorservername, "(%a)([%w_']*)", TitleCase) local authorfaction = GetAddOnMetadata(frame.AddOnName, "X-Author-Faction") authorfaction = string.gsub(authorfaction, "(%a)([%w_']*)", TitleCase) -- localize authorfaction ------- aauthorfaction = string.gsub(authorfaction, "Alliance", FACTION_ALLIANCE) authorfaction = string.gsub(authorfaction, "Horde", FACTION_HORDE) if authorservername and authorfaction then detail:SetFormattedText(L["%s on the %s realm (%s)"], value, authorservername, authorfaction) elseif authorservername and not authorfaction then detail:SetFormattedText(L["%s on the %s realm"], value, authorservername) elseif not authorservername and authorfaction then detail:SetText(value .. "( " .. authorfaction .. ")") else detail:SetText(value) end elseif field == "Version" then local addonversion = GetAddOnMetadata(frame.AddOnName, field) -- Remove @project-revision@ and replace it with Repository addonversion = string.gsub(addonversion, "@project-version@", L["Repository"]) -- Curse addonversion = string.gsub(addonversion, "wowi:revision", L["Repository"]) -- WoWInterface detail:SetText(addonversion) elseif field == "X-License" then local copyright = GetAddOnMetadata(frame.AddOnName, "X-Copyright") if copyright then -- replace with © if applicable copyright = string.gsub(copyright, "Copyright", "\0169") copyright = string.gsub(copyright, "copyright", "\0169") copyright = string.gsub(copyright, "(C)", "\0169") copyright = string.gsub(copyright, "(c)", "\0169") detail:SetText(copyright .. "\n" .. value) else detail:SetText(value) end elseif field == "X-Localizations" then local localizations = GetAddOnMetadata(frame.AddOnName, "X-Localizations"):lower() -- replace with global strings localizations = string.gsub(localizations, "enus", LFG_LIST_LANGUAGE_ENUS) localizations = string.gsub(localizations, "frfr", LFG_LIST_LANGUAGE_FRFR) localizations = string.gsub(localizations, "dede", LFG_LIST_LANGUAGE_DEDE) localizations = string.gsub(localizations, "eses", LFG_LIST_LANGUAGE_ESES) localizations = string.gsub(localizations, "esmx", LFG_LIST_LANGUAGE_ESMX) localizations = string.gsub(localizations, "kokr", LFG_LIST_LANGUAGE_KOKR) localizations = string.gsub(localizations, "itit", LFG_LIST_LANGUAGE_ITIT) localizations = string.gsub(localizations, "ptbr", LFG_LIST_LANGUAGE_PTBR) localizations = string.gsub(localizations, "ruru", LFG_LIST_LANGUAGE_RURU) localizations = string.gsub(localizations, "zhcn", LFG_LIST_LANGUAGE_ZHCN) localizations = string.gsub(localizations, "zhtw", LFG_LIST_LANGUAGE_ZHTW) detail:SetText(localizations) elseif field == "X-Website" then detail:SetText((haseditbox[field] and "|cff77ccff" or "") .. gsub(value, "^https?://", "")) else local email = GetAddOnMetadata(frame.AddOnName, field):lower() email = string.gsub(email, " at ", "@") email = string.gsub(email, " dot ", ".") detail:SetText((haseditbox[field] and "|cff77ccff" or "") .. value) end local lineheight = math.min(detail:GetStringHeight(), 32) title:SetHeight(lineheight) detail:SetHeight(lineheight) if haseditbox[field] then local button = CreateFrame("Button", nil, frame) button:SetAllPoints(detail) button.value = value button:SetScript("OnClick", OpenEditbox) button:SetScript("OnEnter", ShowTooltip) button:SetScript("OnLeave", HideTooltip) end anchor = title end end end -- EoF embedding for AddOn in pairs(lib.embeds) do lib:Embed(AddOn) end Last edited by myrroddin : 09-09-16 at 10:38 PM. Reason: Missed something |
|
09-10-16, 05:55 AM | #2 |
Escape the dash.
Don't know about the URL. Why do you have that OnShow? Doesn't the Ace config thingy do all of that? Edit: Unrelated, but I think "Unknown" looks bad. Just don't show it at all, imo.
__________________
Grab your sword and fight the Horde! |
|
09-11-16, 12:31 AM | #3 | ||||
Some other aesthetic commentary based on your screenshot and the code: 1. You should use values as-is, rather than forcing your "ideal" capitalization onto what the addon author wrote. While replacing "phanx" with "Phanx" might be merely annoying if I preferred all-lowercase, replacing "FSH" with "Fsh" would actually be incorrect if those were my initials or another acronym/initialism, and replacing names like "Billy-Bob McDonald" with "Billy-bob Mcdonald" would also be incorrect. 2. Nobody cares what server/faction the addon's author plays on. Plus, in this day and age, it's unlikely the author's "pen name" is the same as their primary character's name, or maybe even any of their characters' names, so this information doesn't even give someone another way to contact the author. It's just clutter. If you really want to show it anyway for the very small % of addons that bother including it, the current "<name> on the <realm> realm" format feels awkward and overly wordy. "<name> of <realm>" would be better. 3. In copyright fields, you should not replace the word "Copyright" with a "©" symbol. While it's not hugely important here, legally speaking, the "©" symbol is purely aesthetic and has no actual meaning. You also should not replace the phrase "All Rights Reserved" with an arbitrary translation for non-English users. Translating legal terms and documents is a complicated process even for lawyers who specialize in that kind of thing. Most of the time, if you look at any legal documents that are translated into another language, the translation is even prefraced with a notice stating that the translation is not authoriative or legally meaningful, and is provided only for convenience -- only the document in its original language is official. You are not a lawyer, and neither are your volunteer translators, so just leave the legal text as it's written.
To minimize duplication, have a single function that fetches and formats field values: Lua Code:
Then, everywhere else in the code where you need a field value, just call: Lua Code:
Note that this also consolidates formatting the label text (if the third parameter evaluates to true, then the label is prepended to the text inline; otherwise it's provided as a second return value) so you're not repeating that 20 times throughout the rest of the code either. What do you get if you run /dump GetAddOnMetadata("NameOfTheAddon", "X-Email") manually?
(Also, in your non-AceConfig code path, you're stripping off the http or https protocol, but I don't see a reason to do this. Again, just show the values the addon author provided.) Some other issues with your current code: Code:
local function HideTooltip() GameTooltip:Hide() end Code:
local notefield = "Notes" if GetLocale() ~= "enUS" then notefield = notefield .. "-" .. GetLocale() end local notes = GetAddOnMetadata(AddOn, notefield) Code:
local lang, notes = GetLocale() if lang ~= "enUS" then notes = GetAddOnMetadata(AddOn, "Notes-" .. lang) end if not notes then notes = GetAddOnMetadata(AddOn, "Notes") end Code:
local lang, notes, notesLabel = GetLocale() if lang ~= "enUS" then notes, notesLabel = GetDisplayText(AddOn, "Notes-" .. lang) end if not notes then notes, notesLabel = GetDisplayText(AddOn, "Notes") end Your current AceConfig table generator code will throw an error if used on an addon that doesn't specify an author, an author server, and an author faction. You need to check that GetAddOnMetadata actually returned something before performing string operations on that returned value. Also, the parts highlighted in red here are not necessary: Code:
if authorservername and authorfaction then author = string.format(L["%s on the %s realm (%s)"], author, authorservername, authorfaction) elseif authorservername and not authorfaction then author = string.format(L["%s on the %s realm"], author, authorservername) elseif not authorservername and authorfaction then author = (author .. "( " .. authorfaction .. ")") else author = author -- redundancy check end If you get to the second condition, and "authorservername" has a value, you already know that "authorfaction" does not have a value -- if it did, the first condition would have matched instead -- so you don't need to check it again. The "else" part does literally nothing, other than wasting CPU time reassigning a variable to the value it already has. Just delete that. (Also, the unified fetch-and-format function I posted above doesn't have any of these issues.) Code:
local fixed_field = field:gsub("X%-", "") fixed_field = string.gsub(fixed_field, "(%a)([%w_']*)", TitleCase) title:SetText(L[fixed_field]) In this case, the field names are things you specified yourself, in your own code so you already control their capitalization -- and as far as I can see, they're all already "initial capital + remainder lowercase", so running them through more functions to format them that way is just a waste of time.
__________________
Retired author of too many addons. Message me if you're interested in taking over one of my addons. Don’t message me about addon bugs or programming questions. Last edited by Phanx : 09-11-16 at 12:36 AM. |
|||||
09-11-16, 01:21 AM | #4 |
All excellent feedback, as always. Thank you Phanx and Lombra.
As to the lack of effiecency with my existing code, yes, Phanx's solution is by far more optimized and elegant. I did intend on doing something like that after I got the initial thing working, but now I'll just put it straight in. I didn't like the "unknown" thing either, but couldn't figure out a way to bypass a ToC field if it didn't exist. I do now. The TitleCase will be removed, and the camelCase/under_scores will be fixed. Some of that was copy/paste from the original LibAboutPanel. Yeah, no excuses! The copyright and all rights reserved will be reverted, and I admit I am no lawyer as Phanx pointed out, and was unaware of the legalities. Not going one by one though the tips and suggestions, but I will use them. |
|
WoWInterface » Developer Discussions » Lua/XML Help » string.gsub questions |
«
Previous Thread
|
Next Thread
»
|
Display Modes |
Switch to Linear Mode |
Hybrid Mode |
Switch to Threaded Mode |
|
|