Skip to content

Commit

Permalink
wip: lua pattern support
Browse files Browse the repository at this point in the history
  • Loading branch information
luckasRanarison committed Aug 1, 2024
1 parent 7f1dda9 commit de5bd2a
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 26 deletions.
32 changes: 32 additions & 0 deletions lua/tailwind-tools/classes.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
local M = {}

local config = require("tailwind-tools.config")
local patterns = require("tailwind-tools.patterns")
local filetypes = require("tailwind-tools.filetypes")
local tresitter = require("tailwind-tools.treesitter")

---@param bufnr number
M.get_ranges = function(bufnr)
local ft = vim.bo[bufnr].ft
local custom_patterns = config.options.custom_patterns
local pattern_ft = vim.tbl_keys(custom_patterns)
local query_ft = vim.tbl_keys(config.options.custom_queries)

vim.list_extend(filetypes, query_ft)
vim.list_extend(filetypes, pattern_ft)

if not vim.tbl_contains(filetypes, ft) then return end

local class_ranges
local pattern = patterns.builtin_patterns[ft] or custom_patterns[ft]

if pattern then
class_ranges = patterns.find_class_ranges(bufnr, pattern[1], pattern[2])
else
class_ranges = tresitter.find_class_ranges(bufnr, ft)
end

return class_ranges
end

return M
12 changes: 6 additions & 6 deletions lua/tailwind-tools/conceal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ local M = {}
local lsp = require("tailwind-tools.lsp")
local state = require("tailwind-tools.state")
local config = require("tailwind-tools.config")
local treesitter = require("tailwind-tools.treesitter")
local classes = require("tailwind-tools.classes")

---@param bufnr number
local function set_conceal(bufnr)
local class_nodes = treesitter.get_class_nodes(bufnr)
local class_ranges = classes.get_ranges(bufnr)

if not class_nodes then return end
if not class_ranges then return end

vim.wo.conceallevel = 2
vim.api.nvim_buf_clear_namespace(bufnr, vim.g.tailwind_tools.conceal_ns, 0, -1)
Expand All @@ -18,10 +18,10 @@ local function set_conceal(bufnr)

local opts = config.options.conceal

for _, node in pairs(class_nodes) do
local start_row, start_col, end_row, end_col = treesitter.get_class_range(node, bufnr)
for _, range in pairs(class_ranges) do
local start_row, start_col, end_row, end_col = unpack(range)

if not opts.min_length or node:byte_length() >= opts.min_length then
if not opts.min_length or end_row ~= start_row or end_col - start_col >= opts.min_length then
vim.api.nvim_buf_set_extmark(bufnr, vim.g.tailwind_tools.conceal_ns, start_row, start_col, {
end_line = end_row,
end_col = end_col,
Expand Down
3 changes: 2 additions & 1 deletion lua/tailwind-tools/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ M.options = {
fg = "#38BDF8",
},
},
custom_filetypes = {},
custom_patterns = {},
custom_queries = {},
}

