Contenuti




NeoVim: guida completa dal principiante all'esperto

Setup, configurazione e workflow per sviluppatori


NeoVim: guida completa dal principiante all’esperto

NeoVim è una rivisitazione moderna dell’iconico editor Vim, progettato per il XXI secolo. Con un’architettura più pulita, supporto nativo per LSP (Language Server Protocol), configurazione in Lua e una community dinamica, NeoVim è diventato l’editor di scelta per molti sviluppatori professionali.

In questo articolo
  • Performance superiori: Architettura asincrona e ottimizzazioni moderne
  • LSP integrato: Supporto nativo per IntelliSense, diagnostica e refactoring
  • Configurazione Lua: Più veloce e potente di VimScript
  • Ecosistema ricco: Plugin manager moderni e community attiva
  • Integrazione terminale: Terminale integrato e migliore supporto GUI
  • Compatibilità retroattiva: 99% compatibile con Vim esistente

Indice della Guida

  1. Installazione e setup
  2. Modalita e navigazione
  3. Configurazione base
  4. Plugin e plugin manager
  5. Alternativa IDE completa: NvChad
  6. LSP e Tree-sitter
  7. Editing avanzato
  8. Workflow e produttivita
  9. Customizzazione avanzata
  10. Risoluzione problemi
  11. Conclusioni e prossimi passi

Installazione e setup

Installazione su Diversi Sistemi

Ubuntu/Debian

1
2
3
4
5
6
7
8
# Scegli uno dei metodi sotto
# Aggiungere repository unstable per ultima versione
sudo add-apt-repository ppa:neovim-ppa/unstable
sudo apt update
sudo apt install neovim

# Oppure via snap
sudo snap install nvim --classic

CentOS/RHEL/Fedora

1
2
3
4
5
6
# Fedora
sudo dnf install neovim

# CentOS/RHEL (EPEL richiesto)
sudo yum install epel-release
sudo yum install neovim

macOS

1
2
3
4
5
# Homebrew (consigliato)
brew install neovim

# MacPorts
sudo port install neovim

Windows

1
2
3
4
5
6
7
# Chocolatey
choco install neovim

# Scoop
scoop install neovim

# Oppure download diretto da GitHub releases

Compilazione da Sorgenti

1
2
3
4
5
6
7
8
9
# Dipendenze Ubuntu
sudo apt-get install ninja-build gettext libtool libtool-bin autoconf automake cmake g++ pkg-config unzip curl doxygen

# Clone e build
git clone https://github.com/neovim/neovim.git
cd neovim
git checkout stable
make CMAKE_BUILD_TYPE=RelWithDebInfo
sudo make install

Prima Configurazione

Creare Struttura Config

1
2
3
4
5
6
# Linux/macOS
mkdir -p ~/.config/nvim
cd ~/.config/nvim
touch init.lua  # oppure init.vim per VimScript
mkdir -p lua/config
mkdir -p plugin
1
2
3
4
5
6
# Windows (PowerShell)
New-Item -ItemType Directory -Force -Path "$env:LOCALAPPDATA\\nvim"
Set-Location "$env:LOCALAPPDATA\\nvim"
New-Item -ItemType File -Force -Path "init.lua"
New-Item -ItemType Directory -Force -Path "lua\\config"
New-Item -ItemType Directory -Force -Path "plugin"

File init.lua Base

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
-- ~/.config/nvim/init.lua
-- NeoVim Configuration

-- Leader key impostazione (deve essere prima di tutto)
vim.g.mapleader = " "
vim.g.maplocalleader = " "

-- Opzioni base
vim.opt.number = true           -- Mostra numeri di riga
vim.opt.relativenumber = true   -- Numeri relativi
vim.opt.mouse = 'a'             -- Supporto mouse
vim.opt.ignorecase = true       -- Ricerca case-insensitive
vim.opt.smartcase = true        -- Ma smart quando maiuscole
vim.opt.hlsearch = false        -- Non evidenziare ricerche
vim.opt.wrap = false            -- No word wrap
vim.opt.breakindent = true      -- Mantieni indentazione su wrap
vim.opt.tabstop = 4             -- Tab = 4 spazi
vim.opt.shiftwidth = 4          -- Indentazione = 4 spazi
vim.opt.expandtab = true        -- Usa spazi invece di tab
vim.opt.splitright = true       -- Split verticali a destra
vim.opt.splitbelow = true       -- Split orizzontali sotto
vim.opt.scrolloff = 8           -- Mantieni 8 righe dal bordo
vim.opt.sidescrolloff = 8       -- Mantieni 8 colonne dal bordo

