From 2e6bf39f80669f670e6f199f4ff88030bbe4b1c5 Mon Sep 17 00:00:00 2001 From: Zananok Date: Thu, 21 Mar 2024 16:41:46 +0100 Subject: [PATCH] Add 'sd' replace method --- README.md | 8 ++++-- doc/spectre.txt | 2 +- lua/spectre/config.lua | 4 +++ lua/spectre/replace/sd.lua | 52 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 lua/spectre/replace/sd.lua diff --git a/README.md b/README.md index 742f178..62bf212 100644 --- a/README.md +++ b/README.md @@ -254,7 +254,11 @@ require('spectre').setup({ desc = "ignore case" }, } - } + }, + ['sd'] = { + cmd = "sd", + options = { }, + }, }, default = { find = { @@ -325,7 +329,7 @@ option. This is the list of directories or files to search in, regardless of the ## Replace Method -There are two replace methods `sed` and `oxi`. +There are three replace methods `sed`, `oxi` and `sd`. | Sed | oxi | | -------------------------- | ----------------------------------- | diff --git a/doc/spectre.txt b/doc/spectre.txt index f61957d..2184ed3 100644 --- a/doc/spectre.txt +++ b/doc/spectre.txt @@ -319,7 +319,7 @@ CUSTOM FUNCTIONS ~ REPLACE METHOD *spectre-replace-method* -There are two replace methods `sed` and `oxi`. +There are three replace methods `sed`, `oxi` and `sd`. │ Sed │ oxi │ │group number by '\0' │group number by '${0}' │ diff --git a/lua/spectre/config.lua b/lua/spectre/config.lua index 65931da..e27848b 100644 --- a/lua/spectre/config.lua +++ b/lua/spectre/config.lua @@ -196,6 +196,10 @@ local config = { }, }, }, + ['sd'] = { + cmd = "sd", + options = { }, + }, }, default = { find = { diff --git a/lua/spectre/replace/sd.lua b/lua/spectre/replace/sd.lua new file mode 100644 index 0000000..caa8a03 --- /dev/null +++ b/lua/spectre/replace/sd.lua @@ -0,0 +1,52 @@ +local Path = require('plenary.path') +local log = require('spectre._log') + +local sd = {} + +sd.init = function(_, config) + return config +end + +sd.replace = function(self, value) + local cwd = value.cwd or vim.loop.cwd() + if not value.filename:match('^%/') then + value.filename = Path:new(cwd):joinpath(value.filename):absolute() + end + + -- Read the original file + local lines = {} + local file = io.open(value.filename, "r") + for line in file:lines() do + table.insert(lines, line) + end + file:close() + + if value.lnum <= #lines then + -- Use `io.popen` to get the transformed line using `sd` + local command = string.format("echo '%s' | sd '%s' '%s'", lines[value.lnum], value.search_text, value.replace_text) + local handle = io.popen(command, 'r') + if handle then + local transformedLine = handle:read("*a") + handle:close() + -- Replace the line in memory + lines[value.lnum] = transformedLine:gsub("\n$", "") -- Remove trailing newline added by `echo` + else + self:on_error(false, value) + return + end + else + log.debug("Line number out of bounds.") + return + end + + -- Write the modified lines back to the file + file = io.open(value.filename, "w") + for _, line in ipairs(lines) do + file:write(line, "\n") + end + file:close() + + self:on_done(true, value) +end + +return sd