Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add match_before_cursor field to constant augend #98

Merged
merged 2 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/dial.jax
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,10 @@ CONSTANT *dial-augends-constant*
word = false,
cyclic = true,
},
augend.constant.new{
elements = {"let", "const"},
match_before_cursor = true,
},
},
}
<
Expand All @@ -999,6 +1003,10 @@ CONSTANT *dial-augends-constant*
pattern_regexp (string, default: `\C\V\<\(%s\)\>`)
文字列検索を行う際の正規表現。 elements に指定した文字列を
`%s` に指定します。
match_before_cursor (boolean, default: false)
true のとき、カーソルが対象の単語より後ろにある場合でもマッチ
します。ただし、カーソル上またはカーソルの後に他の有効な被加数が
存在すればそちらが優先されます。

注意: `&&` と `||` のように、記号からなる文字列を相互変換するときは `cyclic`
を false にしてください。
Expand Down
8 changes: 8 additions & 0 deletions doc/dial.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,10 @@ Predefined sequence of strings. You can use this rule with
word = false,
cyclic = true,
},
augend.constant.new{
elements = {"let", "const"},
match_before_cursor = true,
},
},
}
<
Expand All @@ -1033,6 +1037,10 @@ The argument table of `augend.constant.new` can take the following keys:
pattern_regexp (string, default: `\C\V\<\(%s\)\>`)
A regular expression used in search. `%s` represents the string
specified in `elements.`
match_before_cursor (boolean, default: false)
If true, it matches even when the cursor is positioned after
the target word. In that case, however, any other valid augend
on or after the cursor will take precedence.

NOTE: Set `cyclic` to false when cross-converting strings consisting of
symbols, such as `&&` and `||`.
Expand Down
16 changes: 14 additions & 2 deletions lua/dial/augend/common.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ local M = {}

---augend の find field を簡単に実装する。
---@param ptn string
---@param allow_match_before_cursor? boolean
---@return findf
function M.find_pattern(ptn)
function M.find_pattern(ptn, allow_match_before_cursor)
---@param line string
---@param cursor? integer
---@return textrange?
local function f(line, cursor)
local match_before_cursor = nil
local idx_start = 1
while idx_start <= #line do
local s, e = line:find(ptn, idx_start)
Expand All @@ -21,6 +23,7 @@ function M.find_pattern(ptn)
-- cursor が終了文字より後ろにあったら終了
return { from = s, to = e }
else
match_before_cursor = { from = s, to = e }
-- 終了文字の後ろから探し始める
idx_start = e + 1
end
Expand All @@ -29,19 +32,24 @@ function M.find_pattern(ptn)
break
end
end
if allow_match_before_cursor then
return match_before_cursor
end
return nil
end
return f
end

-- augend の find field を簡単に実装する。
---@param ptn string
---@param allow_match_before_cursor? boolean
---@return findf
function M.find_pattern_regex(ptn)
function M.find_pattern_regex(ptn, allow_match_before_cursor)
---@param line string
---@param cursor? integer
---@return textrange?
local function f(line, cursor)
local match_before_cursor = nil
local idx_start = 1
while idx_start <= #line do
local s, e = vim.regex(ptn):match_str(line:sub(idx_start))
Expand All @@ -55,6 +63,7 @@ function M.find_pattern_regex(ptn)
-- cursor が終了文字より後ろにあったら終了
return { from = s, to = e }
else
match_before_cursor = { from = s, to = e }
-- 終了文字の後ろから探し始める
idx_start = e + 1
end
Expand All @@ -63,6 +72,9 @@ function M.find_pattern_regex(ptn)
break
end
end
if allow_match_before_cursor then
return match_before_cursor
end
return nil
end
return f
Expand Down
10 changes: 7 additions & 3 deletions lua/dial/augend/constant.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
local util = require "dial.util"
local common = require "dial.augend.common"

---@alias AugendConstantConfig { elements: string[], cyclic: boolean, pattern_regexp: string, preserve_case: boolean }
---@alias AugendConstantConfig { elements: string[], cyclic: boolean, pattern_regexp: string, preserve_case: boolean, match_before_cursor: boolean }

---@class AugendConstant
---@implement Augend
Expand Down Expand Up @@ -33,7 +33,7 @@ local function preserve_case(word)
return nil
end

---@param config { elements: string[], word?: boolean, cyclic?: boolean, pattern_regexp?: string, preserve_case?: boolean }
---@param config { elements: string[], word?: boolean, cyclic?: boolean, pattern_regexp?: string, preserve_case?: boolean, match_before_cursor?: boolean }
---@return Augend
function M.new(config)
util.validate_list("config.elements", config.elements, "string")
Expand All @@ -43,10 +43,14 @@ function M.new(config)
cyclic = { config.cyclic, "boolean", true },
pattern_regexp = { config.pattern_regexp, "string", true },
preserve_case = { config.preserve_case, "boolean", true },
match_before_cursor = { config.match_before_cursor, "boolean", true },
}
if config.preserve_case == nil then
config.preserve_case = false
end
if config.match_before_cursor == nil then
config.match_before_cursor = false
end
if config.pattern_regexp == nil then
local case_sensitive_flag = util.if_expr(config.preserve_case, [[\c]], [[\C]])
local word = util.unwrap_or(config.word, true)
Expand All @@ -70,7 +74,7 @@ function AugendConstant:find(line, cursor)
return vim.fn.escape(e, [[/\]])
end, self.config.elements)
local vim_regex_ptn = self.config.pattern_regexp:format(table.concat(escaped_elements, [[\|]]))
return common.find_pattern_regex(vim_regex_ptn)(line, cursor)
return common.find_pattern_regex(vim_regex_ptn, self.config.match_before_cursor)(line, cursor)
end

---@param text string
Expand Down
21 changes: 21 additions & 0 deletions tests/dial/augend/constant_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,25 @@ local constant = require("dial.augend").constant

describe("Test of constant between two words", function()
local augend = constant.new { elements = { "true", "false" } }

describe("find function", function()
it("can find a completely matching word", function()
assert.are.same(augend:find("enable = true", 1), { from = 10, to = 13 })
assert.are.same(augend:find("enable = false", 1), { from = 10, to = 14 })
end)
it("does not find a word including element words", function()
assert.are.same(augend:find("mistakenly construed", 1), nil)
end)
it("does not find a word before the cursor when match_before_cursor = false", function()
assert.are.same(augend:find("true negative", 5), nil)
end)
end)

augend = constant.new { elements = { "true", "false" }, match_before_cursor = true }

describe("find function", function()
it("does find a word before the cursor when match_before_cursor = true", function()
assert.are.same(augend:find("true positive", 5), { from = 1, to = 4 })
end)
end)
end)
Loading