----------------------------------------------------------------------- -- Exporter template in Lua for SciTE -- Version 0.9.2, 20070805 -- -- By Kein-Hong Man -- This program is hereby placed into Public Domain. -- -- This template code is very generic. Generic methods should not be -- copyrightable. Share and enjoy. -- ----------------------------------------------------------------------- -- USAGE -- * This script contains extensive comments for your convenience. -- * By default, performs a verbose information dump. ----------------------------------------------------------------------- ----------------------------------------------------------------------- -- a simple check to alert of namespace collision, but allows different -- files to define their own functions in the exporters table ----------------------------------------------------------------------- if exporters then -- Another exporter has already defined the table, now check for -- a possible name collision within the table. If you have more than -- one entry to insert, then test all of them. if exporters.SaveToXXX then error("SciTE_ExporterXXX: exporters.SaveToXXX already defined") end else exporters = {} -- create table end ----------------------------------------------------------------------- -- exporters:SaveToXXX -- -- Exports the document in the current window to an information dump -- file with the extension of XXX. -- -- * usually a single function is enough to do everything -- * remember to define local variables only to avoid polluting the -- global namespace, it's good to keep things clean ----------------------------------------------------------------------- function exporters:SaveToXXX() --------------------------------------------------------------------- -- use this if you want the ability to export selected text -- if no text is selected, the whole document will be exported --------------------------------------------------------------------- local selBeg, selEnd = exportutil.GetSelPos() --------------------------------------------------------------------- -- if you want to always export the whole document, then change to: --------------------------------------------------------------------- --[[ local selBeg, selEnd = 0, editor.Length ]] --------------------------------------------------------------------- -- always present, to force (re-?)lexing of the whole document --------------------------------------------------------------------- editor:Colourise(0, -1) --------------------------------------------------------------------- -- a quick way to initialize a numerical exporter property -- string properties should use props[""] directly -- the tonumber(...) will give a nil if the property does not exist -- or the property is not a number, then the default will be 4 --------------------------------------------------------------------- --[[ local tabSize = tonumber(props["tabsize"]) or 4 ]] --------------------------------------------------------------------- -- an alternative with better checks to ensure sane values -- sane defaults you don't want to expose can be defined as locals, -- like HTMLDefaultTabSize below --------------------------------------------------------------------- local HTMLDefaultTabSize = 4 local tabSize = tonumber(props["tabsize"]) if not tabSize or tabSize <= 0 or tabSize >= 99 then tabSize = HTMLDefaultTabSize end --------------------------------------------------------------------- -- handling true/false properties: 0 is false, non-0 is true -- the exportutil.propbool() call has a default of false, a 1 changes -- the default to true for convertTabs and background --------------------------------------------------------------------- local convertTabs = exportutil.propbool("export.xxx.converttabs", 1) local stylesUsed = exportutil.propbool("export.xxx.styleused") local background = exportutil.propbool("export.xxx.background", 1) --------------------------------------------------------------------- -- use this to get only the styles that are used in a document range --------------------------------------------------------------------- local styleIsUsed = {} if stylesUsed then -- look for used styles for i = selBeg, selEnd - 1 do styleIsUsed[exportutil.StyleAt(i)] = true end else -- set all styles to used for i = 0, exportutil.STYLE_MAX do styleIsUsed[i] = true end end -- The default style is always used since it gives a complete -- specification of the base style. Other styles build on this -- base style, or inherits the base style properties styleIsUsed[exportutil.STYLE_DEFAULT] = true --------------------------------------------------------------------- -- this is the standard code for: -- (1) building a file name and path to use -- (2) opening the file for writing -- * some exporters will need binary output, so use "wb" --------------------------------------------------------------------- local saveName = exportutil.exportfile(props["FileDir"], props["FileName"], "xxx") local fp = io.open(saveName, "wt") if not fp then error("exporters:SaveToXXX: could not save file \""..saveName.."\"") end --------------------------------------------------------------------- -- this is a standard alert to tell the user that the script is working --------------------------------------------------------------------- if exportutil.VERBOSE ~= 0 then _ALERT("\nExporting to XXX, filepath: "..saveName) end --------------------------------------------------------------------- -- use fp:write() to write stuff to the output file, e.g.: -- fp:write("") -- calling with a list of data is usually more efficient than -- concatenating the data in advance --------------------------------------------------------------------- local originalName = props["FileNameExt"] fp:write("Exporter Template information dump for: ", props["FileNameExt"], "\n\n") --------------------------------------------------------------------- -- this is always required, to initialize the style tables using the -- style manager given the current style lexer -- * if you want to add another layer of overrides, then see the -- stylemgr sources in SciTE_ExportBase.lua --------------------------------------------------------------------- stylemgr:setlexer(editor.Lexer) --------------------------------------------------------------------- -- this loops though all styles and does some processing -- configuration information prior to document content start can be -- written to the exported file in this section --------------------------------------------------------------------- fp:write("Style information:\n\n") for i = 0, exportutil.STYLE_MAX do if styleIsUsed[i] then fp:write("style["..i.."] =\n") ----------------------------------------------------------------- -- call to parse style property information and return a -- reference to the table that is produced. the table is -- cached in stylemgr to speed up later retrievals ----------------------------------------------------------------- local sd = stylemgr:locate(i) ----------------------------------------------------------------- -- for processing only if this style has one or more elements -- explicitly defined in its property value. Here, convert style -- information in the table into the exporter data format ----------------------------------------------------------------- if sd.specified ~= "" then fp:write(" specified = \""..sd.specified.."\"\n") --------------------------------------------------------------- -- test for sd.specified elements if you want to process -- only styles that were explicitly specified by a style, -- otherwise you can build a complete style specification -- by processing the whole table, or do parts of it --------------------------------------------------------------- --[[if string.find(sd.specified, "back", 1, 1) then ... end]] --------------------------------------------------------------- -- if you want to do special processing for the default -- case, test for it using STYLE_DEFAULT like this: --------------------------------------------------------------- --[[if i == STYLE_DEFAULT then ... end]] --------------------------------------------------------------- -- here we process selected styles regardless whether it -- was explicitly specified in the style property -- font is a string while size is a number --------------------------------------------------------------- if sd.font then fp:write(" font = \""..sd.font.."\"\n") end if sd.size then fp:write(" size = "..sd.size.."\n") end --------------------------------------------------------------- -- use stylemgr:hexstr() to get HTML-style colour specs --------------------------------------------------------------- if sd.fore then fp:write(" fore = \""..stylemgr:hexstr(sd.fore).."\"\n") end --------------------------------------------------------------- -- example of a style field controlled by a user-set boolean -- property, allows customization without going down into Lua --------------------------------------------------------------- if background and sd.back then fp:write(" back = \""..stylemgr:hexstr(sd.back).."\"\n") end --------------------------------------------------------------- -- these are boolean style values, reported if they are -- explicitly specified in the style property --------------------------------------------------------------- if string.find(sd.specified, "italics", 1, 1) then fp:write(" italics = "..tostring(sd.italics).."\n") end if string.find(sd.specified, "bold", 1, 1) then fp:write(" bold = "..tostring(sd.bold).."\n") end if string.find(sd.specified, "eolfilled", 1, 1) then fp:write(" eolfilled = "..tostring(sd.eolfilled).."\n") end if string.find(sd.specified, "underlined", 1, 1) then fp:write(" underlined = "..tostring(sd.underlined).."\n") end end else ----------------------------------------------------------------- -- something to do if this style is unused ----------------------------------------------------------------- fp:write("style["..i.."] = nil\n") end--if styleIsUsed end--for i --------------------------------------------------------------------- -- write out any stuff here prior to processing document proper --------------------------------------------------------------------- fp:write("\nDocument information:\n\n") --------------------------------------------------------------------- -- line-by-line processing example (untested) -- * this eliminates the need for CR/LF/CRLF handling --------------------------------------------------------------------- --[[ local lineBeg = editor:LineFromPosition(selBeg) local lineEnd = editor:LineFromPosition(selEnd - 1) for l = lineBeg, lineEnd do local posBeg = editor:PositionFromLine(l) -- remove to always process whole lines if l == lineBeg then posBeg = selBeg end local posEnd = editor.LineEndPosition[ln] -- remove to always process whole lines if l == lineEnd then posEnd = selEnd end -- do stuff pre-line for i = posBeg, posEnd do -- do stuff per-character end -- do stuff post-line end --]] --------------------------------------------------------------------- -- generic character-by-character processing -- the common handlers needed are for: -- (a) change of style -- (b) tab processing -- (c) CR/LF/CRLF handling --------------------------------------------------------------------- -- column is commonly used for tab calculation --------------------------------------------------------------------- local column = 0 local i = selBeg local styleCurrent --------------------------------------------------------------------- -- main loop here --------------------------------------------------------------------- while i < selEnd do ------------------------------------------------------------------- -- standard calls to get the character value and style -- use the exportutil calls for convenience, see SciTE_ExportBase -- for an explanation of the quirks of the primitive calls ------------------------------------------------------------------- local ch = exportutil.CharAt(i) local style = exportutil.StyleAt(i) ------------------------------------------------------------------- -- generic change of style handling code ------------------------------------------------------------------- if style ~= styleCurrent then fp:write("<"..style..">") styleCurrent = style end--style ------------------------------------------------------------------- -- character handling, a long if-then-elseif-end block, while -- significant control characters are handled first -- a table lookup is probably faster ------------------------------------------------------------------- -- standard tab processing, with an optional user-controlled flag ------------------------------------------------------------------- if ch == "\t" then if convertTabs then local ts = tabSize - column % tabSize fp:write(string.rep(" ", ts)) column = column + ts else fp:write(ch) column = column + 1 end ------------------------------------------------------------------- -- generic handling for CR/LF/CRLF EOL formats ------------------------------------------------------------------- elseif ch == "\r" or ch == "\n" then if ch == "\r" and exportutil.CharAt(i + 1) == "\n" then i = i + 1 end column = 0 fp:write("
\n") ------------------------------------------------------------------- -- other characters are handled here -- escapes for particular characters are done here (for example, -- converting symbols to their HTML entity equivalent) ------------------------------------------------------------------- else local chv = string.byte(ch) if chv < 32 then fp:write("("..chv..")") elseif ch == "<" then fp:write("<") elseif ch == ">" then fp:write(">") else fp:write(ch) end column = column + 1 end--if ch ------------------------------------------------------------------- -- final part of main loop ------------------------------------------------------------------- i = i + 1 end--while --------------------------------------------------------------------- -- all post-main loop operations should be done here, for example, -- you might need to close balanced brackets or stuff like that --------------------------------------------------------------------- fp:write("\n\n") --------------------------------------------------------------------- -- normal call to close the exported document --------------------------------------------------------------------- fp:close() --------------------------------------------------------------------- -- this is a standard alert at the end of the script --------------------------------------------------------------------- if exportutil.VERBOSE ~= 0 then exportutil.progress("... done.") end end -- end of script