1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
local PAIRS_AND_INVALID_CHARS = {}
string.gsub('\'"=$()[]<>{} \t\n\r', '.', function(char) PAIRS_AND_INVALID_CHARS[string.byte(char)] = true end)
local CLOSING_PAIR = {
[string.byte('<')] = string.byte('>'),
[string.byte('[')] = string.byte(']'),
[string.byte('(')] = string.byte(')'),
[string.byte('{')] = string.byte('}'),
[string.byte('"')] = string.byte('"'),
[string.byte("'")] = string.byte("'"),
}
local ALPHANUMERIC = {}
string.gsub(
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
'.',
function(char) ALPHANUMERIC[string.byte(char)] = true end
)
--- Gets the prefix of the given text, stopping at brackets and quotes
--- @param text string
--- @return string
local function get_prefix_before_brackets_and_quotes(text)
local closing_pairs_stack = {}
local word = ''
local add = function(char)
word = word .. string.char(char)
-- if we've seen the opening pair, and we've just received the closing pair,
-- remove it from the closing pairs stack
if closing_pairs_stack[#closing_pairs_stack] == char then
table.remove(closing_pairs_stack, #closing_pairs_stack)
-- if the character is an opening pair, add it to the closing pairs stack
elseif CLOSING_PAIR[char] ~= nil then
table.insert(closing_pairs_stack, CLOSING_PAIR[char])
end
end
local has_alphanumeric = false
for i = 1, #text do
local char = string.byte(text, i)
if PAIRS_AND_INVALID_CHARS[char] == nil then
add(char)
has_alphanumeric = has_alphanumeric or ALPHANUMERIC[char]
elseif not has_alphanumeric or #closing_pairs_stack ~= 0 then
add(char)
-- if we had an alphanumeric, and the closing pairs stack *just* emptied,
-- because the current character is a closing pair, we exit
if has_alphanumeric and #closing_pairs_stack == 0 then break end
else
break
end
end
return word
end
return get_prefix_before_brackets_and_quotes
|