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

Below is some code to create a plugin for Vim that sets enviroment (better) for a C project. I have made this very modular so you can adopt this for different languanges or situations. This should work for simple makefile type projects as well as "out-of-source-build" projects like CMake.

To make this a plugin, place this in a file (assuming you set vim's `packpath` variable like I said above):
~/.vim/pack/plugins/start/cpp-devel-vim/plugin/cpp-devel-vim.vim

This code will:
1. When a file of ".c" is opened we search for a makefile (upwards from the current location).
If we do not find a makefile, we look for some common out-of-source-build-directories and make the assumption we're using CMake or Xmake.
2. Set vim's internal $PATH to that location.
3. Generate a "make-string" to call make with (-e.g. make -f <location we found>)
4. Create an override for the built in ":make" command (just some convinencies).

I have tried to add pleny of comments for you to follow along if necessary--and make this super cool(er).

I honeslty hope this helps you (or someone).

Code:
" vim: sw=4 sts=4 et
"------------------------------------------------------------------------------
" Some `public' overrides for an end-user to change if they want.
let s:MakeProgram             = 'make'
let s:MakeCmdLineArgs         = ''
let s:MakefileName            = 'Makefile'

" `common' build directory names to search for; this will determine
" `projectRoot'. Much of this script uses `projectRoot' so this is
" these directories are essential to this scripts functionality if a
" `makefile` is NOT found first.
"
" I imagine a directory structure something like the following:
"       ProjectName
"             |
"             +-- bin
"             |
"             +-- doc
"             |
"             +-- src
"             |    |
"              ...
let s:BuildDirectoriesToSearch = [ 'bin',
                                 \ 'build',
                                 \ 'binary',
                                 \ 'Development',
                                 \ 'Debug',
                                 \ 'Release',
                                 \ 'src'
                                 \ ]

let s:BuildFilesToSearch = [ 'makefile',
                           \ 'Makefile',
                           \ s:MakefileName
                           \ ]

" --------------------------------------------------------------------
" SetCppCodingStyle()
" Sets the current style based functions, like textwidth, path, brace
" and paren settings.
" --------------------------------------------------------------------
function! SetCppCodingStyle()                           "{{{
    " Don't include these in filename completions
    set suffixes+=.lo,.o,.moc,.la,.closure,.loT

    "--------------------------------------------------------------
    " Path Stuff

    " Set the current working path to the same location where make
    " is set to run from.
    exe "cd " . s:PathToRunMakeFrom
    let &tags = s:AssumedProjectRoot . '/tags'

    " Include the typical unix include directories in the
    " `path` variable.
    let s:TypicalUnixIncludeDirectories = '/usr/include,/usr/local/include'
    let &path = s:TypicalUnixIncludeDirectories . ',' . s:AssumedProjectRoot . ',' . '**7/'
    " Allow `path' to search 7 levels deep.

    " End Path Stuff
    "--------------------------------------------------------------

    call s:CreateCommands()

    " Misc stuff
    set shiftwidth=2
    set sts=4
    set et
    set tw=100
    set listchars=tab:?\ ,trail:?
    " mark 'misplaced' tab characters
    set list
    iab i i
    set incsearch

    set errorformat+=%f:%l:\ %m
    " Set the error format for the Clang compiler.

    if &syntax == 'cmake'
        call SmartParensOff()
        set sw=3
        set ts=3
        set et
        set tw=0
        return
    endif
endfunction "}}}

" --------------------------------------------------------------------
" s:CreateVariables()
" Creates the following variables:
"
"           s:AssumedProjectRoot
"           s:BinDirectory
"           s:FileLocation
"           s:MakefileLocation
"           s:PathToRunMakeFrom
" --------------------------------------------------------------------
function! s:CreateVariables()       "{{{

    " -Find the assumed project root. The assumption being that a
    "  `makefile` is kept in the project root folder.
    let s:AssumedProjectRoot = fnamemodify(s:File_Search(s:BuildFilesToSearch, ['.;']), ':p:h')

    " -Find a build directory. The assumption being that a
    "  `CMakeLists.txt` file is kept in the project root but cmake
    "  will need to be run from within this bin folder.
    let s:BinDirectory = s:Directory_Search(s:BuildDirectoriesToSearch, ['.;'])

    " -A variable storing the current file being edited.
    let s:FileLocation = fnamemodify(expand(getcwd()), '%:p')

    " -Establish the directory to run make from.
    " -Run this search frist, because the makefile location search
    "  may result in a different location and if it does this
    "  variable will be reset.
    let s:PathToRunMakeFrom = fnamemodify(s:File_Search(s:BuildFilesToSearch, ['.;']), ':p:h')

    " -Search for a makefile.
    let s:MakefileLocation = s:File_Search(s:BuildFilesToSearch, ['.;'])
    " -If the search for a makefile resulted in "." assume we are
    "  using a different build system than Make (like cmake or
    "  xmake) so we need to check the BIN folder.
    if s:MakefileLocation == '.'
        let s:MakefileLocation = findfile(s:BinDirectory . s:MakefileName, ".;")
        let s:PathToRunMakeFrom = s:BinDirectory
    endif

endfunction "}}}

" --------------------------------------------------------------------
" s:CreateCommands()
" Creates the following commands:
"
"           :make           :       Overrides built in make command
" --------------------------------------------------------------------
function! s:CreateCommands()                            "{{{
    "=============================================================================
    "~ W A R N I N G ~
    "=============================================================================
    "The following section is a command override for the make
    "command
    "-----------------------------------------------------------------------------
    :command! -nargs=0 Make :call Make()
    " Create a command for the Make() function.
    :cabbrev make <c-r>=(getcmdtype()==':' && getcmdpos()==1 ? 'Make' : 'make')<CR>
    " Override the built-in `make' command to use ours instead.
    "-----------------------------------------------------------------------------
endfunction     "}}}

" --------------------------------------------------------------------
" s:Directory_Search(directories, path)
"
"           directories     :       The directories to search for.
"           path            :       The path to start looking from and
"                                   direction to search (up/down/both)
" --------------------------------------------------------------------
function! s:Directory_Search(directories, path)        "{{{
    let s:path = get(a:path, 'path', ['.;'])
    for $dir in a:directories
        if finddir($dir, s:path) != ""
            " return expand(finddir($dir, ".;"))
            return fnamemodify(expand(finddir($dir, ".;")), ':p')
        endif
    endfor
    return "."
endfunction "}}}

" --------------------------------------------------------------------
" s:File_Search(files, path)
"
"           files           :       The files to search for.
"           path            :       The path to start looking from and
"                                   direction to search (up/down/both)
" --------------------------------------------------------------------
function! s:File_Search(files, path)        "{{{
    let s:path = get(a:path, 'path', ['.;'])
    for $file in a:files
        if findfile($file, s:path) != ""
            " return expand(findfile($file, ".;"))
            return fnamemodify(expand(findfile($file, ".;")), ':p')
        endif
    endfor
    return "."
endfunction "}}}

" --------------------------------------------------------------------
" MakeSetup()
" Locate the makefile and set the makeprog string.
" --------------------------------------------------------------------
function! MakeSetup()                                   "{{{
    let s:MakeProgString = s:MakeProgram . ' --directory="' . s:PathToRunMakeFrom . '" ' . ' --makefile="' . s:MakefileLocation . '" ' .s:MakeCmdLineArgs
    let &makeprg=s:MakeProgString
endfunction     "}}}

" --------------------------------------------------------------------
" Make()
" Custom Make() command.
" --------------------------------------------------------------------
function! Make( )                                        "{{{
    " close the issues window
    exe    ":cclose"
    " update : write source file if necessary
    exe    ":update"
    " issue `make`
    make
    " open the issues window
    exe    ":botright cwindow"
endfunction     "}}}

" ================================
" Autogroup settings.
" ================================
augroup CPPProgramming
    autocmd!
    autocmd BufNewFile,BufRead,BufEnter *.c,*.cc,*.cpp,*.h,*.hpp call s:CreateVariables()
    autocmd BufNewFile,BufRead,BufEnter *.c,*.cc,*.cpp,*.h,*.hpp call SetCppCodingStyle()
    autocmd BufNewFile,BufRead,BufEnter *.c,*.cc,*.cpp,*.h,*.hpp call MakeSetup()
augroup END
 
Not intending to start an editor war but; I spent many years using vi and vim but in time I got frustrated with maintaining the config files and dealing with differences on various systems I worked on remotely. I found that I was typically having to stick with stock vi bindings and no plug-ins and only reaping the benefits of a heavily customized vim config on my personal machines. Which all usually differed in small ways.

Years ago I moved over the emacs full time and ditched vim bindings in favor of emacs style bindings. To avoid emacs pinky I simply re-map left ctrl to CAPLOCKS. Then I spent about a week trying various add-ons/plug-ins for emacs and styling it to my liking. From then on my config was mostly portable and remained consistent across most machines I worked on. I still use vi a lot on machines I don't have any control over. But typically I'm only editing config files on such machines. So I don't need anything fancy.

I encourage you to go through the default emacs tutorial and learn the default bindings. Once you learn them you might find you prefer them like I and many others do. Instead of having to worry about what mode you're in and constantly entering and exiting modes to do stuff you can simply jump right in and edit some text. Want to save the file? It's a simple ctrl+something binding away. Want to close the file? same thing. Want to open a reference text and split the screen vertically? You can do it. Need to open another file? 1-2 keystrokes away every time.

Emacs gets a bad rap due to long start up times compared to vim/neovim. In practice I don't find this to be much of a problem even when I'm not using the emacs daemon. Even if initial start up was several seconds I wouldn't care because I'm going to leave emacs open for the entire session anyway. I have a very heavily customized config now and it still starts up in an acceptable amount of time (less than a few seconds) and it's doing A LOT on initial start up. Since I'm using it for most everything like; reading mail, calendar/schedule, news reader, connecting to multiple IRC servers, gathering basic information about the machine from config files and many other things. I have a customized welcome screen upon start up that displays all this information along with the last several files I was editing. You can make it do whatever you want. It's really like its own self contained OS.

I feel that emacs is a better IDE than vim/neovim could ever be. It's certainly more powerful and less prone to barfing on its config file provided you've spent time to set it up correctly and don't go overboard. Although these days I mostly use it for org-mode and creative writing. I can't live without org-mode anymore it's simply too useful and allows me to export one type of mark up into most any other kind of mark-up I want. The only downside is the steep learning curve up front and the fact that you can get lost pretty quickly customizing it instead of getting any real work done. But once it's set-up the config can follow you around for years without breakage. You should consider trying it.

Yes it's true a lot of people like evil mode. I used it a lot at first too. But frankly I don't like the way evil mode/vi works. I always liked how I could just jump into a text file and start typing in emacs. Anything I'd do in vi with a key press (e.g. hjkl etc.) can be done just as quickly with CAPLOCKS+key-bind. Moving my pinky from A key to CAPSLOCK is not a big deal and I don't even notice it for functions that require two strokes (e.g. ctrl+x -> ctrl-s to save).

For awhile I fell for the "do everyting in emacs" way and even used EXWM as my window manager. But the nature of emacs is it's single threaded and this is sometimes annoying to deal with. So what I eventually settled on was using a WM like dwm or cwm and giving it the super+alt keys. Emacs starts at log-in as daemon and runs on its own desktop/tag. My browser and everyting else I use on different tags or very rarely split on the same tag with emacs. I do most of my text based stuff through emacs still but not the terminal. For the terminal I use a proper terminal emulator and sometimes tmux. Everything lives pretty happily together this way without keybinds stepping on top of each other. When emacs rarely crashes or chokes on a long process it doesn't take down the entire WM with it. It's a pretty happy medium.

Now if emacs ever gets multi-threading I might consider going back to attempting to use it as my entire WM. But for now I don't see much issue with my custom compiled dwm and handful of other applications like st.

All that aside you should really consider joining the dark side and embracing emacs. LISP is really nice and I've found myself using it for other things since I learned it through emacs. For example, the guix package manager is really nice and when I do install Linux on bare hardware now I tend to learn towards it more and more often. It solves all the major issues that are in nix. The learning curve is kind of steep but the reward is worth it in my opinion.

Not trying to knock vim/neovim either. But I don't think it can ever compare to what emacs can give you as far as text editing goes. org-mode alone is worth learning emacs.
 
Below is some code to create a plugin for Vim that sets enviroment (better) for a C project. I have made this very modular so you can adopt this for different languanges or situations. This should work for simple makefile type projects as well as "out-of-source-build" projects like CMake.

To make this a plugin, place this in a file (assuming you set vim's `packpath` variable like I said above):
~/.vim/pack/plugins/start/cpp-devel-vim/plugin/cpp-devel-vim.vim

This code will:
1. When a file of ".c" is opened we search for a makefile (upwards from the current location).
If we do not find a makefile, we look for some common out-of-source-build-directories and make the assumption we're using CMake or Xmake.
2. Set vim's internal $PATH to that location.
3. Generate a "make-string" to call make with (-e.g. make -f <location we found>)
4. Create an override for the built in ":make" command (just some convinencies).

I have tried to add pleny of comments for you to follow along if necessary--and make this super cool(er).

I honeslty hope this helps you (or someone).

Code:
" vim: sw=4 sts=4 et
"------------------------------------------------------------------------------
" Some `public' overrides for an end-user to change if they want.
let s:MakeProgram             = 'make'
let s:MakeCmdLineArgs         = ''
let s:MakefileName            = 'Makefile'

" `common' build directory names to search for; this will determine
" `projectRoot'. Much of this script uses `projectRoot' so this is
" these directories are essential to this scripts functionality if a
" `makefile` is NOT found first.
"
" I imagine a directory structure something like the following:
"       ProjectName
"             |
"             +-- bin
"             |
"             +-- doc
"             |
"             +-- src
"             |    |
"              ...
let s:BuildDirectoriesToSearch = [ 'bin',
                                 \ 'build',
                                 \ 'binary',
                                 \ 'Development',
                                 \ 'Debug',
                                 \ 'Release',
                                 \ 'src'
                                 \ ]

let s:BuildFilesToSearch = [ 'makefile',
                           \ 'Makefile',
                           \ s:MakefileName
                           \ ]

" --------------------------------------------------------------------
" SetCppCodingStyle()
" Sets the current style based functions, like textwidth, path, brace
" and paren settings.
" --------------------------------------------------------------------
function! SetCppCodingStyle()                           "{{{
    " Don't include these in filename completions
    set suffixes+=.lo,.o,.moc,.la,.closure,.loT

    "--------------------------------------------------------------
    " Path Stuff

    " Set the current working path to the same location where make
    " is set to run from.
    exe "cd " . s:PathToRunMakeFrom
    let &tags = s:AssumedProjectRoot . '/tags'

    " Include the typical unix include directories in the
    " `path` variable.
    let s:TypicalUnixIncludeDirectories = '/usr/include,/usr/local/include'
    let &path = s:TypicalUnixIncludeDirectories . ',' . s:AssumedProjectRoot . ',' . '**7/'
    " Allow `path' to search 7 levels deep.

    " End Path Stuff
    "--------------------------------------------------------------

    call s:CreateCommands()

    " Misc stuff
    set shiftwidth=2
    set sts=4
    set et
    set tw=100
    set listchars=tab:?\ ,trail:?
    " mark 'misplaced' tab characters
    set list
    iab i i
    set incsearch

    set errorformat+=%f:%l:\ %m
    " Set the error format for the Clang compiler.

    if &syntax == 'cmake'
        call SmartParensOff()
        set sw=3
        set ts=3
        set et
        set tw=0
        return
    endif
endfunction "}}}

" --------------------------------------------------------------------
" s:CreateVariables()
" Creates the following variables:
"
"           s:AssumedProjectRoot
"           s:BinDirectory
"           s:FileLocation
"           s:MakefileLocation
"           s:PathToRunMakeFrom
" --------------------------------------------------------------------
function! s:CreateVariables()       "{{{

    " -Find the assumed project root. The assumption being that a
    "  `makefile` is kept in the project root folder.
    let s:AssumedProjectRoot = fnamemodify(s:File_Search(s:BuildFilesToSearch, ['.;']), ':p:h')

    " -Find a build directory. The assumption being that a
    "  `CMakeLists.txt` file is kept in the project root but cmake
    "  will need to be run from within this bin folder.
    let s:BinDirectory = s:Directory_Search(s:BuildDirectoriesToSearch, ['.;'])

    " -A variable storing the current file being edited.
    let s:FileLocation = fnamemodify(expand(getcwd()), '%:p')

    " -Establish the directory to run make from.
    " -Run this search frist, because the makefile location search
    "  may result in a different location and if it does this
    "  variable will be reset.
    let s:PathToRunMakeFrom = fnamemodify(s:File_Search(s:BuildFilesToSearch, ['.;']), ':p:h')

    " -Search for a makefile.
    let s:MakefileLocation = s:File_Search(s:BuildFilesToSearch, ['.;'])
    " -If the search for a makefile resulted in "." assume we are
    "  using a different build system than Make (like cmake or
    "  xmake) so we need to check the BIN folder.
    if s:MakefileLocation == '.'
        let s:MakefileLocation = findfile(s:BinDirectory . s:MakefileName, ".;")
        let s:PathToRunMakeFrom = s:BinDirectory
    endif

endfunction "}}}

" --------------------------------------------------------------------
" s:CreateCommands()
" Creates the following commands:
"
"           :make           :       Overrides built in make command
" --------------------------------------------------------------------
function! s:CreateCommands()                            "{{{
    "=============================================================================
    "~ W A R N I N G ~
    "=============================================================================
    "The following section is a command override for the make
    "command
    "-----------------------------------------------------------------------------
    :command! -nargs=0 Make :call Make()
    " Create a command for the Make() function.
    :cabbrev make <c-r>=(getcmdtype()==':' && getcmdpos()==1 ? 'Make' : 'make')<CR>
    " Override the built-in `make' command to use ours instead.
    "-----------------------------------------------------------------------------
endfunction     "}}}

" --------------------------------------------------------------------
" s:Directory_Search(directories, path)
"
"           directories     :       The directories to search for.
"           path            :       The path to start looking from and
"                                   direction to search (up/down/both)
" --------------------------------------------------------------------
function! s:Directory_Search(directories, path)        "{{{
    let s:path = get(a:path, 'path', ['.;'])
    for $dir in a:directories
        if finddir($dir, s:path) != ""
            " return expand(finddir($dir, ".;"))
            return fnamemodify(expand(finddir($dir, ".;")), ':p')
        endif
    endfor
    return "."
endfunction "}}}

" --------------------------------------------------------------------
" s:File_Search(files, path)
"
"           files           :       The files to search for.
"           path            :       The path to start looking from and
"                                   direction to search (up/down/both)
" --------------------------------------------------------------------
function! s:File_Search(files, path)        "{{{
    let s:path = get(a:path, 'path', ['.;'])
    for $file in a:files
        if findfile($file, s:path) != ""
            " return expand(findfile($file, ".;"))
            return fnamemodify(expand(findfile($file, ".;")), ':p')
        endif
    endfor
    return "."
endfunction "}}}

" --------------------------------------------------------------------
" MakeSetup()
" Locate the makefile and set the makeprog string.
" --------------------------------------------------------------------
function! MakeSetup()                                   "{{{
    let s:MakeProgString = s:MakeProgram . ' --directory="' . s:PathToRunMakeFrom . '" ' . ' --makefile="' . s:MakefileLocation . '" ' .s:MakeCmdLineArgs
    let &makeprg=s:MakeProgString
endfunction     "}}}

" --------------------------------------------------------------------
" Make()
" Custom Make() command.
" --------------------------------------------------------------------
function! Make( )                                        "{{{
    " close the issues window
    exe    ":cclose"
    " update : write source file if necessary
    exe    ":update"
    " issue `make`
    make
    " open the issues window
    exe    ":botright cwindow"
endfunction     "}}}

" ================================
" Autogroup settings.
" ================================
augroup CPPProgramming
    autocmd!
    autocmd BufNewFile,BufRead,BufEnter *.c,*.cc,*.cpp,*.h,*.hpp call s:CreateVariables()
    autocmd BufNewFile,BufRead,BufEnter *.c,*.cc,*.cpp,*.h,*.hpp call SetCppCodingStyle()
    autocmd BufNewFile,BufRead,BufEnter *.c,*.cc,*.cpp,*.h,*.hpp call MakeSetup()
augroup END
Thank you, I will look into that.
Eventually I could translate the vimscript part into lua, too.
 
Last edited:
Not intending to start an editor war but; I spent many years using vi and vim but in time I got frustrated with maintaining the config files and dealing with differences on various systems I worked on remotely.

Sorry, but why didn't you just build your config with guards and ship one config around instead of maintaining one for each?

Code:
let g:MSWIN = has("win16") || has("win32")   || has("win64")     || has("win95")
let g:UNIX  = has("unix")  || has("macunix") || has("win32unix") || !g:MSWIN

...

if g:MSWIN
        let packpath = $VIMHOME . 'vimfiles/pack/plugins/'
else
        let packpath = $VIMHOME . 'pack/plugins/'
endif

I do the same for all of my other config files like: .zshrc, and etc..

I don't think Vim has ever changed my config files...I don't think it even has that ability.


Thank you, I will look into that.
Eventually I could translate the vimscript part into lua, too.

I was trying out Xmake (which uses Lua) a while back so I started down the Lua path--nice enough language--but I haven't touched it in years. I'd be interested in that. If you get a repo started, let me know and I'll try to help out. But I hope the code helps (I had to pull it out of a larger plugin I have so I hope I got all the parts, and whatnot). Same with the "makefile generator" script.
 
My obligatory posting of Unix is my IDE

I'm almost positive I agree but I will read the link. But before I do (please allow me a chance to possibly put my foot in my mouth).

I know it fly's against the grain but I honestly cannot get past the syntax of code sometimes.

Code:
int 
contains(char **array, int size, const char *value)
{
vs
Code:
int contains(char **array, int size, const char *value) {

Just for the sake of grep alone.
Code:
./main.c:62:int contains(char **array, int size, const char
*value) {

just because this grep return tells me so much like: "is function def", "has return int", "arguments". I had to create an alias just so I can call grep with "--context=2".

sorry, off to read now.
 
Usagi
Your post is really helpful, and I also do not intend to start an editor war, but I just want to get the right tool for the right job, and coding in a UI IDE environment is of uppermost importance for me.
It seems that emac has that kind of capabilities built in without much of a hassle.

I have a few questions regarding emacs, and DWM.

Emacs:
I read in the internet, too that it is more of an IDE by nature due to being build in LISP.
It has native LSP capabilities, too.
In my current situation I want to have support for the following LSPs:
-> Bash through Bash-Language-Server
-> C/C++ through clangd or ccls. Which of them do you recommend ?
-> C# through csharp-ls
-> Python through pyright

To accomplish that do I need npm for emacs or does emacs have some other way to get these server binaries ?
My current problem not with neovim itself, but with the approach to get these binaries working is that I need npm.
Downloading pyright with npm works, and I can get the LSP working with python scripts.
The situation changes with clangd or ccls.
I can download clangd, but the binary is not found in the npm related folder.
CCLS, and bash-language-server do not work at all, and npm throws an error attempting to download them.

DWM:
I have read their tutorials, and I am very interested in it.
Can I somehow change the config.h file, and rebuild DWM with poudriere each time I want to add new settings or do I need to do it manually ?
 
Just for the sake of grep alone.
I believe the reason is to do with grep. Often your codebase will have the word contains in many places, you likely won't want them all, just the signature and implementation.

So you can grep for ^contains and you will be fairly guaranteed that only two results will be returned with term being the first element on a line. It possibly allows for quicker navigation when grepping.

(Note: I rarely use the latter format either unless working on codebases that already do)
 
I believe the reason is to do with grep. Often your codebase will have the word contains in many places, you likely won't want them all, just the signature and implementation.

So you can grep for ^contains and you will be fairly guaranteed that only two results will be returned with term being the first element on a line. It possibly allows for quicker navigation when grepping.

(Note: I rarely use the latter format either unless working on codebases that already do)
Very true and good point.

FYI: I wondered if BSD-ctags still picked up on the latter format and it does.
Code:
    /*
     * if we have a current token, parenthesis on
     * level zero indicates a function.
     */
    case '(':
      do {
        if (GETC(==, EOF))
          return;
      } while (iswhite(c));
...
 
Sorry, but why didn't you just build your config with guards and ship one config around instead of maintaining one for each?
My point was it is annoying having to do that in the first place. Emacs is emacs no matter where it runs. The config I write is inherently portable and I don't have to worry about my custom binds being very different from the default vi on some server somewhere that I'm only going to be on for 5 minutes.
To accomplish that do I need npm for emacs or does emacs have some other way to get these server binaries ?

Anything you need is probably already a package. I don't do much web stuff anymore (and when I do I don't use stuff like npm) so I can't suggest a package. But you should look here for packages/add-ons: https://elpa.gnu.org/ and https://melpa.org

You can use the built in package manager for emacs but a lot of people use third party ones with more features. I use elpaca to manage my emacs packages these days. There are multiple package managers each with their own benefits but elpaca is the newest one and a lot of people simply don't use it because they already have a config written in straight.el or are content with managing everything manually. Whatever you want there is undoubtedly multiple pre-existing packages out there for it.

Just look around and see what others are using. My config these days is pretty bare bones (well compared to in the past) and I basically only need syntax highlighting and some stuff for org-mode. I don't want to suggest anything because an emacs config is a very personal thing and you'll probably spend many months tweaking your own before you find a balance between features you want and size of your personal config/start up times. In my experience once someone "gets" emacs for the first time they go wild with extending it then over the years they scale back their customization. You really can make it a self contained OS. It'll do anything you can imagine and it's easy to throw together your own add-ons once you know LISP.

Emacs is probably the most widely used IDE on the planet and has been since the late 80s. So it'll do anything you need. It's just a matter of groking and setting it up.

DWM:
I have read their tutorials, and I am very interested in it.
Can I somehow change the config.h file, and rebuild DWM with poudriere each time I want to add new settings or do I need to do it manually ?

Do not try to manage dwm through a package manager/ports. While it is possible it's a huge pain. Everyone I know just pulls in suckless tools to a sub-directory in their home folder and edits config.h and/or adds their patches. Then compile with make + make install. There is no point in using a packaged version unless you want the default config (which you probably don't want since changing key bindings requires editing the config.h file). Save yourself the headache. All the suckless tools are small self contained applications. If you do feel the need to have some revision control just track them with git instead of patching manually with patch.

Suckless tools are also kind of like emacs in the respect that people seem to go wild with customization at first then scale things back after awhile. My own copy of dwm only has 4 or 5 patches I think along with a few customized keybinds (like swapping the default alt modkey over to the super key).

Be aware that on OpenBSD (and I think FreeBSD) you'll need to uncomment a couple of lines in the config.mk file to make it search the right PATH. Otherwise compiling it will fail. I know that's the case with dwm and st on OpenBSD at least. I'm not running it on my FreeBSD box at the moment. I only really use dwm on my laptops. On my desktops I have trackballs and multiple monitors and use Openbox typically with each application dedicated to one monitor.

Right now I have 6 monitors on my main workstation. Which sounds like over kill but the way I have them set-up (side-by-side + stacked + one off in a corner (a TV)) doesn't take up that much desk space. I run 2 CRTs, 2 HD resolution monitors in the middle, a third HD resolution monitor in portrait mode to the other side, then the 6th monitor is a consumer HDTV off in a corner that I use for checking content on what would be a typical consumer set-up from a distance). Hence I don't need something like dwm on that workstation. Although I have used a tiling WM on that workstation in the past and it works well. But it's kind of useless with applications autostarting on certain monitors anyway and when I have a trackball to move around. On that workstation some things I don't work on full screen and don't want automatically scaling to full/half/quater screen. It's eaiser just to sometimes resize applications manually instead of having to write custom rules for everything. I rarely do such work on my laptops. On those it's mostly text/terminal stuff so it's better just to have the WM automatically manage everything for me.
 
Checking elpa, and melpa I can say that they have all the packages I need for development.
Elpaca is also very interesting, and I am going to give it a try, after I have read through the book Learning GNU Emacs.

Starting, and almost finishing my trip through Learning Gnu Emacs toady, I have found many useful features in emacs built in.
For example the auto-saving feature, a saved buffer in case I want to revert back to the initial state of the written file, open another file while staying in the editor.
The default keybindings are very straightforward, too, and I like emacs already a lot.
I am not planning to go wild with emacs settings as I already know what I want, and what not.
 
My point was it is annoying having to do that in the first place. Emacs is emacs no matter where it runs. The config I write is inherently portable and I don't have to worry about my custom binds being very different from the default vi on some server somewhere that I'm only going to be on for 5 minutes.
Ah, whut? I'm confused by your point(s) about Vim not being portable across different systems? Any *nix os will put your .*rc at $HOME so the only need to use "an OS Guard" (like I shown above is for when a user installs on a Windows Machine and does that "very-old-school-install-at-c:-thing". For some reason (I do not remember why) it was "a thing" to install vim/emacs on C:/. I imagine this was because of spaces in the path but you can put vim in $HOME on windows too (just as you can emacs). It's not 1992 anymore.

Or? Are you saying that Vim has to have different key bindings for different OS'. No. h,j,k,l,:,g,w,etc. is the same on windows and *nix.

So, you're installing emacs/vim on a remote machine your only on for 5 minutes? Why don't you just remote edit and use your local config/settings? Both Vim and Emacs support that.

I don't understand how this neovim question/post became a "sales pitch for emacs/pick on vim" thread. If you don't like Vim, don't use it. And if you don't want configs, tools, don't ask because I'm not going to spend 1 or 2 hours assembling stuff just for kicks (I have better things to do, like take care of two small kids).
 
I don't understand how this neovim question/post became a "sales pitch for emacs/pick on vim" thread. If you don't like Vim, don't use it. And if you don't want configs, tools, don't ask because I'm not going to spend 1 or 2 hours assembling stuff just for kicks (I have better things to do, like take care of two small kids).
Read the title of this thread carefully first, please.
The title of this thread is: "Neovim as an IDE/IDE alternatives for C, C++, C#, Python programming languages".
IDE alternatives are also a welcoming point.
It is neither about VIM solely nor about EMACS.
Both editors are welcome.

I programmed with Vim and NVim under linux, and it worked.
NPM worked, too.
On FreeBSD however I only managed to get C/C++, and Python to work for my case with neovim so far.
Emacs in this regard works with C, C++, C#, Python on my FreeBSD system without much hassle.
Your configs worked fine for their purpose with VIM/NeoVim and that is it, thank you.
Whether you spend 1 or 2 or 3 or million of hours just assembling stuff, and sending it, it is your decision, not mine, not everyone else.
 
You need to think about what you want (and what you want to control). If you look at the "plugin skeleton" I gave you, you will notice that:

1. Upon opening a C,H,CPP file "SetCodingStyle" and "Makesetup" happens.

2. In 'setcodingstyle' you set any settings you want for programming (working in) a type of file. If that be C (like this example) is irrelevant; you establish "per use" settings to your liking. Like "turn off spell checking".

3. In 'makesetup' I redefine the ":make" command to do something (in the case of C programming, that's obviously still going to be calling "make" and compiling but this can be anything you specify for any given filetype (-i.e. it could be "send an email every time you type ":make" in a ".txt" file. These operations are up to you, and they don't always have to be preforming a build).

So, I've given you the basis for a "filetype-smart-thing-which-can-do-what-you-want".

So, your question an "IDE alternative" is vague and not well defined. The last few discussion points seem to be about an "emacs package manager". An IDE to me will do several things like turn off spelling, set a tabstop to some reasonable value, do this, do that, every time I open a programming language file. For example: the skeleton code I gave you searches the directory looking for a build system file and sets an internal path variable to that location (so the editor knows where to call make from--or whatever dumb setting you want). The example I provided was a relevant starting point because of things like *nix CTAGS (because in *nix the OS is your IDE--the point someone else brought up too), and the editor "goto file" command, not to mention locate the OS built-in C headers. You can change/add to that 'setcodestyle' or 'makesetup' function to call clang-format or whatever need you have. -e.g. if you want to make the editor's colorscheme pink when you open a .lsp file, you'd have that ability using the skeleton code I gave you. You are searching for an IDE alternative which means what (functionality)?

The fact that you want Emacs or Vim I do not care; you asked about vim, I know vim so I will share Vim concepts for you "BUILDING YOUR IDE NEEDS". -i.e., With the C language you need a compiler (shipped with FreeBSD), you want a LSP (the parts for one are shipped with FreeBSD and NeoVim--turn it on; you don't need a package manager for a C based LSP). Now, when you want to add other languages like C#, python you will need a compiler/tool/etc.. I would imagine there are plenty of choices for a package manager for Vim/Emacs you can choose from--The question I posed to you was "do you really need a package manager if you have Git?" (and what does that have to do with a LSP).

Auto-Saving and opening another file while not leaving your editor is a pretty low bar (I think it would be hard finding an editor that cannot do those things).

Discussions about what editor can do what thing is a very dumb discussion to have because both have been in development for a very long time (Vim is over 33 years old; do you honestly think there is "missing functionality" at this point?). Decide what functionality you want to do in an editor and set it up. You said C# doesn't work in NeoVim; why (what compiler did you install, what LSP did you install, etc.)?

For example: "Instead of a full blown LSP, I want my editor to just show a function signature in bottom of the editor window instead of an annoying balloon popup like VSCode." and "I want my editor to put a space after an IF, FOR, WHILE, etc. function." and "I want a brace on the same line as a FOR statement." These were some of my needs; so, I made my vim do this.

All of that aside, there are "workflow" differences between Emacs, and Vim. For example, Vim is smaller, so you typically add only the functionality you need (use a combination of the OS and the editor to preform operations). AND/OR in Emacs you tend to stay in the editor. You need to decide which workflow you like best. For me, I prefer to have the often times more powerful OS level (third party) tools instead of using an editor's functionality, but this is your choice (I prefer speed you may choose something else).
 
You need to think about what you want (and what you want to control). If you look at the "plugin skeleton" I gave you, you will notice that:

1. Upon opening a C,H,CPP file "SetCodingStyle" and "Makesetup" happens.

2. In 'setcodingstyle' you set any settings you want for programming (working in) a type of file. If that be C (like this example) is irrelevant; you establish "per use" settings to your liking. Like "turn off spell checking".

3. In 'makesetup' I redefine the ":make" command to do something (in the case of C programming, that's obviously still going to be calling "make" and compiling but this can be anything you specify for any given filetype (-i.e. it could be "send an email every time you type ":make" in a ".txt" file. These operations are up to you, and they don't always have to be preforming a build).

So, I've given you the basis for a "filetype-smart-thing-which-can-do-what-you-want".
Yes, I noticed that you gave me a plugin skeleton.
I managed to get C/C++ to work with it with clangd.

If not, are there eventually another plugins for neovim which replace mason, and work on FreeBSD ? (Other Plugins)

Another question is:
Are there any alternatives for an UI IDE on FreeBSD which are similar to nvim, and eventually support vim like keybindings ? (UI alternatives like emacs, vscode ((G)UI))
So, your question an "IDE alternative" is vague and not well defined. The last few discussion points seem to be about an "emacs package manager".
For me, and other users who posted on this thread the question seems to be clear, hence the topics about emacs, and VSCode.
I honestly do not get your point.
What is wrong about providing information about package managers if an UI IDE alternative seems to suit the needs ?
It started with IDE alternatives (tools for programming), and the path lead to helping tools.

The fact that you want Emacs or Vim I do not care; you asked about vim, I know vim so I will share Vim concepts for you "BUILDING YOUR IDE NEEDS". -i.e., With the C language you need a compiler (shipped with FreeBSD), you want a LSP (the parts for one are shipped with FreeBSD and NeoVim--turn it on; you don't need a package manager for a C based LSP). Now, when you want to add other languages like C#, python you will need a compiler/tool/etc.. I would imagine there are plenty of choices for a package manager for Vim/Emacs you can choose from--The question I posed to you was "do you really need a package manager if you have Git?" (and what does that have to do with a LSP).
You mentioned that you only do C.
For C/C++ you have already a clangd binary to connect to, and of course it works without any package manager, etc.
I asked about vim, and I asked about emacs, I got information on both, and I tried both out.
There are plenty of pkg managers for emacs, and plugin managers for (n)vim as far as I know you do not have pkgs on (n)vim, and npm is originally for node JS, not (n)vim.
Git downloads the sources only.
A LSP is not always available natively, for example bashls is not, at least I did not find it.
For bashls I need npm in order to get it working since it looks like it is packaged for usage through npm.

Auto-Saving and opening another file while not leaving your editor is a pretty low bar (I think it would be hard finding an editor that cannot do those things).

Discussions about what editor can do what thing is a very dumb discussion to have because both have been in development for a very long time (Vim is over 33 years old; do you honestly think there is "missing functionality" at this point?). Decide what functionality you want to do in an editor and set it up. You said C# doesn't work in NeoVim; why (what compiler did you install, what LSP did you install, etc.)?
I just found it neat to have by default that is it.
The intention to start a discussion about setting x,y,z was not my intention, besides I did not say that vim does not have that kind of settings available.
Sorry about the misconception with C#, I phrased it wrong.
I tried out C/C++ -> Pyright -> Bashls in that order.
C# should come after bashls, but since bashls did not work, I stopped there.

Well, did you ever manage to get bashls working with vim on FreeBSD ?
If yes, I would be really interested how you fixed the npm errors.


EDIT:
I got everything now working in neovim...
I do not know why, but after reinstalling npm, and issuing as root npm i -g bash-language-server, everything worked.
I get now autocompletion and everything else fine in bash scripts.
The registry error npm had before, finding the bash-language-server github side is also gone now.
Well, if that is the case I will of course see to get C# working, and continue my programming journey like in linux.
 
Last time I counted I programed in 13 different languages but what is the difference between an example for 1 or 2 or 13 languages (I'm discussing core functionality/principles)? I only use LSP in neovim for one language (c) but a while ago I wrote "a thing" to show me function signatures in Vim's command line which I find far less obtrusive, so my LSP usage is only recent.

Why didn't you just use the -n flag for Bash itself? I know ALE--the light weight lsp I told you to at least try--supports this; you'll have to check your LSP.

That skeleton is for building upon; it is probably useful in itself--as is-, but it was meant to offer you a way to build things you want for as many different languages as you want/need.

I would hate to count the number of package managers there are for Vim and NeoVim. A conservative guess would be in the dozens. Again, 33+ years of people using a product, results in a lot of customization.
 
Last time I counted I programed in 13 different languages but what is the difference between an example for 1 or 2 or 13 languages (I'm discussing core functionality/principles)?
If it works, there is no difference.

Why didn't you just use the -n flag for Bash itself? I know ALE--the light weight lsp I told you to at least try--supports this; you'll have to check your LSP.
I looked into ALE roughly 30 minutes ago. It is an asynchronous lint engine with support for various LSPs.
ALE itself is not an LSP, but a client,, at least the github site tells it, and it provides additionally semantic error checking to the already available syntax checking LSPs provide.
I am still thinking whether I should use ALE or not, because for me it would only add semantic error checking.
What does bash -n provide ?
I only read it in the manual that it is for no command execution.
Bash works now as with its LSP as intended.

That skeleton is for building upon; it is probably useful in itself--as is-, but it was meant to offer you a way to build things you want for as many different languages as you want/need.
I know, it is very useful (I tried it with vim9).
It is interesting whether your skeleton, and examples could be converted to lua.
Sadly I do not know enough lua, though, but I managed finally to create a clean structure which could be further refined.

I would hate to count the number of package managers there are for Vim and NeoVim. A conservative guess would be in the dozens. Again, 33+ years of people using a product, results in a lot of customization.
I do not know whether you tried lazy vim or not, but it lazy loads plugins (only lua, though).
Basically it does not matter whether you have 1 LSP or 100 LSPs installed, because if you open 1 file, let us say a file with the .c extension, then from the 100 LSPs only 1 will be loaded, and the other LSPs will just be cached.
The same goes for another plugins as well.
Yes it is another plugin manager, but its lazy load feature sets it apart from other ones.
I would recommend it, but there is nothing wrong with vimscript, too.
 
Checking elpa, and melpa I can say that they have all the packages I need for development.
Elpaca is also very interesting, and I am going to give it a try, after I have read through the book Learning GNU Emacs.

Starting, and almost finishing my trip through Learning Gnu Emacs toady, I have found many useful features in emacs built in.
For example the auto-saving feature, a saved buffer in case I want to revert back to the initial state of the written file, open another file while staying in the editor.
The default keybindings are very straightforward, too, and I like emacs already a lot.
I am not planning to go wild with emacs settings as I already know what I want, and what not.
Best laid plans and all of that. A lot of people dip their toes into emacs and one day they look up and it's weeks later. They've accomplished nothing but hacking on emacs. It's constantly evolving and getting new features most of which aren't exposed by default. You have to dig around inside of it and discover them. I've been using it for decades now and I still stumble upon new things now and again. The only downside of it is the fact that by default it consumes about 60MB of RAM even with a small config. But these days it isn't very heavy compared to most anything else that offers that kind of feature set.

You may find this list useful: https://github.com/emacs-tw/awesome-emacs

I didn't want to get too deep into the weeds about what I personally use. I use a lot of packages but most aren't really reccomended anymore (development has slowed and people have moved on to newer things) and I'm always trying to trim them or figure out ways to make do with built-in functions. I also build from source so I'm usually a version or two ahead of what most users are running. Most people running binaries are still on version 29 or earlier where I've been on v30 for awhile now.

If you can try to get one built against gtk2. It consumes slightly less RAM than if it's built with gtk3, behaves better with everything that isn't Gnome and will start just a little faster. Not that gtk3 is horrible or anything. But I don't run gtk on my systems now so I'd rather not pull it in if I can help it. I'm kind of out of date too. I need to start trying out all this new LSP stuff.

I pretty much skipped it when it was available elsewhere and have always preferred to do things mostly manually. I don't use frameworks for javascript/php/webdev for example preferring to do things like I did them in the late 90s-early 2000s when I was working on "ground breaking web 2.0" stuff using AJAX to dynamically serve content without forcing a page refresh. I am perfectly content using something like ed or vi to write C and such. Like I said I mostly use emacs for org-mode these days (I do a lot of creative writing and org-mode helps me with that in a lot of ways including sticking to my plans/agenda and exporting what I write to various text formats).

If you're feeling frisky a lot of the older X11 stuff like athena is still supported provided you're willing to build from source. Of course if you're on the wayland train you'll probably want gtk3 because it's the only way to run emacs without relying on Xwayland or whatever the Xorg-inside-wayland layer is called now. If you're on X11 you have a few options outside of gtk though (not Qt of course) all the old school stuff GUI wise is still fully supported if you want/need it. Last I checked emacs still runs fine on most of my older systems. It pre-dates Linux and *BSD so I suppose that's to be expected. If runs fine inside of a terminal too of course if you're willing to live without the benefits of modern graphic support.

Anyway, the above link should give you a good idea about what's avaiable and what the cool kids are using these days. It changes from year to year.
 
Back
Top