refactor: make telescope dependency optional

lazy load the telescope popup, so that if it's disabled
it won't be attempted
This commit is contained in:
2024-05-04 23:27:31 +03:00
committed by Chen Asraf
parent bb177a3360
commit 8de9125de1
6 changed files with 219 additions and 201 deletions

View File

@@ -8,7 +8,6 @@ TextTransform.replace_word() text-transform.txt /*TextTransform.replace_word()*
TextTransform.restore_positions() text-transform.txt /*TextTransform.restore_positions()*
TextTransform.save_positions() text-transform.txt /*TextTransform.save_positions()*
TextTransform.setup() text-transform.txt /*TextTransform.setup()*
TextTransform.telescope_popup() text-transform.txt /*TextTransform.telescope_popup()*
TextTransform.to_camel_case() text-transform.txt /*TextTransform.to_camel_case()*
TextTransform.to_const_case() text-transform.txt /*TextTransform.to_const_case()*
TextTransform.to_dot_case() text-transform.txt /*TextTransform.to_dot_case()*
@@ -20,5 +19,6 @@ TextTransform.to_words() text-transform.txt /*TextTransform.to_words()*
TextTransform.toggle() text-transform.txt /*TextTransform.toggle()*
TextTransform.transform_words() text-transform.txt /*TextTransform.transform_words()*
find_word_boundaries() text-transform.txt /*find_word_boundaries()*
telescope.telescope_popup() text-transform.txt /*telescope.telescope_popup()*
utils.dump() text-transform.txt /*utils.dump()*
utils.merge() text-transform.txt /*utils.merge()*

View File

@@ -82,18 +82,6 @@ Usage ~
`require("text-transform").setup()` (add `{}` with your |TextTransform.options| table)
==============================================================================
------------------------------------------------------------------------------
*TextTransform.telescope_popup()*
`TextTransform.telescope_popup`()
Pops up a telescope menu, containing the available case transformers.
When a transformer is selected, the cursor position/range/columns will be used to replace the
words around the cursor or inside the selection.
The cursor positions/ranges are saved before opening the menu and restored once a selection is
made.
==============================================================================
------------------------------------------------------------------------------
*find_word_boundaries()*
@@ -164,6 +152,18 @@ Restore the cursor position, mode, and visual selection ranges saved using `save
or a given modified state, if passed as the first argument
==============================================================================
------------------------------------------------------------------------------
*telescope.telescope_popup()*
`telescope.telescope_popup`()
Pops up a telescope menu, containing the available case transformers.
When a transformer is selected, the cursor position/range/columns will be used to replace the
words around the cursor or inside the selection.
The cursor positions/ranges are saved before opening the menu and restored once a selection is
made.
==============================================================================
------------------------------------------------------------------------------
*TextTransform.to_words()*

View File

@@ -1,195 +1,14 @@
local D = require("text-transform.util.debug")
local state = require("text-transform.state")
local replacers = require("text-transform.replacers")
local popup = {}
local pickers = require("telescope.pickers")
local finders = require("telescope.finders")
local telescope_conf = require("telescope.config").values
local actions = require("telescope.actions")
local action_state = require("telescope.actions.state")
local dropdown = require("telescope.themes").get_dropdown({})
local Sorter = require("telescope.sorters").Sorter
local generic_sorter = telescope_conf.generic_sorter()
local TextTransform = {}
local items = {
{ label = "camelCase", value = "camel_case" },
{ label = "snake_case", value = "snake_case" },
{ label = "PascalCase", value = "pascal_case" },
{ label = "kebab-case", value = "kebab_case" },
{ label = "dot.case", value = "dot_case" },
{ label = "Title Case", value = "title_case" },
{ label = "CONST_CASE", value = "const_case" },
}
local default_frequency = {
camel_case = 1,
snake_case = 1,
pascal_case = 1,
kebab_case = 1,
dot_case = 1,
title_case = 1,
const_case = 1,
}
local frequency_file = vim.fn.stdpath("config") .. "/text-transform-frequency.json"
local frequency
local function load_frequency()
if frequency then
return frequency
end
if vim.fn.filereadable(frequency_file) == 0 then
frequency = default_frequency
vim.fn.writefile({ vim.fn.json_encode(frequency) }, frequency_file)
else
frequency = vim.fn.json_decode(vim.fn.readfile(frequency_file))
end
D.log("telescope", "frequency loaded: %s", vim.inspect(frequency))
return frequency
end
local function inc_frequency(name)
frequency[name] = (frequency[name] or 0) + 1
D.log("telescope", "new frequency: %s %d", name, frequency[name])
vim.fn.writefile({ vim.fn.json_encode(frequency) }, frequency_file)
end
local function entry_maker(entry)
return {
value = entry.value,
display = entry.label,
ordinal = entry.label,
frequency = frequency[entry.value] or 1,
}
end
local frequency_sorter = Sorter:new({
---@diagnostic disable-next-line: unused-local
scoring_function = function(self, prompt, line)
local entry
for _, item in ipairs(items) do
if item.label == line then
entry = entry_maker(item)
break
end
end
D.log("telescope", "prompt %s line %s", prompt, line)
-- Basic filtering based on prompt matching, non-matching items score below 0 to exclude them
local basic_score = (generic_sorter:scoring_function(prompt, line) or 0)
D.log("telescope", "%s basic_score: %s", entry.value, basic_score)
if basic_score < 0 then
return basic_score
end
-- D.log("telescope", "entry: %s", vim.inspect(entry))
-- D.log("telescope", "prompt: %s", prompt)
-- Calculate score based on frequency, higher frequency should have lower score
local freq_score = (entry.frequency or 1) * 10
D.log("telescope", "freq_score: %s", freq_score)
local final_score = 999999999 - freq_score + basic_score
D.log("telescope", "%s final_score: %s", line, final_score)
-- Combine scores, with frequency having the primary influence if present
return final_score
end,
})
local sorter_map = {
frequency = frequency_sorter,
name = generic_sorter,
}
---@diagnostic disable-next-line: unused-local
-- for _i, k in pairs(default_ordered_keys) do
-- local v = map[k]
-- vim.cmd("amenu TransformsWord." .. k .. " :lua TextTransform.replace_word('" .. v .. "')<CR>")
-- vim.cmd(
-- "amenu TransformsSelection." .. k .. " :lua TextTransform.replace_columns('" .. v .. "')<CR>"
-- )
-- end
local function select(selection)
vim.schedule(function()
replacers.replace_selection(selection.value)
state.restore_positions()
end)
end
--- Pops up a telescope menu, containing the available case transformers.
--- When a transformer is selected, the cursor position/range/columns will be used to replace the
--- words around the cursor or inside the selection.
---
--- The cursor positions/ranges are saved before opening the menu and restored once a selection is
--- made.
function TextTransform.telescope_popup()
state.save_positions()
local filtered = {}
local config = _G.TextTransform.config
local sorter = sorter_map[config.sort_by] or generic_sorter
if config.sort_by == "frequency" then
load_frequency()
end
for _, item in ipairs(items) do
if not config.replacers[item.value] or not config.replacers[item.value].enabled then
goto continue
end
table.insert(filtered, item)
::continue::
end
local picker = pickers.new(dropdown, {
prompt_title = "Change Case",
finder = finders.new_table({
results = items,
entry_maker = entry_maker,
}),
sorter = sorter,
attach_mappings = function(prompt_bufnr)
actions.select_default:replace(function()
local selection = action_state.get_selected_entry()
inc_frequency(selection.value)
actions.close(prompt_bufnr)
select(selection)
end)
return true
end,
})
vim.schedule(function()
picker:find()
end)
end
function TextTransform.select_popup()
state.save_positions()
vim.ui.select(items, {
prompt = "Change Case",
format_item = function(item)
return item.label
end,
}, function(choice)
if not choice then
return
end
local item = entry_maker(choice)
select(item)
end)
end
function TextTransform.show_popup()
function popup.show_popup()
local config = _G.TextTransform.config
if config.popup_type == "telescope" then
TextTransform.telescope_popup()
local telescope = require("text-transform.telescope")
telescope.telescope_popup()
else
TextTransform.select_popup()
local select = require("text-transform.select")
select.select_popup()
end
end
return TextTransform
return popup

View File

@@ -0,0 +1,66 @@
local D = require("text-transform.util.debug")
local state = require("text-transform.state")
local replacers = require("text-transform.replacers")
local popup_common = {}
popup_common.items = {
{ label = "camelCase", value = "camel_case" },
{ label = "snake_case", value = "snake_case" },
{ label = "PascalCase", value = "pascal_case" },
{ label = "kebab-case", value = "kebab_case" },
{ label = "dot.case", value = "dot_case" },
{ label = "Title Case", value = "title_case" },
{ label = "CONST_CASE", value = "const_case" },
}
popup_common.default_frequency = {
camel_case = 1,
snake_case = 1,
pascal_case = 1,
kebab_case = 1,
dot_case = 1,
title_case = 1,
const_case = 1,
}
local frequency_file = vim.fn.stdpath("config") .. "/text-transform-frequency.json"
local frequency
function popup_common.load_frequency()
if frequency then
return frequency
end
if vim.fn.filereadable(frequency_file) == 0 then
frequency = popup_common.default_frequency
vim.fn.writefile({ vim.fn.json_encode(frequency) }, frequency_file)
else
frequency = vim.fn.json_decode(vim.fn.readfile(frequency_file))
end
D.log("telescope", "frequency loaded: %s", vim.inspect(frequency))
return frequency
end
function popup_common.inc_frequency(name)
frequency[name] = (frequency[name] or 0) + 1
D.log("telescope", "new frequency: %s %d", name, frequency[name])
vim.fn.writefile({ vim.fn.json_encode(frequency) }, frequency_file)
end
function popup_common.entry_maker(entry)
return {
value = entry.value,
display = entry.label,
ordinal = entry.label,
frequency = frequency[entry.value] or 1,
}
end
function popup_common.select(selection)
vim.schedule(function()
replacers.replace_selection(selection.value)
state.restore_positions()
end)
end
return popup_common

View File

@@ -0,0 +1,32 @@
local common = require("text-transform.popup_common")
local state = require("text-transform.state")
local select = {}
function select.select_popup()
state.save_positions()
vim.ui.select(common.items, {
prompt = "Change Case",
format_item = function(item)
return item.label
end,
}, function(choice)
if not choice then
return
end
local item = common.entry_maker(choice)
common.select(item)
end)
end
function select.show_popup()
local config = _G.TextTransform.config
if config.popup_type == "telescope" then
select.telescope_popup()
else
select.select_popup()
end
end
return select

View File

@@ -0,0 +1,101 @@
local common = require("text-transform.popup_common")
local D = require("text-transform.util.debug")
local state = require("text-transform.state")
local pickers = require("telescope.pickers")
local finders = require("telescope.finders")
local telescope_conf = require("telescope.config").values
local actions = require("telescope.actions")
local action_state = require("telescope.actions.state")
local dropdown = require("telescope.themes").get_dropdown({})
local Sorter = require("telescope.sorters").Sorter
local generic_sorter = telescope_conf.generic_sorter()
local telescope = {}
local frequency_sorter = Sorter:new({
---@diagnostic disable-next-line: unused-local
scoring_function = function(self, prompt, line)
local entry
for _, item in ipairs(common.items) do
if item.label == line then
entry = common.entry_maker(item)
break
end
end
D.log("telescope", "prompt %s line %s", prompt, line)
-- Basic filtering based on prompt matching, non-matching items score below 0 to exclude them
local basic_score = (generic_sorter:scoring_function(prompt, line) or 0)
D.log("telescope", "%s basic_score: %s", entry.value, basic_score)
if basic_score < 0 then
return basic_score
end
-- D.log("telescope", "entry: %s", vim.inspect(entry))
-- D.log("telescope", "prompt: %s", prompt)
-- Calculate score based on frequency, higher frequency should have lower score
local freq_score = (entry.frequency or 1) * 10
D.log("telescope", "freq_score: %s", freq_score)
local final_score = 999999999 - freq_score + basic_score
D.log("telescope", "%s final_score: %s", line, final_score)
-- Combine scores, with frequency having the primary influence if present
return final_score
end,
})
local sorter_map = {
frequency = frequency_sorter,
name = generic_sorter,
}
--- Pops up a telescope menu, containing the available case transformers.
--- When a transformer is selected, the cursor position/range/columns will be used to replace the
--- words around the cursor or inside the selection.
---
--- The cursor positions/ranges are saved before opening the menu and restored once a selection is
--- made.
function telescope.telescope_popup()
state.save_positions()
local filtered = {}
local config = _G.TextTransform.config
local sorter = sorter_map[config.sort_by] or generic_sorter
if config.sort_by == "frequency" then
common.load_frequency()
end
for _, item in ipairs(common.items) do
if not config.replacers[item.value] or not config.replacers[item.value].enabled then
goto continue
end
table.insert(filtered, item)
::continue::
end
local picker = pickers.new(dropdown, {
prompt_title = "Change Case",
finder = finders.new_table({
results = common.items,
entry_maker = common.entry_maker,
}),
sorter = sorter,
attach_mappings = function(prompt_bufnr)
actions.select_default:replace(function()
local selection = action_state.get_selected_entry()
common.inc_frequency(selection.value)
actions.close(prompt_bufnr)
common.select(selection)
end)
return true
end,
})
vim.schedule(function()
picker:find()
end)
end
return telescope