update jsregexp to 0.0.6.

Still continues to work with 0.0.5 too, but also support 0.0.6, which,
despite having the same API, is a bit harder to set up (see `util/jsregexp.lua`)
This commit is contained in:
L3MON4D3 2023-11-29 23:01:28 +01:00 committed by L3MON4D3
parent 1def353778
commit e449e6e325
14 changed files with 161 additions and 80 deletions

View file

@ -15,4 +15,4 @@ jobs:
LUAROCKS_API_KEY: ${{ secrets.LUAROCKS_API_KEY }}
with:
dependencies: |
jsregexp == 0.0.5
jsregexp >= 0.0.5, <= 0.0.6

2
.gitignore vendored
View file

@ -2,3 +2,5 @@
/deps/nvim_multiversion
/doc/tags
/lua/luasnip-jsregexp.so
/deps/luasnip-jsregexp.so
/lua/luasnip-jsregexp.lua

5
.gitmodules vendored
View file

@ -1,3 +1,6 @@
[submodule "deps/jsregexp"]
path = deps/jsregexp
url = ../../kmarius/jsregexp/
url = ../../kmarius/jsregexp
[submodule "deps/jsregexp005"]
path = deps/jsregexp005
url = ../../kmarius/jsregexp

View file

@ -40,32 +40,42 @@ ifeq ($(LUASNIP_DETECTED_OS),Darwin)
# remove -bundle, should be equivalent to the -shared hardcoded by jsregexp.
LUA_LDLIBS=-undefined dynamic_lookup -all_load
endif
JSREGEXP_PATH=deps/jsregexp
JSREGEXP005_PATH=deps/jsregexp005
jsregexp:
git submodule init
git submodule update
make "INCLUDE_DIR=-I$(shell pwd)/deps/lua51_include/" LDLIBS="${LUA_LDLIBS}" -C ${JSREGEXP_PATH}
make "INCLUDE_DIR=-I$(shell pwd)/deps/lua51_include/" LDLIBS="${LUA_LDLIBS}" -C ${JSREGEXP005_PATH}
install_jsregexp: jsregexp
# access via require("luasnip-jsregexp")
# The hyphen must be used here, otherwise the luaopen_*-call will fail.
# See the package.loaders-section [here](https://www.lua.org/manual/5.1/manual.html#pdf-require)
cp "$(shell pwd)/${JSREGEXP_PATH}/jsregexp.so" "$(shell pwd)/lua/luasnip-jsregexp.so"
# remove old binary.
rm "$(shell pwd)/lua/luasnip-jsregexp.so" || true
# there is some additional trickery to make this work with jsregexp-0.0.6 in
# util/jsregexp.lua.
cp "$(shell pwd)/${JSREGEXP_PATH}/jsregexp.lua" "$(shell pwd)/lua/luasnip-jsregexp.lua"
# just move out of jsregexp-directory, so it is not accidentially deleted.
cp "$(shell pwd)/${JSREGEXP_PATH}/jsregexp.so" "$(shell pwd)/deps/luasnip-jsregexp.so"
uninstall_jsregexp:
# also remove binaries of older version.
rm "$(shell pwd)/lua/luasnip-jsregexp.so"
rm "$(shell pwd)/lua/deps/luasnip-jsregexp.so"
rm "$(shell pwd)/lua/luasnip-jsregexp.lua"
TEST_07?=true
TEST_09?=true
TEST_MASTER?=true
# Expects to be run from repo-location (eg. via `make -C path/to/luasnip`).
test: nvim jsregexp
test: nvim install_jsregexp
# unset PATH and CPATH to prevent system-env leaking into the neovim-build,
# add our helper-functions to lpath.
# exit as soon as an error occurs.
unset LUA_PATH LUA_CPATH; \
export LUASNIP_SOURCE=$(shell pwd); \
export JSREGEXP_PATH=$(shell pwd)/${JSREGEXP_PATH}; \
export JSREGEXP_ABS_PATH=$(shell pwd)/${JSREGEXP_PATH}; \
export JSREGEXP005_ABS_PATH=$(shell pwd)/${JSREGEXP005_PATH}; \
export TEST_FILE=$(realpath ${TEST_FILE}); \
export BUSTED_ARGS=--lpath=$(shell pwd)/tests/?.lua; \
set -e; \

