Index ¦ Archives

Neovim

Neovim is a refactor, and sometimes redactor, in the tradition of Vim (which itself derives from Stevie). It is not a rewrite but a continuation and extension of Vim. Many clones and derivatives exist, some very cleverβ€”but none are Vim. Neovim is built for users who want the good parts of Vim, and more.

Goals

  • Enable new contributors, remove barriers to entry.
  • Unblock plugin authors.
  • Develop first-class Lua/LuaJIT scripting alternative to VimL.
  • Target all platforms supported by libuv.
  • Leverage ongoing Vim development.
  • Optimize out of the box, for new users but especially regular users.
  • Deliver consistent cross-platform experience.
  • In matters of taste/ambiguity, favor tradition/compatibility...
  • ...but prefer usability if the benefits are extreme.

Non-goals

  • Turn Vim into an IDE
  • Limit third-party applications (such as IDEs!) built with Neovim
  • Deprecate VimL
  • POSIX vi-compatibility

Install

sudo apt install neovim

Lazzy

mkdir -p ~/.config/nvim/lua/
touch ~/.config/nvim/init.lua
touch ~/.config/nvim/lua/init.lua
touch ~/.config/nvim/lua/settings.lua
touch ~/.config/nvim/lua/keymaps.lua
touch ~/.config/nvim/lua/plugins.lua
touch ~/.config/nvim/lua/configs.lua

nvim ~/.config/nvim/init.lua

local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
  vim.fn.system({
    "git",
    "clone",
    "--filter=blob:none",
    "https://github.com/folke/lazy.nvim.git",
    "--branch=stable", -- latest stable release
    lazypath,
  })
end
vim.opt.rtp:prepend(lazypath)

require("init")

nvim ~/.config/nvim/lua/init.lua

-- Lazy
require("lazy").setup("plugins")

-- Settings, keymaps and plugins configs
require("settings")
require("keymaps")
require("configs")

nvim ~/.config/nvim/lua/settings.lua

vim.cmd[[ syntax on ]]
vim.cmd[[ filetype plugin on ]]
vim.cmd[[ set encoding=UTF-8 ]]
vim.cmd[[ set textwidth=101 ]]
vim.cmd[[ set tabstop=4 ]]
vim.cmd[[ set shiftwidth=4 smarttab ]]
vim.cmd[[ set softtabstop=0 ]]
vim.cmd[[ set smartindent ]]
vim.cmd[[ set expandtab ]]
vim.cmd[[ set smarttab ]]
vim.cmd[[ set laststatus=4 ]]
vim.cmd[[ set ignorecase ]]
vim.cmd[[ set t_Co=256 ]]
vim.cmd[[ set noshowmode ]]
vim.cmd[[ set hlsearch ]]
vim.cmd[[ set hidden ]]
vim.cmd[[ set nobuflisted ]]
vim.cmd[[ set nu! ]]
vim.cmd[[ set termguicolors ]]

nvim ~/.config/nvim/lua/keymaps.lua

vim.cmd[[nmap <M-n> :bn<CR>]]
vim.cmd[[nmap <M-p> :bp<CR>]]
vim.cmd[[nmap <M-d> :bd<CR>]]
vim.cmd[[nmap <M-l> :Lazy<CR>]]
vim.cmd[[nmap <M-e> :NvimTreeToggle<CR>]]
vim.cmd[[nmap <M-g> :Neogit<CR>]]
vim.cmd[[nmap <M-t> :Telescope<CR>]]

nvim ~/.config/nvim/lua/plugins.lua

