A comprehensive Neovim plugin for C project management with build system detection, execution, testing, and debugging capabilities.
- Features
- Installation
- Commands
- Quick Start
- Configuration
- Storage
- Examples
- JSON Configuration Schema
- Dependencies
- Architecture
- Testing
- Related Projects
- License
- Contributing
- Roadmap
- Build System Detection: Automatically detects CMake and Makefile-based projects
- Project Execution: Build and run entire projects with async execution
- Test Runner: Execute tests with results in quickfix list
- Debug Integration: Auto-configure nvim-dap for GDB and CodeLLDB
- LSP Helper: Generate compile_commands.json for clangd and other LSP servers
- Interactive Configuration: Customize build, run, test, and debug settings via UI
- Persistent Storage: JSON-based configuration stored per-project
- Multi-Build Support: Handle projects with multiple build systems with preference storage
Using lazy.nvim
{
'michael-duren/neo-c.nvim',
ft = 'c', -- Lazy load on C files
dependencies = {
'MunifTanjim/nui.nvim', -- Optional: for better UI
'mfussenegger/nvim-dap', -- Optional: for debugging support
},
config = function()
require('neo-c').setup({
-- Your custom configuration here (optional)
})
end,
}Using packer.nvim
use {
'michael-duren/neo-c.nvim',
ft = 'c', -- Lazy load on C files
requires = {
'MunifTanjim/nui.nvim', -- Optional: for better UI
'mfussenegger/nvim-dap', -- Optional: for debugging support
},
config = function()
require('neo-c').setup({
-- Your custom configuration here (optional)
})
end,
}
Create a new C project from interactive templates. Available globally in Neovim.
:NewCProjectFeatures:
- Interactive project name and location selection
- Three project templates:
- Simple: Single
main.cfile for quick prototyping - CMake: Modern CMake-based project with src/, include/, and tests/ directories
- Makefile: Traditional Makefile-based project with organized directory structure
- Simple: Single
- Automatically creates README.md with build instructions
- Option to immediately open the newly created project
Templates include:
Simple Template:
main.c- Single source fileREADME.md- Basic documentation
CMake Template:
CMakeLists.txt- CMake configuration with compile_commands.json generationsrc/main.c- Main source fileinclude/- Header files directorytests/CMakeLists.txt- Test configurationtests/test_main.c- Basic test fileREADME.md- Build and test instructions
Makefile Template:
Makefile- Complete Makefile with build, run, clean targetssrc/- Source files directoryinclude/- Header files directoryobj/- Object files directory (created during build)bin/- Binary output directoryREADME.md- Build instructions
Use case: Quickly scaffold new C projects with proper structure and build configuration.
Quick compile and run the current buffer without needing project detection.
:CRunFeatures:
- Compiles current C file with
gcc -Wall -Wextra -std=c11 - Outputs to
/tmp/makec/a.out - Runs immediately after successful compilation
- Opens in a split terminal
- Compilation errors populate quickfix list
- Perfect for quick testing and single-file programs
Use case: When you want to quickly test a single C file without setting up a full project.
Detect all build systems in the current project and store configuration.
:CDetectDetects:
- CMake projects (CMakeLists.txt)
- Makefile projects (Makefile)
Stores configuration in ~/.local/share/nvim/neo-c/projects/<sha256>.json
Build the entire project using the detected build system.
:CRunProjectFeatures:
- Async execution with vim.loop
- CMake configure step handled automatically
- Build errors populate quickfix list
- Handles multi-build-system projects with selection prompt
Build and run the entire project.
:CRunProjectRunRuns the custom run command configured via :CConfig after successful build.
Run project tests.
:CTestSupports:
- CTest for CMake projects
make testfor Makefile projects- Custom test commands via
:CConfig
Start a debugging session with auto-configured nvim-dap.
:CDebugFeatures:
- Auto-detects program path from run command
- Supports GDB and CodeLLDB adapters
- Saves debug configuration for reuse
Requirements: nvim-dap
Generate compile_commands.json for LSP servers.
:CGenerateCompileCommands- CMake: Symlinks from
build/compile_commands.jsonto project root - Make: Uses Bear to generate
Interactive configuration menu.
:CConfigOptions:
- Set build system (for multi-build projects)
- Set run command
- Set test command
- Set debug program path
- Set debug adapter (gdb/codelldb)
- Set compiler flags
- Open a C file in Neovim
- Run
:CRunto compile and execute immediately
- Navigate to a C project with CMake or Makefile
- Run
:CDetectto detect the build system - Run
:CConfigto set a run command (e.g.,./build/my-project) - Run
:CRunProjectRunto build and execute your project
The plugin works out-of-the-box with sensible defaults. No configuration is required.
To customize the plugin, call setup() in your Neovim config:
require('neo-c').setup({
-- Keybindings configuration
keybindings = {
enabled = true, -- Set to false to disable all keybindings
run = '<leader>cr', -- Compile and run current buffer
detect = '<leader>cd', -- Detect build systems
build = '<leader>cb', -- Build project
build_and_run = '<leader>cR', -- Build and run project
test = '<leader>ct', -- Run tests
debug = '<leader>cD', -- Start debugging
generate_compile_commands = '<leader>cl', -- Generate compile_commands.json
config = '<leader>cc', -- Open configuration menu
-- Global keybindings (available everywhere, not just in C buffers)
global = {
new_project = '<leader>cn', -- Create a new C project
},
},
-- Compiler options for CRun command
compiler = {
executable = 'gcc',
flags = {'-Wall', '-Wextra', '-std=c11'},
output_dir = '/tmp/makec',
},
})| Keybinding | Command | Description |
|---|---|---|
<leader>cn |
:NewCProject |
Create a new C project |
The following keybindings are automatically set when opening C files (.c extension):
| Keybinding | Command | Description |
|---|---|---|
<leader>cr |
:CRun |
Compile and run current buffer |
<leader>cd |
:CDetect |
Detect build systems |
<leader>cb |
:CRunProject |
Build project |
<leader>cR |
:CRunProjectRun |
Build and run project |
<leader>ct |
:CTest |
Run tests |
<leader>cD |
:CDebug |
Start debugging |
<leader>cl |
:CGenerateCompileCommands |
Generate compile_commands.json |
<leader>cc |
:CConfig |
Open configuration menu |
Note: These keybindings use <leader>c as the prefix (e.g., if your leader is <Space>, press <Space>cn to create a new project or <Space>cr to run current buffer).
Disable all keybindings:
require('neo-c').setup({
keybindings = {
enabled = false,
},
})Use custom keybindings:
require('neo-c').setup({
keybindings = {
run = '<F5>', -- Press F5 to compile and run
build = '<F7>', -- Press F7 to build project
debug = '<F9>', -- Press F9 to debug
test = '<leader>tt', -- Custom prefix
-- Set any binding to false to disable it
config = false, -- Disable :CConfig keybinding
-- Customize global keybindings
global = {
new_project = '<leader>np', -- Custom keybinding for new project
},
},
})Customize compiler settings:
require('neo-c').setup({
compiler = {
executable = 'clang', -- Use clang instead of gcc
flags = {'-Wall', '-Wextra', '-std=c17', '-O2'}, -- Custom flags
output_dir = '/tmp/my-c-builds', -- Custom output directory
},
})Project configurations are stored in:
- Linux/macOS:
~/.local/share/nvim/neo-c/projects/<sha256>.json - Windows:
%LOCALAPPDATA%\nvim-data\neo-c\projects\<sha256>.json
Each project is identified by SHA256 hash of its path.
# Open a simple C file
nvim hello.c:CRun " Compile and run immediatelyhello.c:
#include <stdio.h>
int main(void) {
printf("Hello, World!\n");
return 0;
}After :CRun, the program compiles to /tmp/makec/a.out and runs in a split terminal.
# In a CMake project directory
nvim:CDetect " Detect CMake
:CConfig " Set run command: ./build/my-app
:CRunProjectRun " Build and run
:CTest " Run tests
:CGenerateCompileCommands " Generate for clangd
:CDebug " Start debugging# In a Makefile project directory
nvim:CDetect " Detect Makefile
:CConfig " Set run command: ./bin/program
:CRunProject " Build only
:CTest " Run make test# Project with both CMakeLists.txt and Makefile
nvim:CDetect " Detects both
:CRunProject " Prompts for selection
" Select [1] CMake
" Choice is remembered
:CRunProject " Uses CMake (no prompt){
"version": "1.0",
"project_path": "/path/to/project",
"project_name": "my-project",
"detected_at": "2026-02-15T10:30:00Z",
"build_systems": [
{
"type": "cmake",
"detected": true,
"file": "CMakeLists.txt",
"build_dir": "build",
"commands": {
"configure": "cmake -B build -S . -DCMAKE_EXPORT_COMPILE_COMMANDS=1",
"build": "cmake --build build",
"clean": "cmake --build build --target clean",
"test": "ctest --test-dir build --output-on-failure"
},
"targets": ["all", "clean", "test"],
"compile_commands_path": "build/compile_commands.json"
}
],
"selected_build_system": "cmake",
"custom_commands": {
"run": "./build/my-project"
},
"compiler": {
"cc": "gcc",
"cxx": "g++",
"cflags": ["-Wall", "-Wextra", "-std=c11"]
},
"debug_config": {
"adapter": "gdb",
"program": "./build/my-project",
"args": []
}
}- Neovim 0.8+ (for vim.json and vim.loop)
- nui.nvim - For better UI (falls back to vim.fn.input)
- nvim-dap - For debugging support
- Bear - For compile_commands.json generation with Make
- Storage Layer: JSON persistence using
vim.jsonandstdpath('data') - Detection Layer: File-based build system detection with priority ordering
- Execution Layer: Async job execution using
vim.loop(libuv) - UI Layer: Interactive configuration using nui.nvim with fallback
- Integration Layer: LSP, DAP, and quickfix integration
neo-c.nvim includes a comprehensive test suite using plenary.nvim.
# Run all tests
make test
# Or directly
./tests/run_tests.sh
# Run specific test suites
make test-storage
make test-utils
make test-detect
make test-executor- storage_spec.lua (20 tests): Config persistence, JSON serialization, project ID generation
- utils_spec.lua (25 tests): Project root detection, path utilities
- detect_spec.lua (30 tests): Build system detection, target parsing
- executor_spec.lua (28 tests): Async/sync execution, command handling
Total: 103 test cases covering all core functionality.
See tests/README.md for detailed documentation on writing and running tests.
Tests run automatically on every push via GitHub Actions across multiple platforms (Ubuntu, macOS) and Neovim versions (stable, nightly).
- build.nvim - Build system detection
- compiler.nvim - Multi-language compilation
- cmake-tools.nvim - CMake-specific tools
MIT License - See LICENSE file for details
Contributions are welcome! Please open an issue or pull request.
- Support for additional build systems (Meson, Ninja, Autotools)
- Enhanced Makefile target parsing
- CMake target extraction from CMakeLists.txt
- Build output parsing and error highlighting
- C extension for performance-critical parsing
- Project templates (like CStart from original research)
- Integration with telescope.nvim for target selection