-- Backup e swap
vim.opt.backup = false
vim.opt.writebackup = false
vim.opt.undofile = true
vim.opt.swapfile = false

-- Colorscheme
vim.opt.termguicolors = true
vim.cmd('colorscheme habamax')  -- Colorscheme di default

-- Keymaps di base
local keymap = vim.keymap.set

-- Escape con jk
keymap("i", "jk", "<ESC>", { desc = "Exit insert mode with jk" })

-- Clear search highlights
keymap("n", "<leader>nh", ":nohl<CR>", { desc = "Clear search highlights" })

-- Window management
keymap("n", "<leader>sv", "<C-w>v", { desc = "Split window vertically" })
keymap("n", "<leader>sh", "<C-w>s", { desc = "Split window horizontally" })
keymap("n", "<leader>se", "<C-w>=", { desc = "Make splits equal size" })
keymap("n", "<leader>sx", "<cmd>close<CR>", { desc = "Close current split" })

-- Tab management
keymap("n", "<leader>to", "<cmd>tabnew<CR>", { desc = "Open new tab" })
keymap("n", "<leader>tx", "<cmd>tabclose<CR>", { desc = "Close current tab" })
keymap("n", "<leader>tn", "<cmd>tabn<CR>", { desc = "Go to next tab" })
keymap("n", "<leader>tp", "<cmd>tabp<CR>", { desc = "Go to previous tab" })

-- Better movement
keymap("n", "J", "mzJ`z", { desc = "Join line below" })
keymap("n", "<C-d>", "<C-d>zz", { desc = "Scroll down and center" })
keymap("n", "<C-u>", "<C-u>zz", { desc = "Scroll up and center" })
keymap("n", "n", "nzzzv", { desc = "Next search result centered" })
keymap("n", "N", "Nzzzv", { desc = "Previous search result centered" })

print("NeoVim configuration loaded successfully!")

Modalita e navigazione

Le Modalità di NeoVim

NeoVim opera in diverse modalità, ognuna ottimizzata per specifiche operazioni:

1. Normal Mode (Modalità Normale)

La modalità predefinita per navigazione e comandi.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
Navigazione base:
h ← sinistra    j ↓ giù    k ↑ su    l → destra

		  ↑
            k
       ← h     l →
           j
           ↓

Movimenti rapidi:
w  - Prossima parola
b  - Parola precedente
e  - Fine parola
0  - Inizio riga
^  - Primo carattere non-spazio
$  - Fine riga
gg - Inizio file
G  - Fine file

2. Insert Mode (Modalità Inserimento)

Per inserire e modificare testo.

1
2
3
4
5
6
7
Entrare in Insert Mode:
i  - Inserisci prima del cursore
I  - Inserisci all'inizio della riga
a  - Inserisci dopo il cursore
A  - Inserisci alla fine della riga
o  - Nuova riga sotto
O  - Nuova riga sopra

3. Visual Mode (Modalità Visuale)

Per selezionare testo.

1
2
3
4
Tipi di Visual Mode:
v  - Visual carattere per carattere
V  - Visual riga per riga
<C-v> - Visual block (colonna)

4. Command Mode (Modalità Comando)

Per comandi ed operazioni sui file.

1
2
3
4
5
6
7
Comandi essenziali:
:w     - Salva file
:q     - Esci
:wq    - Salva ed esci
:q!    - Esci senza salvare
:e filename - Apri file
:bn/:bp - Buffer next/previous

Movimenti Precisi

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
-- Configurazione per movimenti avanzati in init.lua

-- Jump list navigation
keymap("n", "<C-o>", "<C-o>", { desc = "Jump back in jump list" })
keymap("n", "<C-i>", "<C-i>", { desc = "Jump forward in jump list" })

-- Line numbers jump
keymap("n", "<leader>g", ":lua vim.ui.input({prompt='Go to line: '}, function(input) if input then vim.cmd(input) end end)<CR>", { desc = "Go to line number" })

-- Paragraph navigation
keymap("n", "{", "{", { desc = "Previous paragraph" })
keymap("n", "}", "}", { desc = "Next paragraph" })