return {
    -- Style
    {
        'navarasu/onedark.nvim',
        'nvim-lualine/lualine.nvim',
        'norcalli/nvim-colorizer.lua',
        'windwp/nvim-autopairs',
        'lukas-reineke/indent-blankline.nvim'
    },
    -- Tree
    {
        'nvim-tree/nvim-tree.lua',
        'nvim-tree/nvim-web-devicons',
        'akinsho/bufferline.nvim',
    },
    -- Git
    {
        { 'NeogitOrg/neogit', tag = 'v0.0.1' },
        'nvim-lua/plenary.nvim',
        'sindrets/diffview.nvim',
        'ibhagwan/fzf-lua',
        'APZelos/blamer.nvim'
    },
    -- Telescope
    {
        { 'nvim-telescope/telescope.nvim', tag = '0.1.6' },
        'BurntSushi/ripgrep',
        'nvim-telescope/telescope-fzf-native.nvim',
        'sharkdp/fd',
        'nvim-treesitter/nvim-treesitter'
    },
    -- LPS
    {
        'neovim/nvim-lspconfig',
        'hrsh7th/nvim-cmp',
        'hrsh7th/cmp-nvim-lsp',
        'hrsh7th/cmp-buffer',
        'hrsh7th/cmp-path',
        'hrsh7th/cmp-cmdline',
        'saadparwaiz1/cmp_luasnip',
        'L3MON4D3/LuaSnip',
        'rafamadriz/friendly-snippets',
        'ray-x/lsp_signature.nvim',
        'onsails/lspkind-nvim'
    }
}

nvim ~/.config/nvim/lua/configs.lua

-- Style
require('onedark').setup{
    style = 'darker',
    transparent = true
}
require('onedark').load()
require('lualine').setup()
require'colorizer'.setup()
require'nvim-autopairs'.setup()
require("ibl").setup()
vim.g.loaded_netrw = 1
vim.g.loaded_netrwPlugin = 1
vim.opt.termguicolors = true

-- Tree
require("nvim-tree").setup()
local function my_on_attach(bufnr)
  local api = require "nvim-tree.api"

  local function opts(desc)
    return {
        desc = "nvim-tree: " .. desc, buffer = bufnr, noremap = true, silent = true, nowait = true
    }
  end

  api.config.mappings.default_on_attach(bufnr)

  vim.keymap.set('n', '<C-t>', api.tree.change_root_to_parent,        opts('Up'))
  vim.keymap.set('n', '?',     api.tree.toggle_help,                  opts('Help'))
end
require("nvim-tree").setup({
  sort_by = "case_sensitive",
  view = {
    width = 30,
  },
  renderer = {
    group_empty = true,
  },
  filters = {
    dotfiles = false,
  },
  update_focused_file = {
  enable = true,
  },
  on_attach = my_on_attach,
})
require('bufferline').setup()

-- Git
require('neogit').setup()
local async = require "plenary.async"
require('fzf-lua').setup()
require('diffview').setup()
vim.g.blamer_enabled = true

-- Telescope
require('telescope').setup()
local has_any_words_before = function()
    if vim.api.nvim_buf_get_option(0, "buftype") == "prompt" then
        return false
    end
    local line, col = unpack(vim.api.nvim_win_get_cursor(0))
    return col ~= 0 and vim.api.nvim_buf_get_lines(
        0, line - 1, line, true
    )[1]:sub(col, col):match("%s") == nil
end

-- LSP
require'lspconfig'.clangd.setup{}
require "lsp_signature".setup()
vim.o.completeopt = 'menuone,noselect'

local cmp = require'cmp'
local luasnip = require("luasnip")