2
deps/jsregexp vendored

@ -1 +1 @@
Subproject commit c3e473240eebb65a8870abebafeff83b6c9e7f16
Subproject commit b5a81e21d0875667ba2458ac8ae903afd5568698

1
deps/jsregexp005 vendored Submodule

@ -0,0 +1 @@
Subproject commit dd65498ae2c29b882d6c02c0a30577b08d660b94

View file

@ -1,4 +1,4 @@
local jsregexp = require("luasnip.util.util").jsregexp
local jsregexp_compile_safe = require("luasnip.util.jsregexp")
-- these functions get the line up to the cursor, the trigger, and then
-- determine whether the trigger matches the current line.
@ -42,9 +42,9 @@ local function match_pattern(line_to_cursor, trigger)
end
local ecma_engine
if jsregexp then
if jsregexp_compile_safe then
ecma_engine = function(trig)
local trig_compiled, err_maybe = jsregexp.compile(trig .. "$", "")
local trig_compiled, err_maybe = jsregexp_compile_safe(trig .. "$", "")
if not trig_compiled then
error(("Error while compiling regex: %s"):format(err_maybe))
end

View file

@ -0,0 +1,40 @@
local Path = require("luasnip.util.path")
-- neovim-loader does not handle module-names with dots correctly, so for
-- jsregexp-0.0.6, the call to require("jsregexp.core") in jsregexp.lua errors
-- even if the library is in rtp.
-- Resolve path to jsregexp.so manually, and loadlib it in preload (and remove
-- preload after requires are done and have failed/worked).
-- omit "@".
local this_file = debug.getinfo(1).source:sub(2)
local repo_dir = vim.fn.fnamemodify(this_file, ":h:h:h:h")
local jsregexp_core_path = Path.join(repo_dir, "deps", "luasnip-jsregexp.so")
-- rather gracefully, if the path does not exist, or loadlib can't do its job
-- for some other reason, the preload will be set to nil, ie not be set.
--
-- This means we don't hinder a regularly installed 0.0.6-jsregexp-library,
-- since its `require("jsregexp.core")` will be unaffected.
package.preload["jsregexp.core"] = package.loadlib(jsregexp_core_path, "luaopen_jsregexp_core")
-- jsregexp: first try loading the version installed by luasnip, then global ones.
local jsregexp_ok, jsregexp = pcall(require, "luasnip-jsregexp")
if not jsregexp_ok then
jsregexp_ok, jsregexp = pcall(require, "jsregexp")
end
-- don't want to affect other requires.
package.preload["jsregexp.core"] = nil
if not jsregexp_ok then
return false
end
-- detect version, and return compile-function.
-- 0.0.6-compile_safe and 0.0.5-compile behave the same, ie. nil, err on error.
if jsregexp.compile_safe then
return jsregexp.compile_safe
else
return jsregexp.compile
end

View file