-- Function/method navigation (with TreeSitter)
keymap("n", "[[", "[[", { desc = "Previous function" })
keymap("n", "]]", "]]", { desc = "Next function" })

Marks e Jumps

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Marks (Segnalibri):
ma    - Imposta mark 'a'
'a    - Vai al mark 'a'
''    - Torna alla posizione precedente
'.    - Ultima modifica
'^    - Ultima posizione insert mode

Jump list:
<C-o> - Vai indietro nella jump list
<C-i> - Vai avanti nella jump list

Configurazione base

Opzioni Essenziali

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
-- lua/config/options.lua
local opt = vim.opt

-- Appearance
opt.number = true
opt.relativenumber = true
opt.signcolumn = "yes"
opt.cursorline = true
opt.colorcolumn = "80"
opt.showmode = false
opt.cmdheight = 1
opt.pumheight = 10

-- Search
opt.ignorecase = true
opt.smartcase = true
opt.hlsearch = false
opt.incsearch = true

-- Indentation
opt.tabstop = 4
opt.softtabstop = 4
opt.shiftwidth = 4
opt.expandtab = true
opt.smartindent = true
opt.autoindent = true

-- Line wrapping
opt.wrap = false
opt.breakindent = true
opt.linebreak = true

-- Folding
opt.foldmethod = "expr"
-- Richiede nvim-treesitter configurato
opt.foldexpr = "nvim_treesitter#foldexpr()"
opt.foldenable = false
opt.foldlevel = 99

-- Splitting
opt.splitright = true
opt.splitbelow = true

-- Performance
opt.updatetime = 250
opt.timeoutlen = 500
opt.redrawtime = 10000
opt.maxmempattern = 20000

-- File handling
opt.backup = false
opt.writebackup = false
opt.undofile = true
opt.swapfile = false
opt.autoread = true
opt.hidden = true

-- Completion
opt.completeopt = { "menu", "menuone", "noselect" }
opt.shortmess:append("c")

-- Clipboard
opt.clipboard:append("unnamedplus")

-- Mouse
opt.mouse = "a"
opt.mousefocus = true

-- Scrolling
opt.scrolloff = 8
opt.sidescrolloff = 8

Keymaps Avanzate

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
-- lua/config/keymaps.lua
local keymap = vim.keymap.set
local opts = { noremap = true, silent = true }

-- Leader key
vim.g.mapleader = " "
vim.g.maplocalleader = " "

-- General keymaps
keymap("i", "jk", "<ESC>", opts)
keymap("n", "<leader>nh", ":nohl<CR>", { desc = "Clear search highlights" })
keymap("n", "<leader>+", "<C-a>", { desc = "Increment number" })
keymap("n", "<leader>-", "<C-x>", { desc = "Decrement number" })

-- Window management
keymap("n", "<leader>sv", "<C-w>v", { desc = "Split window vertically" })
keymap("n", "<leader>sh", "<C-w>s", { desc = "Split window horizontally" })
keymap("n", "<leader>se", "<C-w>=", { desc = "Make splits equal size" })
keymap("n", "<leader>sx", ":close<CR>", { desc = "Close current split" })

-- Navigate between splits
keymap("n", "<C-h>", "<C-w>h", { desc = "Navigate to left split" })
keymap("n", "<C-j>", "<C-w>j", { desc = "Navigate to bottom split" })
keymap("n", "<C-k>", "<C-w>k", { desc = "Navigate to top split" })
keymap("n", "<C-l>", "<C-w>l", { desc = "Navigate to right split" })

-- Resize splits
keymap("n", "<C-Up>", ":resize -2<CR>", opts)
keymap("n", "<C-Down>", ":resize +2<CR>", opts)
keymap("n", "<C-Left>", ":vertical resize -2<CR>", opts)
keymap("n", "<C-Right>", ":vertical resize +2<CR>", opts)

-- Tab management
keymap("n", "<leader>to", ":tabnew<CR>", { desc = "Open new tab" })
keymap("n", "<leader>tx", ":tabclose<CR>", { desc = "Close current tab" })
keymap("n", "<leader>tn", ":tabn<CR>", { desc = "Go to next tab" })
keymap("n", "<leader>tp", ":tabp<CR>", { desc = "Go to previous tab" })
keymap("n", "<leader>tf", ":tabnew %<CR>", { desc = "Open current buffer in new tab" })

