fix: merge main

This commit is contained in:
Myzel394 2025-06-06 12:43:58 +02:00
commit 895e9adfdf
Signed by: Myzel394
GPG Key ID: 79E65B4AA44EBBF0
6 changed files with 1116 additions and 1117 deletions

View File

@ -1,47 +1,42 @@
local M = {};
local M = {}
local _cache = {};
local _cache = {}
---@param buffer integer
function M:cache_buffer(buffer, value)
_cache[buffer] = value;
_cache[buffer] = value
end
---@param buffer integer
function M:invalidate_buffer(buffer)
_cache[buffer] = nil;
_cache[buffer] = nil
end
---@param buffer integer
---@return string[]|nil
function M:get_cache(buffer)
return _cache[buffer];
return _cache[buffer]
end
local _listening_buffers = {};
local _listening_buffers = {}
---@param buffer integer
function M:register_listeners(buffer)
if _listening_buffers[buffer] then
return;
return
end
_listening_buffers[buffer] = true;
_listening_buffers[buffer] = true
vim.api.nvim_buf_attach(
buffer,
false,
{
vim.api.nvim_buf_attach(buffer, false, {
on_lines = function()
self:invalidate_buffer(buffer)
end,
on_detach = function()
self:invalidate_buffer(buffer)
_listening_buffers[buffer] = nil;
_listening_buffers[buffer] = nil
end,
}
);
})
end
return M;
return M

View File

