September 24, 2024
Minimalist Configuration for NeoVim and Flutter

I recently started using NeoVim as my main IDE for all my projects, including Flutter.
A terminal : WezTerm
Since I use Flutter primarily to develop mobile applications, I have no choice but to work on macOS, as it is required to build iOS applications.
I chose to use the WezTerm terminal, which offers several important features for me:
- Open source: Having access to the source code of such a sensitive application as a terminal is essential so that everyone can ensure its security.
- No server: For the same security reasons, the terminal must not send data to a remote server (often for AI-related features).
- Configurable with the Lua language: The configuration method is quite similar to NeoVim.
- Cross-platform: in case I want to use it on Linux or Windows, I can use the same environment and configuration.
A distribution : LazyVim
As for the default configuration of NeoVim, I decided to use a well-known distribution: LazyVim!
This distribution includes a set of plugins, shortcuts, and themes. It also contains a specific plugin called LazyExtra, which makes it easier to install and configure languages or plugins.
However, there's a small issue... Dart is not included among the supported languages by default, meaning no support for Flutter.
Avoiding flutter-tools.nvim
There is a dedicated plugin for Flutter called flutter-tools.nvim.
But after trying it out for some time, I decided to stop using it. In fact, a lot of compatibility errors occurred due to dependency updates or conflicts with my LazyVim configuration. After trying to tweak these tools, I eventually came to the conclusion that I didn't need everything included: a simple connection to the Dart Language Server Protocol should be enough for me.
Setup the Language Server Protocol
So, I searched for minimalist configurations and was inspired by Robert's configuration (thanks to him!) to adapt it to the LazyVim setup. Instead of using lsp-config directly like he did, I reused the default LSP plugin configuration format from LazyVim and added the dartls server with the corresponding options!
Here is my working addition to the dotfiles/.config/nvim/lua/plugins/plugins.lua
file.
return {
-- ...
{
"neovim/nvim-lspconfig",
event = "LazyFile",
dependencies = {
"mason.nvim",
{ "williamboman/mason-lspconfig.nvim", config = function() end },
},
opts = function()
local ret = {
diagnostics = {},
inlay_hints = {
enabled = true,
},
codelens = {
enabled = true,
},
document_highlight = {
enabled = true,
},
capabilities = {
workspace = {
fileOperations = {
didRename = true,
willRename = true,
},
},
},
format = {
formatting_options = nil,
timeout_ms = nil,
},
servers = {
dartls = {
mason = false,
cmd = {
"dart",
"language-server",
"--protocol=lsp",
},
filetypes = { "dart" },
init_options = {
onlyAnalyzeProjectsWithOpenFiles = false,
suggestFromUnimportedLibraries = true,
closingLabels = true,
outline = false,
flutterOutline = false,
},
settings = {
dart = {
analysisExcludedFolders = {
vim.fn.expand("$HOME/AppData/Local/Pub/Cache"),
vim.fn.expand("$HOME/.pub-cache"),
vim.fn.expand("/opt/homebrew/"),
vim.fn.expand("$HOME/tools/flutter/"),
},
updateImportsOnRename = true,
completeFunctionCalls = true,
showTodos = true,
},
},
},
-- ...
},
setup = {},
}
return ret
end,
},
}
```lua
-- Flutter commands
vim.api.nvim_create_user_command("FlutterRun", function(opts)
-- Open a new wezterm pane on the right
local command = "wezterm cli split-pane --right --percent 30 --cwd '"
.. opts.args
.. "' -- bash -c 'flutter run; exec bash'"
-- Run the command to create the new pane and capture the pane ID
local handle = io.popen(command)
if handle ~= nil then
local result = handle:read("*a")
handle:close()
-- Assuming the pane ID is printed after the pane is created
-- Here you would normally extract the pane ID from the command output if necessary.
-- In case you need to get pane details use `wezterm cli list --format json`.
wezterm_pane_id = result:match("%d+") -- Extract pane ID
end
end, { nargs = 1 })
vim.api.nvim_create_user_command("FlutterInput", function(input)
if wezterm_pane_id then
-- Send input to the stored pane ID
local send_command = "wezterm cli send-text --pane-id " .. wezterm_pane_id .. " '" .. input.args .. "'"
os.execute(send_command)
else
print("Error: No WezTerm pane created yet. Run :FlutterRun first.")
end
end, { nargs = 1 })
With this, you can add actions to trigger a Hot Reload, a Hot Restart, or any other supported action with a simple shortcut!
-- Keymaps
vim.keymap.set("n", "<leader>off", function()
vim.ui.input({ prompt = "In which directory?", default = vim.fn.getcwd() }, function(input)
if input then
vim.cmd("FlutterRun " .. input)
end
end)
end, {
desc = "Start the app.",
noremap = true,
silent = true,
})
vim.api.nvim_set_keymap("n", "<leader>ofr", ":FlutterInput r<CR>", {
desc = "Hot reload. 🔥🔥🔥",
noremap = true,
silent = true,
})
By the way, my full NeoVim configuration is available on GitHub.