gaoDean / autolist.nvim

Automatic list continuation and formatting for neovim, powered by lua
MIT License
248 stars 6 forks source link

Move config to separate file #66

Open benbrastmckie opened 1 year ago

benbrastmckie commented 1 year ago

I would like for my plugins.lua file to be as simple, including such lines as:

  use { "gaoDean/autolist.nvim" }

I would then like to have my configuration in a separate config file named autolist.lua which goes something like:

local status_ok, autolist = pcall(require, "autolist")
if not status_ok then
  return
end

autolist.setup({
  ft = {
    "markdown",
    "text",
    "tex",
    "plaintex",
  },
  config = function()
    autolist.create_mapping_hook("i", "<CR>", autolist.new)
    autolist.create_mapping_hook("i", "<Tab>", autolist.indent)
    autolist.create_mapping_hook("i", "<S-Tab>", autolist.indent, "<C-D>")
    autolist.create_mapping_hook("n", "o", autolist.new)
    autolist.create_mapping_hook("n", "O", autolist.new_before)
    autolist.create_mapping_hook("n", ">>", autolist.indent)
    autolist.create_mapping_hook("n", "<<", autolist.indent)
    autolist.create_mapping_hook("n", "<leader>r", autolist.force_recalculate)
    autolist.create_mapping_hook("n", "<leader>x", autolist.invert_entry, "")
      vim.api.nvim_create_autocmd("TextChanged", {
        pattern = "-",
        callback = function()
          vim.cmd.normal({autolist.force_recalculate(nil, nil), bang = false})
        end
      })
  end,
})

However, I'm having trouble getting any functionality out of autolist when I divide things up in this way. Any pointers would be much appreciated.

gaoDean commented 1 year ago

that is not how you use the config. If you have a pulgin manager like lazy.nvim, you can specify the ft and config fields. plugging them straight into the setup function wont work. I suggest looking into a plugin manager like packer.nvim or lazy.nvim

benbrastmckie commented 1 year ago

I'm using packer, and it goes like this:


-- Packer 
return packer.startup(function(use)

  use({
    "gaoDean/autolist.nvim",
    ft = {
      "markdown",
      "text",
      "tex",
      "plaintex",
    },
    config = function()
      local autolist = require("autolist")
      autolist.setup()
      autolist.create_mapping_hook("i", "<CR>", autolist.new)
      autolist.create_mapping_hook("i", "<Tab>", autolist.indent)
      autolist.create_mapping_hook("i", "<S-Tab>", autolist.indent, "<C-D>")
      autolist.create_mapping_hook("n", "o", autolist.new)
      autolist.create_mapping_hook("n", "O", autolist.new_before)
      -- autolist.create_mapping_hook("n", ">>", autolist.indent)
      -- autolist.create_mapping_hook("n", "<<", autolist.indent)
      autolist.create_mapping_hook("n", "<leader>r", autolist.force_recalculate)
      autolist.create_mapping_hook("n", "<leader>x", autolist.invert_entry, "")
        vim.api.nvim_create_autocmd("TextChanged", {
          pattern = "-",
          callback = function()
            vim.cmd.normal({autolist.force_recalculate(nil, nil), bang = false})
          end
        })
    end,
  })

end)

What I would like is to move the ft and config fields to a separate autolist.lua config file which I require in init.lua. Is this possible? It's how all of my other plugins are managed and would like to stay consistent to avoid a long plugins.lua file.

The plugin does work great with the ft and config fields included in the plugins.lua file as above, but was hoping to maintain uniformity in the way that my config is organised.

gaoDean commented 1 year ago

plugins.lua

-- Packer 
return packer.startup(function(use)
  use(require("plugin-autolist.lua"))
end)

plugin-autolist.lua // you can use whatever name

return {
    "gaoDean/autolist.nvim",
    ft = {
      "markdown",
      "text",
      "tex",
      "plaintex",
    },
    config = function()
      local autolist = require("autolist")
      autolist.setup()
      autolist.create_mapping_hook("i", "<CR>", autolist.new)
      autolist.create_mapping_hook("i", "<Tab>", autolist.indent)
      autolist.create_mapping_hook("i", "<S-Tab>", autolist.indent, "<C-D>")
      autolist.create_mapping_hook("n", "o", autolist.new)
      autolist.create_mapping_hook("n", "O", autolist.new_before)
      -- autolist.create_mapping_hook("n", ">>", autolist.indent)
      -- autolist.create_mapping_hook("n", "<<", autolist.indent)
      autolist.create_mapping_hook("n", "<leader>r", autolist.force_recalculate)
      autolist.create_mapping_hook("n", "<leader>x", autolist.invert_entry, "")
        vim.api.nvim_create_autocmd("TextChanged", {
          pattern = "-",
          callback = function()
            vim.cmd.normal({autolist.force_recalculate(nil, nil), bang = false})
          end
        })
    end,
  }
gaoDean commented 1 year ago