@ -1,18 +1,18 @@
local utils = require"jsonfly.utils"
local utils = require("jsonfly.utils")
-- This string will be used to position the cursor properly.
-- Once everything is set, the cursor searches for this string and jumps to it.
-- After that, it will be removed immediately.
local CURSOR_SEARCH_HELPER = "_jsonFfFfFfLyY0904857CursorHelperRrRrRrR"
local M = {};
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]
sliced[#sliced + 1] = tbl[i]
end
return sliced
@ -46,17 +46,17 @@ end
---@return number|nil
local function find_best_fitting_entry(entries, keys)
local entry_index
local current_indexes = {1, #entries}
local current_indexes = { 1, #entries }
for kk=1, #keys do
for kk = 1, #keys do
local key = keys[kk]
local start_index = current_indexes[1]
local end_index = current_indexes[2]
current_indexes = {nil, nil}
current_indexes = { nil, nil }
for ii=start_index, end_index do
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
@ -84,7 +84,7 @@ local function write_keys(keys, index, lines)
local key = keys[index]
if index == #keys then
lines[#lines + 1] = "\"" .. key.key .. "\": \"" .. CURSOR_SEARCH_HELPER .. "\""
lines[#lines + 1] = '"' .. key.key .. '": "' .. CURSOR_SEARCH_HELPER .. '"'
return
end
@ -100,7 +100,7 @@ local function write_keys(keys, index, lines)
lines[#lines + 1] = "}"
elseif key.type == "key" then
lines[#lines + 1] = "\"" .. key.key .. "\":"
lines[#lines + 1] = '"' .. key.key .. '":'
write_keys(keys, index + 1, lines)
elseif key.type == "array_wrapper" then
@ -117,7 +117,7 @@ local function write_keys(keys, index, lines)
elseif key.type == "array_index" then
local amount = tonumber(key.key)
-- Write previous empty array objects
for _=1, amount do
for _ = 1, amount do
lines[#lines + 1] = "{},"
end
@ -131,22 +131,17 @@ 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,
math.max(0, ii - BUFFER_SIZE),
ii,
false
)
for ii = insertion_line, 0, -BUFFER_SIZE do
local previous_lines = vim.api.nvim_buf_get_lines(buffer, math.max(0, ii - BUFFER_SIZE), ii, false)
if #previous_lines == 0 then
return
end
for jj=#previous_lines, 1, -1 do
for jj = #previous_lines, 1, -1 do
local line = previous_lines[jj]
for char_index=#line, 1, -1 do
for char_index = #line, 1, -1 do
local char = line:sub(char_index, char_index)
if char ~= " " and char ~= "\t" and char ~= "\n" and char ~= "\r" then
@ -156,14 +151,7 @@ local function add_comma(buffer, insertion_line)
-- Insert comma at position
local line_number = math.max(0, ii - BUFFER_SIZE) + jj - 1
vim.api.nvim_buf_set_text(
buffer,
line_number,
char_index,
line_number,
char_index,
{","}
)
vim.api.nvim_buf_set_text(buffer, line_number, char_index, line_number, char_index, { "," })
return
end
end
@ -179,16 +167,10 @@ local function expand_empty_object(buffer, line_number)
local position_closing_bracket = string.find(line, "[%}%]]")
local remaining_line = string.sub(line, position_closing_bracket + 1)
vim.api.nvim_buf_set_lines(
buffer,
line_number,
line_number + 1,
false,
{
vim.api.nvim_buf_set_lines(buffer, line_number, line_number + 1, false, {
"{",
"}" .. remaining_line
}
)
"}" .. remaining_line,
})
return line_number + 1
end
@ -202,7 +184,7 @@ local function get_key_descriptor_index(keys, input_key_depth)
local depth = 0
local index = 0
for ii=1, #keys do
for ii = 1, #keys do
if keys[ii].type == "key" or keys[ii].type == "array_index" then
depth = depth + 1
end
@ -220,13 +202,13 @@ end
---@param keys string[]
---@return integer|nil - The index of the entry
local function get_entry_by_keys(entries, keys)
for ii=1, #entries do
for ii = 1, #entries do
local entry = entries[ii]
local splitted = utils:split_by_char(entry.key, ".")
local found = true
for jj=1, #keys do
for jj = 1, #keys do
if keys[jj] ~= splitted[jj] then
found = false
break
@ -244,7 +226,7 @@ end
local function flatten_key_description(keys)
local flat_keys = {}
for ii=1, #keys do
for ii = 1, #keys do
if keys[ii].type == "key" then
flat_keys[#flat_keys + 1] = keys[ii].key
elseif keys[ii].type == "array_index" then
@ -272,7 +254,7 @@ end
---@param entries Entry[] - Entries, they must be children of a top level array
---Counts how many top level children an array has
local function count_array_children(entries)
for ii=1, #entries do
for ii = 1, #entries do
if string.match(entries[ii].key, "^%d+$") then
return ii
end
@ -294,11 +276,11 @@ function M:jump_to_cursor_helper(buffer)
position[2],
position[1] - 1,
position[2] + #CURSOR_SEARCH_HELPER,
{""}
{ "" }
)
-- -- Go into insert mode
vim.cmd [[execute "normal a"]]
vim.cmd([[execute "normal a"]])
end
-- TODO: Handle top level empty arrays
@ -307,7 +289,7 @@ end
---@param buffer number
function M:insert_new_key(entries, keys, buffer)
-- Close current buffer
vim.cmd [[quit!]]
vim.cmd([[quit!]])
local input_key = flatten_key_description(keys)
---@type boolean
@ -326,8 +308,8 @@ function M:insert_new_key(entries, keys, buffer)
position = {
key_start = 1,
line_number = 1,
value_start = 1
}
value_start = 1,
},
}
should_add_comma = false
else
@ -353,8 +335,8 @@ function M:insert_new_key(entries, keys, buffer)
position = {
key_start = 1,
line_number = 1,
value_start = 1
}
value_start = 1,
},
}
else
local existing_input_keys_depth = #utils:split_by_char(entry.key, ".") + 1
@ -372,7 +354,7 @@ function M:insert_new_key(entries, keys, buffer)
write_keys(remaining_keys, 1, _writes)
local writes = {}
for ii=1, #_writes do
for ii = 1, #_writes do
if _writes[ii] == true then
-- Unwrap table
writes[#writes] = writes[#writes][1]
@ -382,8 +364,8 @@ function M:insert_new_key(entries, keys, buffer)
end
-- Hacky way to jump to end of object
vim.api.nvim_win_set_cursor(0, {entry.position.line_number, entry.position.value_start})
vim.cmd [[execute "normal %"]]
vim.api.nvim_win_set_cursor(0, { entry.position.line_number, entry.position.value_start })
vim.cmd([[execute "normal %"]])
local changes = #writes
local start_line = vim.api.nvim_win_get_cursor(0)[1] - 1
@ -403,10 +385,10 @@ function M:insert_new_key(entries, keys, buffer)
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.api.nvim_win_set_cursor(0, { start_line, 1 })
vim.cmd('execute "normal =' .. changes .. 'j"')
M:jump_to_cursor_helper(buffer)
end
return M;
return M

View File

@ -1,4 +1,4 @@
local VERSION = '20161109.21' -- version history at end of file
local VERSION = "20161109.21" -- version history at end of file
local AUTHOR_NOTE = "-[ JSON.lua package by Jeffrey Friedl (http://regex.info/blog/lua/json) version 20161109.21 ]-"
local OBJDEF = {
@ -6,13 +6,21 @@ local OBJDEF = {
AUTHOR_NOTE = AUTHOR_NOTE,
}
local default_pretty_indent = " "
local default_pretty_options = { pretty = true, align_keys = false, indent = default_pretty_indent }
local isArray = { __tostring = function() return "JSON array" end } isArray.__index = isArray
local isObject = { __tostring = function() return "JSON object" end } isObject.__index = isObject
local isArray = {
__tostring = function()
return "JSON array"
end,
}
isArray.__index = isArray
local isObject = {
__tostring = function()
return "JSON object"
end,
}
isObject.__index = isObject
function OBJDEF:newArray(tbl)
return setmetatable(tbl or {}, isArray)
@ -22,36 +30,56 @@ function OBJDEF:newObject(tbl)
return setmetatable(tbl or {}, isObject)
end
local function getnum(op)
return type(op) == 'number' and op or op.N
return type(op) == "number" and op or op.N
end
local isNumber = {
__tostring = function(T) return T.S end,
__unm = function(op) return getnum(op) end,
__tostring = function(T)
return T.S
end,
__unm = function(op)
return getnum(op)
end,
__concat = function(op1, op2) return tostring(op1) .. tostring(op2) end,
__add = function(op1, op2) return getnum(op1) + getnum(op2) end,
__sub = function(op1, op2) return getnum(op1) - getnum(op2) end,
__mul = function(op1, op2) return getnum(op1) * getnum(op2) end,
__div = function(op1, op2) return getnum(op1) / getnum(op2) end,
__mod = function(op1, op2) return getnum(op1) % getnum(op2) end,
__pow = function(op1, op2) return getnum(op1) ^ getnum(op2) end,
__lt = function(op1, op2) return getnum(op1) < getnum(op2) end,
__eq = function(op1, op2) return getnum(op1) == getnum(op2) end,
__le = function(op1, op2) return getnum(op1) <= getnum(op2) end,
__concat = function(op1, op2)
return tostring(op1) .. tostring(op2)
end,
__add = function(op1, op2)
return getnum(op1) + getnum(op2)
end,
__sub = function(op1, op2)
return getnum(op1) - getnum(op2)
end,
__mul = function(op1, op2)
return getnum(op1) * getnum(op2)
end,
__div = function(op1, op2)
return getnum(op1) / getnum(op2)
end,
__mod = function(op1, op2)
return getnum(op1) % getnum(op2)
end,
__pow = function(op1, op2)
return getnum(op1) ^ getnum(op2)
end,
__lt = function(op1, op2)
return getnum(op1) < getnum(op2)
end,
__eq = function(op1, op2)
return getnum(op1) == getnum(op2)
end,
__le = function(op1, op2)
return getnum(op1) <= getnum(op2)
end,
}
isNumber.__index = isNumber
function OBJDEF:asNumber(item)
if getmetatable(item) == isNumber then
-- it's already a JSON number object.
return item
elseif type(item) == 'table' and type(item.S) == 'string' and type(item.N) == 'number' then
elseif type(item) == "table" and type(item.S) == "string" and type(item.N) == "number" then
-- it's a number-object table that lost its metatable, so give it one
return setmetatable(item, isNumber)
else
@ -65,7 +93,7 @@ function OBJDEF:asNumber(item)
end
function OBJDEF:forceString(item)
if type(item) == 'table' and type(item.S) == 'string' then
if type(item) == "table" and type(item.S) == "string" then
return item.S
else
return tostring(item)
@ -73,30 +101,26 @@ function OBJDEF:forceString(item)
end
function OBJDEF:forceNumber(item)
if type(item) == 'table' and type(item.N) == 'number' then
if type(item) == "table" and type(item.N) == "number" then
return item.N
else
return tonumber(item)
end
end
local function unicode_codepoint_as_utf8(codepoint)
--
-- codepoint is a number
--
if codepoint <= 127 then
return string.char(codepoint)
elseif codepoint <= 2047 then
--
-- 110yyyxx 10xxxxxx <-- useful notation from http://en.wikipedia.org/wiki/Utf8
--
local highpart = math.floor(codepoint / 0x40)
local lowpart = codepoint - (0x40 * highpart)
return string.char(0xC0 + highpart,
0x80 + lowpart)
return string.char(0xC0 + highpart, 0x80 + lowpart)
elseif codepoint <= 65535 then
--
-- 1110yyyy 10yyyyxx 10xxxxxx
@ -114,18 +138,16 @@ local function unicode_codepoint_as_utf8(codepoint)
-- Check for an invalid character (thanks Andy R. at Adobe).
-- See table 3.7, page 93, in http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf#G28070
--
if ( highpart == 0xE0 and midpart < 0xA0 ) or
( highpart == 0xED and midpart > 0x9F ) or
( highpart == 0xF0 and midpart < 0x90 ) or
( highpart == 0xF4 and midpart > 0x8F )
if
(highpart == 0xE0 and midpart < 0xA0)
or (highpart == 0xED and midpart > 0x9F)
or (highpart == 0xF0 and midpart < 0x90)
or (highpart == 0xF4 and midpart > 0x8F)
then
return "?"
else
return string.char(highpart,
midpart,
lowpart)
return string.char(highpart, midpart, lowpart)
end
else
--
-- 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx
@ -137,10 +159,7 @@ local function unicode_codepoint_as_utf8(codepoint)
local midB = math.floor(remainder / 0x40)
local lowpart = remainder - 0x40 * midB
return string.char(0xF0 + highpart,
0x80 + midA,
0x80 + midB,
0x80 + lowpart)
return string.char(0xF0 + highpart, 0x80 + midA, 0x80 + midB, 0x80 + lowpart)
end
end
@ -187,8 +206,7 @@ local function grok_number(self, text, start, options)
--
-- Grab the integer part
--
local integer_part = text:match('^-?[1-9]%d*', start)
or text:match("^-?0", start)
local integer_part = text:match("^-?[1-9]%d*", start) or text:match("^-?0", start)
if not integer_part then
self:onDecodeError("expected number", text, start, options.etc)
@ -200,14 +218,14 @@ local function grok_number(self, text, start, options)
--
-- Grab an optional decimal part
--
local decimal_part = text:match('^%.%d+', i) or ""
local decimal_part = text:match("^%.%d+", i) or ""
i = i + decimal_part:len()
--
-- Grab an optional exponential part
--
local exponent_part = text:match('^[eE][-+]?%d+', i) or ""
local exponent_part = text:match("^[eE][-+]?%d+", i) or ""
i = i + exponent_part:len()
@ -223,21 +241,19 @@ local function grok_number(self, text, start, options)
-- I suppose we should really look to see whether the exponent is actually big enough one
-- way or the other to trip stringification, but I'll be lazy about it until someone asks.
--
if (options.decodeIntegerStringificationLength
and
(integer_part:len() >= options.decodeIntegerStringificationLength or exponent_part:len() > 0))
or
(options.decodeDecimalStringificationLength
and
(decimal_part:len() >= options.decodeDecimalStringificationLength or exponent_part:len() > 0))
if
(
options.decodeIntegerStringificationLength
and (integer_part:len() >= options.decodeIntegerStringificationLength or exponent_part:len() > 0)
)
or (
options.decodeDecimalStringificationLength
and (decimal_part:len() >= options.decodeDecimalStringificationLength or exponent_part:len() > 0)
)
then
return full_number_text, i -- this returns the exact string representation seen in the original JSON
end
local as_number = tonumber(full_number_text)
if not as_number then
@ -248,10 +264,8 @@ local function grok_number(self, text, start, options)
return as_number, i
end
local function grok_string(self, text, start, options)
if text:sub(start,start) ~= '"' then
if text:sub(start, start) ~= '"' then
self:onDecodeError("expected string's opening quote", text, start, options.etc)
return nil, start -- in case the error method doesn't abort, return something sensible
end
@ -260,30 +274,33 @@ local function grok_string(self, text, start, options)
local text_len = text:len()
local VALUE = ""
while i <= text_len do
local c = text:sub(i,i)
local c = text:sub(i, i)
if c == '"' then
return VALUE, i + 1
end
if c ~= '\\' then
if c ~= "\\" then
VALUE = VALUE .. c
i = i + 1
elseif text:match('^\\b', i) then
elseif text:match("^\\b", i) then
VALUE = VALUE .. "\b"
i = i + 2
elseif text:match('^\\f', i) then
elseif text:match("^\\f", i) then
VALUE = VALUE .. "\f"
i = i + 2
elseif text:match('^\\n', i) then
elseif text:match("^\\n", i) then
VALUE = VALUE .. "\n"
i = i + 2
elseif text:match('^\\r', i) then
elseif text:match("^\\r", i) then
VALUE = VALUE .. "\r"
i = i + 2
elseif text:match('^\\t', i) then
elseif text:match("^\\t", i) then
VALUE = VALUE .. "\t"
i = i + 2
else
local hex = text:match('^\\u([0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])', i)
local hex = text:match(
"^\\u([0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])",
i
)
if hex then
i = i + 6 -- bypass what we just read
@ -292,7 +309,8 @@ local function grok_string(self, text, start, options)
local codepoint = tonumber(hex, 16)
if codepoint >= 0xD800 and codepoint <= 0xDBFF then
-- it's a hi surrogate... see whether we have a following low
local lo_surrogate = text:match('^\\u([dD][cdefCDEF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])', i)
local lo_surrogate =
text:match("^\\u([dD][cdefCDEF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])", i)
if lo_surrogate then
i = i + 6 -- bypass the low surrogate we just read
codepoint = 0x2400 + (codepoint - 0xD800) * 0x400 + tonumber(lo_surrogate, 16)
@ -301,11 +319,9 @@ local function grok_string(self, text, start, options)
end
end
VALUE = VALUE .. unicode_codepoint_as_utf8(codepoint)
else
-- just pass through what's escaped
VALUE = VALUE .. text:match('^\\(.)', i)
VALUE = VALUE .. text:match("^\\(.)", i)
i = i + 2
end
end
@ -326,7 +342,7 @@ end
-- Count newlines in `text` up to `start`
local function count_newlines(text, start)
local _, count = text:sub(1, start):gsub('\n', '\n')
local _, count = text:sub(1, start):gsub("\n", "\n")
return count
end
@ -339,7 +355,7 @@ local function get_relative_i(text, i)
local count = 0
for j = i, 1, -1 do
if text:sub(j, j) == '\n' then
if text:sub(j, j) == "\n" then
break
end
count = count + 1
@ -351,17 +367,16 @@ end
local grok_one -- assigned later
local function grok_object(self, text, start, options)
if text:sub(start,start) ~= '{' then
if text:sub(start, start) ~= "{" then
self:onDecodeError("expected '{'", text, start, options.etc)
return nil, start -- in case the error method doesn't abort, return something sensible
end
local i = skip_whitespace(text, start + 1) -- +1 to skip the '{'
local VALUE = self.strictTypes and self:newObject { } or { }
local VALUE = self.strictTypes and self:newObject({}) or {}
if text:sub(i,i) == '}' then
if text:sub(i, i) == "}" then
return VALUE, i + 1
end
local text_len = text:len()
@ -375,7 +390,7 @@ local function grok_object(self, text, start, options)
i = skip_whitespace(text, new_i)
if text:sub(i, i) ~= ':' then
if text:sub(i, i) ~= ":" then
self:onDecodeError("expected colon", text, i, options.etc)
return nil, i -- in case the error method doesn't abort, return something sensible
end
@ -397,13 +412,13 @@ local function grok_object(self, text, start, options)
--
i = skip_whitespace(text, new_i)
local c = text:sub(i,i)
local c = text:sub(i, i)
if c == '}' then
if c == "}" then
return VALUE, i + 1
end
if text:sub(i, i) ~= ',' then
if text:sub(i, i) ~= "," then
self:onDecodeError("expected comma or '}'", text, i, options.etc)
return nil, i -- in case the error method doesn't abort, return something sensible
end
@ -416,14 +431,14 @@ local function grok_object(self, text, start, options)
end
local function grok_array(self, text, start, options)
if text:sub(start,start) ~= '[' then
if text:sub(start, start) ~= "[" then
self:onDecodeError("expected '['", text, start, options.etc)
return nil, start -- in case the error method doesn't abort, return something sensible
end
local i = skip_whitespace(text, start + 1) -- +1 to skip the '['
local VALUE = self.strictTypes and self:newArray { } or { }
if text:sub(i,i) == ']' then
local VALUE = self.strictTypes and self:newArray({}) or {}
if text:sub(i, i) == "]" then
return VALUE, i + 1
end
@ -449,11 +464,11 @@ local function grok_array(self, text, start, options)
--
-- Expect now either ']' to end things, or a ',' to allow us to continue.
--
local c = text:sub(i,i)
if c == ']' then
local c = text:sub(i, i)
if c == "]" then
return VALUE, i + 1
end
if text:sub(i, i) ~= ',' then
if text:sub(i, i) ~= "," then
self:onDecodeError("expected comma or ']'", text, i, options.etc)
return nil, i -- in case the error method doesn't abort, return something sensible
end
@ -463,7 +478,6 @@ local function grok_array(self, text, start, options)
return nil, i -- in case the error method doesn't abort, return something sensible
end
grok_one = function(self, text, start, options)
-- Skip any whitespace
start = skip_whitespace(text, start)
@ -475,25 +489,18 @@ grok_one = function(self, text, start, options)
if text:find('^"', start) then
return grok_string(self, text, start, options.etc)
elseif text:find('^[-0123456789 ]', start) then
elseif text:find("^[-0123456789 ]", start) then
return grok_number(self, text, start, options)
elseif text:find('^%{', start) then
elseif text:find("^%{", start) then
return grok_object(self, text, start, options)
elseif text:find('^%[', start) then
elseif text:find("^%[", start) then
return grok_array(self, text, start, options)
elseif text:find('^true', start) then
elseif text:find("^true", start) then
return true, start + 4
elseif text:find('^false', start) then
elseif text:find("^false", start) then
return false, start + 5
elseif text:find('^null', start) then
elseif text:find("^null", start) then
return nil, start + 4
else
self:onDecodeError("can't parse JSON", text, start, options.etc)
return nil, 1 -- in case the error method doesn't abort, return something sensible
@ -504,7 +511,7 @@ function OBJDEF:decode(text, etc, options)
--
-- If the user didn't pass in a table of decode options, make an empty one.
--
if type(options) ~= 'table' then
if type(options) ~= "table" then
options = {}
end
@ -516,12 +523,12 @@ function OBJDEF:decode(text, etc, options)
options.etc = etc
end
if text:match('^%s*$') then
if text:match("^%s*$") then
-- an empty string is nothing, but not an error
return nil
end
if text:match('^%s*<') then
if text:match("^%s*<") then
-- Can't be JSON... we'll assume it's HTML
local error_message = "HTML passed to JSON:decode()"
self:onDecodeOfHTMLError(error_message, text, nil, options.etc)
@ -533,7 +540,7 @@ function OBJDEF:decode(text, etc, options)
-- Those are perfectly valid encodings for JSON (as per RFC 4627 section 3),
-- but this package can't handle them.
--
if text:sub(1,1):byte() == 0 or (text:len() >= 2 and text:sub(2,2):byte() == 0) then
if text:sub(1, 1):byte() == 0 or (text:len() >= 2 and text:sub(2, 2):byte() == 0) then
local error_message = "JSON package groks only UTF-8, sorry"
self:onDecodeError(error_message, text, nil, options.etc)
return nil, error_message -- in case the error method doesn't abort, return something sensible
@ -558,7 +565,6 @@ function OBJDEF:decode(text, etc, options)
local success, value, next_i = pcall(grok_one, self, text, 1, options)
if success then
local error_message = nil
if next_i ~= #text + 1 then
-- something's left over after we parsed the first thing.... whitespace is allowed.
@ -570,9 +576,7 @@ function OBJDEF:decode(text, etc, options)
end
end
return value, error_message
else
-- If JSON:onDecodeError() didn't abort out of the pcall, we'll have received
-- the error message here as "value", so pass it along as an assert.
local error_message = value
@ -584,7 +588,6 @@ function OBJDEF:decode(text, etc, options)
-- ...and if we're still here (because the assert didn't throw an error),
-- return a nil and throw the error message on as a second arg
return nil, error_message
end
end
@ -595,7 +598,7 @@ end
OBJDEF.__index = OBJDEF
function OBJDEF:new(args)
local new = { }
local new = {}
if args then
for key, val in pairs(args) do
@ -607,5 +610,3 @@ function OBJDEF:new(args)
end
return OBJDEF:new()

View File

@ -66,7 +66,7 @@ function M:get_entries_from_lua_json(t)
line_number = raw_value.line_number,
key_start = raw_value.key_start,
value_start = raw_value.value_start,
}
},
}
table.insert(keys, entry)
@ -75,7 +75,7 @@ function M:get_entries_from_lua_json(t)
if type(v) == "table" then
local sub_keys = M:get_entries_from_lua_json(v)
for index=1, #sub_keys do
for index = 1, #sub_keys do
local sub_key = sub_keys[index]
---@type Entry
@ -129,7 +129,6 @@ function M:parse_lsp_value(result)
end
end
---@class Symbol
---@field name string
---@field kind number 2 = Object, 16 = Number, 15 = String, 18 = Array, 13 = Null, 17 = Boolean
@ -151,7 +150,7 @@ end
function M:get_entries_from_lsp_symbols(symbols)
local keys = {}
for index=1, #symbols do
for index = 1, #symbols do
local symbol = symbols[index]
local key = symbol.name
@ -167,14 +166,14 @@ function M:get_entries_from_lsp_symbols(symbols)
-- `"my_key": "my_value"`
-- Since we get the end of the key, we can just add 4 to get the start of the value
value_start = symbol.selectionRange["end"].character + 3,
}
},
}
keys[#keys + 1] = entry
if CONTAINS_CHILDREN_TYPES[symbol.kind] then
local sub_keys = M:get_entries_from_lsp_symbols(symbol.children)
for jindex=1, #sub_keys do
for jindex = 1, #sub_keys do
---@type Entry
local entry = {
key = key .. "." .. sub_keys[jindex].key,

View File

@ -86,7 +86,7 @@ function M:create_display_preview(value, conceal, render_objects)
if conceal then
return value, "string"
else
return "\"" .. value .. "\"", "string"
return '"' .. value .. '"', "string"
end
elseif t == "boolean" then
return value and "true" or "false", "boolean"
@ -198,7 +198,7 @@ function M:extract_key_description(text)
{
key = text,
type = "key",
}
},
}
end

