I’m trying to learn neovim. I’ve started with the kickstart configuration and managed to make fortls work, but the linter plugin (nvim lint) doesn’t come configured for fortran, so it’s not showing warnings and errors like on VSCode. Does anyone have a config example? nvim lint has some instructions on how to config a custom linter but to be honest I don’t really know how to start.
@DCLopes once you figure out how to setup nvim with Fortran, it would be great if you could send a PR against GitHub - fortran-lang/webpage: New Fortran webpage to document this. I also use nvim, but I didn’t have time to figure out how to set all this up.
I’ve set up nvim-lint by using gfortran as the linter, here is my config for it:
local lint = require "lint"
local gfortran_diagnostic_args = { "-Wall", "-Wextra", "-fmax-errors=5" }
lint.linters_by_ft = {
fortran = {
"gfortran",
},
}
local pattern = "^([^:]+):(%d+):(%d+):%s+([^:]+):%s+(.*)$"
local groups = { "file", "lnum", "col", "severity", "message" }
local severity_map = {
["Error"] = vim.diagnostic.severity.ERROR,
["Warning"] = vim.diagnostic.severity.WARN,
}
local defaults = { ["source"] = "gfortran" }
local required_args = { "-fsyntax-only", "-fdiagnostics-plain-output" }
local args = vim.list_extend(required_args, gfortran_diagnostic_args)
lint.linters.gfortran = {
cmd = "gfortran",
stdin = false,
append_fname = true,
stream = "stderr",
env = nil,
args = args,
ignore_exitcode = true,
parser = require("lint.parser").from_pattern(pattern, groups, severity_map, defaults),
}
Hopefully this helps
@ShadowRim awesome, thanks for posting the config and welcome to the forum!
I want to try it out. Which file do I put this in and how do I enable it in neovim? If I need to install some packages, which ones and how do I install them?
@certik this can go in a file in your plugins config folder, I just called mine lint.lua in a config folder.
I use the lazy package manager, so the plugin entry in my init.lua looks like this:
{
"mfussenegger/nvim-lint",
event = { "BufWritePost", "InsertLeave" },
config = function()
require "configs.lint"
end,
}
Then I have an autocommand that triggers the linting
vim.api.nvim_create_autocmd({ "BufEnter", "InsertLeave", "BufWritePost" }, {
callback = function()
local lint_status, lint = pcall(require, "lint")
if lint_status then
lint.try_lint()
end
end,
})
If you have any trouble, share your config structure and I can try to help out
Here is what I tried on Ubuntu 22.04:
- Install lazy-nvim: 🛠️ Installation | lazy.nvim, “Single File Setup”
- It requied newer nvim, so I installed nvim 0.10.0 from Release Nvim v0.10.0 · neovim/neovim · GitHub
- Then it complained about conflicting
init.vim
andinit.lua
in~/config/nvim
, so I renamedinit.vim
for now - Then nvim finally started and I got:
Here is the init.lua
with the modifications that you suggested:
-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
local lazyrepo = "https://github.com/folke/lazy.nvim.git"
local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
if vim.v.shell_error ~= 0 then
vim.api.nvim_echo({
{ "Failed to clone lazy.nvim:\n", "ErrorMsg" },
{ out, "WarningMsg" },
{ "\nPress any key to exit..." },
}, true, {})
vim.fn.getchar()
os.exit(1)
end
end
vim.opt.rtp:prepend(lazypath)
-- Make sure to setup `mapleader` and `maplocalleader` before
-- loading lazy.nvim so that mappings are correct.
-- This is also a good place to setup other settings (vim.opt)
vim.g.mapleader = " "
vim.g.maplocalleader = "\\"
-- Setup lazy.nvim
require("lazy").setup({
spec = {
-- add your plugins here
{
"mfussenegger/nvim-lint",
event = { "BufWritePost", "InsertLeave" },
config = function()
require "configs.lint"
end,
}
},
-- Configure any other settings here. See the documentation for more details.
-- colorscheme that will be used when installing plugins.
install = { colorscheme = { "habamax" } },
-- automatically check for plugin updates
checker = { enabled = true },
})
vim.api.nvim_create_autocmd({ "BufEnter", "InsertLeave", "BufWritePost" }, {
callback = function()
local lint_status, lint = pcall(require, "lint")
if lint_status then
lint.try_lint()
end
end,
})
I also noticed the newer nvim’s syntax highlighting does not work anymore. Before:
After:
I don’t have the time to maintain complicated configurations, and debugging why it doesn’t work by default. I used to have long .vimrc
file, but there was always something that broke, so over time I simplified my config files to bare minimum. Then I switched to neovim, because it had better defaults and could save the file automatically when the terminal lost focus. But unfortunately it looks like their very latest default is a step back.
Finally, the compiler integration must just work. I don’t want to maintain custom setups that easily break like above.
I think the solution is that the editor itself must have first-class support for langauge servers and integrations, and then users just provide adaptors for their (custom) compilers. The furthest along is VSCode, where things almost just work. Somebody should create a similar experience in a terminal. I did think of writing my own vi-style editor for the small vi subset that I use (around 50 commands) where things just work. Maybe after I finish LFortran.
Have you checked :colorscheme vim
to use old vim style colorschemes?
It surely gets frustrating when something that used to work, does not anymore overnight.
But I think that, sometimes things are so that these “breaking” changes are what’s really needed to strive for the better, in a long term view. And I bet you know a lot more on this regard from the development of LFortran.
That seems to have fixed it. Thanks! I put it into my init.vim
. Do you know why they changed it?
No. My guess is that they are trying to make it clear that Neovim is not Vim, although they have quite a lot in common indeed. And at a level where they even recoloured the colorschemes in a new “Neovim style”. If you want “old” Vim style, then you now need to explicitly request so.
But again, it’s just my speculation. There might be other, technical reasons I am not aware of.
I recognize neovim immediately by the command line at the bottom, there is a white block there that is missing in vim.
I didn’t manage to get the linter working yet (I tried a few more times and gave up), but I did manage to get fortls working! I wrote up exact instructions, so that others can also get it working: Exact instructions how to setup fortls with neovim · Issue #426 · fortran-lang/fortls · GitHub.
Here is an example of tab completion:
I am not happy with the overall complexity to set things up. Perhaps there is an easier way, and if I figure it out, I’ll share it.
Sorry for ghosting this thread, I thought I would get a notification but for some reason it just stopped. I’ve done some work, and I’ve come up with a minimal-ish config to get nvim-lint working and fortls.
Looks ugly but customization should be easy to slot in. One thing is that the default lazy bootstrap will load the colorscheme habamax when installing new plugins but not when opening nvim without a new plugin, which I didn’t bother to remove. The config directory structure is based on how lazy.nvim docs suggests doing it, so it loads every plugin in the plugins folder. I’ve set this up on a new Arch install (wsl) and the only thing it requires is python3 and gfortran.
init.lua
require "config.lazy"
vim.api.nvim_create_autocmd({"BufEnter", "InsertLeave", "BufWritePost"}, {
callback = function()
local lint_status, lint = pcall(require, "lint")
if lint_status then
lint.try_lint()
end
end
})
lua/config/lazy.lua
-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
local lazyrepo = "https://github.com/folke/lazy.nvim.git"
local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
if vim.v.shell_error ~= 0 then
vim.api.nvim_echo({
{ "Failed to clone lazy.nvim:\n", "ErrorMsg" },
{ out, "WarningMsg" },
{ "\nPress any key to exit..." },
}, true, {})
vim.fn.getchar()
os.exit(1)
end
end
vim.opt.rtp:prepend(lazypath)
-- Make sure to setup `mapleader` and `maplocalleader` before
-- loading lazy.nvim so that mappings are correct.
-- This is also a good place to setup other settings (vim.opt)
vim.g.mapleader = " "
vim.g.maplocalleader = "\\"
-- Setup lazy.nvim
require("lazy").setup({
spec = {
-- import your plugins
{ import = "plugins" },
},
-- Configure any other settings here. See the documentation for more details.
-- colorscheme that will be used when installing plugins.
install = { colorscheme = { "habamax" } },
-- automatically check for plugin updates
checker = { enabled = true },
})
plugins/lint.lua
return {
"mfussenegger/nvim-lint",
event = { "BufWritePost", "InsertLeave" },
config = function()
local lint = require "lint"
local gfortran_diagnostic_args = { "-Wall", "-Wextra", "-fmax-errors=5" }
lint.linters_by_ft = {
fortran = {
"gfortran",
},
}
local pattern = "^([^:]+):(%d+):(%d+):%s+([^:]+):%s+(.*)$"
local groups = { "file", "lnum", "col", "severity", "message" }
local severity_map = {
["Error"] = vim.diagnostic.severity.ERROR,
["Warning"] = vim.diagnostic.severity.WARN,
}
local defaults = { ["source"] = "gfortran" }
local required_args = { "-fsyntax-only", "-fdiagnostics-plain-output" }
local args = vim.list_extend(required_args, gfortran_diagnostic_args)
lint.linters.gfortran = {
cmd = "gfortran",
stdin = false,
append_fname = true,
stream = "stderr",
env = nil,
args = args,
ignore_exitcode = true,
parser = require("lint.parser").from_pattern(pattern, groups, severity_map, defaults),
}
end,
}
plugins/lsp.lua
return {
{
"williamboman/mason.nvim",
config = function()
require("mason").setup{}
end,
},
{
"williamboman/mason-lspconfig.nvim",
config = function()
require("mason-lspconfig").setup({
ensure_installed = { "fortls" }
})
end,
},
{
"neovim/nvim-lspconfig",
config = function()
local lspconfig = require("lspconfig")
lspconfig.fortls.setup({})
end,
}
}