-- Buffer management
keymap("n", "<leader>bn", ":bnext<CR>", { desc = "Next buffer" })
keymap("n", "<leader>bp", ":bprevious<CR>", { desc = "Previous buffer" })
keymap("n", "<leader>bd", ":bdelete<CR>", { desc = "Delete buffer" })

-- Better paste
keymap("v", "p", '"_dP', opts)

-- Move text up and down
keymap("v", "J", ":m '>+1<CR>gv=gv", opts)
keymap("v", "K", ":m '<-2<CR>gv=gv", opts)

-- Indent/outdent in visual mode
keymap("v", "<", "<gv", opts)
keymap("v", ">", ">gv", opts)

-- Better terminal navigation
keymap("t", "<C-h>", "<C-\\><C-N><C-w>h", opts)
keymap("t", "<C-j>", "<C-\\><C-N><C-w>j", opts)
keymap("t", "<C-k>", "<C-\\><C-N><C-w>k", opts)
keymap("t", "<C-l>", "<C-\\><C-N><C-w>l", opts)

-- File operations
keymap("n", "<leader>w", ":w<CR>", { desc = "Save file" })
keymap("n", "<leader>q", ":q<CR>", { desc = "Quit" })
keymap("n", "<leader>Q", ":qa!<CR>", { desc = "Force quit all" })

-- Quick fix list
keymap("n", "<leader>qo", ":copen<CR>", { desc = "Open quickfix list" })
keymap("n", "<leader>qf", ":cfirst<CR>", { desc = "First quickfix" })
keymap("n", "<leader>qn", ":cnext<CR>", { desc = "Next quickfix" })
keymap("n", "<leader>qp", ":cprev<CR>", { desc = "Previous quickfix" })
keymap("n", "<leader>ql", ":clast<CR>", { desc = "Last quickfix" })
keymap("n", "<leader>qc", ":cclose<CR>", { desc = "Close quickfix" })

Plugin e plugin manager

Plugin Manager: lazy.nvim

Perché lazy.nvim?
  • Lazy loading: Plugin caricati solo quando necessari
  • Performance: Startup time ottimizzato
  • Lock file: Versioni consistenti dei plugin
  • UI moderna: Interfaccia user-friendly per gestione plugin
  • Dependency management: Gestione automatica dipendenze

Installazione lazy.nvim

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-- ~/.config/nvim/init.lua
-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not 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)

-- Load plugins
require("lazy").setup({
  -- Plugin specs go here
}, {
  -- Configuration options
  change_detection = {
    notify = false,
  },
})

Plugin Essenziali Setup

Struttura Plugin Directory

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
~/.config/nvim/
├── init.lua
├── lua/
│   ├── config/
│   │   ├── options.lua
│   │   ├── keymaps.lua
│   │   └── autocmds.lua
│   └── plugins/
│       ├── colorscheme.lua
│       ├── treesitter.lua
│       ├── lsp.lua
│       ├── completion.lua
│       ├── telescope.lua
│       └── ui.lua

Plugin consigliati

  • lazy.nvim: plugin manager moderno e veloce. Repo GitHub
  • nvim-lspconfig: configurazione LSP per i linguaggi principali. Repo GitHub
  • nvim-treesitter: parsing e highlighting avanzato. Repo GitHub
  • nvim-cmp: completamento intelligente con sorgenti multiple. Repo GitHub
  • telescope.nvim: ricerca file, simboli e live grep. Repo GitHub
  • gitsigns.nvim: indicatori Git inline e hunk actions. Repo GitHub
  • lualine.nvim: statusline leggera e configurabile. Repo GitHub

Alternativa IDE completa: NvChad

Se preferisci una configurazione pronta all’uso, NvChad offre un’esperienza tipo IDE completa, con LSP, UI moderna e workflow ottimizzati. Si installa con un solo comando e puoi personalizzarla gradualmente.

Installazione su Linux e macOS

1
2
3
4
5
6
7
8
9
# Backup della config attuale (opzionale)
mv ~/.config/nvim ~/.config/nvim.bak 2>/dev/null
mv ~/.local/share/nvim ~/.local/share/nvim.bak 2>/dev/null

# Installazione NvChad
git clone https://github.com/NvChad/NvChad ~/.config/nvim --depth 1

# Avvio
nvim

Installazione su Windows

