mirror of
https://github.com/Myzel394/jsonfly.nvim.git
synced 2025-06-18 04:05:26 +02:00
fix: merge main
This commit is contained in:
commit
895e9adfdf
@ -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
|
||||
|
@ -1,11 +1,11 @@
|
||||
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)
|
||||
@ -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
|
||||
@ -132,12 +132,7 @@ local function add_comma(buffer, insertion_line)
|
||||
|
||||
-- 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
|
||||
)
|
||||
local previous_lines = vim.api.nvim_buf_get_lines(buffer, math.max(0, ii - BUFFER_SIZE), ii, false)
|
||||
|
||||
if #previous_lines == 0 then
|
||||
return
|
||||
@ -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
|
||||
@ -298,7 +280,7 @@ function M:jump_to_cursor_helper(buffer)
|
||||
)
|
||||
|
||||
-- -- 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
|
||||
@ -383,7 +365,7 @@ function M:insert_new_key(entries, keys, buffer)
|
||||
|
||||
-- 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.cmd([[execute "normal %"]])
|
||||
|
||||
local changes = #writes
|
||||
local start_line = vim.api.nvim_win_get_cursor(0)[1] - 1
|
||||
@ -409,4 +391,4 @@ function M:insert_new_key(entries, keys, buffer)
|
||||
M:jump_to_cursor_helper(buffer)
|
||||
end
|
||||
|
||||
return M;
|
||||
return M
|
||||
|
@ -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,9 +264,7 @@ 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
|
||||
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
|
||||
@ -264,26 +278,29 @@ local function grok_string(self, text, start, options)
|
||||
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
|
||||
@ -399,11 +414,11 @@ local function grok_object(self, text, start, options)
|
||||
|
||||
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
|
||||
|
||||
@ -450,10 +465,10 @@ 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
|
||||
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)
|
||||
@ -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
|
||||
|
||||
@ -607,5 +610,3 @@ function OBJDEF:new(args)
|
||||
end
|
||||
|
||||
return OBJDEF:new()
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
||||
@ -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
|
||||
@ -167,7 +166,7 @@ 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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,21 +99,18 @@ 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
|
||||
map(
|
||||
@ -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,11 +150,16 @@ 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 {
|
||||
return displayer({
|
||||
{ depth, "TelescopeResultsNumber" },
|
||||
{
|
||||
utils:truncate_overflow(
|
||||
@ -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,
|
||||
},
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user