Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<CR> not working with autopairs plugin #43

Closed
goingtosleep opened this issue Jan 2, 2023 · 20 comments · Fixed by #45 or #51
Closed

<CR> not working with autopairs plugin #43

goingtosleep opened this issue Jan 2, 2023 · 20 comments · Fixed by #45 or #51

Comments

@goingtosleep
Copy link

goingtosleep commented Jan 2, 2023

When I set create_mapping_hook("i", "<cr>", require("autolist").new), it will kind of override the of autopairs plugins (like auto-pairs) and results in the following error:

Error detected while processing BufEnter Autocommands for "*"..function autopairs#AutoPai
rsTryInit[14]..autopairs#AutoPairsInit[17]..autopairs#Keybinds#mapKeys:                  
line   27:                                                                               
E716: Key not present in Dictionary: "rhs"                                               
line   28:                                                                               
E121: Undefined variable: old_cr                                                         
E116: Invalid arguments for function autopairs#Keybinds#ExpandMap                        
line   29:                                                                               
E121: Undefined variable: old_cr                                                         
E116: Invalid arguments for function substitute                                          
line   52:                                                                               
E121: Undefined variable: old_cr                                                         
Press ENTER or type command to continue

It was still working fine with commit 761e0f9, but that commit has the annoying space in the beginning of the new line.

My setup:

  • nvim: 0.8.1
  • package manager: lazy.nvim
  • autopairs plugin: tested both nvim-autopairs and auto-pairs. With nvim-autopairs, the autopairs feature when doesn't work without showing any error.

Reproduce

Run nvim -u repro.lua tmp.md. The file repro.lua is given below.

repro.lua

local root = vim.fn.fnamemodify("./.repro", ":p")

-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "cache" }) do
  vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end

-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    "git",
    "clone",
    "--filter=blob:none",
    "--single-branch",
    "https://github.com/folke/lazy.nvim.git",
    lazypath,
  })
end
vim.opt.runtimepath:prepend(lazypath)


-- install plugins
local plugins = {
  "folke/tokyonight.nvim",
  "LunarWatcher/auto-pairs",
  {
    "gaoDean/autolist.nvim",
    config = function()
      local autolist = require("autolist")
      autolist.setup()

      local function create_mapping_hook(mode, mapping, hook, alias)
        vim.keymap.set(
        mode,
        mapping,
        function(motion)
          local keys = hook(motion, alias or mapping)
          if not keys then keys = '' end
          return keys
        end,
        { expr = true }
        )
      end

      create_mapping_hook("i", "<CR>", autolist.new)
      create_mapping_hook("n", "o", autolist.new)
    end,
  },
}


require("lazy").setup(plugins, {
  root = root .. "/plugins",
})

-- add anything else here
vim.opt.termguicolors = true
-- do not remove the colorscheme!
vim.cmd([[colorscheme tokyonight]])
@gaoDean
Copy link
Owner

gaoDean commented Jan 2, 2023

Yeah good pickup, I’ll have to install an auto pairs plugin tmr to see what the issue is.

@mawkler
Copy link

mawkler commented Jan 2, 2023

I noticed a similar issue with autopairs. I didn't get an error but I noticed that autopairs overrides autolist's o mapping. I solved this by adding buffer = true to vim.keymap.set() inside create_mapping_hook() to make the mapping buffer-only, like so:

local function create_mapping_hook(mode, mapping, hook, alias)
  vim.keymap.set(
    mode,
    mapping,
    function(motion)
      local keys = hook(motion, alias or mapping)
      if not keys then keys = '' end
      return keys
    end,
    { expr = true, buffer = true }
  )
end

Perhaps this should be changed in the README since this is the desired behaviour.

@goingtosleep
Copy link
Author

goingtosleep commented Jan 2, 2023

@mawkler : I tried adding buffer = true, the error does go away, however the feature of auto-pairs doesn't work. See this gif:

Peek.2023-01-02.20-28.mp4

The expected behavior is like this:

Peek 2023-01-02 20-18

I'm not sure if this is possible as mkdnflow.nvim explicitly mentioned that one has to disable mapping of autopairs. But it worked at commit 761e0f9, so hopefully @gaoDean can do something 😊

@gaoDean
Copy link
Owner

gaoDean commented Jan 3, 2023

