mirror of
https://github.com/Myzel394/jsonfly.nvim.git
synced 2025-06-18 12:15:25 +02:00
fix: Fix key insertion
This commit is contained in:
parent
eed1e27309
commit
98cdf4ccee
172
lua/jsonfly/insert.lua
Normal file
172
lua/jsonfly/insert.lua
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
local utils = require"jsonfly.utils"
|
||||||
|
|
||||||
|
|
||||||
|
local M = {};
|
||||||
|
|
||||||
|
-- https://stackoverflow.com/a/24823383/9878135
|
||||||
|
function table.slice(tbl, first, last, step)
|
||||||
|
local sliced = {}
|
||||||
|
|
||||||
|
for i = first or 1, last or #tbl, step or 1 do
|
||||||
|
sliced[#sliced+1] = tbl[i]
|
||||||
|
end
|
||||||
|
|
||||||
|
return sliced
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param entry Entry
|
||||||
|
---@param key string
|
||||||
|
---@param index number
|
||||||
|
local function check_key_equal(entry, key, index)
|
||||||
|
local splitted = utils:split_by_char(entry.key, ".")
|
||||||
|
|
||||||
|
return splitted[index] == key
|
||||||
|
end
|
||||||
|
|
||||||
|
---Find the entry in `entries` with the most matching keys at the beginning based on the `keys`.
|
||||||
|
---Returns the index of the entry
|
||||||
|
---@param entries Entry[]
|
||||||
|
---@param keys KeyDescription[]
|
||||||
|
---@return number|nil
|
||||||
|
local function find_best_fitting_entry(entries, keys)
|
||||||
|
local entry_index
|
||||||
|
local current_indexes = {1, #entries}
|
||||||
|
|
||||||
|
for kk=1, #keys do
|
||||||
|
local key = keys[kk].key
|
||||||
|
|
||||||
|
local start_index = current_indexes[1]
|
||||||
|
local end_index = current_indexes[2]
|
||||||
|
|
||||||
|
current_indexes = {nil, nil}
|
||||||
|
|
||||||
|
for ii=start_index, end_index do
|
||||||
|
if check_key_equal(entries[ii], key, kk) then
|
||||||
|
if current_indexes[1] == nil then
|
||||||
|
current_indexes[1] = ii
|
||||||
|
end
|
||||||
|
|
||||||
|
current_indexes[2] = ii
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if current_indexes[1] == nil then
|
||||||
|
-- No entries found
|
||||||
|
break
|
||||||
|
else
|
||||||
|
entry_index = current_indexes[1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return entry_index
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param keys KeyDescription
|
||||||
|
---@param index number - Index of the key
|
||||||
|
local function write_keys(keys, index)
|
||||||
|
local lines = {}
|
||||||
|
|
||||||
|
if index == #keys then
|
||||||
|
return {
|
||||||
|
{ "\"" .. keys[index].key .. "\": \"\""},
|
||||||
|
true
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local insertions = write_keys(keys, index + 1)
|
||||||
|
|
||||||
|
lines[#lines + 1] = "\"" .. keys[index].key .. "\": {"
|
||||||
|
|
||||||
|
for ii=1, #insertions do
|
||||||
|
lines[#lines + 1] = insertions[ii]
|
||||||
|
end
|
||||||
|
|
||||||
|
lines[#lines + 1] = "}"
|
||||||
|
|
||||||
|
return lines
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param buffer number
|
||||||
|
---@param insertion_line number
|
||||||
|
local function add_comma(buffer, insertion_line)
|
||||||
|
local BUFFER_SIZE = 5
|
||||||
|
|
||||||
|
-- Find next non-empty character in reverse
|
||||||
|
for ii=insertion_line, 0, -BUFFER_SIZE do
|
||||||
|
local previous_lines = vim.api.nvim_buf_get_lines(buffer, ii - BUFFER_SIZE, ii, false)
|
||||||
|
|
||||||
|
if #previous_lines == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for jj=#previous_lines, 0, -1 do
|
||||||
|
local line = previous_lines[jj]
|
||||||
|
|
||||||
|
for char_index=#line, 0, -1 do
|
||||||
|
local char = line:sub(char_index, char_index)
|
||||||
|
|
||||||
|
if char ~= " " and char ~= "\t" and char ~= "\n" and char ~= "\r" then
|
||||||
|
if char == "," then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Insert comma at position
|
||||||
|
vim.api.nvim_buf_set_text(buffer, ii - 1, char_index, ii - 1, char_index, {","})
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param entries Entry[]
|
||||||
|
---@param keys KeyDescription[]
|
||||||
|
---@param buffer number
|
||||||
|
function M:insert_new_key(entries, keys, buffer)
|
||||||
|
-- Close current buffer
|
||||||
|
vim.cmd [[quit!]]
|
||||||
|
|
||||||
|
local entry_index = find_best_fitting_entry(entries, keys) or 0
|
||||||
|
local entry = entries[entry_index]
|
||||||
|
local existing_keys_depth = #utils:split_by_char(entry.key, ".") + 1
|
||||||
|
local remaining_keys = table.slice(keys, existing_keys_depth, #keys)
|
||||||
|
|
||||||
|
local _writes = write_keys(remaining_keys, 1)
|
||||||
|
local writes = {}
|
||||||
|
|
||||||
|
for ii=1, #_writes do
|
||||||
|
if _writes[ii] == true then
|
||||||
|
-- Unwrap table
|
||||||
|
writes[#writes] = writes[#writes][1]
|
||||||
|
else
|
||||||
|
writes[#writes + 1] = _writes[ii]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_win_set_cursor(0, {entry.position.line_number, entry.position.value_start})
|
||||||
|
-- Hacky way to jump to end of object
|
||||||
|
vim.cmd [[execute "normal %"]]
|
||||||
|
local start_line = vim.api.nvim_win_get_cursor(0)[1] - 1
|
||||||
|
|
||||||
|
-- Add comma to previous line
|
||||||
|
add_comma(buffer, start_line)
|
||||||
|
--
|
||||||
|
-- Insert new lines
|
||||||
|
vim.api.nvim_buf_set_lines(buffer, start_line, start_line, false, writes)
|
||||||
|
--
|
||||||
|
-- -- -- Format lines
|
||||||
|
vim.api.nvim_win_set_cursor(0, {start_line, 1})
|
||||||
|
vim.cmd('execute "normal =' .. #writes .. 'j"')
|
||||||
|
--
|
||||||
|
-- -- Jump to the key
|
||||||
|
vim.api.nvim_win_set_cursor(0, {start_line + math.ceil(#writes / 2), 0})
|
||||||
|
vim.cmd [[execute "normal $a"]]
|
||||||
|
|
||||||
|
-- vim.schedule(function()
|
||||||
|
-- vim.cmd [[%]]
|
||||||
|
-- end)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return M;
|
@ -23,6 +23,7 @@
|
|||||||
local parsers = require"jsonfly.parsers"
|
local parsers = require"jsonfly.parsers"
|
||||||
local utils = require"jsonfly.utils"
|
local utils = require"jsonfly.utils"
|
||||||
local cache = require"jsonfly.cache"
|
local cache = require"jsonfly.cache"
|
||||||
|
local insert = require"jsonfly.insert"
|
||||||
|
|
||||||
local json = require"jsonfly.json"
|
local json = require"jsonfly.json"
|
||||||
local finders = require "telescope.finders"
|
local finders = require "telescope.finders"
|
||||||
@ -54,141 +55,6 @@ local opts = {
|
|||||||
use_cache = 500,
|
use_cache = 500,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- https://stackoverflow.com/a/24823383/9878135
|
|
||||||
function table.slice(tbl, first, last, step)
|
|
||||||
local sliced = {}
|
|
||||||
|
|
||||||
for i = first or 1, last or #tbl, step or 1 do
|
|
||||||
sliced[#sliced+1] = tbl[i]
|
|
||||||
end
|
|
||||||
|
|
||||||
return sliced
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param entry Entry
|
|
||||||
---@param key string
|
|
||||||
---@param index number
|
|
||||||
local function check_key_equal(entry, key, index)
|
|
||||||
local splitted = utils:split_by_char(entry.key, ".")
|
|
||||||
|
|
||||||
return splitted[index] == key
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param entries Entry[]
|
|
||||||
---@param keys KeyDescription[]
|
|
||||||
---@return [Entry, string[]]
|
|
||||||
local function find_remaining_keys(entries, keys)
|
|
||||||
local start_index = 1
|
|
||||||
|
|
||||||
local existing_keys_depth = nil
|
|
||||||
|
|
||||||
local potential_keys_indexes = {}
|
|
||||||
|
|
||||||
for kk=1, #keys do
|
|
||||||
local found_result = false
|
|
||||||
local key = keys[kk].key
|
|
||||||
|
|
||||||
for ii=start_index, #entries do
|
|
||||||
if check_key_equal(entries[ii], key, kk) then
|
|
||||||
found_result = true
|
|
||||||
start_index = ii
|
|
||||||
potential_keys_indexes[#potential_keys_indexes + 1] = ii
|
|
||||||
-- Not sure if this can be used for optimization
|
|
||||||
-- break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not found_result then
|
|
||||||
existing_keys_depth = kk
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if existing_keys_depth == nil then
|
|
||||||
existing_keys_depth = #keys
|
|
||||||
end
|
|
||||||
|
|
||||||
local existing_keys = table.slice(keys, 1, existing_keys_depth - 1)
|
|
||||||
local remaining_keys = table.slice(keys, existing_keys_depth, #keys)
|
|
||||||
local existing_key_str = ""
|
|
||||||
|
|
||||||
for ii=1, #existing_keys do
|
|
||||||
existing_key_str = existing_key_str .. existing_keys[ii].key
|
|
||||||
if ii < #existing_keys then
|
|
||||||
existing_key_str = existing_key_str .. "."
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Find key that matches perfectly
|
|
||||||
for ii=1, #potential_keys_indexes do
|
|
||||||
local index = potential_keys_indexes[ii]
|
|
||||||
local entry = entries[index]
|
|
||||||
|
|
||||||
if entry.key == existing_key_str then
|
|
||||||
return {entry, remaining_keys}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Weird case, return the first one in hope that it's correct
|
|
||||||
return {potential_keys_indexes[1], remaining_keys}
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param keys KeyDescription
|
|
||||||
---@param index number - Index of the key
|
|
||||||
local function write_keys(keys, index)
|
|
||||||
local lines = {}
|
|
||||||
|
|
||||||
if index == #keys then
|
|
||||||
return { "\"" .. keys[index].key .. "\": \"\""}
|
|
||||||
end
|
|
||||||
|
|
||||||
local insertions = write_keys(keys, index + 1)
|
|
||||||
|
|
||||||
lines[#lines + 1] = "\"" .. keys[index].key .. "\": {"
|
|
||||||
|
|
||||||
for ii=1, #insertions do
|
|
||||||
lines[#lines + 1] = insertions[ii]
|
|
||||||
end
|
|
||||||
|
|
||||||
lines[#lines + 1] = "}"
|
|
||||||
|
|
||||||
return lines
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param entries Entry[]
|
|
||||||
---@param keys KeyDescription[]
|
|
||||||
---@param buffer number
|
|
||||||
local function insert_new_key(entries, keys, buffer)
|
|
||||||
-- Close current buffer
|
|
||||||
vim.cmd [[quit!]]
|
|
||||||
|
|
||||||
local _result = find_remaining_keys(entries, keys)
|
|
||||||
local entry = _result[1]
|
|
||||||
local remaining_keys = _result[2]
|
|
||||||
|
|
||||||
local writes = write_keys(remaining_keys, 1)
|
|
||||||
vim.api.nvim_buf_set_lines(buffer, start_line, start_line, false, writes)
|
|
||||||
|
|
||||||
print(vim.inspect(entry))
|
|
||||||
print(vim.inspect(remaining_keys))
|
|
||||||
print(vim.inspect(writes))
|
|
||||||
|
|
||||||
-- for parts=#keys, 1, -1 do
|
|
||||||
-- ---@type Entries[]
|
|
||||||
-- local sub_keys = table.slice(keys, 1, parts)
|
|
||||||
-- local path = ""
|
|
||||||
--
|
|
||||||
-- for ii=1, #sub_keys do
|
|
||||||
-- path = path .. sub_keys[ii].key
|
|
||||||
-- if ii < #sub_keys then
|
|
||||||
-- path = path .. "."
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- print(path)
|
|
||||||
-- end
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param entries Entry[]
|
---@param entries Entry[]
|
||||||
---@param buffer number
|
---@param buffer number
|
||||||
local function show_picker(entries, buffer)
|
local function show_picker(entries, buffer)
|
||||||
@ -220,7 +86,7 @@ local function show_picker(entries, buffer)
|
|||||||
|
|
||||||
local key_descriptor = utils:extract_key_description(input)
|
local key_descriptor = utils:extract_key_description(input)
|
||||||
|
|
||||||
insert_new_key(entries, key_descriptor, buffer)
|
insert:insert_new_key(entries, key_descriptor, buffer)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user