Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 77 additions & 1 deletion lua/jsonpath.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ local contains_special_characters = function(str)
return str:match("[^a-zA-Z0-9_]")
end

M.get = function()
local get_json_path = function()
if not parsers.has_parser() then
return ""
end
Expand Down Expand Up @@ -88,4 +88,80 @@ M.get = function()
return path
end

local function get_yaml_path()
if not parsers.has_parser() then
return ""
end

local current_node = ts_utils.get_node_at_cursor()
if not current_node then
return ""
end

local accessors = {}
local node = current_node

while node do
local accessor = ""

if node:type() == "block_mapping_pair" then
local key_node = unpack(node:field("key"))
local key = get_node_text(key_node)

if key and starts_with_number(key) or contains_special_characters(key) then
Comment on lines +107 to +111

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, this doesn't handle JSON inside YAML.

For instance, with my cursor on

json_map: { |"key": "value" }

It returns json_map. I'd expect it to return json_map.key.

I could make it work by changing also handle the node type flow_pair

Suggested change
if node:type() == "block_mapping_pair" then
local key_node = unpack(node:field("key"))
local key = get_node_text(key_node)
if key and starts_with_number(key) or contains_special_characters(key) then
if node:type() == "block_mapping_pair" or node:type() == "flow_pair" then
local key_node = unpack(node:field("key"))
local key = get_node_text(key_node)
if key and starts_with_number(key) or contains_special_characters(key) then

But then the result would be also unexpected, json_map[""key""] instead of json_map.key. So we should handle the node double_scalar_key separately.

The node string_scalar seems to work fine, for instance in this line:

and quotes are optional: { |key: [ 3, 2, 1, takeoff ] }

accessor = string.format('["%s"]', key)
else
accessor = string.format("%s", key)
end
end

if node:type() == "block_sequence" then

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could improve this here by also handling the nodes of type flow_sequence. I didn't find something unexpected with the following change:

Suggested change
if node:type() == "block_sequence" then
if node:type() == "block_sequence" or node:type() == "flow_sequence" then

For instance, in this line:

json_seq: [ 3, 2, 1, "takeoff" ]

accessor = "[]"

for i, child in ipairs(ts_utils.get_named_children(node)) do
if ts_utils.is_parent(child, current_node) then
accessor = string.format("[%d]", i - 1)
end
end
end

if accessor ~= "" then
table.insert(accessors, 1, accessor)
end

node = node:parent()
end

if #accessors == 0 then
return "."
end

local path = ""

for i, accessor in ipairs(accessors) do
if i == 1 then
path = path .. "." .. accessor
elseif vim.startswith(accessor, "[") then
path = path .. accessor
else
path = path .. "." .. accessor
end
end

return path
end

M.get = function()
local filetype = vim.bo.filetype

if filetype == "json" then
return get_json_path()
elseif filetype == "yaml" or filetype == "yml" then
return get_yaml_path()
else
return ""
end
end

return M