@ -3,7 +3,7 @@ local types = Ast.node_type
local util = require("luasnip.util.util")
local Str = require("luasnip.util.str")
local log = require("luasnip.util.log").new("parser")
local jsregexp = require("luasnip.util.util").jsregexp
local jsregexp_compile_safe = require("luasnip.util.jsregexp")
local directed_graph = require("luasnip.util.directed_graph")
@ -303,40 +303,46 @@ local function apply_transform_format(nodes, captures)
end
function M.apply_transform(transform)
if jsregexp then
local reg_compiled =
jsregexp.compile(transform.pattern, transform.option)
-- can be passed to functionNode!
return function(lines)
-- luasnip expects+passes lines as list, but regex needs one string.
lines = table.concat(lines, "\n")
local matches = reg_compiled(lines)
if jsregexp_compile_safe then
local reg_compiled, err =
jsregexp_compile_safe(transform.pattern, transform.option)
local transformed = ""
-- index one past the end of previous match.
-- This is used to append unmatched characters to `transformed`, so
-- it's initialized such that the first append is from 1.
local prev_match_end = 0
for _, match in ipairs(matches) do
-- begin_ind and end_ind are inclusive.
transformed = transformed
.. lines:sub(prev_match_end + 1, match.begin_ind - 1)
.. apply_transform_format(transform.format, match.groups)
if reg_compiled then
-- can be passed to functionNode!
return function(lines)
-- luasnip expects+passes lines as list, but regex needs one string.
lines = table.concat(lines, "\n")
local matches = reg_compiled(lines)
-- end-inclusive
prev_match_end = match.end_ind
local transformed = ""
-- index one past the end of previous match.
-- This is used to append unmatched characters to `transformed`, so
-- it's initialized such that the first append is from 1.
local prev_match_end = 0
for _, match in ipairs(matches) do
-- begin_ind and end_ind are inclusive.
transformed = transformed
.. lines:sub(prev_match_end + 1, match.begin_ind - 1)
.. apply_transform_format(transform.format, match.groups)
-- end-inclusive
prev_match_end = match.end_ind
end
transformed = transformed .. lines:sub(prev_match_end + 1, #lines)
return vim.split(transformed, "\n")
end
transformed = transformed .. lines:sub(prev_match_end + 1, #lines)
return vim.split(transformed, "\n")
else
log.error("Failed parsing regex `%s` with options `%s`: %s", transform.pattern, transform.option, err)
-- fall through to returning identity.
end
else
-- without jsregexp, we cannot properly transform whatever is supposed to
-- be transformed here.
-- Just return a function that returns the to-be-transformed string
-- unmodified.
return util.id
end
-- without jsregexp, or without a valid regex, we cannot properly transform
-- whatever is supposed to be transformed here.
-- Just return a function that returns the to-be-transformed string
-- unmodified.
return util.id
end
---Variables need the text which is in front of them to determine whether they

View file

@ -1,11 +1,5 @@
local session = require("luasnip.session")
-- jsregexp: first try loading the version installed by luasnip, then global ones.
local jsregexp_ok, jsregexp = pcall(require, "luasnip-jsregexp")
if not jsregexp_ok then
jsregexp_ok, jsregexp = pcall(require, "jsregexp")
end
local function get_cursor_0ind()
local c = vim.api.nvim_win_get_cursor(0)
c[1] = c[1] - 1
@ -528,6 +522,5 @@ return {
indx_of = indx_of,
lazy_table = lazy_table,
ternary = ternary,
jsregexp = jsregexp_ok and jsregexp,
pos_cmp = pos_cmp,
}

View file

@ -5,11 +5,53 @@ local assert = require("luassert")
local M = {}
function M.setup_jsregexp()
-- append default-path.
exec_lua(
('package.cpath = "%s"'):format(os.getenv("JSREGEXP_PATH") .. "/?.so;;")
)
function M.jsregexp_it(it, name, fn)
for _, version in ipairs({"005", "006", "luasnip"}) do
it(name .. " (jsregexp-" .. version .. ")", function()
exec_lua([[
local version, jsregexp_005_path, jsregexp_path = ...
if version ~= "luasnip" then
if version == "005" then
package.preload["jsregexp"] = package.loadlib(jsregexp_005_path .. "/jsregexp.so", "luaopen_jsregexp")
if package.preload["jsregexp"]().compile_safe then
error("wrong jsregexp-version loaded")
end
else
package.preload["jsregexp.core"] = package.loadlib(jsregexp_path .. "/jsregexp.so", "luaopen_jsregexp_core")
package.path = jsregexp_path .. "/?.lua;;"
-- populate package now, before jsregexp-core-preload is overwritten in util/jsregexp.lua.
-- also load it to check the version.
local jsregexp = require("jsregexp")
-- is actually 0.0.6.
if not jsregexp.compile_safe then
error("wrong jsregexp-version loaded")
end
end
-- don't accidentially load luasnip-jsregexp with unknown version.
local old_require = require
require = function(modulename)
if modulename == "luasnip-jsregexp" then
error("Disabled by `prevent_jsregexp`")
end
return old_require(modulename)
end
else
-- don't accidentially load regular jsregexp.
local old_require = require
require = function(modulename)
if modulename == "jsregexp" then
error("Disabled by `prevent_jsregexp`")
end
return old_require(modulename)
end
end
]], version, os.getenv("JSREGEXP005_ABS_PATH"), os.getenv("JSREGEXP_ABS_PATH"))
fn()
end)
end
end
function M.prevent_jsregexp()

View file

@ -205,8 +205,7 @@ describe("Parser", function()
})
end)
it("can parse transformed variables.", function()
ls_helpers.setup_jsregexp()
ls_helpers.jsregexp_it(it, "can parse transformed variables", function()
ls_helpers.session_setup_luasnip()
local snip = '"a${TM_LINE_INDEX/(.*)/asdf $1 asdf/g}a"'
@ -244,8 +243,7 @@ describe("Parser", function()
})
end)
it("can parse transformed tabstop.", function()
ls_helpers.setup_jsregexp()
ls_helpers.jsregexp_it(it, "can parse transformed tabstop.", function()
ls_helpers.session_setup_luasnip()
local snip = '"$1 a ${1/(.*)/asdf $1 asdf/} a"'
@ -297,8 +295,7 @@ describe("Parser", function()
error("unexpected key " .. modifier .. " in expected_map")
end
it("applies " .. modifier .. " correctly", function()
ls_helpers.setup_jsregexp()
ls_helpers.jsregexp_it(it, "applies " .. modifier .. " correctly", function()
ls_helpers.session_setup_luasnip()
local snip = ('"${1:%s} ${1/(.*)/${1:/%s}/}"'):format(
text,
@ -406,12 +403,7 @@ describe("Parser", function()
{2:-- SELECT --} |]],
})
exec_lua("ls.jump(1)")
screen:expect({
grid = [[
^q{3:wer} asdf |
{0:~ }|
{2:-- SELECT --} |]],
})
screen:expect({ unchanged = true })
end)
it("turns the correct nodes into insert/functionNode", function()
@ -450,8 +442,7 @@ describe("Parser", function()
})
end)
it("can modify groups in transform.", function()
ls_helpers.setup_jsregexp()
ls_helpers.jsregexp_it(it, "can modify groups in transform.", function()
ls_helpers.session_setup_luasnip()
local snip = '"$1 a ${1/(.*)/asdf ${1:/upcase} asdf/} a"'
@ -474,8 +465,7 @@ describe("Parser", function()
})
end)
it("handle multiple captures in transform.", function()
ls_helpers.setup_jsregexp()
ls_helpers.jsregexp_it(it, "handle multiple captures in transform.", function()
ls_helpers.session_setup_luasnip()
local snip = '"${1:bbb} a ${1/(.)b(.)/${1:/upcase} $2/g} a"'
@ -703,8 +693,7 @@ describe("Parser", function()
})
end)
it("Applies transform to empty variable.", function()
ls_helpers.setup_jsregexp()
ls_helpers.jsregexp_it(it, "Applies transform to empty variable.", function()
ls_helpers.session_setup_luasnip()
local snip = "${TM_SELECTED_TEXT/(.*)/ asd /}"
@ -718,8 +707,7 @@ describe("Parser", function()
})
end)
it("correctly transforms multiline-values.", function()
ls_helpers.setup_jsregexp()
ls_helpers.jsregexp_it(it, "correctly transforms multiline-values.", function()
ls_helpers.session_setup_luasnip()
local snip = "${TM_SELECTED_TEXT/([^]*)/a ${1} a/}"
@ -737,10 +725,9 @@ describe("Parser", function()
})
end)
it(
ls_helpers.jsregexp_it(it,
"correctly transforms if the match does not include the first character.",
function()
ls_helpers.setup_jsregexp()
ls_helpers.session_setup_luasnip()
local snip = "${1:asdf.asdf} ${1/[\\.]/-/g}"
@ -872,8 +859,7 @@ describe("Parser", function()
})
end)
it("Correctly parses unescaped characters.", function()
ls_helpers.setup_jsregexp()
ls_helpers.jsregexp_it(it, "Correctly parses unescaped characters.", function()
ls_helpers.session_setup_luasnip()
local snip = "${} asdf"

View file

@ -20,7 +20,6 @@ describe("session", function()
before_each(function()
helpers.clear()
ls_helpers.setup_jsregexp()
ls_helpers.session_setup_luasnip({ hl_choiceNode = true })
-- add a rather complicated snippet.

View file

@ -8,7 +8,6 @@ describe("snippets_basic", function()
before_each(function()
helpers.clear()
ls_helpers.setup_jsregexp()
ls_helpers.session_setup_luasnip()
screen = Screen.new(50, 3)