Neovim

2798 readers
3 users here now

founded 2 years ago
MODERATORS
1
2
3
4
5
6
 
 

Anybody know what's going on?

7
8
9
10
11
12
 
 

Haven’t seen much exposure to this awesome plugin, even on reddit it seems that it’s not so well known, so i wanted to share it. It’s basically a git-log replacement integrated with neovim(and fugitive) that updates automatically(or manually) whenever you do any changes to your git repository. Really useful to get a overall picture of what’s going on in a repo. Or for debugging git branch problems etc.

13
14
 
 

The upcoming Neovim 0.12 release will have a built-in plugin manager. It is implemented in Lua and is available as a built-in vim.pack module (hence the name).

15
16
 
 

In master branch of nvim-treesitter you had to do something like this to achieve it : https://pawelgrzybek.com/nvim-incremental-selection/

In the main branch (that they switched to) they removed it completely. Now it was added into v0.12 so nvim natively supports this without any additional plugins!

This is so good!

17
 
 

Triforce is a Neovim plugin with beautiful UI that adds a bit of RPG flavor to your coding — XP, levels, and achievements while you work. - gisketch/triforce.nvim

18
19
 
 

Here's a little puzzle for you Vim specialists:

Say I have a random text file containing the following lines:

This is foo1 and bar1: it has bar1 and foo1, or foo1 and bar1 if you prefer.  
foo1 is not exactly like bar1.  
bar1 has the same number of letters as foo1 and the same trailing number.  

I want to search and replace all instances of foo1 and bar1 in all the lines in the file so the number after foo and bar increments at each matched line, so the file becomes:

This is foo1 and bar1: it has bar1 and foo1, or foo1 and bar1 if you prefer.  
foo2 is not exactly like bar2.  
bar3 has the same number of letters as foo3 and the same trailing number.  

I can search all instances of foo1 and bar1 and replace them with foo2 and bar2 easily enough with:

:%s/\(foo\|bar\)1/\12/g

(the file then becomes:

This is foo2 and bar2: it has bar2 and foo2, or foo2 and bar2 if you prefer  
foo2 is not like bar2  
bar2 has the same number of letters as foo2 and the same number  

)

and I can search foo1 and replace it with foo1, foo2, foo3, foo4... line-wise with a vimscript:

:let i=1 | %g/foo1/ s//\='foo' . i/g | let i+=1

(the file then becomes:

This is foo1 and bar1: it has bar1 and foo1, or foo1 and bar1 if you prefer       
foo2 is not like bar1                                                            
bar1 has the same number of letters as foo3 and the same number  

)

The question is, how can I do both?

The problem is the \= substitute operator, that expects (and evaluates) an expression: I need it to expand i in the substitution pattern.

