feat: use neo-tree if available for tree view

must also add it to registered sources: add `codemp.neo-tree` and done
This commit is contained in:
əlemi 2024-08-24 01:58:03 +02:00
parent 3e26103064
commit db24f06633
Signed by: alemi
GPG key ID: A4895B84D311642C
6 changed files with 364 additions and 2 deletions

132
src/neo-tree/bridge.lua Normal file
View file

@ -0,0 +1,132 @@
local renderer = require("neo-tree.ui.renderer")
local codemp = require("codemp.session")
local cc = require("neo-tree.sources.common.commands")
local buf_manager = require("codemp.buffers")
local M = {}
---@class Item
---@field id string
---@field name string
---@field type string
---@field loaded any
---@field filtered_by any
---@field extra table
---@field is_nested any
---@field skip_node any
---@field is_empty_with_hidden_root any
---@field stat any
---@field stat_provider any
---@field is_link any
---@field link_to any
---@field path any
---@field ext any
---@field search_pattern any
---@param workspace string workspace name
---@param path string buffer relative path
---@return Item
local function new_item(workspace, path)
return {
id = string.format("codemp://%s/%s", workspace, path),
name = path,
type = "buffer",
extra = {},
children = {},
}
end
---@param workspace string workspace name
---@param username string user display name
---@return Item
local function new_user(workspace, username)
return {
id = string.format("codemp://%s@%s", username, workspace),
name = username,
type = "user",
extra = {},
children = {},
}
end
---@param name string workspace name
---@param owned boolean true if this workspace is owned by us
---@param expanded? boolean if node should be pre-expanded
---@return Item
local function new_workspace(name, owned, expanded)
return {
id = "codemp://" .. name,
name = name,
type = "workspace",
['_is_expanded'] = expanded, -- TODO this is nasty can we do better?
extra = {
owned = owned,
},
children = {},
}
end
local function spacer()
return {
id = "codemp-ws-spacer-" .. vim.fn.rand() % 1024,
name = "",
type = "spacer",
}
end
M.update_state = function(state)
---@type Item
local root
if codemp.workspace ~= nil then
root = {
id = "codemp",
name = codemp.client.username .. "@" .. codemp.workspace.name,
type = "root",
extra = {},
children = {}
}
table.insert(root.children, spacer())
for i, path in ipairs(codemp.workspace:filetree()) do
table.insert(root.children, new_item(codemp.workspace.name, path))
end
table.insert(root.children, spacer())
for user, buffer in pairs(buf_manager.users) do
table.insert(root.children, new_user(codemp.workspace.name, user))
end
elseif codemp.client ~= nil then
root = {
id = "codemp",
name = codemp.client.username .. "@codemp",
type = "root",
extra = {},
children = {}
}
for _, ws in ipairs(codemp.available) do
local workspace = new_workspace(ws.name, ws.owned)
if codemp.workspace ~= nil and codemp.workspace.name == ws.name then
end
table.insert(root.children, workspace)
end
else
root = {
id = "codemp",
name = "codemp",
type = "root",
extra = {},
children = {}
}
end
renderer.show_nodes({ root }, state)
if codemp.workspace ~= nil then
for _, node in ipairs(state.tree:get_nodes()) do
node:expand()
end
end
end
return M

69
src/neo-tree/commands.lua Normal file
View file

@ -0,0 +1,69 @@
local cc = require("neo-tree.sources.common.commands")
local utils = require("neo-tree.utils")
local manager = require("neo-tree.sources.manager")
local session = require("codemp.session")
local renderer = require("neo-tree.ui.renderer")
local ws_manager = require("codemp.workspace")
local buf_manager = require("codemp.buffers")
local client_manager = require("codemp.client")
local M = {}
M.refresh = require("neo-tree.utils").wrap(manager.refresh, "codemp")
M.open = function(state, path, extra)
local selected = state.tree:get_node()
if selected.type == "spacer" then return end
if selected.type == "root" then
if session.client ~= nil then
print(" +-+ connected to codemp as " .. session.client.username)
else
client_manager.connect()
end
return
end
if selected.type == "workspace" then
if selected:is_expanded() then
vim.ui.input({ prompt = "disconnect from workspace?" }, function (input)
if input == nil then return end
if input ~= "y" then return end
ws_manager.leave()
selected:collapse()
manager.refresh("codemp")
end)
else
if session.workspace ~= nil and session.workspace.name ~= selected.name then
error("must leave current workspace first")
end
if session.workspace == nil then
ws_manager.join(selected.name)
end
selected:expand()
manager.refresh("codemp")
end
return
end
if selected.type == "buffer" then
local window = utils.get_appropriate_window(state)
vim.api.nvim_set_current_win(window)
buf_manager.attach(selected.name)
return
end
if selected.type == "user" then
print("another remote user")
return
end
error("unrecognized node type")
end
M.add = function(_state)
if session.workspace == nil then error("not in a workspace") end
vim.ui.input({ prompt = "name" }, function(input)
if input == nil or input == "" then return end
session.workspace:create_buffer(input):await()
manager.refresh("codemp")
end)
end
cc._add_common_commands(M)
return M

