neovim/neovim
OS and platform
Purpose
src/nvim/os/ is the platform-abstraction layer. It is the only directory in the C tree that knows about Unix vs Windows differences, ptys, environment variables, signal handling, and stdpaths. Everything above os/ calls into it through a uniform C interface; everything below is libuv plus a handful of platform-specific syscalls.
Directory layout
src/nvim/os/
├── defs.h, os.h, os_defs.h Common types
├── unix_defs.h, win_defs.h Per-platform typedefs
├── env.c Environment variable handling (35k bytes)
├── fs.c File-system primitives (40k bytes)
├── fileio.c Buffered file I/O
├── input.c Read input from stdin / TUI
├── lang.c Locale and language detection
├── proc.c Process info / signals
├── pty_proc_unix.c, _win.c PTY implementations
├── pty_conpty_win.c Windows conpty-specific
├── shell.c `:!cmd` and shell escaping (40k bytes)
├── signal.c SIGINT / SIGWINCH / SIGTERM
├── stdpaths.c XDG paths (config, data, state, cache, log, run)
├── time.c Wall clock + monotonic
├── users.c System user lookup
├── dl.c dlopen wrapper for `libcall()`
├── os_win_console.c Windows console mode
└── nvim.{manifest,rc} Win32 resource filesKey abstractions
| Function family | File | Purpose |
|---|---|---|
os_getenv, os_setenv, os_unsetenv |
env.c |
Environment access. Wraps libuv plus locale-aware logic. |
os_fileinfo, os_path_exists, os_isdir |
fs.c |
Stat-like probes. |
os_open, os_read, os_write, os_close |
fs.c |
File handle ops. |
os_resolve_shortcut, os_realpath |
fs.c |
Path resolution. |
os_call_shell, os_system |
shell.c |
Run an external program, optionally capture output. |
os_get_hostname, os_get_pid |
various | Lightweight info. |
os_proc_* |
proc.c |
Process metadata (pid, parent, cwd). |
pty_proc_* |
pty_proc_unix.c/_win.c |
Spawn a child under a pty (used by :terminal). |
stdpaths_get_xdg_var, stdpaths_user_*_subpath |
stdpaths.c |
XDG-compliant data/config paths. |
os_inchar |
input.c |
Block on stdin and return bytes. |
os_breakcheck |
input.c |
Probe for pending CTRL-C without consuming a key. |
How it works
The most-touched function on this list is os_breakcheck. It is what makes Neovim responsive to <C-c> even inside a long-running operation: a hot loop in the editor calls os_breakcheck() periodically, which polls libuv for a single byte and sets got_int if it sees <C-c>. Functions that may take a long time (regex, substitution, :edit of a huge file) bail out as soon as got_int becomes true.
The trade-off: any function that calls os_breakcheck() is not re-entrant. That is why API functions marked api-fast are forbidden from calling it. See Patterns and conventions.
Filesystem path policy
From runtime/doc/dev_arch.txt: forward slashes everywhere except at the edges. The conversion sites are:
src/nvim/path.c#slash_adjust— convert outgoing paths to native separators.src/nvim/os/fs.c#FS_PATHcalls — input from libuv.src/nvim/path.c#path_to_absolute— combine with cwd.
Windows accepts forward slashes for nearly all syscalls anyway. The conversion exists to make user-visible output match platform conventions (e.g., :pwd prints \ on Windows).
stdpaths
os/stdpaths.c implements XDG Base Directory Specification on Linux/macOS and the Windows equivalent (using FOLDERID_RoamingAppData etc.) on Windows. The user-facing API is stdpath('config' | 'data' | 'cache' | 'state' | 'log' | 'run') in Vimscript and vim.fn.stdpath(...) in Lua. The same paths drive where Neovim looks for init.lua, where shada is written, and where $NVIM_LOG_FILE defaults.
ptys
pty_proc_unix.c opens /dev/ptmx, sets up the child controlling-tty, and spawns through libuv. pty_proc_win.c uses ConPTY (pty_conpty_win.c) on Windows 10+; older Windows fell back to winpty but that path has been removed.
:terminal, vim.system({pty=true}), and jobstart({pty=1}) all flow through these. The vendored libvterm in src/nvim/vterm/ is the in-process terminal emulator that interprets the bytes coming back; see Embedded terminal.
Shell execution
os/shell.c is the largest file in this directory (40 KB). It implements os_call_shell() and os_system() — the workhorses behind :!cmd, system(), systemlist(), and (historically) :make. The bulk of the file is shell-quoting and pipe-handling logic: every shell on every platform escapes arguments slightly differently.
Modern Lua-side code prefers vim.system({argv}) (runtime/lua/vim/_core/system.lua) which spawns directly via libuv and skips the shell entirely.
Integration points
- Event loop — every async syscall goes through libuv. The OS layer just provides the convenience wrappers.
- Buffer I/O —
bufwrite.candfileio.ccall intoos/fs.cfor the actual reads/writes. :terminal— combinesos/pty_proc_*.c+src/nvim/terminal.c+src/nvim/vterm/.- Lua
vim.fs—runtime/lua/vim/fs.luawraps a subset ofos/fs.cplus libuv FS functions for plugin authors. vim.system—runtime/lua/vim/_core/system.luais the Lua front end toos/proc.c+ libuv.
Entry points for modification
- A new platform-abstracted call: add it to
src/nvim/os/<area>.cwith a stub for the other platform. The naming convention isos_<verb>_<noun>. - A new XDG path: edit
os/stdpaths.cand add the correspondingXDG_<NAME>_HOMEenum. - A new shell quirk: most likely a one-line change in
os/shell.c; the file's structure is "switch on the user's shell, escape accordingly".
Key source files
| File | Purpose |
|---|---|
src/nvim/os/fs.c |
File-system primitives (open/read/write/stat/realpath) |
src/nvim/os/env.c |
Environment variable handling and locale-aware lookups |
src/nvim/os/shell.c |
External shell invocation, quoting, capture |
src/nvim/os/input.c |
Stdin reader, os_breakcheck |
src/nvim/os/proc.c |
Process metadata and signals |
src/nvim/os/pty_proc_unix.c |
Unix pty spawning |
src/nvim/os/pty_proc_win.c |
Windows ConPTY spawning |
src/nvim/os/stdpaths.c |
XDG path resolution |
src/nvim/os/time.c |
Wall clock + monotonic helpers |
src/nvim/os/dl.c |
dlopen wrapper for libcall() |
src/nvim/os/signal.c |
Process signal handlers |
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.