Compatible Android
This commit is contained in:
@ -0,0 +1,284 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
local funcdef = "([A-Za-z_][A-Za-z0-9_%.%:]*)%s*"
|
||||
local decindent = {
|
||||
['else'] = true, ['elseif'] = true, ['until'] = true, ['end'] = true}
|
||||
local incindent = {
|
||||
['else'] = true, ['elseif'] = true, ['for'] = true, ['do'] = true,
|
||||
['if'] = true, ['repeat'] = true, ['while'] = true}
|
||||
local function isfndef(str)
|
||||
local l
|
||||
local s,e,cap,par = string.find(str, "function%s+" .. funcdef .. "(%(.-%))")
|
||||
-- try to match without brackets now, but only at the beginning of the line
|
||||
if (not s) then
|
||||
s,e,cap = string.find(str, "^%s*function%s+" .. funcdef)
|
||||
end
|
||||
-- try to match "foo = function()"
|
||||
if (not s) then
|
||||
s,e,cap,par = string.find(str, funcdef .. "=%s*function%s*(%(.-%))")
|
||||
end
|
||||
if (s) then
|
||||
l = string.find(string.sub(str,1,s-1),"local%s+$")
|
||||
cap = cap .. " " .. (par or "(?)")
|
||||
end
|
||||
return s,e,cap,l
|
||||
end
|
||||
local q = EscapeMagic
|
||||
|
||||
local function ldoc(tx, typepatt)
|
||||
local varname = "([%w_]+)"
|
||||
-- <type> == ?string, ?|T1|T2
|
||||
-- anything that follows optional "|..." is ignored
|
||||
local typename = "%??"..typepatt
|
||||
-- @tparam[...] <type> <paramname>
|
||||
-- @param[type=<type>] <paramname>
|
||||
-- @string[...] <paramname>; not handled
|
||||
local t, v = tx:match("--%s*@tparam%b[]%s+"..typename.."%s+"..varname)
|
||||
if not t then -- try without optional [...] part
|
||||
t, v = tx:match("--%s*@tparam%s+"..typename.."%s+"..varname)
|
||||
end
|
||||
if not t then
|
||||
t, v = tx:match("--%s*@param%s*%[type="..typename.."%]%s+"..varname)
|
||||
end
|
||||
return t, v
|
||||
end
|
||||
|
||||
return {
|
||||
exts = {"lua", "rockspec", "wlua"},
|
||||
lexer = wxstc.wxSTC_LEX_LUA,
|
||||
apitype = "lua",
|
||||
linecomment = "--",
|
||||
sep = ".:",
|
||||
isdecindent = function(str)
|
||||
str = str:gsub('%-%-%[=*%[.*%]=*%]',''):gsub('%-%-.*','')
|
||||
-- this handles three different cases:
|
||||
local term = (str:match("^%s*(%w+)%s*$")
|
||||
or str:match("^%s*(elseif)[%s%(]")
|
||||
or str:match("^%s*(until)[%s%(]")
|
||||
or str:match("^%s*(else)%f[%W]")
|
||||
)
|
||||
-- (1) 'end', 'elseif', 'else', 'until'
|
||||
local match = term and decindent[term]
|
||||
-- (2) 'end)', 'end}', 'end,', and 'end;'
|
||||
if not term then term, match = str:match("^%s*(end)%s*([%)%}]*)%s*[,;]?") end
|
||||
-- endFoo could be captured as well; filter it out
|
||||
if term and str:match("^%s*(end)%w") then term = nil end
|
||||
-- (3) '},', '};', '),' and ');'
|
||||
if not term then match = str:match("^%s*[%)%}]+%s*[,;]?%s*$") end
|
||||
|
||||
return match and 1 or 0, match and term and 1 or 0
|
||||
end,
|
||||
isincindent = function(str)
|
||||
-- remove "long" comments and escaped slashes (to process \' and \" below)
|
||||
str = str:gsub('%-%-%[=*%[.-%]=*%]',''):gsub('\\[\\\'"]','')
|
||||
while true do
|
||||
local num, sep = nil, str:match("['\"]")
|
||||
if not sep then break end
|
||||
str, num = str:gsub(sep..".-\\"..sep,sep):gsub(sep..".-"..sep,"")
|
||||
if num == 0 then break end
|
||||
end
|
||||
str = (str
|
||||
:gsub('%[=*%[.-%]=*%]','') -- remove long strings
|
||||
:gsub('%[=*%[.*','') -- remove partial long strings
|
||||
:gsub('%-%-.*','') -- strip comments after strings are processed
|
||||
:gsub("%b()","()") -- remove all function calls
|
||||
)
|
||||
|
||||
local term = str:match("^%s*(%w+)%W*")
|
||||
local terminc = term and incindent[term] and 1 or 0
|
||||
-- fix 'if' not terminated with 'then'
|
||||
-- or 'then' not started with 'if'
|
||||
if (term == 'if' or term == 'elseif') and not str:match("%f[%w]then%f[%W]")
|
||||
or (term == 'for') and not str:match("%S%s+do%f[%W]")
|
||||
or (term == 'while') and not str:match("%f[%w]do%f[%W]") then
|
||||
terminc = 0
|
||||
elseif not (term == 'if' or term == 'elseif') and str:match("%f[%w]then%f[%W]")
|
||||
or not (term == 'for') and str:match("%S%s+do%f[%W]")
|
||||
or not (term == 'while') and str:match("%f[%w]do%f[%W]") then
|
||||
terminc = 1
|
||||
end
|
||||
local _, opened = str:gsub("([%{%(])", "%1")
|
||||
local _, closed = str:gsub("([%}%)])", "%1")
|
||||
local func = (isfndef(str) or str:match("%W+function%s*%(")) and 1 or 0
|
||||
-- ended should only be used to negate term and func effects
|
||||
local anon = str:match("%W+function%s*%(.+%Wend%W")
|
||||
local ended = (terminc + func > 0) and (str:match("%W+end%s*$") or anon) and 1 or 0
|
||||
|
||||
return opened - closed + func + terminc - ended
|
||||
end,
|
||||
marksymbols = function(code, pos, vars)
|
||||
local PARSE = require 'lua_parser_loose'
|
||||
local LEX = require 'lua_lexer_loose'
|
||||
local lx = LEX.lexc(code, nil, pos)
|
||||
return coroutine.wrap(function()
|
||||
local varnext = {}
|
||||
PARSE.parse_scope_resolve(lx, function(op, name, lineinfo, vars, nobreak)
|
||||
if not(op == 'Id' or op == 'Statement' or op == 'Var'
|
||||
or op == 'Function' or op == 'String'
|
||||
or op == 'VarNext' or op == 'VarInside' or op == 'VarSelf'
|
||||
or op == 'FunctionCall' or op == 'Scope' or op == 'EndScope') then
|
||||
return end -- "normal" return; not interested in other events
|
||||
|
||||
-- level needs to be adjusted for VarInside as it comes into scope
|
||||
-- only after next block statement
|
||||
local at = vars[0] and (vars[0] + (op == 'VarInside' and 1 or 0))
|
||||
if op == 'Statement' then
|
||||
for _, token in pairs(varnext) do coroutine.yield(unpack(token)) end
|
||||
varnext = {}
|
||||
elseif op == 'VarNext' or op == 'VarInside' then
|
||||
table.insert(varnext, {'Var', name, lineinfo, vars, at, nobreak})
|
||||
end
|
||||
|
||||
coroutine.yield(op, name, lineinfo, vars, op == 'Function' and at-1 or at, nobreak)
|
||||
end, vars)
|
||||
end)
|
||||
end,
|
||||
|
||||
typeassigns = function(editor)
|
||||
local maxlines = 48 -- scan up to this many lines back
|
||||
local iscomment = editor.spec.iscomment
|
||||
local assigns = {}
|
||||
local endline = editor:GetCurrentLine()-1
|
||||
local line = math.max(endline-maxlines, 0)
|
||||
|
||||
while (line <= endline) do
|
||||
local ls = editor:PositionFromLine(line)
|
||||
local tx = editor:GetLine(line) --= string
|
||||
local s = bit.band(editor:GetStyleAt(ls + #tx:match("^%s*") + 2),31)
|
||||
|
||||
-- check for assignments
|
||||
local sep = editor.spec.sep
|
||||
local varname = "([%w_][%w_"..q(sep:sub(1,1)).."]*)"
|
||||
local identifier = "([%w_][%w_"..q(sep).."%s]*)"
|
||||
|
||||
-- special hint
|
||||
local typ, var = tx:match("%s*%-%-=%s*"..varname.."%s+"..identifier)
|
||||
local ldoctype, ldocvar = ldoc(tx, varname)
|
||||
if var and typ then
|
||||
assigns[var] = typ:gsub("%s","")
|
||||
elseif ldoctype and ldocvar then
|
||||
assigns[ldocvar] = ldoctype
|
||||
elseif not iscomment[s] then
|
||||
-- real assignments
|
||||
local var,typ = tx:match("%s*"..identifier.."%s*=%s*([^;]+)")
|
||||
|
||||
var = var and var:gsub("local",""):gsub("%s","")
|
||||
-- handle `require` as a special case that returns a type that matches its parameter
|
||||
-- (this is without deeper analysis on loaded files and should work most of the time)
|
||||
local req = typ and typ:match("^require%s*%(?%s*['\"](.+)['\"]%s*%)?")
|
||||
typ = req or typ
|
||||
typ = (typ and typ
|
||||
:gsub("%b()","")
|
||||
:gsub("%b{}","")
|
||||
:gsub("%b[]",".0")
|
||||
-- replace concatenation with addition to avoid misidentifying types
|
||||
:gsub("%.%.+","+")
|
||||
-- remove comments; they may be in strings, but that's okay here
|
||||
:gsub("%-%-.*",""))
|
||||
if (typ and (typ:match(",") or typ:match("%sor%s") or typ:match("%sand%s"))) then
|
||||
typ = nil
|
||||
end
|
||||
typ = typ and typ:gsub("%s","")
|
||||
typ = typ and typ:gsub(".+", function(s)
|
||||
return (s:find("^'[^']*'$")
|
||||
or s:find('^"[^"]*"$')
|
||||
or s:find('^%[=*%[.*%]=*%]$')) and 'string' or s
|
||||
end)
|
||||
|
||||
-- filter out everything that is not needed
|
||||
if typ and typ ~= 'string' -- special value for all strings
|
||||
and (not typ:match('^'..identifier..'$') -- not an identifier
|
||||
or typ:match('^%d') -- or a number
|
||||
or editor.api.tip.keys[typ] -- or a keyword
|
||||
) then
|
||||
typ = nil
|
||||
end
|
||||
|
||||
if (var and typ) then
|
||||
local class,func = typ:match(varname.."["..q(sep).."]"..varname)
|
||||
if (assigns[typ] and not req) then
|
||||
assigns[var] = assigns[typ]
|
||||
elseif (func) then
|
||||
local added
|
||||
local funcnames = {"new","load","create"}
|
||||
for _,v in ipairs(funcnames) do
|
||||
if (func == v) then
|
||||
assigns[var] = class
|
||||
added = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if (not added) then
|
||||
-- let's hope autocomplete info can resolve this
|
||||
assigns[var] = typ
|
||||
end
|
||||
else
|
||||
assigns[var] = typ
|
||||
end
|
||||
end
|
||||
end
|
||||
line = line+1
|
||||
end
|
||||
|
||||
return assigns
|
||||
end,
|
||||
|
||||
lexerstyleconvert = {
|
||||
text = {wxstc.wxSTC_LUA_IDENTIFIER,},
|
||||
|
||||
lexerdef = {wxstc.wxSTC_LUA_DEFAULT,},
|
||||
comment = {wxstc.wxSTC_LUA_COMMENT,
|
||||
wxstc.wxSTC_LUA_COMMENTLINE,
|
||||
wxstc.wxSTC_LUA_COMMENTDOC,},
|
||||
stringtxt = {wxstc.wxSTC_LUA_STRING,
|
||||
wxstc.wxSTC_LUA_CHARACTER,
|
||||
wxstc.wxSTC_LUA_LITERALSTRING,},
|
||||
stringeol = {wxstc.wxSTC_LUA_STRINGEOL,},
|
||||
preprocessor= {wxstc.wxSTC_LUA_PREPROCESSOR,},
|
||||
operator = {wxstc.wxSTC_LUA_OPERATOR,},
|
||||
number = {wxstc.wxSTC_LUA_NUMBER,},
|
||||
|
||||
keywords0 = {wxstc.wxSTC_LUA_WORD,},
|
||||
keywords1 = {wxstc.wxSTC_LUA_WORD2,},
|
||||
keywords2 = {wxstc.wxSTC_LUA_WORD3,},
|
||||
keywords3 = {wxstc.wxSTC_LUA_WORD4,},
|
||||
keywords4 = {wxstc.wxSTC_LUA_WORD5,},
|
||||
keywords5 = {wxstc.wxSTC_LUA_WORD6,},
|
||||
keywords6 = {wxstc.wxSTC_LUA_WORD7,},
|
||||
keywords7 = {wxstc.wxSTC_LUA_WORD8,},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
[[and break do else elseif end for function goto if in local not or repeat return then until while]],
|
||||
|
||||
[[_G _VERSION _ENV false io.stderr io.stdin io.stdout nil math.huge math.pi self true]],
|
||||
|
||||
[[assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring
|
||||
module next pairs pcall print rawequal rawget rawlen rawset require
|
||||
select setfenv setmetatable tonumber tostring type unpack xpcall]],
|
||||
|
||||
[[bit32.arshift bit32.band bit32.bnot bit32.bor bit32.btest bit32.bxor bit32.extract
|
||||
bit32.lrotate bit32.lshift bit32.replace bit32.rrotate bit32.rshift
|
||||
coroutine.create coroutine.resume coroutine.running coroutine.status coroutine.wrap coroutine.yield
|
||||
coroutine.isyieldable
|
||||
debug.debug debug.getfenv debug.gethook debug.getinfo debug.getlocal
|
||||
debug.getmetatable debug.getregistry debug.getupvalue debug.getuservalue debug.setfenv
|
||||
debug.sethook debug.setlocal debug.setmetatable debug.setupvalue debug.setuservalue
|
||||
debug.traceback debug.upvalueid debug.upvaluejoin
|
||||
io.close io.flush io.input io.lines io.open io.output io.popen io.read io.tmpfile io.type io.write
|
||||
close flush lines read seek setvbuf write
|
||||
math.abs math.acos math.asin math.atan math.atan2 math.ceil math.cos math.cosh math.deg math.exp
|
||||
math.floor math.fmod math.frexp math.ldexp math.log math.log10 math.max math.min math.modf
|
||||
math.pow math.rad math.random math.randomseed math.sin math.sinh math.sqrt math.tan math.tanh
|
||||
math.type math.tointeger math.maxinteger math.mininteger math.ult
|
||||
os.clock os.date os.difftime os.execute os.exit os.getenv os.remove os.rename os.setlocale os.time os.tmpname
|
||||
package.loadlib package.searchpath package.seeall package.config
|
||||
package.cpath package.loaded package.loaders package.path package.preload package.searchers
|
||||
string.byte string.char string.dump string.find string.format string.gmatch string.gsub string.len
|
||||
string.lower string.match string.rep string.reverse string.sub string.upper
|
||||
byte find format gmatch gsub len lower match rep reverse sub upper
|
||||
table.move, string.pack, string.unpack, string.packsize
|
||||
table.concat table.insert table.maxn table.pack table.remove table.sort table.unpack]]
|
||||
},
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
exts = {"txt"},
|
||||
--lexer = wxstc.wxSTC_LEX_POV,
|
||||
--apitype = "luxres",
|
||||
linecomment = ">",
|
||||
}
|
Reference in New Issue
Block a user