local lspkind = require('lspkind')
local source_mapping = {
    buffer = "β—‰ Buffer",
    nvim_lsp = "πŸ‘ LSP",
    nvim_lua = "πŸŒ™ Lua",
    cmp_tabnine = "πŸ’‘ Tabnine",
    path = "🚧 Path",
    luasnip = "🌜 LuaSnip"
}
cmp.setup({
    sources = {
        { name = 'nvim_lsp' },
        { name = 'luasnip' },
        { name = 'buffer' },
        { name = 'path' },
        { name = 'nvim_lua' },
    },

    formatting = {
        format = function(entry, vim_item)
        vim_item.kind = lspkind.presets.default[vim_item.kind]
        local menu = source_mapping[entry.source.name]
        if entry.source.name == 'cmp_tabnine' then
            if entry.completion_item.data ~= nil and entry.completion_item.data.detail ~= nil then
                menu = entry.completion_item.data.detail .. ' ' .. menu
            end
            vim_item.kind = ''
        end
        vim_item.menu = menu
        return vim_item
        end
    },

    snippet = {
        expand = function(args)
            require('luasnip').lsp_expand(args.body)
        end,
    },
    mapping = {
        ['<C-n>'] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }),
        ['<C-p>'] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }),
        ['<Down>'] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Select }),
        ['<Up>'] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Select }),
        ['<C-d>'] = cmp.mapping.scroll_docs(-4),
        ['<C-f>'] = cmp.mapping.scroll_docs(4),
        ['<C-Space>'] = cmp.mapping.complete(),
        ['<C-e>'] = cmp.mapping.close(),
        ['<CR>'] = cmp.mapping.confirm({
            behavior = cmp.ConfirmBehavior.Replace,
            select = true,
        }),

        ['<Tab>'] = function(fallback)
            if cmp.visible() then
                cmp.select_next_item()
            elseif luasnip.expand_or_jumpable() then
                vim.fn.feedkeys(
                    vim.api.nvim_replace_termcodes('<Plug>luasnip-expand-or-jump',
                    true,
                    true,
                    true
                ), '')
            else
                fallback()
            end
        end,
        ['<S-Tab>'] = function(fallback)
        if cmp.visible() then
            cmp.select_prev_item()
        elseif luasnip.jumpable(-1) then
            vim.fn.feedkeys(vim.api.nvim_replace_termcodes(
                '<Plug>luasnip-jump-prev',
                true,
                true,
                true),
            '')
        else
            fallback()
        end
    end,},
})
require("luasnip/loaders/from_vscode").load()

Shortcuts