return M
1 change: 1 addition & 0 deletions lua/tailwind-tools/filetypes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ return {
"vue",
"svelte",
"astro",
"rust",
"heex",
"elixir",
"htmldjango",
Expand Down
11 changes: 5 additions & 6 deletions lua/tailwind-tools/lsp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ local log = require("tailwind-tools.log")
local utils = require("tailwind-tools.utils")
local state = require("tailwind-tools.state")
local config = require("tailwind-tools.config")
local treesitter = require("tailwind-tools.treesitter")
local classes = require("tailwind-tools.classes")

local color_events = {
"BufEnter",
Expand Down Expand Up @@ -176,15 +176,14 @@ M.sort_classes = function()

local bufnr = vim.api.nvim_get_current_buf()
local params = vim.lsp.util.make_text_document_params(bufnr)
local class_nodes = treesitter.get_class_nodes(bufnr, true)
local class_ranges = classes.get_ranges(bufnr)

if not class_nodes then return end
if not class_ranges then return end

local class_text = {}
local class_ranges = {}

for _, node in pairs(class_nodes) do
local start_row, start_col, end_row, end_col = treesitter.get_class_range(node, bufnr)
for _, range in pairs(class_ranges) do
local start_row, start_col, end_row, end_col = unpack(range)
local text = vim.api.nvim_buf_get_text(bufnr, start_row, start_col, end_row, end_col, {})

class_text[#class_text + 1] = table.concat(text, "\n")
Expand Down
2 changes: 1 addition & 1 deletion lua/tailwind-tools/motions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ local treesitter = require("tailwind-tools.treesitter")

---@param comp fun(a: number, b: number): boolean
local move_to_class = function(comp)
local nodes = treesitter.get_class_nodes(0, true)
local nodes = treesitter.find_class_nodes(0, true)

if not nodes then return end
if #nodes == 0 then return log.info("No classes") end
Expand Down
64 changes: 64 additions & 0 deletions lua/tailwind-tools/patterns.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
local M = {}

---@param b_start number
---@param b_end number
---@param bufnr number
local function byte_range_to_pos(b_start, b_end, bufnr)
local line_count = vim.api.nvim_buf_line_count(bufnr)
local line_offsets = {}

for i = 1, line_count do
line_offsets[i] = vim.api.nvim_buf_get_offset(bufnr, i - 1)
end

local start_row, start_col, end_row, end_col

for line, offset in pairs(line_offsets) do
local next_offset = line_offsets[line + 1]

if not next_offset or b_start >= offset and b_start < next_offset then
start_row = line - 1
start_col = b_start - offset
end

if not next_offset or b_end >= offset and b_end < next_offset then
end_row = line - 1
end_col = b_end - offset
break
end
end

return start_row, start_col, end_row, end_col
end

---@param bufnr number
---@param pattern string
---@param delimiter string
M.find_class_ranges = function(bufnr, pattern, delimiter)
local results = {}
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, true)
local s = table.concat(lines, "\n")
local offset = 1

while true do
local substr = s:sub(offset)
local b_start, b_end, class = substr:find(pattern)

if b_start == nil then break end

local class_start = substr:find(delimiter) + offset
local class_end = class_start + #class
local pos = table.pack(byte_range_to_pos(class_start - 1, class_end - 1, bufnr))

results[#results + 1] = pos
offset = offset + b_end
end

return results
end

M.builtin_patterns = {
rust = { "class=[\"']([^\"']+)[\"']", "[\"']" },
}

return M
33 changes: 21 additions & 12 deletions lua/tailwind-tools/treesitter.lua
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
local M = {}

local log = require("tailwind-tools.log")
local config = require("tailwind-tools.config")
local filetypes = require("tailwind-tools.filetypes")

---@param bufnr number
---@param all boolean?
M.get_class_nodes = function(bufnr, all)
local ft = vim.bo[bufnr].ft
local supported_filetypes = vim.tbl_extend("keep", filetypes, config.options.custom_filetypes)

if not vim.tbl_contains(supported_filetypes, ft) then return end

---@param ft string
local function find_class_nodes(bufnr, ft)
local results = {}
local parser = vim.treesitter.get_parser(bufnr)

if not parser then return log.warn("No parser available for " .. ft) end
if all and vim.version().minor >= 10 then parser:parse(true) end
if not parser then return log.error("No parser available for " .. ft) end
if vim.version().minor >= 10 then parser:parse(true) end

parser:for_each_tree(function(tree, lang_tree)
local root = tree:root()
Expand All @@ -36,7 +29,7 @@ end

---@param node TSNode
---@param bufnr number
M.get_class_range = function(node, bufnr)
local function get_class_range(node, bufnr)
local start_row, start_col, end_row, end_col = node:range()
local children = node:named_children()

Expand All @@ -49,4 +42,20 @@ M.get_class_range = function(node, bufnr)
return start_row, start_col, end_row, end_col
end

---@param bufnr number
---@param ft string
M.find_class_ranges = function(bufnr, ft)
local nodes = find_class_nodes(bufnr, ft)

if not nodes then return end

local results = {}

for _, node in pairs(nodes) do
results[#results + 1] = table.pack(get_class_range(node, bufnr))
end

return results
end

return M

0 comments on commit de5bd2a

Please sign in to comment.