1
2
3
4
5
6
7
8
9
# Backup della config attuale (opzionale)
Rename-Item "$env:LOCALAPPDATA\\nvim" "nvim.bak" -ErrorAction SilentlyContinue
Rename-Item "$env:LOCALAPPDATA\\nvim-data" "nvim-data.bak" -ErrorAction SilentlyContinue

# Installazione NvChad
git clone https://github.com/NvChad/NvChad "$env:LOCALAPPDATA\\nvim" --depth 1

# Avvio
nvim

Installazione Nerd Font (consigliato)

NvChad usa icone e simboli: imposta un Nerd Font nel terminale.

1
Esempio consigliato: Hack Nerd Font (non la variante "Mono")

Pre-requisiti Windows

  • NeoVim 0.11 o superiore
  • Nerd Font impostato nel terminale (evita i font con suffisso “Mono” se vuoi icone piu grandi)
  • Ripgrep opzionale per la ricerca in Telescope
  • GCC: installa MinGW e aggiungilo al PATH
  • Make: installa GnuWin32 e aggiungilo al PATH
  • Rimozione vecchie cartelle: elimina vecchie cartelle NeoVim prima di installare

Comandi utili (PowerShell):

1
2
3
# Rimuove config e dati precedenti
Remove-Item -Recurse -Force "$env:LOCALAPPDATA\\nvim" -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force "$env:LOCALAPPDATA\\nvim-data" -ErrorAction SilentlyContinue

Link utili:

Installazione rapida con winget:

1
2
winget install --id BurntSushi.ripgrep
winget install --id MSYS2.MSYS2

Installazione rapida con Chocolatey:

1
2
3
choco install ripgrep -y
choco install mingw -y
choco install make -y

LSP e Tree-sitter

LSP con nvim-lspconfig

1
2
3
4
5
6
7
8
9
-- lua/plugins/lsp.lua
return {
  "neovim/nvim-lspconfig",
  config = function()
    local lspconfig = require("lspconfig")
    lspconfig.pyright.setup({})
    lspconfig.tsserver.setup({})
  end,
}

Tree-sitter

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
-- lua/plugins/treesitter.lua
return {
  "nvim-treesitter/nvim-treesitter",
  build = ":TSUpdate",
  config = function()
    require("nvim-treesitter.configs").setup({
      ensure_installed = { "lua", "python", "javascript", "html", "css" },
      highlight = { enable = true },
      indent = { enable = true },
    })
  end,
}

Editing avanzato

Macro e registri

1
2
3
4
q{registro}   - Inizia registrazione macro
q             - Ferma registrazione
@{registro}   - Esegui macro
@@            - Ripeti ultima macro

Ricerca e sostituzione

1
2
:%s/vecchio/nuovo/g       - Sostituzione globale
:%s/vecchio/nuovo/gc      - Con conferma

Workflow e produttivita

Sessioni

1
2
:mksession! ~/.config/nvim/session.vim
:source ~/.config/nvim/session.vim

Buffer e file

1
2
3
:ls        - Lista buffer
:bnext     - Buffer successivo
:bprev     - Buffer precedente

Customizzazione avanzata

Tema e UI

1
2
3
4
vim.opt.termguicolors = true
vim.cmd("colorscheme habamax")
vim.opt.cursorline = true
vim.opt.number = true

Autocmd essenziali

1
2
3
4
5
vim.api.nvim_create_autocmd("TextYankPost", {
  callback = function()
    vim.highlight.on_yank()
  end,
})

Risoluzione problemi

Diagnostica rapida

1
2
:checkhealth
:messages

Plugin lenti all’avvio

  • Disabilita plugin non usati o rendili lazy.
  • Controlla :Lazy profile per individuare i tempi di caricamento.

Conclusioni e prossimi passi

Workflow di Apprendimento Consigliato

  1. Settimana 1-2: Padroneggia le modalità base e navigazione
  2. Settimana 3-4: Installa e configura plugin essenziali
  3. Settimana 5-6: Setup LSP per i tuoi linguaggi principali
  4. Settimana 7-8: Personalizza keymaps e workflow
  5. Settimana 9-10: Esplora plugin avanzati e automazioni
  6. Ongoing: Ottimizza e affina la configurazione

Risorse per Approfondimento

Documentazione Ufficiale

Community e Plugin

Configurazioni di Riferimento