General
:q        close
:w        write/saves
:wa[!]    write/save all windows [force]
:wq       write/save and close
:x        save and quit, same as wq
:q!       force close if file has changed and not save changes
v        Enter visual mode for selection of LINES
C-v      Enter visual mode for selection of BLOCKS
y        Yank/copy selected region
yy       Yank/copy entire line
"<reg>y  Yank/copy marked region into register <reg> (register from a-z)
c        Cut selection
p        Paste yanked content
"<reg>p  Paste yanked content in register <reg> (from a-z)
P        Paste yanked content BEFORE
u        Undo
C-r      Redo
:!<cmd>  Execute shell command <cmd>
C-z      send vim to background (fg brings it to front again)
C-ws     Split current window horizontally (alternative :split)
C-wv     Split current window vertically (alternative :vsplit)
C-ww     Jump to the next window
C-wo     Only one window (close all)
C-wARROW Jump to window left/right/top/bottom (arrow keys) to the current
C-w#<    Shrink/resize current window from the right by # (default 1)
C-w#>    Increase/resize current window to the right by # (default 1)
a        Append text after the cursor
A        Append text at the end of the line
i        Insert text before the cursor
I        Insert text before the first non-blank in the line
o        Begin a new line BELOW the cursor and insert text
O        Begin a new line ABOVE the cursor and insert text
s        Erase the current letter under the cursor, set insert-mode
S        Erase the whole line, set insert-mode
cc       Delete the current line, set insert-mode
cw       Delete word, set insert-mode
dd       Delete line under curser
q[a-z]   Start recording, everything will be recorded including movement actions.
@[a-z]   Execute the recorded actions.
nnoremap <silent> <leader>s :set spell!<cr>
<leader>s Toggle Spelling
]s       Next spelling mistake
[s       Previous spelling mistake
z=       Give Suggestions (prepent 1, use first suggestions automatically)
zg       Add misspelled to spellfile
zug      Remove word from spellfile
Navigation
h        cursor left
j        cursor down
l        cursor right
k        cursor up
H        Jump to TOP of screen
M        Jump to MIDDLE of screen
L        Jump to BOTTOM of screen
C-b      Move back one full screen (page up)
C-f      Move forward one full screen (page down)
C-d      Move forward 1/2 screen; half page down
C-u      Move back (up) 1/2 screen; half page up
w        jump by start of words (punctuation considered words)
e        jump to end of words (punctuation considered words)
b        jump backward by words (punctuation considered words)
0 (zero) start of line
^        first non-blank character of line
$        end of line
G        bottom of file
gg       top of file
E        jump to end of words (no punctuation)
W        jump by words (spaces separate words)
B        jump backward by words (no punctuation)
#G       goto line #
#gg      goto line #
Search
*        search for word under cursor (forward) and highlight occurrence (see incsearch, hlsearch below)
%        jump from open/close ( / #if / ( / { to corresponding ) / #endif / }
[{       jump to start of current code block
]}       jump to end of current code block
gd       jump to var declaration (see incsearch, hlsearch below)
f<c>     Find char <c> from current cursor position -- forwards
F<c>     Find char <c> from current cursor position -- backwards
,        Repeat previous f<c> or F<c> in opposite direction
;        Repeat previous f<c> or F<c> in same direction
'.       jump back to last edited line.
g;       jump back to last edited position.
[m       jump to start of funtion body
[i       show first declartion/use of the word under cursor
[I       show all occurrences of word under cursor in current file
[/       cursor to N previous start of a C comment
:vimgrep /<regex>/g %        Search for <regex> with multiple occasions per line (g)
                             in current file (%)
:vimgrep /<C-r>// %          On the command line, <C-r>/ (that is: CTRL-R followed by /)
                             will insert the last search pattern.
:vimgrep /<a>/g <filelist>   Search in the given files (<filelist>)
:vimgrep /<a>/g *.cc         Search in all *.cc files current directory
:vimgrep /<a>/g **/*.cc      Search in all *.cc files in every sub-directory (recursively)
:vimgrep /<a>/g `find . -type f`
                             Search in all files that are returns by the backtick command.

:vim     short for :vimgrep

:cnext   Jump to next record/match in quickfix list
:cprev   Jump to previous record/match in quickfix list
[q       see :cprev
]q       see :cnext
[Q       see :cfirst
]Q       see :clast
Marks
ma       set mark a at current cursor location
'a       jump to line of mark a (first non-blank character in line)
`a       jump to position (line and column) of mark a
d'a      delete from current line to line of mark a
d`a      delete from current cursor position to position of mark a
c'a      change text from current line to line of mark a
y`a      yank text to unnamed buffer from cursor to position of mark a
:marks   list all the current marks
:marks aB list marks a, B
Editing
x        Delete char UNDER cursor
X        Delete char BEFORE cursor
#x       Delete the next # chars. starting from char under cursor
dw       Delete next word
dW       Delete UP TO the next word
d^       Delete up unto the beginning of the line
d$       Delete until end of the line
D        See d$, delete until end of the line
dd       Delete whole line
dib      Delete contents in parenthesis '(' ')' block (e.g. function args)
diB      Delete inner '{' '}' block
daB      Delete a '{' '}' block
das      Delete a senctence
diw      Delete word under cursor
df<c>    Delete until next occurence of <c> (char) found (including <c>) [in single line]
dt<c>    Delete until next occurence of <c> (char) found (without <c>!!!) [in single line]

ciw      Change word under cursor
ciB      Change inner '{' '}' block
cf<c>    See "df<c>" but change instead of delete
ct<c>    See "dt<c>" but change instead of delete

#J       Merge # number of lines together
Misc
gq       (in visual-mode) format selected text according to line-width
gqq      format current line according to line-width
#gqq     format next #-lines
C-n      Keyword completion
Tab      Keyword completion (SuperTab plugin)
r<c>     Replace char <c>
#r<c>    Replace follow # chars with <c>, : csock, cursor on s, 3re ceeek
:s/xxx/yyy/    Replace xxx with yyy at the first occurrence
:s/xxx/yyy/g   Replace xxx with yyy first occurrence, global (whole sentence)
:s/xxx/yyy/gc  Replace xxx with yyy global with confirm
:%s/xxx/yyy/g  Replace xxx with yyy global in the whole file
u        Convert selection (visual mode) to lowercase
U        Convert selection (visual mode) to uppercase
:g/^#/d  Delete all lines that begins with #
:g/^$/d  Delete all lines that are empty
gg=G    Reident all

Neovim

© 2000-2022 by Daniel Pimentel (d4n1). Under MIT.