8000 Merge pull request #1 from rxtsel/feat/refactor · rxtsel/template-string.nvim@fc00138 · GitHub
[go: up one dir, main page]

Skip to content
This repository was archived by the owner on May 23, 2025. It is now read-only.

Commit fc00138

Browse files
author
Cristhian Melo
authored
Merge pull request #1 from rxtsel/feat/refactor
feat/refactor all code
2 parents fbb916c + 06a3e97 commit fc00138

File tree

7 files changed

+150
-115
lines changed

7 files changed

+150
-115
lines changed

README.md

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,8 @@ Install using your favorite package manager for Neovim. For example, using [lazy
2525
event = "BufReadPost",
2626
dependencies = {
2727
"nvim-lua/plenary.nvim",
28-
},
29-
config = function()
30-
require("template-string").setup()
31-
end,
28+
"nvim-treesitter/nvim-treesitter",
29+
}
3230
}
3331
```
3432

@@ -53,19 +51,6 @@ const props = {
5351
<Test greeting={`Hello, ${props.name}!`} />;
5452
```
5553

56-
## Configuration
57-
58-
The `setup` function accepts an optional configuration object with the following options:
59-
60-
- **jsx_brackets** `boolean | nil`: Enable/disable wrapping template literals with `{``}` inside JSX/TSX components. Defaults to `true` if not provided.
61-
62-
```lua
63-
-- Default configuration
64-
require('template-string').setup({
65-
jsx_brackets = true, -- Wrap template literals with {``} inside JSX/TSX components
66-
})
67-
```
68-
6954
## License
7055

7156
This plugin is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.

lua/template-string.lua

Lines changed: 8 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,18 @@
1-
---@class TemplateStringConfig
2-
---@field jsx_brackets boolean | nil
3-
41
local M = {}
52