or even plugins.lua (im not sure if this works but it moves config and ft to seperate file

return packer.startup(function(use)
  use({"gaoDean/autolist.nvim", table.unpack(require("plugin-autolist.lua"))})
end)

and plugins-autolist.lua

return {
    ft = {
      "markdown",
      "text",
      "tex",
      "plaintex",
    },
    config = function()
      local autolist = require("autolist")
      autolist.setup()
      autolist.create_mapping_hook("i", "<CR>", autolist.new)
      autolist.create_mapping_hook("i", "<Tab>", autolist.indent)
      autolist.create_mapping_hook("i", "<S-Tab>", autolist.indent, "<C-D>")
      autolist.create_mapping_hook("n", "o", autolist.new)
      autolist.create_mapping_hook("n", "O", autolist.new_before)
      -- autolist.create_mapping_hook("n", ">>", autolist.indent)
      -- autolist.create_mapping_hook("n", "<<", autolist.indent)
      autolist.create_mapping_hook("n", "<leader>r", autolist.force_recalculate)
      autolist.create_mapping_hook("n", "<leader>x", autolist.invert_entry, "")
        vim.api.nvim_create_autocmd("TextChanged", {
          pattern = "-",
          callback = function()
            vim.cmd.normal({autolist.force_recalculate(nil, nil), bang = false})
          end
        })
    end,
  }
benbrastmckie commented 1 year ago

I tried both versions of what you suggested above, but they don't preserve the plugin's functionality. Although there are no errors with the first suggestion, the second suggestion did produce errors since it seems unable to find the file I want my config to go in, even appropriately renamed. I'm also wondering if it is redundant to require the autolist.lua config file here instead of in my init.lua file as with all of the other plugin config files I have. I'm curious to know why I can't seem to move the ft and config fields to a config file I require in init.lua.

Thanks again for the help!

darg2012 commented 1 year ago

Hi,

I was looking to achieve the same separate file config setup using Packer as well and came across vim's autocmd. After looking into nvim's implementation, I later found that Packer itself (in packer_compiled.lua) also uses autocmd (& augroup) to lazy load the autolist when using the ft = {"markdown ", ...} option on the Packer configuration.

TL:DR here's the setup on packer

-- within return require('packer').startup(function(use)
    use {
        "gaoDean/autolist.nvim",
        ft = {
            "markdown",
            "text",
            "tex",
            "plaintex",
            "norg",
        }
    }

On your autolist.lua (I have mine on after/plugin/)

local ft = {
        "markdown",
        "text",
        "tex",
        "plaintex",
        "norg",
    }

function AutolistLoad()
    -- use default config from README
    -- modify to taste
    -- even include the keymaps as suggested under Installation
end

-- here's the secret sauce
local autolist_group = vim.api.nvim_create_augroup("autolist", {})
vim.api.nvim_create_autocmd("FileType", {
    pattern = ft,
    group = autolist_group,
    callback = AutolistLoad
    }
)

Hopefully you find it useful.

benbrastmckie commented 1 year ago

Hey thanks so much for this! I gave it a try, but I must be making some mistake. I'm far from confident with Lua. Here is what I have in my autolist.lua file, though I'm not sure that it is all necessary:

local ft = {
        "markdown",
        "text",
        "tex",
        "plaintex",
        "norg",
    }

function AutolistLoad()
  -- use default config from README
  -- modify to taste
  -- even include the keymaps as suggested under Installation
  config = function()
    require("autolist").setup()
    -- vim.keymap.set("i", "<tab>", "<cmd>AutolistTab<cr>")
    -- vim.keymap.set("i", "<s-tab>", "<cmd>AutolistShiftTab<cr>")
    vim.keymap.set("i", "<CR>", "<CR><cmd>AutolistNewBullet<cr>")
    vim.keymap.set("n", "o", "o<cmd>AutolistNewBullet<cr>")
    vim.keymap.set("n", "O", "O<cmd>AutolistNewBulletBefore<cr>")
    -- functions to recalculate list on edit
    vim.keymap.set("i", "<tab>", "<Esc>>lla<cmd>AutolistRecalculate<cr>")
    vim.keymap.set("i", "<s-tab>", "<Esc><<cmd>AutolistRecalculate<cr>a")
    vim.keymap.set("n", "dd", "dd<cmd>AutolistRecalculate<cr>")
    vim.keymap.set("v", "d", "d<cmd>AutolistRecalculate<cr>")
  end
end

-- here's the secret sauce
local autolist_group = vim.api.nvim_create_augroup("autolist", {})
vim.api.nvim_create_autocmd("FileType", {
    pattern = ft,
    group = autolist_group,
    callback = AutolistLoad
    }
)

local list_patterns = {
    neorg_1 = "%-",
    neorg_2 = "%-%-",
    neorg_3 = "%-%-%-",
    neorg_4 = "%-%-%-%-",
    neorg_5 = "%-%-%-%-%-",
    unordered = "[-+*]", -- - + *
    digit = "%d+[.)]", -- 1. 2. 3.
    ascii = "%a[.)]", -- a) b) c)
    roman = "%u*[.)]", -- I. II. III.
    latex_item = "\\item",
}