View file

@ -0,0 +1,84 @@
-- This file contains the built-in components. Each componment is a function
-- that takes the following arguments:
-- config: A table containing the configuration provided by the user
-- when declaring this component in their renderer config.
-- node: A NuiNode object for the currently focused node.
-- state: The current state of the source providing the items.
--
-- The function should return either a table, or a list of tables, each of which
-- contains the following keys:
-- text: The text to display for this item.
-- highlight: The highlight group to apply to this text.
local highlights = require("neo-tree.ui.highlights")
local common = require("neo-tree.sources.common.components")
local codemp_utils = require("codemp.utils")
local codemp_buffers = require("codemp.buffers")
local M = {}
M.icon = function(config, node, state)
local icon, highlight
if node.type == "buffer" then
icon = "- "
highlight = highlights.FILE_ICON
elseif node.type == "directory" then
icon = "= "
highlight = highlights.DIRECTORY_ICON
elseif node.type == "root" then
icon = "> "
highlight = highlights.FILE_STATS_HEADER
elseif node.type == "workspace" then
if node:is_expanded() then
icon = "| "
else
icon = "+ "
end
highlight = highlights.SYMBOLIC_LINK_TARGET
elseif node.type == "user" then
icon = ":"
highlight = codemp_utils.color(node.name)
end
return {
text = icon,
highlight = highlight,
}
end
M.name = function(config, node, state)
local highlight = config.highlight or highlights.FILE_NAME
if node.type == "root" then
highlight = highlights.ROOT_NAME
elseif node.type == "workspace" then
highlight = highlights.SYMBOLIC_LINK_TARGET
end
return {
text = node.name,
highlight = highlight,
}
end
M.spacer = function(config, node, state)
return {
text = " ",
highlight = highlights.NORMAL,
}
end
M.users = function(config, node, state)
local out = {}
-- TODO this is rather inefficient, maybe store reverse map precalculated?
for user, buf in pairs(codemp_buffers.users) do
if buf == node.name then
table.insert(out, {
text = " ",
highlight = codemp_utils.color(user),
align = "right",
})
end
end
return out
end
return vim.tbl_deep_extend("force", common, M)

45
src/neo-tree/init.lua Normal file
View file

@ -0,0 +1,45 @@
local bridge = require("codemp.neo-tree.bridge")
local M = { name = "codemp" }
M.navigate = function(state, path)
if path == nil then
path = vim.fn.getcwd()
end
state.path = path
bridge.update_state(state)
end
M.setup = function(config, global_config)
end
M.default_config = {
renderers = {
spacer = {
{ "indent" },
},
root = {
{ "icon" },
{ "name" },
},
workspace = {
{ "indent" },
{ "icon" },
{ "name" },
},
user = {
{ "indent" },
{ "icon" },
{ "name" },
},
buffer = {
{ "indent" },
{ "icon" },
{ "name" },
{ "spacer" },
{ "users" },
},
},
}
return M

View file

@ -1,3 +1,17 @@
local success, manager = pcall(require, "neo-tree.sources.manager")
if success then
-- we have Neotree installed! use it for cool tree view
return {
update = function () manager.refresh("codemp") end,
init = function () end,
open = function () vim.cmd(":Neotree open source=codemp<CR>") end,
toggle = function () vim.cmd(":Neotree toggle source=codemp<CR>") end,
}
end
-- we don't have Neotree installed, cook a rough window
local session = require('codemp.session')
local utils = require('codemp.utils')
local buffers = require('codemp.buffers')
@ -144,6 +158,4 @@ return {
open = open_window,
update = update_window,
toggle = toggle_window,
buffer = buffer_id,
id = window_id,
}

View file

@ -5,6 +5,25 @@ local window = require('codemp.window')
local user_hl = {}
local function fetch_workspaces_list(client)
local new_list = {}
local owned = client:list_workspaces(true, false):await()
for _, ws in pairs(owned) do
table.insert(new_list, {
name = ws,
owned = true,
})
end
local invited = client:list_workspaces(false, true):await()
for _, ws in pairs(invited) do
table.insert(new_list, {
name = ws,
owned = false,
})
end
return new_list
end
---@param ws Workspace
local function register_cursor_callback(ws)
local controller = ws.cursor
@ -97,4 +116,5 @@ return {
join = join,
leave = leave,
map = user_hl,
list = fetch_workspaces_list,
}