@goingtosleep I tried using windwp's autopairs but with your example, it does the expected behavior even with and without the autopairs plugin. I tried disabling treesitter and autolist, but the expected behavior still arises. Is there any more complex autopairs-specific behavior that I can try?

@gaoDean
Copy link
Owner

gaoDean commented Jan 3, 2023

Okay I tried ((<cr>)) with windwp/nvim-autopairs and the result was

((

))

whereas without autopairs, the result was

((

)

Even if I turned on autolist, nothing changed

@gaoDean
Copy link
Owner

gaoDean commented Jan 3, 2023

Here's my config with lazy.nvim and default lazy.nvim settings:

  {
    "windwp/nvim-autopairs",
    config = true,
    enabled = true,
  },
  {
    "gaoDean/autolist.nvim",
    dev = true,
    enabled = true, -- doesn't matter if this is false
    ft = {
      "markdown",
      "txt",
    },
    config = function()
      require("autolist").setup()
      function create_mapping_hook(mode, mapping, hook, alias)
        vim.keymap.set(
          mode,
          mapping,
          function(motion)
            local keys = hook(motion, alias or mapping)
            if not keys then keys = "" end
            return keys
          end,
          { expr = true}
        )
      end

      create_mapping_hook("i", "<cr>", require("autolist").new)
      create_mapping_hook("i", "<tab>", require("autolist").indent)
      create_mapping_hook("i", "<s-tab>", require("autolist").indent, "<c-d>")
      create_mapping_hook("n", "dd", require("autolist").force_recalculate)
      create_mapping_hook("n", "o", require("autolist").new)
      create_mapping_hook("n", "O", require("autolist").new_before)
      create_mapping_hook("n", ">>", require("autolist").indent)
      create_mapping_hook("n", "<<", require("autolist").indent)
      create_mapping_hook("n", "<c-r>", require("autolist").force_recalculate)
      create_mapping_hook("n", "<leader>x", require("autolist").invert_entry, "")
    end,
  }

@gaoDean
Copy link
Owner

gaoDean commented Jan 3, 2023

oh I see, I wasn't using the repro.lua.

@gaoDean
Copy link
Owner

gaoDean commented Jan 3, 2023

I noticed a similar issue with autopairs. I didn't get an error but I noticed that autopairs overrides autolist's o mapping. I solved this by adding buffer = true to vim.keymap.set() inside create_mapping_hook() to make the mapping buffer-only, like so:

@mawkler For me, o worked with buffer = false too

@gaoDean
Copy link
Owner

gaoDean commented Jan 3, 2023

@mawkler @goingtosleep Okay so temporary fix, just set autolist's priority to be very high

@gaoDean
Copy link
Owner

gaoDean commented Jan 3, 2023

Alright, more permanent fix, add branch = "dev3", to autolist in the lazy plugins (ik, such a descriptive branch name)

@gaoDean gaoDean reopened this Jan 3, 2023
@gaoDean
Copy link
Owner

gaoDean commented Jan 3, 2023

whoops didnt mean to close it, but try it out now

@goingtosleep
Copy link
Author

Just tried with the latest commit @gaoDean, but it seems the issue is still there 🥲.

Sometimes autopairs works and autolist doesn't:
https://user-images.githubusercontent.com/47395035/210298513-64ebaa4e-f0ac-4ccd-b8ca-a880e5c9830c.mp4

Sometimes the reversed:
https://user-images.githubusercontent.com/47395035/210298522-ae3ff50f-8fb9-439e-a46b-e833f19f920b.mp4

I tried using the repro.lua with windwp/nvim-autopairs. Is the behavior the same on your side? Do you enable defaults = { lazy = true } in lazy.nvim and specified an order for the plugins?

@gaoDean
Copy link
Owner

gaoDean commented Jan 3, 2023

@goingtosleep ohh, I see the problem. They are probably competing for the "" mapping, and when autolist wins, it still presses "<cr>", but with noremap (because of recursion). Then when autopairs wins, the opposite happens. (at least i think that is what is happening)

@gaoDean
Copy link
Owner

gaoDean commented Jan 3, 2023

even with this:

			vim.keymap.set("n", "<cr>", function()
				print("test1")
				return "<cr>"
			end, { expr = true, remap = true })
			vim.keymap.set("n", "<cr>", function()
				print("test2")
				return "<cr>"
			end, { expr = true, remap = true })

only the second one runs, so I can't really see a way to do this.

@gaoDean
Copy link
Owner

gaoDean commented Jan 3, 2023

The only way I can see is to get the function that is mapped to "" (nvim_buf_get_keymap) in create_mapping_hook, and then call that function, and then do the autolist funtcion.

@gaoDean
Copy link
Owner

gaoDean commented Jan 3, 2023

@goingtosleep ok im really close with this now but my dad says i gotta go to bed lmao

(this is all in the config function

map.lhs is the mapping (like <CR>)
map.rhs is either a "v:lua." string or a function depending on if it was made with nvim_buf_set_keymap or vim.keymap.set respectively

you must make sure that autopairs is loaded first

nvim-autopairs is annoying cus it uses nvim_buf_set... so theres no callback function, theres only a "v:lua" string

you can see it nearly working if you replace the ending return hook... with return ""

      local autolist = require("autolist")
      autolist.setup()

      local function mapping_hook(mode, mapping, hook, alias)
				-- if the requested mapping is occupied, add current function to it

				local additional_map = nil
				local maps = vim.api.nvim_get_keymap(mode)
				for _, map in ipairs(maps) do
					if map.lhs == mapping then
						if map.rhs then
							additional_map = map.rhs:gsub("^v:lua%.", "", 1)
						else
							additional_map = map.callback
						end
						pcall(vim.keymap.del, mode, mapping)
					end
				end
        vim.keymap.set(
					mode,
					mapping,
					function(motion)
						if additional_map then
							if type(additional_map) == "string" then
								local ok, res = pcall(load("return " .. additional_map))
								if ok then
									vim.fn.feedkeys(res, "nt")
								end
							else
								vim.fn.feedkeys(additional_map(), "nt")
							end
						end
						return hook(motion, alias or mapping) or ""
					end,
					{ expr = true, remap = true }
        )
      end

      mapping_hook("i", "<CR>", require("autolist").new)

@gaoDean
Copy link
Owner

gaoDean commented Jan 4, 2023

@goingtosleep try this

local plugins = {
  "folke/tokyonight.nvim",
  {
    "gaoDean/autolist.nvim",
		ft = {
			"markdown",
			"text"
		},
    config = function()
      local autolist = require("autolist")
      autolist.setup()

      local function mapping_hook(mode, mapping, hook, alias)
				local additional_function = nil
				local maps = vim.api.nvim_get_keymap(mode)
				for _, map in ipairs(maps) do
					if map.lhs == mapping then
						if map.rhs then
							additional_function = map.rhs:gsub("^v:lua%.", "", 1)
						else
							additional_function = map.callback
						end
						pcall(vim.keymap.del, mode, mapping)
					end
				end
        vim.keymap.set(
					mode,
					mapping,
					function(motion)
						local additional_map = nil
						if additional_function then
							if type(additional_function) == "string" then
								local ok, res = pcall(load("return " .. additional_function))
								if ok then
									additional_map = res or ""
								end
							else
								additional_map = additional_function() or ""
							end
						end
						return hook(motion, additional_map or mapping) or ""
					end,
					{ expr = true, buffer = true }
        )
      end

      mapping_hook("i", "<CR>", autolist.new)
      mapping_hook("n", "o", require("autolist").new)
    end,
		dependencies = {
			{
				"windwp/nvim-autopairs",
				config = true,
				event = "VeryLazy"
			},
		},
  },
}

@gaoDean
Copy link
Owner

gaoDean commented Jan 4, 2023

i might add this to autolist so the user wont have to copy in a massive function

@gaoDean
Copy link
Owner

gaoDean commented Jan 4, 2023

okay 2nd revision because for the above one, autopairs wont work for filetypes that are not markdown and text

local plugins = {
	"folke/tokyonight.nvim",
	{
		"windwp/nvim-autopairs",
		config = true,
		priority = 2,
	},
	{
		"gaoDean/autolist.nvim",
		priority = 1, -- load after autopairs
		branch = "dev2",
		ft = {
			"markdown",
			"text"
		},
		config = function()
			local autolist = require("autolist")
			autolist.setup()
			autolist.create_mapping_hook("i", "<CR>", autolist.new)
			autolist.create_mapping_hook("n", "o", autolist.new)
		end,
	},
}

@goingtosleep
Copy link
Author

Nice @gaoDean, the dev2 branch worked for me. Thanks for the great effort 😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants