Solved Neovim as an IDE/IDE alternatives for C, C++, C#, Python programming languages

Yesterday, and today from 6 a.m. I am trying to set up Neovim as an IDE for programming.
I tried out lazy vim as my plugin manager of choice.
It works well, and I could install some plugins, but after starting to try to add LSPs, DAPs, Linter, and Formatter, mason tells me that the downloaded binaries are not supported.
I think it has something to do with mason downloading linux binaries for LSP, DAP, Linter, and Formatter.

Now, since mason is actually a popular choice, but seems not to work right on FreeBSD, are there any alternatives ?
If not, are there eventually another plugins for neovim which replace mason, and work on FreeBSD ?

Another question is:
Are there any alternatives for an UI IDE on FreeBSD which are similar to nvim, and eventually support vim like keybindings ?
 
Are there any alternatives for an UI IDE on FreeBSD which are similar to nvim, and eventually support vim like keybindings ?
Some options:
In some ways, I do recommend going with either vim or nvim but try to cut down on *some* of the plugins. I.e rather than things like NERDtree, instead get proficient in the inbuilt :ls, :b, :e and tab complete (I think NETRW is also built in these days if you like that). I find you lose some of the snappiness when the editor is loaded with plugins and starts to feel like it has ADHD. Plus the benefit of jumping on almost any server gets undone if you need to start lugging around the plugin baggage with you.

What I have been using for a long time is the classic (n)vi as part of FreeBSD base alongside tmux (with some scripts to glue them together). I find the lack of extensibility to be refreshing and simple.

Obviously if you do want language servers then yes, you will need some fairly substantial plugins.
 
Long time vim user. Question, why not use the built-in package manager?
:he packages
I use ALE (and clang) so I don't do a lot of setup myself so, I was just curious.

sidenote: all of my stuff is written in VimL so if I'm using either vim or nvim my setup doesn't change much. I too, like as few dependencies as possible and if I can, I will use (n)vi if I can (I won't install (neo)vim in a jail if I don't need it; I'll just write a .nexrc file with my settings).
 
Obviously if you do want language servers then yes, you will need some fairly substantial plugins.
And here the problem begins.
I do not know whether I need LSPs for Python, C, C++, C#.
I do not want to have a plugin baggage, and always strive to keep as less plugins as possible to ensure nvim staying fast and snappy.

As for my ideal use case, I want to have:
-> color highlighting for the programming languages mentioned (a nvim-treesitter alternative which is not so heavy)
-> something like neo-tree if a nvim alternative does not exist (I work on projects with many directories and files, and I want to switch without leaving nvim)
-> compiling/interpreting through a keystroke (can be achieved through nvim directly, though)
 
Last edited:
Long time vim user. Question, why not use the built-in package manager?
:he packages
I use ALE (and clang) so I don't do a lot of setup myself so, I was just curious.

sidenote: all of my stuff is written in VimL so if I'm using either vim or nvim my setup doesn't change much. I too, like as few dependencies as possible and if I can, I will use (n)vi if I can (I won't install (neo)vim in a jail if I don't need it; I'll just write a .nexrc file with my settings).
I did not know about nvis existence, but it looks interesting. Neovim is well regarded for development by some people, maybe it is just a hype, though. I will look into nvi.

I did not know that (n)vi has a built in package manager, although learning vim some time ago.
 
No, sorry. There may be some confusion. VI is old. Vim was "VI improved" (added stuff like visual selection, syntax highlighting, etc.). NeoVim is sort of a fork of Vim offering better "this and that".

Vi doesnt have a package manger. VIM does, and so does NEOVIM. VI is very basic but good for a lot of what you need sometimes (like in a jail).
EDIT: "when kpederson and I said: "(n)vi" we are basically saying "VI".

What languages are you programming in?
 
Okay. Perfect. I'm doing C.

Sorry, I don't have a lot of time at the moment so I will have to go fast with this:

I have this in my VIM setup (remember, I started out on VIM before NeoVim) so we'll have to fix this up a bit later but this should work for a quick setup/demonstration. You need to make some decisions on what config launguage to use for your NeoVim setup (like using the old VimL or Lua). So you will have to translate this to your setup if you want to run a test.

Create a folder (this can be anywhere to be honest but for this conversation...):
mkdir -p ~/.vim/pack/plugins/start


I have the following in my ~/.vimrc

Code:
" A variable to point to vim's home directory
" (allows for fast changing on different systems)
let $VIMHOME = $HOME . '/.vim/'

"==----------------------------------------------------------------==
" Packages
"  These are where I place my packages to load on startup.
"==----------------------------------------------------------------==
let packpath = $VIMHOME . 'pack/plugins/'

Go grab ALE (a simple LSP) and clone it to the
~/.vim/pack/plugins/start/ directory.

Then in your ~/.vimrc or ~/.config/nvim/init.vim or
~/.config/nvim/init.lua file you should be able to add something like:

Code:
let g:ale_completion_enabled = 1
set omnifunc=ale#completion#OmniFunc
let g:ale_hover_to_floating_preview = 1
let g:ale_fixers = {
\   'c': [
\       'clang-format',
\   ],
\ }

And now you should have LSP type stuff for C/Cpp.

Using VIM's built in package manager will not automatically load new versions, you'd have to pull down new updates (but this is the sole reason I use it; I don't like things breaking).

About my comment above about VimL or LUA, VIML is vimscript and is as old as VIM itself (there are tons of plugins written in it). But pause and think before you go too far, because you can only have one ~/.config/nvim/init.(vim/lua) file.

I have to run, but I'll check back later. Good luck and I hope I cleared a few things up so you can at least try out a LSP in NeoVim.
 
I forgot to mention, if you use ~/.config/nvim/init.vim you can copy all those settings I just gave you in that file. I am not sure if you use an ~/.config/nvim/init.lua file though. And you should be able to create that directory ~/.vim/pack/plugins/start at something like: ~/.config/nvim/pack/plugins/start and change the path I used instead.
 
Interesting.
First of all, I did setup Neovim, because I thought or read back then that Neovim has far more plugins, and makes life easier as a lightweight IDE compared to Vim.

Today I also must go soon, but I will think whether to use lua or vimscript first.
 
because I thought or read back then that Neovim has far more plugins, and makes life easier as a lightweight IDE compared to Vim.

I'd say there are probably more vim plugins written in VimL (vimscript), perl, python, and C but that's because Lua support is a recent addition (NeoVim can use all of those old VimL plugins too because it is just 'a fork of Vim'. NeoVim in my opinion is better with the LSP stuff than plain Vim). NeoVim defiantly has more "fancy" plugins but that's only because of the influx of new users brought in. Some of those colorschemes are really cool.

You can read a ton of howto's on how to set up neovim as an "IDE replacement" (and even watch youtube videos) but at the end of the day I say you want something easily configured and maintained. Meaning, no one wants to launch (neo)Vim one day and find out it can no longer read .c files because some stupid plugin "updated".

My current setup:
1. I have only a few plugins (and I use the built-in pack manager).
2. I typically navigate to my C project in my shell, launch vim on a file and start typing (where ALE+clang annoy me every time I start typing "printf"). :)
3. When I want to compile, I type ":make" (some custom stuff does some magic for me when I opened the .c file).
4. If I want to test my program, I type ":term".
5. Rinse and repeat.

If your projects are simple, I can give you my simple makefile generator script. And I can give you some of the 'magic stuff' I built to allow my vim to find my makefile/cmake/xmake build file--so I can just "hit make"--but you should describe how you want to work with (neo)Vim so we can discuss features and cool things. You can certainly have anything I've got/done but I didn't go too far down the linting/LSP path to be honest.
 
Yes any worthwhile editor can set a key binding to a built in command (I don’t think anyone doubts EMacs would support make or allow for a key binding to be used).
 
I think it has something to do with mason downloading linux binaries for LSP, DAP, Linter, and Formatter.
Yes, sound like something like this...same issues i had
Have you tried native ? nvim-lspconfig ? ( i dont have it )
I tried out lazy vim as my plugin manager of choice.
Lazy is package manager, mason is manager for LSP servers, DAP servers, linters, and formatters. You can try to do manually without Mason.
 
I'd say there are probably more vim plugins written in VimL (vimscript), perl, python, and C but that's because Lua support is a recent addition (NeoVim can use all of those old VimL plugins too because it is just 'a fork of Vim'. NeoVim in my opinion is better with the LSP stuff than plain Vim). NeoVim defiantly has more "fancy" plugins but that's only because of the influx of new users brought in. Some of those colorschemes are really cool.
According to fresh ports neovim it has an asynchronous plugin architecture, too compared to plain vim.
Lua support was added due to some limitations in VimScript 0.4+ I believe.
Based on Lua being the recent choice for many good plugins, and a better option for neovim, I decided to go with lua.

I found out that there are multiple options to configure language server protocols.
1) vim-lsp combined with vim-lsp-settings.
Both work well with vim, and also neovim, too, and they strive to make the process to add lsps as easy as on vs code.
I consider it a choice, too, given that they support all the lsps I need.
But my question here would be, are they compatible with FreeBSD ?

2) nvim-lspconfig which I looked into it, and it looks quite interesting, but I do not know whether it is a better choice for neovim or not, over vim-lsp with vim-lsp-settings.
 
You can read a ton of howto's on how to set up neovim as an "IDE replacement" (and even watch youtube videos) but at the end of the day I say you want something easily configured and maintained. Meaning, no one wants to launch (neo)Vim one day and find out it can no longer read .c files because some stupid plugin "updated".
I thought at the beginning that setting up neovim as an "IDE replacement" would be a good solution, but it is like you said, I exactly want something easily configured so I can maintain it, add eventually options to it, etc.

My current setup:
1. I have only a few plugins (and I use the built-in pack manager).
2. I typically navigate to my C project in my shell, launch vim on a file and start typing (where ALE+clang annoy me every time I start typing "printf"). :)
3. When I want to compile, I type ":make" (some custom stuff does some magic for me when I opened the .c file).
4. If I want to test my program, I type ":term".
5. Rinse and repeat.
This is exactly a similar kind of setup I had in my mind while reading some tutorials on how to setup neovim as an IDE.
If possible doing something like that for multiple programming languages with as less plugins as possible.
The only plugins I would probably need are color/syntax highlighting, transparency, and some plugin to open new files in the current directory, and its subdirectories, because I have currently one large project (Ryujinx) to maintain. It has quite a lot of files in it so, I do not want to close, reopen, and closing another file again, if I can stay in the editor and just go to the next file.
Another plugin would be something like searching the current directory and its subdirectory files for a specific word, or pattern.
And that is probably everything I would need regarding plugins.

I would like to have something like typing, while in the file, !gcc "current file", !g++ "current file", or something like that, which shows me then my syntax error on line x:y for example.
For linking multiple files a make file would be good, of course.

If your projects are simple, I can give you my simple makefile generator script. And I can give you some of the 'magic stuff' I built to allow my vim to find my makefile/cmake/xmake build file--so I can just "hit make"--but you should describe how you want to work with (neo)Vim so we can discuss features and cool things. You can certainly have anything I've got/done but I didn't go too far down the linting/LSP path to be honest.
That would be great if you could give me the makefile generator script, and the 'magic stuff' build.
I though I had right now is to use external tools (syntax checker, debugger) calling them then needed, instead of having it running in the background.

As for lsps there is ccls or clangd which I would consider for C/C++.
I have something on my mind regarding my neovim setup right now, and will try it out, maybe I can get stuff working.
On my linux days, I had vim once configured with lsps, linters, formatters, auto-completion, etc, everything done with mason, but vim was very slow after that.
 
Emacs
compile make file

M-x compile
thats it
After like 8 hours now + yesterday, and the day before yesterday, getting part of the LSPs to work, and part of them not in neovim, I decided to give Emacs a try.
As far as I got it, evil mode is a mode which provides VI-like keybindings.

What makes Emacs stand out is that it supports natively LSPs compared to vim, and that is quite good.
It is not as lightweight eventually compared to vim, but I want an UI IDE, and are not constrained hardware wise.
I have skimmed through LSP Mode for Emacs, and found the same command a little bit different, though:
Code:
M-x lsp-install-server
bash-ls
for example.
I also noticed on that side the command: npm i -g bash-language-server.
Do I need to execute both, if I want to install the given LSP server ?

The problem is, I can for example install pyright, clangd with npm i -g, but not bash-language-server, or ccls, and it gets very messy to stick for example pyright in init.lua, and nvim-cmp.lua, and then also create a pyright.lua.
 
my (neo)vim is. ...if you want LSP stuff for C/C++, all you'd technically need is neovim (neovim has a LSP built-in) but I've always used "ALE" and haven't read the docs on the built-in (hence my example above).
I tried nvim-lsp, with nvim-lspconfig, it works, but npm cannot download some binaries needed for the server side.
 
I tried nvim-lsp, with

Did you give 'ALE' a try?
The only setting I have in my init.vim is:
Code:
let g:ale_completion_enabled = 1
set omnifunc=ale#completion#OmniFunc
let g:ale_hover_to_floating_preview = 1
let g:ale_fixers = {
\   'c': [
\       'clang-format',
\   ],
\ }
 
Here is my simple makefile generator script. There was a reason why I didnt use `getopt()` but I cannot remember at the moment but I do remember searching for an answer to a problem I had and I found the "while method" code. If you notice any improvements (or know where I got that manual replacement for `getopt()`), feel free to pass them along (I would appreciate another pair of eyes on this).

I will start disassembling some code for calling ":make" from my plugin for C/C++
development in Vim. It will take a bit.

My project directory typically looks like:

Code:
project
    |
    +-- doc
    |
    +-- src
    |   |
    |   +-- include
    |
    +-- test
    |
    +-- makefile
    |
    +-- configure
    ...

sh:
#!/bin/sh

#: mkgen
# This script generates a simple makefile for all the .C files
# found in the current directory and sub directories.

