Files
deb-lite-xl/debian/extra/plugins/language_php.lua
T
vhaudiquet 3bae6fd448 Bundle curated community plugins (2.1.8-4)
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)
2026-09-16 22:45:02 +02:00

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