Compare commits

...

6 Commits

Author SHA1 Message Date
2346a75cae
feat(dev): Add flake.nix 2025-06-06 12:55:07 +02:00
0e5158a8d4
chore: apply stylua 2025-06-06 12:54:16 +02:00
895e9adfdf
fix: merge main 2025-06-06 12:43:58 +02:00
Myzel394
d713d9ef38
Merge pull request #20 from kletobias/custom-jsonfly
Fix: Handle Dictionary Responses in jsonfly.lua for Neovim 0.10.1
2024-09-30 16:22:17 +02:00
Myzel394
8fe79c2783
fix: Fix fallback behavior; apply stylua 2024-09-30 16:18:19 +02:00
Tobias Klein
cbff2a5659 fix(jsonfly.lua): resolve function buf_request_all to work with new nvim
syntax and version changes not accounted for.
Refactored LSP request handling in jsonfly.lua to combine results from multiple LSP responses and handle empty results more gracefully. Improved code readability and maintainability by restructuring the nested if-else blocks.
2024-09-29 15:55:36 +02:00
9 changed files with 1286 additions and 1168 deletions

61
flake.lock generated Normal file
View File

@ -0,0 +1,61 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1748929857,
"narHash": "sha256-lcZQ8RhsmhsK8u7LIFsJhsLh/pzR9yZ8yqpTzyGdj+Q=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "c2a03962b8e24e669fb37b7df10e7c79531ff1a4",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"utils": "utils"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

43
flake.nix Normal file
View File

@ -0,0 +1,43 @@
{
description = "jsonfly";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
utils.url = "github:numtide/flake-utils";
};
outputs = { nixpkgs, utils, ... } @ inputs:
utils.lib.eachDefaultSystem(system:
let
pkgs = nixpkgs.legacyPackages.${system};
logo = pkgs.writeText "logo.txt" ''
'';
in
{
devShells.default = pkgs.mkShell {
packages = with pkgs; [
stylua
# If this ever fails, just remove it. It's just for the logo.
lolcat
];
shellHook = ''
cat ${logo} | lolcat
echo "";
echo "Welcome to the jsonfly.nvim development environment!";
echo "";
'';
};
}
);
}

10
justfile Normal file
View File

@ -0,0 +1,10 @@
#!/usr/bin/env just --justfile
set dotenv-load := true
_default:
just --list -u
lint:
stylua lua

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,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

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,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()

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)
@ -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

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
@ -208,7 +208,9 @@ end
---@param name string
---@return boolean
function M:is_module_available(name)
return pcall(function() require(name) end) == true
return pcall(function()
require(name)
end) == true
end
return M

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 = {
@ -69,9 +69,9 @@ local DEFAULT_CONFIG = {
---@param prompt_bufnr number
function(path, prompt_bufnr)
vim.fn.setreg("+", path)
end
}
}
end,
},
},
}
local global_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(
@ -125,13 +122,16 @@ local function show_picker(entries, buffer, xopts)
local current_picker = action_state.get_current_picker(prompt_bufnr)
local selection = current_picker:get_selection()
local path = jsonpath.get(vim.treesitter.get_node({
local path = jsonpath.get(
vim.treesitter.get_node({
bufnr = buffer,
pos = {
selection.lnum - 1,
selection.index,
}
}), buffer)
},
}),
buffer
)
if path then
global_config.commands.copy_jsonpath[3](path, prompt_bufnr)
@ -142,7 +142,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 +153,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 +180,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 +236,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,
},
})