## usage --
#  Prints usage information.
usage() {
        if ! [ "$@" = "" ]; then
                echo $(basename "$0"): ERROR: "$@" 1>&2
        fi
        echo usage: $(basename "$0") '[-n name]' 1>&2
    exit 1
}

if [ $# -lt 1 ]; then usage "Not enough arguments."; fi

## inside --
# This function returns a TRUE if $2 is inside $1
#
# Uses a case statement, because this is a built-in of the shell,
# and faster.
inside() {
    case "$1" in
        *$2*) return 0;;
    esac
    return 1;
}

done_options=
# a flag which is set upon discovery of "--".

## more_options --
# return true(0) if there are options left to parse
# otherwise, return false
more_options() {

    # check the 'short-circuit' flag
    test $done_options && return 1  # true

    # how many arguments are left?
    [ $# -eq 0 ] && return 0

    # does the next argument start with a hyphen
    inside "$1" '-' && return 0;

    # otherwise, return false
    return 1    # false
}

while more_options "$1"
do
    case "$1" in
    --) done_options=1;;
        -[h]*)
                usage "";
                ;;
    -n)
        [ $# -gt 1 ] || usage "-n requires a value";
        shift
        name="$1";;
    -*) usage "unknown option $1";;
    esac
    shift   # each time around, pop off the option
done

_source_file_list=$(find . -type f -name '*.c')         # find the files
_header_file_list=$(find . -type f -name '*.h')

# Find the length of the header_file_list
header_list_len=0
for cntr in $_header_file_list; do
    header_list_len=$(expr $header_list_len + 1)
done

# Find the length of the source_file_list
source_list_len=0
for cntr in $_source_file_list; do
    source_list_len=$(expr $source_list_len + 1)
done

#cat <<_EOF_>&1
cat <<_EOF_>makefile
#===---------------------------------------------*- makefile -*---===
#: $name
# This file was automatically generated
#
# vim: set noet
#===--------------------------------------------------------------===

$name : HEADERS    =    \\
$(for headerfile in $_header_file_list; do                    # Print the files.
    printf -- "\t%s" "${headerfile#./}"
    header_list_len=$(expr $header_list_len - 1)
    if [ $header_list_len -gt 0 ]; then                             # Add a line continue for
                                                        # all but last file in list.
        printf -- '\t\\'
        printf -- "\n"
    fi
done
printf -- "\n")

$name : SOURCES    =    \\
$(for sourcefile in $_source_file_list; do                    # Print the files.
    printf -- "\t%s" "${sourcefile#./}"
    source_list_len=$(expr $source_list_len - 1)
    if [ $source_list_len -gt 0 ]; then                             # Add a line continue for
                                                        # all but last file in list.
        printf -- '\t\\'
        printf -- "\n"
    fi
done
printf -- "\n")

#--------------------------------------------------------------------
# Set the project directories and build parameters.
#--------------------------------------------------------------------
SRCDIR        =    src
DOCDIR        =    doc
INCDIR        :=    src/include

PREFIX        :=    /usr/local/bin

CC            :=    cc
CFLAGS        :=    -fno-exceptions -pipe -Wall -W
INCPATH         =       -I \$(SRCDIR) -I \$(INCDIR)
REMOVE        :=    rm -f
CP            :=    cp
CTAGS       :=    ctags

#--------------------------------------------------------------------
# Define the target compile instructions.
#--------------------------------------------------------------------
$name: \$(HEADERS) cleanobjs ctags
    $(echo $name | tr '[a-z]' '[A-Z')_TARGET='$name'
                @\$(CC) \$(CFLAGS) \$(INCPATH) -o $name \$(SOURCES)

.PHONY: clean
clean:
    @\$(REMOVE) $name \$(OBJECTS)

.PHONY: ctags
ctags:
    @\$(CTAGS) \$(SOURCES) \$(INCDIR)/.

.PHONY: cleanobjs
cleanobjs:
    @\$(REMOVE) \$(OBJECTS)

.PHONY: install
install:
    @\$(CP) $name \$(PREFIX)/$name

.PHONY: all
all: $name
_EOF_

My configure scripts typically look like this:
sh:
#!/bin/sh

#: configure
# This simple script will set options in the makefile.

prefix='$\(HOME\)\/bin'
buildloc='.'
Q='QUIET        :=      YES'
for arg in "$@"; do
    case "$arg" in
    --prefix=*)
        prefix=`echo $arg | sed 's/--prefix=//'`
        ;;
    --help)
        echo 'usage: ./configure [options]'
        echo 'options:'
        echo '  --prefix=<path>: installation prefix (default $(HOME)/bin)'
        echo 'all invalid options are silently ignored'
        exit 0
        ;;
    esac
done
sed -i '' "s/^prefix.*/prefix            :=    $prefix/g" makefile
echo 'configuration complete, type `make` to build.'
 
Back
Top