Hey everyone! As a developer juggling subscriptions to Gemini, GitHub Copilot, and JetBrains, I'm always looking for the right tool for the job. This past week, I've been in the trenches with my own suite of Neovim plugins for Unreal Engine development. It's one thing to build a tool; it's another to actually live in it.
This is the story of my one-week dogfooding sprint, the painful discoveries I made, and the improvements that followed.
The Brutal Truth: My Own Plugin Was Unusable
After using my plugins full-time for a few days, one conclusion hit me hard:
ULG.nvim
was hopelessly unusable and fundamentally lacked features.
A plugin designed for viewing logs was failing at its primary job. I couldn't in good conscience continue developing it without making it a tool I'd actually want to use myself. So, I spent the week focused on fixing it.
The Fixes: What I Added to ULG.nvim
Here are the key improvements I implemented to make the plugin genuinely useful.
1. Build Log Highlighting
I added color-coding for error and warning lines. This seems basic, but it makes a world of difference when you're trying to spot problems in a massive wall of text from the build system.
2. Go-to-Error on a Single Keystroke
This was a must-have. I implemented a feature to jump directly from an error line in the log to the corresponding source file and line number. It's a fundamental IDE feature that was sorely missing.
3. Taming Live Coding Logs
Live Coding is a critical feature for fast iteration in Unreal C++. I made several changes to integrate it properly:
-
Improved
tail
processing: The real-time log monitoring is now more robust. - Path resolution: The plugin now correctly handles the different log paths used by the Epic Games Launcher version of the engine vs. a source-built version from GitHub.
- User-configurable path: I added an option for users to specify a custom log file path directly in the plugin's settings, making it adaptable to any environment.
4. Running stat
Commands from Anywhere
I added a dedicated command to run console commands like stat fps
and stat unit
directly from Neovim, without needing to have the Unreal Editor's output log window open and focused.
With these changes, ULG.nvim
finally feels like a practical and powerful tool.
My lazy.nvim
Setup: The Grand Unification
With the improvements in place, here is my current lazy.nvim
configuration. It manages all my Unreal Engine plugins in one place.
-- lua/plugins/unreal.lua
local is_open_ui = false
return {
-- UEP.nvim is in development, so I'm using a local path
dir = '~/Documents/git/UEP.nvim/',
dev = true,
-- Load when a C++/C file is opened
ft = { "cpp", "c" },
-- Allow loading via command
cmd = { "UEP" },
-- Allow loading via keymap
keys = {
{ '<c-f>', '<cmd>UEP files --all-deps<CR>', mode = 'n' },
},
-- Dependencies
dependencies = {
"j-hui/fidget.nvim",
"nvim-telescope/telescope.nvim",
"taku25/UNL.nvim",
"taku25/UBT.nvim",
"taku25/UCM.nvim",
"taku25/USH.nvim",
},
opts = {},
config = function(_, opts)
require("UEP").setup(opts)
-- Keymap for switching between header/source files
vim.keymap.set("n", "<leader>a", function()
require("UCM.api").switch_file()
end, { noremap = true, silent = true })
-- A smart keymap for build / live coding
vim.keymap.set("n", "<C-s>", function()
local unl_api = require("UNL.api")
-- Check if the Unreal Editor process is running
unl_api.is_process_running("UnrealEditor", function(is_running)
if is_running then
-- If it's running, trigger a Live Coding compile
require("ULG.api").remote_command("livecoding.compile")
else
-- If not, run a normal build
require("UBT.api").build({})
end
end)
end, { noremap = true, silent = true })
-- Auto-open IDE-like UI
local open_ui = function()
if is_open_ui == true then
return
end
local project = require("UNL.api").find_project(vim.loop.cwd())
if project and project.root then
require("UEP.api").tree() -- Show project tree in neo-tree
require("ULG.api").start() -- Show the log window
is_open_ui = true
end
end
vim.api.nvim_create_autocmd("FileType", {
pattern = { "cpp", "c" },
callback = function()
open_ui()
end,
})
open_ui()
end,
}
Here are the key takeaways from this setup:
- Lazy-loading based on filetype: All the Unreal Engine plugins are loaded together as soon as I open a C++ or C file.
-
IDE-like automatic UI: When I open a C++/C file inside a
.uproject
directory, it automatically opens aneo-tree
view of my project and theULG.nvim
log window. It’s a little heavy, but it's still way faster than launching a full IDE. -
Header/Source Switching: A simple
<leader>a
lets me instantly toggle between.cpp
and.h
files. -
Smart Build/Live Coding Key: My favorite feature.
<C-s>
is now a context-aware build key. It checks if Unreal Editor is running. If it is, it triggers a Live Coding compile. If not, it runs a full build. This lets me use a single key for the optimal build action in any situation.
Putting It All Together: Live Coding in Action
Here’s a look at the workflow, triggering a Live Compile from Neovim with <C-s>
while the editor is running.
I think this is starting to get pretty convenient!
A New Challenger Appears: USH.nvim
While working on this, I learned about an official interactive shell called ushell
from a post on Reddit. This inspired me to create a new plugin to integrate it with Neovim.
I'll be writing more about this one soon!
Wrapping Up
There's still a lot of room for improvement, but the environment for using Neovim as a main IDE for Unreal Engine development is steadily coming together.
To a great "Unreal Engine on Neovim" life, Cheers! 🍻
Top comments (0)