Making Godotsharp and Neovim be friends Sketch
Welcome, friend, to my first sketch tutorial. While I hadn't planned on making this the first it ended up being a roadblock to what I wanted to write about so here we go.
Currently, my main personal project is a solo game in Godot, my editor of choice is neovim, and I have gotten very into isolating my code environments. With all of these factors in mind I set on a journey to make the Godot C# Flatpak work with nvim (including autocomplete, obviously).
This is my story.
The Short Version
System Setup: Fedora 42 - KDE Spin, Alacritty, Zsh
1 - Download the Godot Engine (C#/.NET) flatpak
2 - Download nvim-qt
(this was in the Fedora packages so I could just dnf install
it)
3 - Navigate to where Godot has installed dotnet (my path was /var/lib/flatpak/app/org.godotengine.GodotSharp/current/active/files/lib/dotnet
) and install the language server with ./dotnet tool install --global csharp-ls .
Remember this path since it's needed for the next step.
4 - Add export DOTNET_ROOT="/path/to/godot/flatpak/dotnet/you/found/above"
into your .zshenv
(not .zshrc
!)
5 - Add the c_sharp
language server to your nvim configs in whatever way you're used to. This nightmare process introduced me to Mason. So that was nice.
6 - In Godot in the Editor drop down open Editor Settings and find the External option under the Text Editor Heading
7 - Tick the box that says 'Use External Editor'. Set the Exec Path to flatpak-spawn
and the Exec Flags to --host nvim-qt
8 - When you double click a script in the Godot file system it should open in nvim-qt
your nvim config should load and you should have code completion
9 - If not I don't know what to tell you
NOTE: If things don't seem to be working it's usually worth logging in and out of your user account to make sure your zsh configurations are picked up.
The Long Version
So, I'm back to Linux on my main machine after a sojourn in Windows while writing my book[1]. Call me a senior citizen if you like, but I don't want LLMs anywhere near me and Microsoft's incessant pushing of its Artificial Bullshit Engine[2] was driving me up the wall. I need an operating system that knows its place.
Since I was already well on the road to becoming the Linux Greybeard of my dreams I decided it was time to move to vim as my primary code editor. Well, neovim, I'm not a complete savage. Yet.
I've wanted to be a neovim girly for awhile now. Yeah, I'm slow as hell, and clunky with a modal editor but I have committed just enough of the binds to memory that I am even slower and clunkier without it.
And hey, since I was rebuilding my system from scratch anyways I decided to do that developer thing that never actually works out -- set everything up The Right Way. Which, in this instance, means isolating my dev environments. Stars in my eyes, I dreamed of a setup where I wouldn't be carrying around old databases from cancelled contracts, and I could spin up old failed experiments to see how they worked instead of leaving them to rot after upgrading my ruby versions 12 times since last looking at it.
For most things, direnv and Jetify's devbox were getting me what I needed with basically no fuss. Sure I could learn Nix directly but I was happy. Yes, for a brief time, I knew happiness in my development environment.
Of course, there must always be a problem, and in this case it was that these days most of my personal dev work is solo developing a game in Godot.
Unity had been my favourite engine for a long while though lately I'd been less enchanted. The engine felt like it was falling into a mountain of half-baked, half-deprecated systems and was not sparking joy. Then there was The Debacle. It felt like a good time to play with Godot.
And, of course, despite flouncing dramatically away from Microsoft at the start of this project I remain a confirmed C# lover. Godot has a C# version. Everything was going to be great.
Eventually.
Obviously, there was a long road to get there. This is computers we're talking about.
Because of my newfound love of sandboxing, and code isolation I was happy to see that there was a Godot flatpak with C# included. I had honestly been dreading having to hook Godot into my happy little devbox/direnv workflow. The flatpak also kept my C# version pinned to Godot. In theory, this was all I ever wanted.
Just need to get it working with Neovim. Maybe it wouldn't be that hard.
I already knew I was lying to myself about the ease of the project before I began. Getting Neovim working with Godot had been annoying even when they were both installed locally on my Windows machine[3]. Put abstraction in there? Hoo boy.
But I rationalised that the result I wanted was pretty straightforward -- open my C# files from Godot, and use the C# language server running in the flatpak to do autocomplete in my host's nvim.
My first port of call was the Godotsharp Github issue about external editors. The saints who manage the package had a cool single line of code to open most editors. In fact, I got KWrite hooked into Godot instantly with flatpak-spawn. No fuss. But no matter how hard it tries KWrite cannot be nvim -- for one thing it isn't annoying as hell. But none of the flatpak-spawn
s I was trying could convince Godot to open a terminal with nvim.
While suffering through reading everything ever written about creating an unholy union between flatpaks and the host system I remembered something. Before I was fully ready to use nvim full time I had used vim mode in VSCode as training wheels, if training wheels made things somehow more opaque than learning to ride a bike. A lot of the people in that thread had VSCode working. Was there some kind of nvim GUI I could spawn? Turns out, yes, several.
The big player in the 'GUI for neovim' space is neovide so I opted to start there. There was a brief early success where Godot spawned neovide basically out of the box.
But here is when the two problems I had started to dovetail into one. Getting Godot to spawn my editor was the first problem, but making nvim see the flatpak installed C# version and use that for autocomplete was the other. So, even though I could get Godot to spawn the editor autocomplete wasn't working. At least, not when I spawned the editor with the flatpak -- on my local system autocomplete was working.
I'll cover making the LSP talk to nvim in a minute, but I want to finish talking about spawning the editor in Godot. You might say, I want to isolate the tech problems I was having. Har har.
At the end of the day, Neovide wasn't really a great solution for what I was doing anyways. The easiest way to make it work on Fedora was an AppImage (yet another sandbox's walls I would need to breach). I could also have built it from scratch, but hah, can you imagine? The idea of making a flatpak talk to an AppImage gave my the vapours and I was right on the edge of giving up my code isolation dream. Really, who cares how many versions of dotnet
you have installed anyways?
Fortunately, before I completely lost the plot I had the genius idea of looking up 'alternatives to neovide', and wouldn't you know it but nvim-qt
had been there in the Fedora repos this whole time. Just waiting to be dnf install
ed. Using flatpak-spawn nvim-qt
I had finally arrived at a system that opened neovim in Godot. I was more ecstatic than I should have been given how completely inconsequential this whole venture had been. But Godot, C#, and Neovim were all Voltron-ing together for me.
Let's rewind now, what was all the scuffle about neovide and the lsp?
As I may have said above (this post is getting long and I forget the start of it by now) -- the GodotSharp flatpak has dotnet
installed in it already. Of course, it's isolated from the rest of the system -- that was the whole goal, after all. Making my life a living hell was definitely the goal alright.
But, packages in flatpaks aren't, you know, fictional. They are there on the hard drive. In fact, if you navigate to the dependencies folder for the flatpak in your file system you can run dotnet
like a normal command. Of course, nvim can't see this install because it's contained in the flatpak. Again, this is the point. You can't talk to packages contained within the flatpak.
Unless you go absolutely buckwild with absolute paths that is.
So, I had this brain genius idea where I navigated to the dotnet install directory (see the short version above, which I'm sure you wish you had stopped at) and installed the C# LSP globally. After fumbling with my own configs for awhile, I capitulated and used Mason to install the lsp on the nvim side. Open the editor, and of course get buried in 8000 errors.
Not that this concerned me, I knew that the source of the errors was that nvim couldn't find the path to dotnet. If you need C# and no one has told you where it is it's understandable if you can't... find C#. Apparently, however, you can't tell the editor the path to C# by yelling at your laptop. And believe me, I tried that a lot.
All was not lost, and after two short full work days of bumbling in DuckDuckGo I did eventually find a way to set the dotnet
path in my .zshrc
-- and there was briefly much rejoicing.
However, this is where we need to scroll up a few paragraphs and recall that this was where the neovide issue cut in. Autocomplete was working locally, neovide being spawned by the flatpak and alas, the two could never meet.
Despite not being the answer to my prayers my time spent in neovide's Github issues[4] was not wasted because it contained the answer to making this whole house of cards work with nvim-qt
instead.
It was here that I learned that when a nvim gui gets spawned it doesn't run as an interactive shell[5].
When a shell isn't run as interactive it doesn't read your .zshrc
.
Which was coincidentally where I was putting the path.
When the non-interactive shell gets spawned it does, however, read your .zshenv
.
Slap that dotnet
path in the .zshenv
and wouldn't you know it? Autocomplete in nvim-qt being spawned by Godot.
It only took a week! A stupid, stupid week.
Post Show Comments
- Could this work jumping to line numbers?
- Hell, maybe, but it isn't something I was worried about. Sorry to the line number jumping fans in the audience.
- Can this be hooked into a debugger?
- God, I hope so. Debugger is life. I'm tired right now though.
- Does this work with Omnisharp?
- Also maybe. I'm completely happy with c_sharp though so I haven't tried.
- This doesn't work! Can you help me?
- Christ man, I can't even help myself.
Well, hopefully there's at least one other lunatic out there who wants to do this and I helped them out because I lost a lot of my life for something only I will ever use otherwise.
Scrivener doesn't have a native Linux version and I couldn't imagine how annoying fighting WINE would be when I wanted to write. Especially with how annoying WINE is at literally any other time. ↩︎
I miss when AI was about giving computers feelings (or mental illness). ↩︎
You have to do some stuff with nvim clients and servers, please don't ask, I honestly never really understood what I was doing. This isn't the guide I personally used but it's approximately what I did to get it working. ↩︎
Despite 5 long seconds of searching I cannot find the issue that lead me here and as a result I don't remember why I needed
nvim-qt
and not just neovide. ↩︎Please, I'm begging you. Don't ask me the difference between an interactable shell and a non-interactable. I don't know. I don't know anything anymore. ↩︎