11local Object = require (" nui.object" )
22local _ = require (" nui.utils" )._
33local defaults = require (" nui.utils" ).defaults
4- local is_type = require (" nui.utils" ).is_type
54local tree_util = require (" nui.tree.util" )
65
76-- returns id of the first window that contains the buffer
@@ -11,11 +10,12 @@ local function get_winid(bufnr)
1110 return vim .fn .win_findbuf (bufnr )[1 ]
1211end
1312
13+ --- @param get_tree fun (): NuiTree
1414--- @param nodes NuiTree.Node[]
1515--- @param parent_node ? NuiTree.Node
1616--- @param get_node_id nui_tree_get_node_id
1717--- @return { by_id : table<string , NuiTree.Node> , root_ids : string[] }
18- local function initialize_nodes (nodes , parent_node , get_node_id )
18+ local function initialize_nodes (get_tree , nodes , parent_node , get_node_id )
1919 local start_depth = parent_node and parent_node :get_depth () + 1 or 1
2020
2121 --- @type table<string , NuiTree.Node>
@@ -26,7 +26,9 @@ local function initialize_nodes(nodes, parent_node, get_node_id)
2626 --- @param node NuiTree.Node
2727 --- @param depth number
2828 local function initialize (node , depth )
29+ node ._tree = get_tree
2930 node ._depth = depth
31+ node ._height = 0
3032 node ._id = get_node_id (node )
3133 node ._initialized = true
3234
7577--- @field _depth integer
7678--- @field _parent_id ? string
7779--- @field _child_ids ? string[]
80+ --- @field _next string
81+ --- @field _prev string
7882--- @field __children ? NuiTree.Node[]
7983--- @field [ string] any
8084local TreeNode = {
147151--- @field node_id_by_linenr table<integer , string>
148152--- @field prepare_node nui_tree_prepare_node
149153--- @field win_options table<string , any> # deprecated
154+ --- @field head ? string
155+ --- @field tail ? string
156+ --- @field get_tree fun (): NuiTree
150157
151158--- @class nui_tree_options
152159--- @field bufnr integer
@@ -212,6 +219,10 @@ function Tree:init(options)
212219 linenr = {},
213220 }
214221
222+ self ._ .get_tree = function ()
223+ return self
224+ end
225+
215226 _ .set_buf_options (self .bufnr , self ._ .buf_options )
216227
217228 --- @deprecated
@@ -253,14 +264,48 @@ end
253264--- @return nil | integer linenr
254265--- @return nil | integer linenr
255266function Tree :get_node (node_id_or_linenr )
256- if is_type (" string" , node_id_or_linenr ) then
257- return self .nodes .by_id [node_id_or_linenr ], unpack (self ._ .linenr_by_node_id [node_id_or_linenr ] or {})
267+ local by_id = self .nodes .by_id
268+
269+ if type (node_id_or_linenr ) == " string" then
270+ local node = by_id [node_id_or_linenr ]
271+ if not node then
272+ return
273+ end
274+
275+ local linenr = 1
276+ local head = by_id [self ._head ]
277+ while head and head ~= node do
278+ head = by_id [head ._next ]
279+ linenr = linenr + 1
280+ end
281+
282+ return node , linenr , linenr + node ._height - 1
283+
284+ -- return node, unpack(self._.linenr_by_node_id[node_id_or_linenr] or {})
258285 end
259286
260287 local winid = get_winid (self .bufnr )
261288 local linenr = node_id_or_linenr or vim .api .nvim_win_get_cursor (winid )[1 ]
262- local node_id = self ._ .node_id_by_linenr [linenr ]
263- return self .nodes .by_id [node_id ], unpack (self ._ .linenr_by_node_id [node_id ] or {})
289+
290+ local node , linenr_left = by_id [self ._head ], linenr - 1
291+ local node_height_below = node and node ._height
292+ while node and linenr_left > 0 do
293+ linenr_left = linenr_left - 1
294+ node_height_below = node_height_below - 1
295+ if node_height_below == 0 then
296+ node = by_id [node ._next ]
297+ node_height_below = node and node ._height
298+ end
299+ end
300+
301+ if not node then
302+ return
303+ end
304+
305+ return node , linenr + node_height_below - node ._height , linenr + node_height_below - 1
306+
307+ -- local node_id = self._.node_id_by_linenr[linenr]
308+ -- return self.nodes.by_id[node_id], unpack(self._.linenr_by_node_id[node_id] or {})
264309end
265310
266311--- @param parent_id ? string parent node ' s id
285330--- @param nodes NuiTree.Node[]
286331--- @param parent_node ? NuiTree.Node
287332function Tree :_add_nodes (nodes , parent_node )
288- local new_nodes = initialize_nodes (nodes , parent_node , self ._ .get_node_id )
333+ local new_nodes = initialize_nodes (self . _ . get_tree , nodes , parent_node , self ._ .get_node_id )
289334
290335 self .nodes .by_id = vim .tbl_extend (" force" , self .nodes .by_id , new_nodes .by_id )
291336
307352--- @param nodes NuiTree.Node[]
308353--- @param parent_id ? string parent node ' s id
309354function Tree :set_nodes (nodes , parent_id )
310- self ._ .node_id_by_linenr = {}
311- self ._ .linenr_by_node_id = {}
355+ -- self._.node_id_by_linenr = {}
356+ -- self._.linenr_by_node_id = {}
312357
313358 if not parent_id then
314359 self .nodes = { by_id = {}, root_ids = {} }
@@ -387,11 +432,13 @@ function Tree:_prepare_content(linenr_start)
387432 local tree_linenr = 0
388433 local lines = { len = tree_linenr }
389434
390- local node_id_by_linenr = {}
391- internal .node_id_by_linenr = node_id_by_linenr
435+ -- local node_id_by_linenr = {}
436+ -- internal.node_id_by_linenr = node_id_by_linenr
437+
438+ -- local linenr_by_node_id = {}
439+ -- internal.linenr_by_node_id = linenr_by_node_id
392440
393- local linenr_by_node_id = {}
394- internal .linenr_by_node_id = linenr_by_node_id
441+ local prev_node = nil
395442
396443 local function prepare (node_id , parent_node )
397444 local node = by_id [node_id ]
@@ -400,30 +447,42 @@ function Tree:_prepare_content(linenr_start)
400447 end
401448
402449 local node_lines = internal .prepare_node (node , parent_node )
450+ local node_lines_len = 0
403451 if node_lines then
404452 if type (node_lines ) ~= " table" or node_lines .content then
405453 list_wrapper [1 ] = node_lines
406454 node_lines = list_wrapper
407455 end
408456 --- @cast node_lines - string , - NuiLine
409457
410- local node_linenr = linenr_by_node_id [node_id ] or {}
411- for node_line_idx = 1 , # node_lines do
458+ -- local node_linenr = linenr_by_node_id[node_id] or {}
459+ node_lines_len = # node_lines
460+ for node_line_idx = 1 , node_lines_len do
412461 local node_line = node_lines [node_line_idx ]
413462
414463 tree_linenr = tree_linenr + 1
415- local buffer_linenr = tree_linenr + linenr_start - 1
464+ -- local buffer_linenr = tree_linenr + linenr_start - 1
416465
417466 lines [tree_linenr ] = node_line
418467
419- node_id_by_linenr [buffer_linenr ] = node_id
468+ -- node_id_by_linenr[buffer_linenr] = node_id
469+
470+ -- if node_line_idx == 1 then
471+ -- node_linenr[1] = buffer_linenr
472+ -- end
473+ -- node_linenr[2] = buffer_linenr
474+ end
475+ -- linenr_by_node_id[node_id] = node_linenr
476+ end
477+ node ._height = node_lines_len
420478
421- if node_line_idx == 1 then
422- node_linenr [1 ] = buffer_linenr
423- end
424- node_linenr [2 ] = buffer_linenr
479+ if node ._height > 0 then
480+ node ._prev = prev_node
481+ if prev_node then
482+ node ._prev = node ._prev :get_id ()
483+ prev_node ._next = node :get_id ()
425484 end
426- linenr_by_node_id [ node_id ] = node_linenr
485+ prev_node = node
427486 end
428487
429488 local child_ids = node ._child_ids
@@ -439,6 +498,9 @@ function Tree:_prepare_content(linenr_start)
439498 prepare (root_ids [node_id_idx ])
440499 end
441500
501+ self ._head = root_ids [1 ]
502+ self ._tail = prev_node
503+
442504 lines .len = tree_linenr
443505
444506 return lines
0 commit comments