The problem is, it has to be alone in the substitution pattern (i.e. I can't do s//\1\=i/, which would first expand \1 into foo or bar, then expand \=i into the value of i, and which is what I really want to do).

So my question is, what's the syntax to expand \1 in the \= expression? I tried looking up the syntax for \= but the official documentation is thin on details and I couldn't find how to do it - or even if it's doable at all.

Any idea?

20
21
 
 

Part 1 (Intro)

I am in the process of moving away from astronvim https://docs.astronvim.com/ to a more minimal neovim configuration. I needed something more native to replace Harpoon https://github.com/ThePrimeagen/harpoon, which is a sort of plugin-based buffer switcher, bookmarker.

I eventually came across this reddit thread that implemented something like what i was searching with native arglist: https://www.reddit.com/r/neovim/comments/1om84w2/persistent_harpoon_with_arglist/. The problem was, since arglist doesn't persist by itself when you close neovim, he implemented his own state management for it. He also considered marks-based replacement but it had other, bigger problems.

An idea came to my mind: doesn’t Neovim’s built-in session management already save and restore the arglist?

So I went digging, found the help page https://neovim.io/doc/user/usr_21.html#_sessions and apparently it does !

   A Vim session contains all the information about what you are editing.
This includes things such as the file list, window layout, global variables,
options and other information

AstroNvim uses Resession.nvim https://github.com/stevearc/resession.nvim to manage sessions. I used them in my workflow but sparingly...Honestly, if not for the arglist, I probably would have chosen to not use them at all. Anyways, upon further reading I realized just how simple native session management really is and that I wouldn't need any other extra plugins for my use case.

Part 2 (Sessions)

So I came across this blog post: https://aymanbagabas.com/blog/2023/04/13/simple-vim-session-management.html It implements session management in a hands-off manner. Basically: If you open a directory with nvim, it checks if that directory is a project directory (looks for git file). If it is, it loads the session from ./.nvim/session.vim (if it's there), and on closing saves the session to the same place.

This was fine. I tried it, but soon realized I didn't need this amount of complexity. So I opted for a way simpler setup:

-- #Sessions

-- Save current session to .nvim/session.vim
vim.keymap.set("n", "<leader>ss", function()
    vim.cmd("!mkdir -p .nvim")
    vim.cmd("mksession! .nvim/session.vim")
    print("Session saved!")
end, { desc = "Save current session " })

-- Load session from .nvim/session.vim
vim.keymap.set("n", "<leader>sl", function()
    vim.cmd("source .nvim/session.vim")
    print("Session loaded")
end, { desc = "Load session" })


-- Save session on exit
vim.api.nvim_create_autocmd("vimleave", {
    callback = function(data)
        -- only save session if there's a .nvim/session.nvim file
        local sessionfile = ".nvim/session.vim"

        if vim.fn.filereadable(sessionfile) then
            vim.cmd("mksession! " .. sessionfile)
        end
    end,
})

1 keybinding to save session in ./.nvim/session.vim 1 to load it and 1 autocommand: when you exit Neovim, if a session.vim file already exists, it’s overwritten with the current session state.

Really simple setup that explicitly gives me control when to save my session and when not to. It's way better than what I had back in AstroNvim, where it would auto-save for every directory. And now they're stored in the same project directory, which I like.

Part 3(Arglist)

Now that I had sessions I just needed to add some keybindings to interact with the arglist. For that, this blog post explained everything really well and I based a lot of my keybindings off of it:

https://jkrl.me/vim/2025/05/28/nvim-arglist.html

This is what I ended up with :

-- Show the list
vim.keymap.set("n", "<leader>al", "<C-L><Cmd>args<CR>")

-- Navigate forward / backwards / first / last
vim.keymap.set("n", "[a", '<cmd>exe v:count1 .. "N"<bar>args<cr><esc>')
vim.keymap.set("n", "]a", '<cmd>exe v:count1 .. "n"<bar>args<cr><esc>')
vim.keymap.set("n", "[A", "<cmd>first<bar>args<cr><esc>")
vim.keymap.set("n", "]A", "<cmd>last<bar>args<cr><esc>")

-- Jump to arglist entry 1..6 with Alt+number (and show args)
for i = 1, 6 do
    vim.keymap.set("n", ("<M-%d>"):format(i), ("<cmd>argument %d | args<cr><esc>"):format(i), {
        desc = ("Arglist: go to %d"):format(i),
        silent = true,
    })
end

-- Add current buffer to list
vim.keymap.set("n", "<leader>aa", "<cmd>$arge %<bar>argded<bar>args<cr>")

-- Insert current buffer at x position, shift everything to the right
-- Prefix a number before shortcut that will be the x position in which to insert the current buffer
-- If you don't enter any number before the command, insert at position 0
vim.keymap.set("n", "<leader>ai", function()
    local count = vim.v.count
    vim.cmd(count .. "arge %")
    vim.cmd("args")
end)

-- Delete current buffer from list
vim.keymap.set("n", "<leader>ad", "<cmd>argd %<bar>args<cr>")
-- Delete all
vim.keymap.set("n", "<leader>aD", "<cmd>%argd<cr><C-L>")


A lot of it is self-explanatory from the comments. I use alt + number to navigate through my arglist, don't really even need those navigate forward / backward keybindings but whatever.

And I added a simple autocmd from the Reddit post that jumps to your last cursor position when you open a buffer.

-- #go to last loc when opening a buffer
vim.api.nvim_create_autocmd("bufreadpost", {
    desc = "go to last edit location when opening a new buffer",
    group = vim.api.nvim_create_augroup("last_loc", { clear = true }),
    callback = function(event)
        local exclude = { "gitcommit" }
        local buf = event.buf
        if vim.tbl_contains(exclude, vim.bo[buf].filetype) or vim.b[buf].last_loc_flag then
            return
        end
        vim.b[buf].last_loc_flag = true
        local mark = vim.api.nvim_buf_get_mark(buf, '"')
        local lcount = vim.api.nvim_buf_line_count(buf)
        if mark[1] > 0 and mark[1] <= lcount then
            pcall(vim.api.nvim_win_set_cursor, 0, mark)
        end
    end,
})

Really happy with the results. Everything was like 60 lines of code and using native neovim functionality. I replaced a session plugin and harpoon and it works IMO better than what I had previously.

22
 
 

Before coming across this video I did not know of a way to replace things over multiple files without relying on LSP rename functionality. Apparently you can grep -> send to quickfix list -> use :cdo to run a command once per match.

There's also this quicker.nvim plugin (same creator as oil.nvim) that let's you treat your quickfix list as a buffer you then can edit anything in there and afterwards save, similar to oil.nvim giving you a bit of a more streamlined experience.

I'm not sure whether I'll end up using it but the :cdo command will for sure come in handy!

23
 
 

cross-posted from: https://lemmy.world/post/41297887

I really wanted a HTML live reload plugin that has statusline integration and does not depend on entire chromium to create a simple web server. I couldn't find anything I'd like so I've decided to make my own plugin. I was kinda afraid that implementing websockets in lua would be terrible task but it turns out I didn't need to, because SSE exists. HTTP is simple, watching for file changes as well so I got to work. Result: Very small (Less than 500 lines of code) plugin that launches in 0.1-0.2ms! (It's amazing what you can do when you don't need to load whole V8 from Chromium to serve a simple webpage. I also made support functions for statusline of two popular distors: NvChad and AstroNvim but you can also launch it from cmds if you prefer.

Since I'm kinda new to nvim & lua scripting I'd appreciate any feedback on what could be improved or just done better. For now I plan to add more features inspired vscode's live-server extension although it most likely won't be exact copy of that extension.

Link:

GitHub Repository

24
1
Issue with lsp (piefed.blahaj.zone)
submitted 3 months ago* (last edited 3 months ago) by dragonfeathers@piefed.blahaj.zone to c/neovim@programming.dev
 
 

Hi, Wondering if anyone has had/solved this issue.

I've been fighting with nvim-lspconfig and ruby_lsp. I have a lazyvim setup and used mason to install ruby_lsp. The problem is that every time I open a ruby file the lsp client is loaded twice.

I tried modifying my mason.lua according to a video I found like so:

{
  "mason-org/mason-lspconfig.nvim",
  opts = {
    -- Settings to prevent duplicate clients in buffer
    ensure_installed = {},
    automatic_installation = false,
    automatic_setup = false,
    automatic_enable = false,
    handlers = nil,
  },
},

I tried disabling mason-lspconfig entirely and manually installing the ruby gem for the lsp, hoping that the lspconfig would use that. Rubocop (also installed via mason) stopped loading, but the duplicate clients remained. I'm still not sure if this is a problem with mason, nvim-lspconfig, the lsp itself, or lazyvim. My python and lua lsps have been fine. Right now I've given up and switched to using solargraph, but the issue haunts me and I shall not know peace until I manage to fix it.

25
view more: next ›