grapp-dev / nui-components.nvim

A feature-rich and highly customizable library for creating user interfaces in Neovim.
https://nui-components.grapp.dev
MIT License
303 stars 6 forks source link

Possibilility of dynamic shrink window height? #26

Closed xzbdmw closed 5 months ago

xzbdmw commented 5 months ago

I want to achieve something similar to vscode and zed for lsp_document_symbols

https://github.com/grapp-dev/nui-components.nvim/assets/97848247/58c17363-c302-480e-9a6d-e06d71ceb11e

the main functionality is managed well but lack the dynamic size support in neovim ui. It is possible? For various search plugins, seems only nvim-cmp has this capability.

mobily commented 5 months ago

Hello there! 👋 With the new version (1.4.0), you can shrink the container (using renderer:set_size) and, for instance, the tree component when you receive search results. Below is a snippet that demonstrates this functionality.

local renderer = n.create_renderer({
  width = 80,
  height = 3,
  position = {
    row = 1,
    col = "50%",
  },
})

local data = {
  n.node({ text = "Code Documentation Standards" }),
  n.node({ text = "Version Control Workflow" }),
  n.node({ text = "Essential API Documentation" }),
  n.node({ text = "Bug Reporting Protocol" }),
  n.node({ text = "Testing Strategy Overview" }),
  n.node({ text = "Code Review Checklist" }),
  n.node({ text = "Agile Sprint Planning Guide" }),
  n.node({ text = "Deployment Process Documentation" }),
  n.node({ text = "Continuous Integration Setup" }),
  n.node({ text = "Security Protocol Documentation" }),
}

local signal = n.create_signal({
  search_value = "",
  data = data,
})

local get_data = function()
  return signal.data
    :dup()
    :combine_latest(signal.search_value:debounce(0):start_with(""), function(items, search_value)
      return fn.ifilter(items, function(item)
        return string.find(item.text:lower(), search_value:lower())
      end)
    end)
end

local body = n.rows(
  n.text_input({
    size = 1,
    max_lines = 1,
    autofocus = true,
    on_change = function(value)
      signal.search_value = value
    end,
  }),
  n.tree({
    border_label = "",
    size = get_data()
      :map(function(lines)
        return #lines
      end)
      :tap(function(lines)
        renderer:set_size({ height = math.max(lines + 3, 3) })
      end),
    data = get_data(),
    hidden = get_data():map(function(lines)
      return #lines == 0
    end),
    on_select = function(node)
      print("selected: " .. node.text)
    end,
    prepare_node = function(node, line)
      line:append(node.text)
      return line
    end,
  })
)

renderer:render(body)

https://github.com/grapp-dev/nui-components.nvim/assets/1467712/66d7644d-cea6-4e83-92bc-5de0e7fe85e2

Feel free to let me know if you have any more questions.

xzbdmw commented 5 months ago

Hi, it throws a error saying

E5108: Error executing lua: ...ui-components.nvim/lua/nui-components/component/size.lua:133: attempt to perform arithmetic on local 'size' (a nil value)
stack traceback:
    ...ui-components.nvim/lua/nui-components/component/size.lua:133: in function '_include_border_size'
    ...ui-components.nvim/lua/nui-components/component/size.lua:228: in function 'get_size'
    ...ui-components.nvim/lua/nui-components/component/init.lua:358: in function 'render'
    ...ui-components.nvim/lua/nui-components/component/init.lua:346: in function 'func'
    ...lazy/nui-components.nvim/lua/nui-components/utils/fn.lua:19: in function 'ireduce'
    ...ui-components.nvim/lua/nui-components/component/init.lua:344: in function 'render'
    ...lazy/nui-components.nvim/lua/nui-components/renderer.lua:140: in function 'func'
    ...lazy/nui-components.nvim/lua/nui-components/utils/fn.lua:19: in function 'ireduce'
    ...lazy/nui-components.nvim/lua/nui-components/renderer.lua:138: in function '_get_layout_box'
    ...lazy/nui-components.nvim/lua/nui-components/renderer.lua:150: in function '_set_layout'
    ...lazy/nui-components.nvim/lua/nui-components/renderer.lua:54: in function 'render'
mobily commented 5 months ago

@xzbdmw did you update the plugin?

xzbdmw commented 5 months ago
截屏2024-04-16 14 41 37

Yes my test code

vim.keymap.set("n", "<leader>zz", function()
    local n = require("nui-components")
    local renderer = n.create_renderer({
        width = 80,
        height = 3,
        position = {
            row = 1,
            col = "50%",
        },
    })

    local data = {
        n.node({ text = "Code Documentation Standards" }),
        n.node({ text = "Version Control Workflow" }),
        n.node({ text = "Essential API Documentation" }),
        n.node({ text = "Bug Reporting Protocol" }),
        n.node({ text = "Testing Strategy Overview" }),
        n.node({ text = "Code Review Checklist" }),
        n.node({ text = "Agile Sprint Planning Guide" }),
        n.node({ text = "Deployment Process Documentation" }),
        n.node({ text = "Continuous Integration Setup" }),
        n.node({ text = "Security Protocol Documentation" }),
    }

    local signal = n.create_signal({
        search_value = "",
        data = data,
    })

    local get_data = function()
        return signal.data
            :dup()
            :combine_latest(signal.search_value:debounce(0):start_with(""), function(items, search_value)
                return vim.fn.ifilter(items, function(item)
                    return string.find(item.text:lower(), search_value:lower())
                end)
            end)
    end

    local body = n.rows(
        n.text_input({
            size = 1,
            max_lines = 1,
            autofocus = true,
            on_change = function(value)
                signal.search_value = value
            end,
        }),
        n.tree({
            border_label = "",
            size = get_data()
                :map(function(lines)
                    return #lines
                end)
                :tap(function(lines)
                    renderer:set_size({ height = math.max(lines + 3, 3) })
                end),
            data = get_data(),
            hidden = get_data():map(function(lines)
                return #lines == 0
            end),
            on_select = function(node)
                print("selected: " .. node.text)
            end,
            prepare_node = function(node, line)
                line:append(node.text)
                return line
            end,
        })
    )

    renderer:render(body)
end)
mobily commented 5 months ago

Thanks! The following line of code is incorrect:

return vim.fn.ifilter(items, function(item)

Please use the following instead:

local fn = require("nui-components.utils.fn")
-- and then
return fn.ifilter(items, function(item)