View File

@ -26,19 +26,19 @@
---@field null string - Highlight group for null values, Default: "@constant.builtin.json"
---@field other string - Highlight group for other types, Default: "@label.json"
local parsers = require"jsonfly.parsers"
local utils = require"jsonfly.utils"
local cache = require"jsonfly.cache"
local insert = require"jsonfly.insert"
local parsers = require("jsonfly.parsers")
local utils = require("jsonfly.utils")
local cache = require("jsonfly.cache")
local insert = require("jsonfly.insert")
local json = require"jsonfly.json"
local finders = require "telescope.finders"
local pickers = require "telescope.pickers"
local json = require("jsonfly.json")
local finders = require("telescope.finders")
local pickers = require("telescope.pickers")
local conf = require("telescope.config").values
local make_entry = require "telescope.make_entry"
local entry_display = require "telescope.pickers.entry_display"
local make_entry = require("telescope.make_entry")
local entry_display = require("telescope.pickers.entry_display")
local action_state = require "telescope.actions.state"
local action_state = require("telescope.actions.state")
---@type Options
local DEFAULT_CONFIG = {
@ -82,14 +82,14 @@ local function show_picker(entries, buffer, xopts)
local config = vim.tbl_deep_extend("force", global_config, xopts or {})
local filename = vim.api.nvim_buf_get_name(buffer)
local displayer = entry_display.create {
local displayer = entry_display.create({
separator = " ",
items = {
{ width = 1 },
global_config.key_exact_length and { width = global_config.key_max_length } or { remaining = true },
{ remaining = true },
},
}
})
---@type boolean
local conceal
@ -99,23 +99,20 @@ local function show_picker(entries, buffer, xopts)
conceal = global_config.conceal == true
end
pickers.new(config, {
pickers
.new(config, {
prompt_title = global_config.prompt_title,
attach_mappings = function(_, map)
map(
global_config.commands.add_key[1],
global_config.commands.add_key[2],
function(prompt_bufnr)
map(global_config.commands.add_key[1], global_config.commands.add_key[2], function(prompt_bufnr)
local current_picker = action_state.get_current_picker(prompt_bufnr)
local input = current_picker:_get_prompt()
local key_descriptor = utils:extract_key_description(input)
insert:insert_new_key(entries, key_descriptor, buffer)
end
)
end)
if global_config.commands.copy_jsonpath and utils:is_module_available("jsonpath") then
if global_config.commands.copy_jsonpath and utils:is_module_available("jsonpath") then
map(
global_config.commands.copy_jsonpath[1],
global_config.commands.copy_jsonpath[2],
@ -142,7 +139,7 @@ local function show_picker(entries, buffer, xopts)
return true
end,
finder = finders.new_table {
finder = finders.new_table({
results = entries,
---@param entry Entry
entry_maker = function(entry)
@ -153,12 +150,17 @@ local function show_picker(entries, buffer, xopts)
value = buffer,
ordinal = entry.key,
display = function(_)
local preview, hl_group_key = utils:create_display_preview(entry.value, conceal, global_config.show_nested_child_preview)
local preview, hl_group_key = utils:create_display_preview(
entry.value,
conceal,
global_config.show_nested_child_preview
)
local key = global_config.subkeys_display == "normal" and entry.key or utils:replace_previous_keys(entry.key, " ")
local key = global_config.subkeys_display == "normal" and entry.key
or utils:replace_previous_keys(entry.key, " ")
return displayer {
{ depth, "TelescopeResultsNumber"},
return displayer({
{ depth, "TelescopeResultsNumber" },
{
utils:truncate_overflow(
key,
@ -175,26 +177,26 @@ local function show_picker(entries, buffer, xopts)
),
global_config.highlights[hl_group_key] or "TelescopeResultsString",
},
}
})
end,
bufnr = buffer,
filename = filename,
lnum = entry.position.line_number,
col = global_config.jump_behavior == "key_start"
and entry.position.key_start
col = global_config.jump_behavior == "key_start" and entry.position.key_start
-- Use length ("#" operator) as vim jumps to the bytes, not characters
or entry.position.value_start
or entry.position.value_start,
}, config)
end,
},
}),
previewer = conf.grep_previewer(config),
sorter = conf.generic_sorter(config),
sorting_strategy = "ascending",
}):find()
})
:find()
end
return require("telescope").register_extension {
return require("telescope").register_extension({
setup = function(extension_config)
global_config = vim.tbl_deep_extend("force", DEFAULT_CONFIG, extension_config or {})
end,
@ -231,30 +233,50 @@ return require("telescope").register_extension {
if global_config.backend == "lsp" then
local params = vim.lsp.util.make_position_params(xopts.winnr)
vim.lsp.buf_request_all(
current_buf,
"textDocument/documentSymbol",
params,
function(response)
if response == nil or #response == 0 then
-- Check i
local clients = vim.lsp.get_clients()
local any_support = false
for _, client in ipairs(clients) do
if client.supports_method("textDocument/documentSymbol") then
any_support = true
break
end
end
if any_support then
vim.lsp.buf_request_all(current_buf, "textDocument/documentSymbol", params, function(results)
if results == nil or vim.tbl_isempty(results) then
run_lua_parser()
return
end
local result = response[1].result
local combined_result = {}
local entries = parsers:get_entries_from_lsp_symbols(result)
for _, res in pairs(results) do
if res.result then
vim.list_extend(combined_result, res.result)
end
end
if vim.tbl_isempty(combined_result) then
run_lua_parser()
return
end
local entries = parsers:get_entries_from_lsp_symbols(combined_result)
if allow_cache then
cache:cache_buffer(current_buf, entries)
end
show_picker(entries, current_buf, xopts)
end)
end
)
else
end
run_lua_parser()
end
end
}
}
end,
},
})