mirror of
https://github.com/sbrl/Minetest-WorldEditAdditions.git
synced 2024-09-12 08:08:30 +02:00
107 lines
3.1 KiB
Lua
107 lines
3.1 KiB
Lua
-- worldeditadditions_core = { modpath="/home/sbrl/.minetest/worlds/Mod-Sandbox/worldmods/WorldEditAdditions/worldeditadditions_core/" }
|
|
|
|
local table_map, polyfill
|
|
|
|
if minetest then
|
|
local wea_c = worldeditadditions_core
|
|
table_map = dofile(wea_c.modpath.."/utils/table/table_map.lua")
|
|
polyfill = wea_c
|
|
else
|
|
table_map = require("worldeditadditions_core.utils.table.table_map")
|
|
polyfill = require("worldeditadditions_core.utils.strings.polyfill")
|
|
end
|
|
|
|
local function is_whitespace(char)
|
|
return char:match("%s")
|
|
end
|
|
|
|
local function split_shell(text, autotrim)
|
|
local text_length = #text
|
|
local scan_pos = 1
|
|
local result = { }
|
|
local acc = {}
|
|
local mode = "NORMAL" -- NORMAL, INSIDE_QUOTES_SINGLE, INSIDE_QUOTES_DOUBLE
|
|
|
|
-- print("\n\n\n\n\nDEBUG:split_shell START text", text, "autotrim", autotrim)
|
|
|
|
for i=1,text_length do
|
|
local prevchar = ""
|
|
local curchar = text:sub(i,i)
|
|
local nextchar = ""
|
|
local nextnextchar = ""
|
|
if i > 1 then prevchar = text:sub(i-1, i-1) end
|
|
if i < text_length then nextchar = text:sub(i+1, i+1) end
|
|
if i+1 < text_length then nextnextchar = text:sub(i+2, i+2) end
|
|
|
|
-- print("mode", mode, "prevchar", prevchar, "curchar", curchar, "nextchar", nextchar)
|
|
|
|
if mode == "NORMAL" then
|
|
if is_whitespace(curchar) and #acc > 0 then
|
|
local nextval = polyfill.trim(table.concat(acc, ""))
|
|
if #nextval > 0 then
|
|
table.insert(result, table.concat(acc, ""))
|
|
end
|
|
acc = {}
|
|
elseif (curchar == "\"" or curchar == "'") and #acc == 0 and prevchar ~= "\\" then
|
|
if curchar == "\"" then
|
|
mode = "INSIDE_QUOTES_DOUBLE"
|
|
else
|
|
mode = "INSIDE_QUOTES_SINGLE"
|
|
end
|
|
else
|
|
table.insert(acc, curchar)
|
|
end
|
|
elseif mode == "INSIDE_QUOTES_DOUBLE" then
|
|
if curchar == "\"" and prevchar ~= "\\" and (is_whitespace(nextchar) or #nextchar == 0) then
|
|
-- It's the end of a quote!
|
|
mode = "NORMAL"
|
|
|
|
elseif (curchar == "\\" and (
|
|
nextchar ~= "\""
|
|
or (nextchar == "\"" and not is_whitespace(nextnextchar))
|
|
)) or curchar ~= "\\" then
|
|
-- It's a regular character
|
|
table.insert(acc, curchar)
|
|
end
|
|
elseif mode == "INSIDE_QUOTES_SINGLE" then
|
|
if curchar == "'" and prevchar ~= "\\" and (is_whitespace(nextchar) or nextchar == "") then
|
|
-- It's the end of a quote!
|
|
mode = "NORMAL"
|
|
elseif (curchar == "\\" and (
|
|
nextchar ~= "'"
|
|
or (nextchar == "'" and not is_whitespace(nextnextchar))
|
|
)) or curchar ~= "\\" then
|
|
-- It's a regular character
|
|
table.insert(acc, curchar)
|
|
end
|
|
end
|
|
end
|
|
|
|
if #acc > 0 then
|
|
table.insert(result, table.concat(acc, ""))
|
|
end
|
|
|
|
-- Unwind all escapes by 1 level
|
|
return table_map(result, function(str)
|
|
return str:gsub("\\([\"'\\])", "%1")
|
|
end)
|
|
end
|
|
|
|
return split_shell
|
|
|
|
-- local function test(text)
|
|
-- print("Source", text)
|
|
-- for i,value in ipairs(split_shell(text)) do
|
|
-- print("i", i, "→", value)
|
|
-- end
|
|
-- print("************")
|
|
-- end
|
|
--
|
|
-- test("yay yay yay")
|
|
-- test("dirt \"snow block\"")
|
|
-- test("yay \"yay yay\" yay")
|
|
-- test("yay \"yay\\\" yay\" yay")
|
|
-- test("yay \"yay 'inside quotes' yay\\\"\" yay")
|
|
-- test("yay 'inside quotes' another")
|
|
-- test("y\"ay \"yay 'in\\\"side quotes' yay\" y\\\"ay")
|