Format Lua Script (code snippet)

Description

Simple script to read clipboard contents and re-format the contents (assuming you have a script in the clipboard.

To use with the FH plugin editor CTRL-A and CTRL-C to copy the contents and add this plug in to the tools>menu so you can run it and then CTRL-V to paste the newly formatted code back

Requires: iuplua

Code

Format_script_in_clipboard.fh_lua
--[[
@Title: Format Script in Clipboard
@Author: Jane Taubman
@Version: 1.1
@LastUpdated: October 2012
@Description: Reads the contents of the Clipboard and reformats the contents assuming it is a Lua script.
]]
-- Get IUP for Clipboard
require "iuplua" -- Get IUP for Clipboard
 
function mainfunction()
    local clipboard = iup:clipboard()
    local script = ''
    if clipboard.textavailable then
        script = clipboard.text
    else
        fhMessageBox('Text not found in Clipboard')
        return
    end
    clipboard.text = format(script)
end
 
function format(script)
    local indent = fliptable({'function','if','while', 'for', 'elseif', 'else'},1)
    local outdent = fliptable({'end','next','elseif','else'},-1)
    local newscripttbl = {}
    local tblOutput = {}
    local currentpad = 0
    local nextpad = 0
    local iStep = 4
    local bComment,bMulti = false,false
    for line in script:gmatch("[^\r\n]+") do
        local strNewLine = trim(line)
        -- Look for MultiLine Strings
        if strNewLine:find('%[%[') then
            bMulti =true
        end
        -- Look for Comments and ignore them
        local strWork = strNewLine
        cPos = strWork:find('%-%-')
        if cPos then
            strWork = strNewLine:sub(1,cPos - 1)
        end
        if not(bMulti) then
            strWork = removeQuotedStrings(strWork)
            for word in strWork:gmatch("[%w{}]+") do
                if outdent[word] then
                    nextpad = nextpad + outdent[word]
                    currentpad = nextpad
                end
                if indent[word] then
                    nextpad = nextpad + indent[word]
                end
            end
            for word in string.gmatch(strWork, "{") do
                nextpad = nextpad + 1
            end
            for word in string.gmatch(strWork, "}") do
                nextpad = nextpad - 1
            currentpad = nextpad end
        end
        if strNewLine:find(']]') then
            bMulti =false
        end
        if bMulti then
            strNewLine = line
        else
            if strNewLine:starts('function') then sBlank = '\r\n' else sBlank = '' end
            strNewLine = sBlank..string.rep(' ',currentpad * iStep)..strNewLine
        end
        currentpad = nextpad
        table.insert(newscripttbl,strNewLine)
    end
    return table.concat(newscripttbl,'\r\n')
end
 
function trim(s)
    s = s:gsub('%s+',' ')
    return (s:gsub("^%s*(.-)%s*$", "%1"))
end
 
function removeQuotedStrings(str)
    local bQuote = false -- End of Quote
    local bEsc = false -- Escaped Quote
    local qType = ' ' -- Type of Quote eg ' or "
    local newstr = {}
    for sChar in str:gmatch(".") do
        if ((sChar == '"') or (sChar == "'" )) then
            if not(bEsc) then
                if (bQuote and qType == sChar) then bQuote = false -- leave quote mode
                elseif not(bQuote) then
                    qType = sChar -- Start of quoted text
                    bQuote = true
                end
            end
        end
        if not(bQuote) then
            table.insert(newstr,sChar)
        end
    end
    return table.concat(newstr)
end
 
function fliptable(tbl,value)
    local newtbl = {}
    for i,j in pairs(tbl) do
        local val = value or i
        newtbl[j] = val
    end
    return newtbl
end
 
function string.starts(String,Start)
    return string.sub(String,1,string.len(Start))==Start
end
------------------------------------------------ End of Functions call Main function
mainfunction()