diff --git a/lua/cmp_buffer/cases.lua b/lua/cmp_buffer/cases.lua new file mode 100644 index 0000000..588206d --- /dev/null +++ b/lua/cmp_buffer/cases.lua @@ -0,0 +1,120 @@ +-- slice a word to individual slices. "my_cool_word" -> { "my", "cool", "word" } +function get_word_slices(name) + local slices = {} + local current_word = "" + local last_character_uppercase = true + + for i = 1, #name do + local character = name:sub(i, i) + + if character == "_" or character == "-" then + if current_word ~= "" then + table.insert(slices, current_word) + current_word = "" + end + + last_character_uppercase = false + elseif string.upper(character) == character then + + if last_character_uppercase or current_word == "" then + current_word = current_word .. string.lower(character) + else + table.insert(slices, current_word) + current_word = string.lower(character) + end + + last_character_uppercase = true + else + current_word = current_word .. character + last_character_uppercase = false + end + end + + if current_word ~= "" then + table.insert(slices, current_word) + end + + return slices +end + +-- e.g. my_cool_word +function snake_case(slices) + local word = "" + + for index, slice in ipairs(slices) do + if index > 1 then + word = word .. "_" + end + + word = word .. slice + end + + return word +end + +-- e.g. my-cool-word +function kebab_case(slices) + local word = "" + + for index, slice in ipairs(slices) do + if index > 1 then + word = word .. "-" + end + + word = word .. slice + end + + return word +end + +-- e.g. myCoolWord +function camel_case(slices) + local word = "" + + for index, slice in ipairs(slices) do + if index == 1 then + word = word .. slice + else + word = word .. string.upper(string.sub(slice, 1, 1)) + word = word .. string.sub(slice, 2, -1) + end + end + + return word +end + +-- e.g. MyCoolWord +function pascal_case(slices) + local word = "" + + for _, slice in ipairs(slices) do + word = word .. string.upper(string.sub(slice, 1, 1)) + word = word .. string.sub(slice, 2, -1) + end + + return word +end + +-- e.g. MY_COOL_WORD +function macro_case(slices) + local word = "" + + for index, slice in ipairs(slices) do + if index > 1 then + word = word .. "_" + end + + word = word .. string.upper(slice) + end + + return word +end + +-- lookup table for all cases that are suppored out of the box +return { + ["snake"] = snake_case, + ["camel"] = camel_case, + ["pascal"] = pascal_case, + ["kebab"] = kebab_case, + ["macro"] = macro_case, +} diff --git a/lua/cmp_buffer/source.lua b/lua/cmp_buffer/source.lua index 9be673c..92bb1a8 100644 --- a/lua/cmp_buffer/source.lua +++ b/lua/cmp_buffer/source.lua @@ -1,4 +1,5 @@ local buffer = require('cmp_buffer.buffer') +local case_lookup = require('cmp_buffer.cases') ---@class cmp_buffer.Options ---@field public keyword_length number @@ -7,6 +8,7 @@ local buffer = require('cmp_buffer.buffer') ---@field public indexing_batch_size number ---@field public indexing_interval number ---@field public max_indexed_line_length number +---@field public cases table ---@type cmp_buffer.Options local defaults = { @@ -18,6 +20,7 @@ local defaults = { indexing_batch_size = 1000, indexing_interval = 100, max_indexed_line_length = 1024 * 40, + cases = {}, } local source = {} @@ -37,6 +40,7 @@ source._validate_options = function(_, params) get_bufnrs = { opts.get_bufnrs, 'function' }, indexing_batch_size = { opts.indexing_batch_size, 'number' }, indexing_interval = { opts.indexing_interval, 'number' }, + cases = { opts.cases, 'table' }, }) return opts end @@ -71,6 +75,33 @@ source.complete = function(self, params, callback) label = word, dup = 0, }) + + if opts.cases ~= {} then + local slices = get_word_slices(word) + + for _, case in ipairs(opts.cases) do + local new_word + + if type(case) == "function" then + new_word = case(slices) + else + local converter = case_lookup[case] + if converter ~= nil then + new_word = converter(slices) + end + end + + if type(new_word) == "string" then + if not words[new_word] then + words[new_word] = true + table.insert(items, { + label = new_word, + dup = 0, + }) + end + end + end + end end end end