Vendored from upstream, pinned by commit (see debian/extra/README.source): - gitstatus, gitopen, fontconfig, open_ext, select_colorscheme, smoothcaret, nerdicons (font mapping patched to DATADIR, Ships the Symbols Nerd Font Mono TTF, SIL OFL 1.1) - lite-xl-lsp (complete LSP client; idle until a language server is configured) plus the lite-xl-widgets library it requires - 104 language syntax plugins (none duplicate the nine bundled in core) settings GUI left out upstream is broken: it requires a libraries.widget.fonts widget that does not exist in lite-xl-widgets at any revision. Co-developed-with: ZCode (Z.ai)
422 lines
12 KiB
Lua
422 lines
12 KiB
Lua
-- mod-version:3
|
|
--[[
|
|
language_php.lua
|
|
provides php syntax support allowing mixed html, css and js
|
|
version: 20220614_1
|
|
--]]
|
|
local syntax = require "core.syntax"
|
|
local common = require "core.common"
|
|
local config = require "core.config"
|
|
|
|
-- load syntax dependencies to add additional rules
|
|
require "plugins.language_css"
|
|
require "plugins.language_js"
|
|
|
|
local psql_found = pcall(require, "plugins.language_psql")
|
|
local sql_strings = {}
|
|
|
|
config.plugins.language_php = common.merge({
|
|
sql_strings = true,
|
|
-- The config specification used by the settings gui
|
|
config_spec = {
|
|
name = "Language PHP",
|
|
{
|
|
label = "SQL Strings",
|
|
description = "Highlight as SQL, strings starting with sql statements, "
|
|
.. "depends on language_psql.",
|
|
path = "sql_strings",
|
|
type = "toggle",
|
|
default = true,
|
|
on_apply = function(enabled)
|
|
local syntax_php = syntax.get("file.phps")
|
|
if enabled and psql_found then
|
|
if
|
|
not syntax_php.patterns[6].syntax
|
|
or
|
|
syntax_php.patterns[6].syntax ~= '.sql'
|
|
then
|
|
table.insert(syntax_php.patterns, 5, sql_strings[1])
|
|
table.insert(syntax_php.patterns, 6, sql_strings[2])
|
|
end
|
|
elseif
|
|
syntax_php.patterns[6].syntax
|
|
and
|
|
syntax_php.patterns[6].syntax == '.sql'
|
|
then
|
|
table.remove(syntax_php.patterns, 5)
|
|
table.remove(syntax_php.patterns, 5)
|
|
end
|
|
end
|
|
}
|
|
}
|
|
}, config.plugins.language_php)
|
|
|
|
-- Patterns to match some of the string inline variables
|
|
local inline_variables = {
|
|
{ pattern = "%s+", type = "string" },
|
|
{ pattern = "\\%$", type = "string" },
|
|
{ pattern = "%{[%$%s]*%}", type = "string" },
|
|
-- matches {$varname[index]}
|
|
{ pattern = "{"
|
|
.. "()%$[%a_][%w_]*"
|
|
.. "()%["
|
|
.. "()[%w%s_%-\"\'%(%)|;:,%.#@%%!%^&%*%+=%[%]<>~`%?\\/]*"
|
|
.. "()%]"
|
|
.. "}",
|
|
type = {
|
|
"keyword", "keyword2", "keyword", "string", "keyword"
|
|
}
|
|
},
|
|
{ pattern = "{"
|
|
.. "()%$[%a_][%w_]*"
|
|
.. "()%->"
|
|
.. "()[%a_][%w_]*"
|
|
.. "()}",
|
|
type = {
|
|
"keyword", "keyword2", "keyword", "symbol", "keyword"
|
|
}
|
|
},
|
|
{ pattern = "{()%$[%a_][%w_]*()}",
|
|
type = { "keyword", "keyword2", "keyword" }
|
|
},
|
|
{ pattern = "%$[%a_][%w_]*()%[()[%w_]*()%]",
|
|
type = { "keyword2", "keyword", "string", "keyword" }
|
|
},
|
|
{ pattern = "%$[%a_][%w_]*()%->()%a[%w_]*",
|
|
type = { "keyword2", "keyword", "symbol" }
|
|
},
|
|
{ pattern = "%$[%a_][%w_]*", type = "keyword2" },
|
|
{ pattern = "%w+", type = "string" }
|
|
}
|
|
|
|
local function combine_patterns(t1, t2)
|
|
local temp = { table.unpack(t1) }
|
|
for _, t in ipairs(t2) do
|
|
table.insert(temp, t)
|
|
end
|
|
return temp
|
|
end
|
|
|
|
local function clone(tbl)
|
|
local t = {}
|
|
if tbl then
|
|
for k, v in pairs(tbl) do
|
|
if type(v) == "table" then
|
|
t[k] = clone(v)
|
|
else
|
|
t[k] = v
|
|
end
|
|
end
|
|
end
|
|
return t
|
|
end
|
|
|
|
-- optionally allow sql syntax on strings
|
|
if psql_found then
|
|
-- generate SQL string marker regex
|
|
local sql_markers = { 'create', 'select', 'insert', 'update', 'replace', 'delete', 'drop', 'alter' }
|
|
local sql_regex = table.concat(sql_markers, '|')
|
|
|
|
-- inject inline variable rules to cloned psql syntax
|
|
local syntax_phpsql = clone(syntax.get("file.sql"))
|
|
syntax_phpsql.name = "PHP SQL"
|
|
syntax_phpsql.files = "%.phpsql$"
|
|
table.insert(syntax_phpsql.patterns, 2, { pattern = "\\%$", type = "symbol" })
|
|
table.insert(syntax_phpsql.patterns, 3, { pattern = "%{[%$%s]*%}", type = "symbol" })
|
|
for i=4, 9 do
|
|
table.insert(syntax_phpsql.patterns, i, inline_variables[i])
|
|
end
|
|
|
|
-- SQL strings
|
|
sql_strings = {
|
|
{
|
|
regex = { '"(?=[\\s(]*(?i:'..sql_regex..')\\s+)', '"', '\\' },
|
|
syntax = syntax_phpsql,
|
|
type = "string"
|
|
},
|
|
{
|
|
regex = { "'(?=[\\s(]*(?i:"..sql_regex..")\\s+)", '\'', '\\' },
|
|
syntax = '.sql',
|
|
type = "string"
|
|
},
|
|
}
|
|
end
|
|
|
|
-- define the core php syntax coloring
|
|
syntax.add {
|
|
name = "PHP Source",
|
|
files = { "%.phps$" },
|
|
headers = "^<%?php",
|
|
comment = "//",
|
|
block_comment = {"/*", "*/"},
|
|
patterns = {
|
|
-- Attributes
|
|
{ pattern = {"#%[", "%]"}, type = "normal" },
|
|
-- Comments
|
|
{ pattern = "//.-\n", type = "comment" },
|
|
{ pattern = "#.-\n", type = "comment" },
|
|
{ pattern = { "/%*", "%*/" }, type = "comment" },
|
|
-- Single quote string
|
|
{ pattern = { "'", "'", '\\' }, type = "string" },
|
|
{ pattern = { "<<<'%a%w*'\n", "^%s*%a%w*%f[;]", '\\' },
|
|
type = "string"
|
|
},
|
|
-- Strings with support for some inline variables syntax
|
|
{ pattern = { "<<<%a%w*\n", "^%s*%a%w*%f[;]", '\\' },
|
|
syntax = {
|
|
patterns = combine_patterns(inline_variables, {
|
|
-- prevent matching outside of the parent string
|
|
{ pattern = "^%s*%a%w*();$",
|
|
type = { "string", "normal" }
|
|
},
|
|
{ pattern = "%p", type = "string" },
|
|
}),
|
|
symbols = {}
|
|
},
|
|
type = "string"
|
|
},
|
|
{ pattern = { '"', '"', '\\' },
|
|
syntax = {
|
|
patterns = combine_patterns(inline_variables, {
|
|
-- prevent matching outside of the parent string
|
|
{ pattern = "[^\"]", type = "string" },
|
|
{ pattern = "%p+%f[\"]", type = "string" },
|
|
{ pattern = "%p", type = "string" },
|
|
}),
|
|
symbols = {}
|
|
},
|
|
type = "string"
|
|
},
|
|
{ pattern = { '`', '`', '\\' },
|
|
syntax = {
|
|
patterns = combine_patterns(inline_variables, {
|
|
-- prevent matching outside of the parent string
|
|
{ pattern = "[^`]", type = "string" },
|
|
{ pattern = "%p+%f[`]", type = "string" },
|
|
{ pattern = "%p", type = "string" },
|
|
}),
|
|
symbols = {}
|
|
},
|
|
type = "string"
|
|
},
|
|
{ pattern = "0[bB][%d]+", type = "number" },
|
|
{ pattern = "0[xX][%da-fA-F]+", type = "number" },
|
|
{ pattern = "-?%d[%d_%.eE]*", type = "number" },
|
|
{ pattern = "-?%.?%d+", type = "number" },
|
|
{ pattern = "[%.%+%-=/%*%^%%<>!~|&%?:@]", type = "operator" },
|
|
-- Variables
|
|
{ pattern = "%$[%w_]+", type = "keyword2" },
|
|
-- Respect control structures, treat as keyword not function
|
|
{ pattern = "if[%s]*%f[(]", type = "keyword" },
|
|
{ pattern = "else[%s]*%f[(]", type = "keyword" },
|
|
{ pattern = "elseif[%s]*%f[(]", type = "keyword" },
|
|
{ pattern = "for[%s]*%f[(]", type = "keyword" },
|
|
{ pattern = "foreach[%s]*%f[(]", type = "keyword" },
|
|
{ pattern = "while[%s]*%f[(]", type = "keyword" },
|
|
{ pattern = "catch[%s]*%f[(]", type = "keyword" },
|
|
{ pattern = "switch[%s]*%f[(]", type = "keyword" },
|
|
{ pattern = "match[%s]*%f[(]", type = "keyword" },
|
|
{ pattern = "fn[%s]*%f[(]", type = "keyword" },
|
|
-- All functions that aren't control structures
|
|
{ pattern = "[%a_][%w_]*[%s]*%f[(]", type = "function" },
|
|
-- Array type hint not added on symbols to also make it work
|
|
-- as a function call
|
|
{ pattern = "array", type = "literal" },
|
|
-- Match static or namespace container on sub element access
|
|
{ pattern = "[%a_][%w_]*[%s]*%f[:]", type = "literal" },
|
|
-- Uppercase constants of at least 2 chars in len
|
|
{
|
|
pattern = "%u[%u_][%u%d_]*%f[%s%+%*%-%.%(%)%?%^%%=/<>~|&;:,!]",
|
|
type = "number"
|
|
},
|
|
-- Magic constants
|
|
{ pattern = "__[%u]+__", type = "number" },
|
|
-- Everything else
|
|
{ pattern = "[%a_][%w_]*", type = "symbol" },
|
|
},
|
|
symbols = {
|
|
["return"] = "keyword",
|
|
["if"] = "keyword",
|
|
["else"] = "keyword",
|
|
["elseif"] = "keyword",
|
|
["endif"] = "keyword",
|
|
["declare"] = "keyword",
|
|
["enddeclare"] = "keyword",
|
|
["switch"] = "keyword",
|
|
["endswitch"] = "keyword",
|
|
["as"] = "keyword",
|
|
["do"] = "keyword",
|
|
["for"] = "keyword",
|
|
["endfor"] = "keyword",
|
|
["foreach"] = "keyword",
|
|
["endforeach"] = "keyword",
|
|
["while"] = "keyword",
|
|
["endwhile"] = "keyword",
|
|
["match"] = "keyword",
|
|
["case"] = "keyword",
|
|
["continue"] = "keyword",
|
|
["default"] = "keyword",
|
|
["break"] = "keyword",
|
|
["goto"] = "keyword",
|
|
["yield"] = "keyword",
|
|
|
|
["try"] = "keyword",
|
|
["catch"] = "keyword",
|
|
["throw"] = "keyword",
|
|
["finally"] = "keyword",
|
|
|
|
["class"] = "keyword",
|
|
["enum"] = "keyword",
|
|
["trait"] = "keyword",
|
|
["interface"] = "keyword",
|
|
["public"] = "keyword",
|
|
["static"] = "keyword",
|
|
["protected"] = "keyword",
|
|
["private"] = "keyword",
|
|
["readonly"] = "keyword",
|
|
["abstract"] = "keyword",
|
|
["final"] = "keyword",
|
|
["$this"] = "literal",
|
|
|
|
["function"] = "keyword",
|
|
["fn"] = "keyword",
|
|
["global"] = "keyword",
|
|
["var"] = "keyword",
|
|
["const"] = "keyword",
|
|
|
|
["bool"] = "literal",
|
|
["boolean"] = "literal",
|
|
["int"] = "literal",
|
|
["integer"] = "literal",
|
|
["real"] = "literal",
|
|
["double"] = "literal",
|
|
["float"] = "literal",
|
|
["string"] = "literal",
|
|
["object"] = "literal",
|
|
["callable"] = "literal",
|
|
["iterable"] = "literal",
|
|
["void"] = "literal",
|
|
["parent"] = "literal",
|
|
["self"] = "literal",
|
|
["mixed"] = "literal",
|
|
["never"] = "literal",
|
|
|
|
["namespace"] = "keyword",
|
|
["extends"] = "keyword",
|
|
["implements"] = "keyword",
|
|
["instanceof"] = "keyword",
|
|
["require"] = "keyword",
|
|
["require_once"] = "keyword",
|
|
["include"] = "keyword",
|
|
["include_once"] = "keyword",
|
|
["use"] = "keyword",
|
|
["new"] = "keyword",
|
|
["clone"] = "keyword",
|
|
|
|
["true"] = "number",
|
|
["false"] = "number",
|
|
["NULL"] = "number",
|
|
["null"] = "number",
|
|
|
|
["print"] = "function",
|
|
["echo"] = "function",
|
|
["exit"] = "function",
|
|
},
|
|
}
|
|
|
|
-- insert sql string rules after the "/%*", "%*/" pattern
|
|
if psql_found and config.plugins.language_php.sql_strings then
|
|
local syntax_php = syntax.get("file.phps")
|
|
table.insert(syntax_php.patterns, 5, sql_strings[1])
|
|
table.insert(syntax_php.patterns, 6, sql_strings[2])
|
|
end
|
|
|
|
-- allows html, css and js coloring on php files
|
|
syntax.add {
|
|
name = "PHP",
|
|
files = { "%.php$", "%.phtml" },
|
|
block_comment = { "<!--", "-->" },
|
|
patterns = {
|
|
{
|
|
regex = {
|
|
"<\\?php\\s+",
|
|
"(?:\\?>|(?=`{3}))" -- end if inside markdown code tags
|
|
},
|
|
syntax = ".phps",
|
|
type = "keyword2"
|
|
},
|
|
{
|
|
pattern = {
|
|
"<%?=?",
|
|
"%?>"
|
|
},
|
|
syntax = ".phps",
|
|
type = "keyword2"
|
|
},
|
|
{
|
|
pattern = {
|
|
"<%s*[sS][cC][rR][iI][pP][tT]%f[%s>].->",
|
|
"<%s*/%s*[sS][cC][rR][iI][pP][tT]%s*>"
|
|
},
|
|
syntax = ".js",
|
|
type = "function"
|
|
},
|
|
{
|
|
pattern = {
|
|
"<%s*[sS][tT][yY][lL][eE]%f[%s>].->",
|
|
"<%s*/%s*[sS][tT][yY][lL][eE]%s*>"
|
|
},
|
|
syntax = ".css",
|
|
type = "function"
|
|
},
|
|
{ pattern = { "<!%-%-", "%-%->" }, type = "comment" },
|
|
{ pattern = { '%f[^>][^<]', '%f[<]' }, type = "normal" },
|
|
{ pattern = { '"', '"', '\\' }, type = "string" },
|
|
{ pattern = { "'", "'", '\\' }, type = "string" },
|
|
{ pattern = "0x[%da-fA-F]+", type = "number" },
|
|
{ pattern = "-?%d+[%d%.]*f?", type = "number" },
|
|
{ pattern = "-?%.?%d+f?", type = "number" },
|
|
{ pattern = "%f[^<]![%a_][%w_]*", type = "keyword2" },
|
|
{ pattern = "%f[^<][%a_][%w_]*", type = "function" },
|
|
{ pattern = "%f[^<]/[%a_][%w_]*", type = "function" },
|
|
{ pattern = "[%a_][%w_]*", type = "keyword" },
|
|
{ pattern = "[/<>=]", type = "operator" },
|
|
-- match markdown code tags to be able to end php highlighting
|
|
-- when inside the subsyntax .phps
|
|
{ regex = "(?=`{3})", type = "string" }
|
|
},
|
|
symbols = {},
|
|
}
|
|
|
|
-- allow coloring of php code inside css and js code
|
|
local syntaxes = { "css", "js" }
|
|
for _, ext in pairs(syntaxes) do
|
|
local syntax_table = syntax.get("file."..ext, "")
|
|
|
|
table.insert(
|
|
syntax_table.patterns,
|
|
1,
|
|
{
|
|
pattern = {
|
|
"<%?=?",
|
|
"%?>"
|
|
},
|
|
syntax = ".phps",
|
|
type = "keyword2"
|
|
}
|
|
)
|
|
|
|
table.insert(
|
|
syntax_table.patterns,
|
|
1,
|
|
{
|
|
pattern = {
|
|
"<%?php%s+",
|
|
"%?>"
|
|
},
|
|
syntax = ".phps",
|
|
type = "keyword2"
|
|
}
|
|
)
|
|
end
|