From aa1b35c68b9aef48648f5f621be9817a7d246817 Mon Sep 17 00:00:00 2001
From: juanmagalhaes <contato.juanmagalhaes@gmail.com>
Date: Tue, 15 Aug 2023 01:18:37 -0300
Subject: [PATCH] Modularize complex plugin configs. Add folding plugin

---
 init.lua                              | 12 +++-
 lua/{plugins.lua => plugins/init.lua} | 40 ++----------
 lua/plugins/neo-tree.lua              | 19 ++++++
 lua/plugins/nvim-ufo.lua              | 92 +++++++++++++++++++++++++++
 4 files changed, 129 insertions(+), 34 deletions(-)
 rename lua/{plugins.lua => plugins/init.lua} (85%)
 create mode 100644 lua/plugins/neo-tree.lua
 create mode 100644 lua/plugins/nvim-ufo.lua

diff --git a/init.lua b/init.lua
index 0f4eaafe..8e93b7ce 100644
--- a/init.lua
+++ b/init.lua
@@ -227,8 +227,18 @@ local on_attach = function(_, bufnr)
   -- tsserver organize imports
   nmap('<leader>oi', organize_imports, 'OrganizeImports')
 
+  -- nvim-ufo mappings
+  nmap("zR", require("ufo").openAllFolds, "Open All Folds")
+  nmap("zM", require("ufo").closeAllFolds, "Close All Folds")
+  nmap("zj", function()
+    local winid = require("ufo").peekFoldedLinesUnderCursor()
+    if not winid then
+      vim.lsp.buf.hover()
+    end
+  end, "Peek At Current Fold")
+
   -- Create a command `:Format` local to the LSP buffer
