Skip to content

Commit

Permalink
Add utils.splitstr function (#1276)
Browse files Browse the repository at this point in the history
Fixes #629, #816 and #1267

Co-authored-by: Mathias Fussenegger <[email protected]>
  • Loading branch information
Diaoul and mfussenegger authored Aug 9, 2024
1 parent 9b81479 commit 7bf34e0
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 0 deletions.
16 changes: 16 additions & 0 deletions doc/dap.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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*

Expand Down
39 changes: 39 additions & 0 deletions lua/dap/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
37 changes: 37 additions & 0 deletions spec/utils_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)

0 comments on commit 7bf34e0

Please sign in to comment.