Add utils.splitstr function (#1276)

Fixes #629, #816 and #1267

Co-authored-by: Mathias Fussenegger <f.mathias@zignar.net>
This commit is contained in:
Antoine Bertin 2024-08-09 14:24:24 +02:00 committed by GitHub
parent 9b81479813
commit 7bf34e0917
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 92 additions and 0 deletions

View file

@ -1399,6 +1399,22 @@ pick_file({opts}) *dap.utils.pick_file*
})
<
splitstr({str}) *dap.utils.splitstr*
Split an argument string on whitespace into a list, except if the
whitespace is contained within single or double quotes.
Parameters:
{str} The string to split
>lua
require("dap.utils").splitstr("Hello world")
-- result: {"Hello", "world"}
require("dap.utils").splitstr("Keeps 'a quoted string' intact")
-- result: {"Keeps", "a quoted string", "intact"}
<
==============================================================================
DAP Session *dap-session*

View file

@ -302,4 +302,43 @@ function M.pick_file(opts)
end
--- Split an argument string on whitespace characters into a list,
--- except if the whitespace is contained within single or double quotes.
---
--- Examples:
---
--- ```lua
--- require("dap.utils").splitstr("hello world")
--- {"hello", "world"}
--- ```
---
--- ```lua
--- require("dap.utils").splitstr('a "quoted string" is preserved')
--- {"a", "quoted string", "is, "preserved"}
--- ```
---
--- Requires nvim 0.10+
---
--- @param str string
--- @return string[]
function M.splitstr(str)
local lpeg = vim.lpeg
local P, S, C = lpeg.P, lpeg.S, lpeg.C
---@param quotestr string
---@return vim.lpeg.Pattern
local function qtext(quotestr)
local quote = P(quotestr)
local escaped_quote = P('\\') * quote
return quote * C(((1 - P(quote)) + escaped_quote) ^ 0) * quote
end
local space = S(" \t\n\r") ^ 1
local unquoted = C((1 - space) ^ 0)
local element = qtext('"') + qtext("'") + unquoted
local p = lpeg.Ct(element * (space * element) ^ 0)
return lpeg.match(p, str)
end
return M

View file

@ -89,3 +89,40 @@ describe('utils.fmt_error', function ()
assert.are.same('Bad things happen', result)
end)
end)
describe('utils.splitstr', function ()
if vim.fn.has("nvim-0.10") == 0 then
return
end
it('works with plain string', function ()
assert.are.same({"hello", "world"}, utils.splitstr("hello world"))
end)
it('works extra whitespace', function ()
assert.are.same({"hello", "world"}, utils.splitstr('hello world'))
end)
it('empty quoted', function ()
assert.are.same({"hello", "", "world"}, utils.splitstr('hello "" world'))
end)
it('with double quoted string', function ()
assert.are.same({'with', 'double quoted', 'string'}, utils.splitstr('with "double quoted" string'))
end)
it("with single quoted string", function ()
assert.are.same({'with', 'single quoted', 'string'}, utils.splitstr("with 'single quoted' string"))
end)
it("with unbalanced quote", function ()
assert.are.same({"with", "\"single", "quoted", "string"}, utils.splitstr("with \"single quoted string"))
end)
it("with unbalanced single quoted string", function ()
assert.are.same({"with", "'single", "quoted", "string"}, utils.splitstr("with 'single quoted string"))
end)
it('escaped quote', function ()
assert.are.same({'foo', '"bar'}, utils.splitstr('foo \"bar'))
end)
end)