local default_config = {
  enabled = false,
  colon = { -- if a line ends in a colon
    indent = false, -- if in list and line ends in `:` then create list
    indent_raw = false, -- above, but doesn't need to be in a list to work
    preferred = "-", -- what the new list starts with (can be `1.` etc)
  },
  cycle = { -- Cycles the list type in order
      "-",   -- whatever you put here will match the first item in your list
      "*",   -- for example if your list started with a `-` it would go to `*`
      "1.",  -- this says that if your list starts with a `*` it would go to `1.`
      "1)",  -- this all leverages the power of recalculate.
      "a)",  -- i spent many hours on that function
      "I.",  -- try it, change the first bullet in a list to `a)`, and press recalculate
  },
  lists = { -- configures list behaviours
    -- Each key in lists represents a filetype.
    -- The value is a table of all the list patterns that the filetype implements.
    -- See how to define your custom list below in the readme.
    -- You must put the file name for the filetype, not the file extension
    -- To get the "file name", it is just =:set filetype?= or =:se ft?=.
    markdown = {
      list_patterns.unordered,
      list_patterns.digit,
      list_patterns.ascii, -- for example this specifies activate the ascii list
      list_patterns.roman, -- type for markdown files.
    },
    text = {
      list_patterns.unordered,
      list_patterns.digit,
      list_patterns.ascii,
      list_patterns.roman,
    },
    norg = {
        list_patterns.neorg_1,
        list_patterns.neorg_2,
        list_patterns.neorg_3,
        list_patterns.neorg_4,
        list_patterns.neorg_5,
    },
    tex = { list_patterns.latex_item },
    plaintex = { list_patterns.latex_item },
  },
  checkbox = {
    left = "%[", -- the left checkbox delimiter (you could change to "%(" for brackets)
    right = "%]", -- the right checkbox delim (same customisation as above)
    fill = "x", -- if you do the above two customisations, your checkbox could be (x) instead of [x]
  },

  -- this is all based on lua patterns, see "Defining custom lists" for a nice article to learn them
}

function handle_checkbox()
  local config = require("autolist.config")
  local auto = require("autolist.auto")

  local checkbox_pattern = " [ ]"

  local filetype_lists = config.lists[vim.bo.filetype]
  local line = vim.fn.getline(".")

  for i, list_pattern in ipairs(filetype_lists) do
    local list_item = line:match("^%s*" .. list_pattern .. "%s*")  -- only bullet, no checkbox
    list_item = list_item:gsub("%s+", "")
    local is_list_item = list_item ~= nil -- only bullet, no checkbox
    local is_checkbox_item = line:match("^%s*" .. list_pattern .. "%s*" .. "%[.%]" .. "%s*") ~= nil -- bullet and checkbox  

    if is_list_item == true and is_checkbox_item == false then
      vim.fn.setline(".", (line:gsub(list_item, list_item .. checkbox_pattern, 1)))
      local cursor_pos = vim.api.nvim_win_get_cursor(0)
      vim.api.nvim_win_set_cursor(0, {cursor_pos[1], cursor_pos[2] + checkbox_pattern:len()})
      goto continue
    else
      auto.toggle_checkbox()
      goto continue
    end

  end
  ::continue::
end

Does this look correct? If you think putting it in after/plugin/ would make the difference I can give that a try. Thanks again for your help!

darg2012 commented 1 year ago

Sorry for the confusion, I'm also getting into lua b/c of nvim. I modified the configuration but its seems to be easier if you use the default config.

From what I can see, inside the AutolisLoad() function, you need to extract what is within the config variable, since that is a parameter from the package managers. In your case, my guess is that this simpler setup would work:

function AutolistLoad()
    require("autolist").setup()
    -- vim.keymap.set("i", "<tab>", "<cmd>AutolistTab<cr>")
    -- vim.keymap.set("i", "<s-tab>", "<cmd>AutolistShiftTab<cr>")
    vim.keymap.set("i", "<CR>", "<CR><cmd>AutolistNewBullet<cr>")
    vim.keymap.set("n", "o", "o<cmd>AutolistNewBullet<cr>")
    vim.keymap.set("n", "O", "O<cmd>AutolistNewBulletBefore<cr>")
    -- functions to recalculate list on edit
    vim.keymap.set("i", "<tab>", "<Esc>>lla<cmd>AutolistRecalculate<cr>")
    vim.keymap.set("i", "<s-tab>", "<Esc><<cmd>AutolistRecalculate<cr>a")
    vim.keymap.set("n", "dd", "dd<cmd>AutolistRecalculate<cr>")
    vim.keymap.set("v", "d", "d<cmd>AutolistRecalculate<cr>")
end

You could even try removing everything below the augroup/autocmd part, except your handle_checkbox() function. If you want a modified config, you could try adding them require("autolist").setup({--HERE--}), as shown here.