-  vim.api.nvim_buf_create_user_command(bufnr, 'Format', function(_)
+  vim.api.nvim_buf_create_user_command(bufnr, 'Format', function()
     vim.lsp.buf.format()
   end, { desc = 'Format current buffer with LSP' })
 end
diff --git a/lua/plugins.lua b/lua/plugins/init.lua
similarity index 85%
rename from lua/plugins.lua
rename to lua/plugins/init.lua
index 8e1c257e..29579e9d 100644
--- a/lua/plugins.lua
+++ b/lua/plugins/init.lua
@@ -57,18 +57,6 @@ local plugins = {
     opts = {}
   },
 
-  --[[
-  {
-    -- Theme inspired by Atom
-    --
-    'navarasu/onedark.nvim',
-    priority = 1000,
-    config = function()
-      vim.cmd.colorscheme 'onedark'
-    end,
-  },
-  --]]
-
   {
     -- Theme inspired by Atom
     'Mofiqul/dracula.nvim',
@@ -134,33 +122,19 @@ local plugins = {
     build = ':TSUpdate',
   },
 
-  -- Neo Tree
-  {
-    "nvim-neo-tree/neo-tree.nvim",
-    branch = "v3.x",
-    dependencies = {
-      "nvim-lua/plenary.nvim",
-      "nvim-tree/nvim-web-devicons", -- not strictly required, but recommended
-      "MunifTanjim/nui.nvim",
-    },
-    config = function()
-      require('neo-tree').setup {
-        filesystem = {
-          filtered_items = {
-            visible = true,
-            hide_hidden = false
-          }
-        },
-      }
-    end,
-  },
-
   {
     "mg979/vim-visual-multi",
     branch = "master"
   },
 
+  -- require plugins with more complex config
+
+  require 'plugins.neo-tree',
+
+  require 'plugins.nvim-ufo',
+
   require 'kickstart.plugins.autoformat',
+
   -- require 'kickstart.plugins.debug',
 
   -- NOTE: The import below automatically adds your own plugins, configuration, etc from `lua/custom/plugins/*.lua`
diff --git a/lua/plugins/neo-tree.lua b/lua/plugins/neo-tree.lua
new file mode 100644
index 00000000..e4f2df84
--- /dev/null
+++ b/lua/plugins/neo-tree.lua
@@ -0,0 +1,19 @@
+return {
+  "nvim-neo-tree/neo-tree.nvim",
+  branch = "v3.x",
+  dependencies = {
+    "nvim-lua/plenary.nvim",
+    "nvim-tree/nvim-web-devicons", -- not strictly required, but recommended
+    "MunifTanjim/nui.nvim",
+  },
+  config = function()
+    require('neo-tree').setup {
+      filesystem = {
+        filtered_items = {
+          visible = true,
+          hide_hidden = false
+        }
+      },
+    }
+  end,
+}
diff --git a/lua/plugins/nvim-ufo.lua b/lua/plugins/nvim-ufo.lua
new file mode 100644
index 00000000..57ade383
--- /dev/null
+++ b/lua/plugins/nvim-ufo.lua
@@ -0,0 +1,92 @@
+local handler = function(virtText, lnum, endLnum, width, truncate)
+  local newVirtText = {}
+  local suffix = (' 󰁂 %d '):format(endLnum - lnum)
+  local sufWidth = vim.fn.strdisplaywidth(suffix)
+  local targetWidth = width - sufWidth
+  local curWidth = 0
+  for _, chunk in ipairs(virtText) do
+    local chunkText = chunk[1]
+    local chunkWidth = vim.fn.strdisplaywidth(chunkText)
+    if targetWidth > curWidth + chunkWidth then
+      table.insert(newVirtText, chunk)
+    else
+      chunkText = truncate(chunkText, targetWidth - curWidth)
+      local hlGroup = chunk[2]
+      table.insert(newVirtText, { chunkText, hlGroup })
+      chunkWidth = vim.fn.strdisplaywidth(chunkText)
+      -- str width returned from truncate() may less than 2nd argument, need padding
+      if curWidth + chunkWidth < targetWidth then
+        suffix = suffix .. (' '):rep(targetWidth - curWidth - chunkWidth)
+      end
+      break
+    end
+    curWidth = curWidth + chunkWidth
+  end
+  table.insert(newVirtText, { suffix, 'MoreMsg' })
+  return newVirtText
+end
+
+local function applyFoldsAndThenCloseAllFolds(bufnr, providerName)
+  require('async')(function()
+    bufnr = bufnr or vim.api.nvim_get_current_buf()
+    -- make sure buffer is attached
+    require('ufo').attach(bufnr)
+    -- getFolds return Promise if providerName == 'lsp'
+    local ranges = await(require('ufo').getFolds(bufnr, providerName))
+    local ok = require('ufo').applyFolds(bufnr, ranges)
+    if ok then
+      require('ufo').closeFoldsWith(1)
+    end
+  end)
+end
+
+return {
+  "kevinhwang91/nvim-ufo",
+  dependencies = {
+    "kevinhwang91/promise-async",
+    {
+      "luukvbaal/statuscol.nvim",
+      config = function()
+        local builtin = require("statuscol.builtin")
+        require("statuscol").setup({
+          relculright = true,
+          segments = {
+            { text = { builtin.foldfunc },      click = "v:lua.ScFa" },
+            { text = { "%s" },                  click = "v:lua.ScSa" },
+            { text = { builtin.lnumfunc, " " }, click = "v:lua.ScLa" },
+          },
+        })
+      end,
+    },
+  },
+  event = "BufReadPost",
+  opts = {
+    provider_selector = function()
+      return { "treesitter", "indent" }
+    end,
+  },
+  init = function()
+    vim.o.fillchars = [[eob: ,fold: ,foldopen:,foldsep: ,foldclose:]]
+    vim.o.foldcolumn = '1'
+    vim.o.foldnestmax = 1
+    vim.o.foldlevel = 99
+    vim.o.foldlevelstart = 1
+    vim.o.foldenable = true
+  end,
+  config = function(_, opts)
+    local newOpts = {
+      fold_virt_text_handler = handler
+    }
+
+    for k, v in pairs(newOpts) do opts[k] = v end
+
+    require("ufo").setup(newOpts)
+
+    vim.api.nvim_create_autocmd('BufRead', {
+      pattern = '*',
+      callback = function(e)
+        applyFoldsAndThenCloseAllFolds(e.buf, 'lsp')
+      end
+    })
+  end,
+}