6-
local allowed_filetypes = {
7-
javascript = true,
8-
typescript = true,
9-
javascriptreact = true,
10-
typescriptreact = true,
11-
}
12-
13-
local function is_allowed_filetype()
14-
local filetype = vim.bo.filetype
15-
return allowed_filetypes[filetype] or false
16-
end
17-
18-
-- Function to wrap with {``} if inside a JSX/TSX component
19-
local function wrap_with_brackets_if_necessary(content)
20-
if content:find("%${") then
21-
return "={`" .. content .. "`}"
22-
else
23-
return '="' .. content .. '"'
24-
end
25-
end
26-
27-
-- Function to replace quotes in the current line
28-
local function replace_quotes_in_line()
29-
if not is_allowed_filetype() then
30-
return
31-
end
32-
33-
local row = vim.api.nvim_win_get_cursor(0)[1]
34-
local line = vim.api.nvim_buf_get_lines(0, row - 1, row, false)[1]
35-
36-
if not line then
37-
return
38-
end
39-
40-
local new_line = line
41-
42-
-- Replace quotes with backticks when ${ is found
43-
new_line = new_line:gsub("(['\"])(.-)%${(.-)}(.-)%1", function(quote, before, inside, after)
44-
return "`" .. before .. "${" .. inside .. "}" .. after .. "`"
45-
end)
46-
47-
if M.jsx_brackets then
48-
-- Wrap with {``} if inside a JSX/TSX component
49-
new_line = new_line:gsub("=%s*`([^`]*)`", wrap_with_brackets_if_necessary)
50-
51-
-- Revert backticks to original quotes if ${ is not found
52-
new_line = new_line:gsub("={[`{]+([^`]*)[`}]+}", function(content)
53-
if not content:find("%${") then
54-
-- Determine the original type of quotes, double or single
55-
local original_quote = line:match("=[\"']") and '"' or line:match("=['\"]") and "'" or '"'
56-
return "=" .. original_quote .. content .. original_quote
57-
end
58-
return "={" .. "`" .. content .. "`" .. "}"
59-
end)
60-
end
61-
62-
-- Also handle reverting solitary backticks on normal lines
63-
new_line = new_line:gsub("`([^`]*)`", function(content)
64-
if not content:find("%${") then
65-
-- Determine the original type of quotes, double or single
66-
local original_quote = line:match("[\"']") or '"'
67-
return original_quote .. content .. original_quote
68-
end
69-
return "`" .. content .. "`"
70-
end)
71-
72-
if new_line ~= line then
73-
vim.api.nvim_buf_set_lines(0, row - 1, row, false, { new_line })
74-
end
75-
end
76-
77-
-- Function to execute update with debounce
78-
local function debounce(fn, ms)
79-
local timer = vim.loop.new_timer()
80-
return function(...)
81-
timer:stop()
82-
local argv = { ... }
83-
timer:start(
84-
ms,
85-
0,
86-
vim.schedule_wrap(function()
87-
fn(unpack(argv))
88-
end)
89-
)
90-
end
91-
end
3+
local debounce = require("template-string.debounce")
4+
local quotes = require("template-string.replace_quotes")
925

93-
--- Configures the plugin behavior.
94-
---@param opts TemplateStringConfig | nil Optional plugin configuration.
95-
function M.setup(opts)
96-
opts = opts or {}
97-
-- Enable brackets for JSX/TSX
98-
local jsx_brackets = opts.jsx_brackets == nil or opts.jsx_brackets
99-
M.jsx_brackets = jsx_brackets
6+
--- Configures the behavior of the plugin.
7+
function M.setup()
8+
-- Create a debounced version of the replace_quotes_in_line function
9+
local debounced_replace = debounce.debounce(quotes.replace_quotes_in_line, 100)
10010

101-
-- Enable debounce
102-
local debounced_replace = debounce(replace_quotes_in_line, 100)
11+
-- Set up an autocmd to trigger the debounced function on TextChanged and TextChangedI events
10312
vim.api.nvim_create_autocmd({ "TextChanged", "TextChangedI" }, {
10413
callback = debounced_replace,
10514
})
10615
end
10716

17+
--- @export
10818
return M
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
local vim = vim
2+
3+
local M = {}
4+
5+
-- List of allowed file types for syntax checking
6+
local allowed_filetypes = {
7+
javascript = true,
8+
typescript = true,
9+
javascriptreact = true,
10+
typescriptreact = true,
11+
}
12+
13+
--- Checks if the current buffer's file type is allowed for syntax checking.
14+
-- @return boolean indicating if the file type is allowed.
15+
function M.is_allowed_filetype()
16+
local filetype = vim.bo.filetype
17+
return allowed_filetypes[filetype] or false
18+
end
19+
20+
return M

lua/template-string/debounce.lua

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
local vim = vim
2+
3+
local M = {}
4+
5+
--- Creates a debounced version of a function.
6+
-- @param fn The function to debounce.
7+
-- @param ms The debounce time in milliseconds.
8+
-- @return The debounced function.
9+
function M.debounce(fn, ms)
10+
local timer = vim.loop.new_timer() -- Create a new timer from Vim's event loop
11+
12+
return function(...)
13+
timer:stop() -- Stop the timer to reset debounce time
14+
local argv = { ... } -- Capture arguments passed to the debounced function
15+
16+
timer:start(
17+
ms,
18+
0,
19+
vim.schedule_wrap(function()
20+
fn(unpack(argv)) -- Call the original function after debounce time
21+
end)
22+
)
23+
end
24+
end
25+
26+
return M

lua/template-string/react_utils.lua

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
local ts = require("nvim-treesitter.ts_utils")
2+
3+
local M = {}
4+
5+
--- Checks if the cursor is inside a React prop or JSX/TSX opening element.
6+
-- @return boolean indicating if the cursor is inside a React prop or JSX/TSX opening element.
7+
function M.is_inside_react_opening_element()
8+
local node = ts.get_node_at_cursor()
9+
10+
if not node then
11+
return false
12+
end
13+
14+
-- Check if the node is a JSX/TSX string or template string
15+
if node:type() == "string" or node:type() == "template_string" then
16+
local prev_node = ts.get_previous_node(node)
17+
18+
if not prev_node then
19+
return false
20+
end
21+
22+
-- Check if the previous node is a property identifier
23+
if prev_node:type() == "property_identifier" then
24+
return true
25+
end
26+
end
27+
28+
return false
29+
end
30+
31+
return M
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
local filetypes = require("template-string.allowed_filetypes")
2+
local u = require("template-string.react_utils")
3+
local M = {}
4+
5+
--- Replaces quotes in a line based on the presence of template literals and context.
6+
-- @param line The line of text to process.
7+
-- @param use_brackets A boolean indicating if brackets should be used.
8+
-- @return The processed line with appropriate quote replacements.
9+
local function replace_quotes(line, use_brackets)
10+
-- Replace quotes with backticks and brackets if ${} is found and use_brackets is true
11+
line = line:gsub("(['\"])(.-)(%${.-})(.-)%1", function(quote, before, inside, after)
12+
if use_brackets then
13+
return "{`" .. before .. inside .. after .. "`}"
14+
else
15+
return "`" .. before .. inside .. after .. "`"
16+
end
17+
end)
18+
19+
-- Revert backticks and brackets to original quotes if ${} is not found in the content
20+
line = line:gsub("{`([^`]*)`}", function(content)
21+
if not content:find("%${.-}") then
22+
local original_quote = line:match("[\"']") or '"'
23+
return original_quote .. content .. original_quote
24+
end
25+
return "{`" .. content .. "`}"
26+
end)
27+
28+
-- Revert solitary backticks to original quotes if ${} is not found in the content
29+
line = line:gsub("`([^`]*)`", function(content)
30+
if not content:find("%${.-}") then
31+
local original_quote = line:match("[\"']") or '"'
32+
return original_quote .. content .. original_quote
33+
end
34+
return "`" .. content .. "`"
35+
end)
36+
37+
return line
38+
end
39+
40+
--- Replaces quotes in the current line of the buffer if the filetype is allowed.
41+
function M.replace_quotes_in_line()
42+
if not filetypes.is_allowed_filetype() then
43+
return
44+
end
45+
46+
local row = vim.api.nvim_win_get_cursor(0)[1]
47+
local line = vim.api.nvim_buf_get_lines(0, row - 1, row, false)[1]
48+
local new_line = replace_quotes(line, u.is_inside_react_opening_element())
49+
50+
-- Update the buffer if there were changes
51+
if new_line ~= line then
52+
vim.api.nvim_buf_set_lines(0, row - 1, row, false, { new_line })
53+
end
54+
end
55+
56+
return M

plugin/template-string.vim

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
if exists('g:loaded_template_string')
2+
finish
3+
endif
4+
5+
lua require'template-string'.setup()
6+
7+
let g:loaded_template_string = 1

0 commit comments

Comments
 (0)
0