Skip to content

Commit

Permalink
feat(actions): allow custom placeholders (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
Goose97 committed Dec 19, 2024
1 parent 8b855f4 commit 9e86494
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 26 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,16 @@ You will need to call `require("timber").setup()` to intialize the plugin. You c
swift = [[print("%repeat<%log_target: %log_target><, >")]],
},
},
template_placeholders = {
filename = function()
return vim.fn.expand("%:t")
end,
-- Custom placeholder. For example, this can be used in log templates as %truncated_line
-- truncated_line = function(ctx)
-- local line = ctx.log_target:start()
-- return nvim_buf_get_lines(0, line - 1, line, false)[1]:sub(1, 16)
-- end,
},
-- The string to search for when deleting or commenting log statements
-- Can be used in log templates as %log_marker placeholder
log_marker = "🪵",
Expand Down
28 changes: 28 additions & 0 deletions doc/timber.nvim.txt
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,11 @@ timber.setup({opts}) *timber.setup()*
swift = [[print("%repeat<%log_target: %log_target><, >")]],
},
},
template_placeholders = {
filename = function()
return vim.fn.expand("%:t")
end,
},
log_marker = "🪵",
highlight = {
on_insert = true,
Expand Down Expand Up @@ -620,6 +625,29 @@ placeholders are:
-- Template: [[print("LOG %filename", %log_target)]]
local foo = 1
print("LOG foo.lua", foo)
<
- custom placeholders: users can define custom placeholders in the
`template_placeholders` config. The placeholder is generated by a function
that takes a `Timber.Actions.Context` as input. >lua

---@class Timber.Actions.Context
---@field log_target TSNode?
---@field log_position Timber.Actions.LogPosition

timber.setup({
log_templates = {
default = {
lua = [[print("%hello " .. %log_target)]],
},
},
template_placeholders = {
hello = function(ctx)
local line = ctx.log_target:start()
return string.format("Hello World %s line %s", ctx.log_position, line)
end,
},
})
<

`batch_log_templates` is similar, but for batch log statements. It supports
all placeholders supported by `log_templates`, plus:
Expand Down
69 changes: 43 additions & 26 deletions lua/timber/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ local utils = require("timber.utils")
---@field current_command_arguments Timber.Actions.CurrentCommandArgument
---@field current_selection_range {[1]: number, [2]: number, [3]: number, [4]: number}?

---@class Timber.Actions.Context
---@field log_target TSNode?
---@field log_position Timber.Actions.LogPosition

---@type Timber.Actions.State
local state = {
current_command_arguments = {},
Expand Down Expand Up @@ -78,16 +82,13 @@ end
--- %insert_cursor: after inserting the log statement, go to insert mode and place the cursor here.
--- If there's multiple log statements, choose the first one
--- %watcher_marker_start and %watcher_marker_end: the start and end markers for timber.watchers
---@alias handler (fun(): string) | string
---@alias handler (fun(Timber.Actions.Context): string) | string
---@param log_template string
---@param context Timber.Actions.Context
---@param handlers {log_target: handler, line_number: handler, filename: handler}
---@return string resolved_template, Timber.Watcher.LogPlaceholderId? placeholder_id
local function resolve_template_placeholders(log_template, handlers)
handlers = vim.tbl_extend("force", {
filename = function()
return vim.fn.expand("%:t")
end,
}, handlers)
local function resolve_template_placeholders(log_template, context, handlers)
handlers = vim.tbl_extend("force", config.config.template_placeholders, handlers)

---@type fun(string): string
local invoke_handler = function(handler_name)
Expand All @@ -96,14 +97,18 @@ local function resolve_template_placeholders(log_template, handlers)
error(string.format("No handler for %s", handler_name))
end

---@type Timber.Actions.Context
if type(handler) == "function" then
return handler()
return handler(context)
else
return handler
end
end

local to_resolve = { "log_target", "line_number", "filename" }
local to_resolve = { "log_target", "line_number" }
for k, _ in pairs(config.config.template_placeholders) do
table.insert(to_resolve, k)
end

for _, placeholder in ipairs(to_resolve) do
if string.find(log_template, "%%" .. placeholder) then
Expand Down Expand Up @@ -424,15 +429,19 @@ local function build_capture_log_statements(log_template, lang, position, select
local log_target = entry.log_target
local logable_ranges = entry.logable_ranges

local content, placeholder_id = resolve_template_placeholders(log_template, {
log_target = function()
local bufnr = vim.api.nvim_get_current_buf()
return vim.treesitter.get_node_text(log_target, bufnr)
end,
line_number = function()
return tostring(log_target:start() + 1)
end,
})
local content, placeholder_id = resolve_template_placeholders(
log_template,
{ log_target = log_target, log_position = position },
{
log_target = function(ctx)
local bufnr = vim.api.nvim_get_current_buf()
return vim.treesitter.get_node_text(ctx.log_target, bufnr)
end,
line_number = function(ctx)
return tostring(ctx.log_target:start() + 1)
end,
}
)

local insert_row = get_insert_row(log_target, logable_ranges, position)

Expand All @@ -458,9 +467,13 @@ end
local function build_non_capture_log_statement(log_template, position)
local current_line = vim.fn.getpos(".")[2]
local insert_row = position == "above" and current_line or current_line + 1
local content, placeholder_id = resolve_template_placeholders(log_template, {
line_number = tostring(insert_row),
})
local content, placeholder_id = resolve_template_placeholders(
log_template,
{ log_target = nil, log_position = position },
{
line_number = tostring(insert_row),
}
)

return {
content = content,
Expand Down Expand Up @@ -489,12 +502,16 @@ local function build_batch_log_statement(log_template, batch, insert_line)
local repeat_items = utils.array_map(batch, function(log_target)
return (
resolve_template_placeholders(repeat_item_template, {
log_target = function()
log_target = log_target,
-- Batch log always logs below
log_position = "below",
}, {
log_target = function(ctx)
local bufnr = vim.api.nvim_get_current_buf()
return vim.treesitter.get_node_text(log_target, bufnr)
return vim.treesitter.get_node_text(ctx.log_target, bufnr)
end,
line_number = function()
return tostring(log_target:start() + 1)
line_number = function(ctx)
return tostring(ctx.log_target:start() + 1)
end,
})
)
Expand All @@ -506,7 +523,7 @@ local function build_batch_log_statement(log_template, batch, insert_line)
end

-- Then resolve the rest
local content, placeholder_id = resolve_template_placeholders(result, {
local content, placeholder_id = resolve_template_placeholders(result, { log_target = nil, log_position = "below" }, {
log_target = function()
utils.notify("Cannot use %log_target placeholder outside %repeat placeholder", "error")
return "%log_target"
Expand Down
11 changes: 11 additions & 0 deletions lua/timber/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ local utils = require("timber.utils")
---@field log_templates { [string]: Timber.LogTemplates }
---@field log_marker string? The marker for the %log_marker placeholder. Defaults to `🪵`
---@field batch_log_templates { [string]: Timber.LogTemplates }
---@field template_placeholders table<string, fun(Timber.Actions.Context): string>
---@field highlight Timber.Highlight.Config
---@field keymaps { [Timber.Action | Timber.Operator]: string | boolean }
---@field default_keymaps_enabled boolean Whether to enable default keymaps. Defaults to `true`
Expand Down Expand Up @@ -89,6 +90,16 @@ local default_config = {
swift = [[print("%repeat<%log_target: %log_target><, >")]],
},
},
template_placeholders = {
filename = function()
return vim.fn.expand("%:t")
end,
-- Custom placeholder. For example, this can be used in log templates as %truncated_line
-- truncated_line = function(ctx)
-- local line = ctx.log_target:start()
-- return nvim_buf_get_lines(0, line - 1, line, false)[1]:sub(1, 16)
-- end,
},
-- The string to search for when deleting or commenting log statements
-- Can be used in log templates as %log_marker placeholder
log_marker = "🪵",
Expand Down
32 changes: 32 additions & 0 deletions tests/timber/actions/timber_actions_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,38 @@ describe("timber.actions.insert_log", function()
helper.wait(20)
end)
end)

it("supports custom placeholder in log template", function()
timber.setup({
log_templates = {
testing = {
javascript = [[console.log("%hello", %log_target)]],
},
},
template_placeholders = {
hello = function(ctx)
local line = ctx.log_target:start()
return string.format("Hello World %s line %s", ctx.log_position, line)
end,
},
})

helper.assert_scenario({
input = [[
// Comment
const fo|o = "bar"
]],
filetype = "javascript",
action = function()
actions.insert_log({ template = "testing", position = "below" })
end,
expected = [[
// Comment
const foo = "bar"
console.log("Hello World below line 1", foo)
]],
})
end)
end)

describe("supports log template that doesn't contain %log_target", function()
Expand Down

0 comments on commit 9e86494

Please sign in to comment.