Skip to content

Repository files navigation

nimo

Nim Terminal Text Editor.

A small, friendly terminal text editor written in Nim using only the standard library. It's nano-inspired (discoverable shortcuts, a hint bar at the bottom) but comfortable for people coming from VSCode: a file-tree sidebar shows the whole working directory, editor tabs sit across the top, and the mouse works for clicking files, switching tabs and placing the cursor.

nimo editing its own source tree

Features

  • A file-tree sidebar of the current working directory, shown by default.
  • Editor tabs with a modified dot, closable with the mouse or Ctrl+W; the strip scrolls sideways when more tabs are open than fit.
  • Mouse support: click a file to open it, click a tab to switch, and use the wheel to scroll whichever pane the pointer is over.
  • UTF-8-aware editing with undo/redo and a save-point indicator.
  • Smart-case search, go-to-line, and word-wise cursor movement.
  • Ctrl+Z suspends back to the shell and resumes cleanly with fg.
  • No external libraries — the Nim standard library is the only requirement.

Platforms

Linux, macOS/BSD and Windows share one codebase; only term.nim differs.

PlatformStatus
LinuxSupported (tested on 2.2.10)
macOS / BSDSupported (same POSIX backend)
Windows 10 1703+Supported (tested on 10.0.19045 with Nim 2.2.4 + mingw64)

On Windows the console is switched into VT mode (ENABLE_VIRTUAL_TERMINAL_INPUT / ENABLE_VIRTUAL_TERMINAL_PROCESSING), so it speaks the same escape sequences as a POSIX terminal and the whole decoder is shared. Two differences are unavoidable there:

  • Ctrl+Z suspend needs job control, which Windows has no equivalent for. The key reports that it is unavailable and the hint bar advertises ^G Goto instead.
  • Window resize is polled rather than delivered by SIGWINCH.
  • Bracketed paste is unavailable: the legacy console never implemented it and ConPTY strips the markers, so a paste arrives as ordinary keystrokes. Pasting is still fast — the input loop drains a whole burst before repainting — but each pasted character is its own undo step, so Ctrl+U after a paste undoes one character at a time rather than the paste as a whole.

Windows Terminal is recommended over the legacy console host, particularly for mouse support. Files are written with \n line endings on every platform.

Build

Requires Nim >= 2.0 (tested on 2.2.10). No dependencies to fetch.

nim c -d:release --out:nimo src/nimo.nim

Or via nimble:

nimble build # produces ./nimo
nimble run # build + open the current directory

Run

./nimo # open the editor rooted at the current directory
./nimo path/file # open (or create) a specific file

Keybindings

Everywhere

KeyAction
Ctrl+SSave (prompts for a name if the buffer has none)
Ctrl+XQuit (Ctrl+Q also works; asks to confirm if anything is unsaved)
Ctrl+BToggle the file-tree sidebar
Ctrl+OMove focus to the file tree to browse and open
Ctrl+ZSuspend to the shell (resume with fg; POSIX only)
Shift+TabSwitch focus between the editor and the tree

Editor pane

KeyAction
Arrows / Home / EndMove the cursor
Ctrl+← / Ctrl+→Move by word
Ctrl+Home / Ctrl+EndJump to start / end of file
PageUp / PageDownScroll by a screen
Ctrl+FFind (smart-case; Ctrl+N repeats the last search)
Ctrl+GGo to line number
Ctrl+U / Ctrl+RUndo / redo (Ctrl+Y also redoes)
Ctrl+A / Ctrl+EStart / end of line (nano-style)
Ctrl+WClose the current tab
Ctrl+PageUp / Ctrl+PageDownSwitch to the previous / next tab

File-tree pane

KeyAction
/ Move the selection
/ Expand / collapse (or step into / out of) a folder
EnterOpen a file, or expand/collapse a folder
nCreate a new file in the selected folder
r / F5Refresh the tree from disk
TabReturn focus to the editor

Mouse

ActionResult
Click a tree entryOpen the file, or expand/collapse the folder
Click a tabSwitch to it; click its × / marker to close
Click the / chevronsScroll the tab strip when it overflows
Click in the textPlace the cursor there
Scroll wheelScroll the tree, the text, or the tab strip under the pointer

Design notes

The code splits into four modules. term.nim handles raw mode, key and mouse decoding, bracketed paste, window resize and shell suspend; it holds the two platform backends (termios/signals on POSIX, the console API on Windows) behind one interface, with the escape-sequence decoder shared between them. textbuffer.nim is the editing core: UTF-8 aware, with tab-expansion display math, an undo/redo journal and smart-case search. filetree.nim is the lazy, cached sidebar model. nimo.nim wires them together with the rendering and input loop.

Each open file is its own buffer with its own cursor and scroll position. Opening a file from the tree switches to its tab when it is already open, so nothing is discarded behind your back. Cursor movement, deletion and horizontal scrolling all count whole runes and their on-screen display columns, and the modified dot in the status bar tracks the exact save point, so undoing back past a save clears it. Files that look binary, or that exceed 20 MB, are refused rather than mangled.

Tests

nim c -r tests/test_buffer.nim # unit tests for the editing core
python3 tests/pty_smoke.py # drives the real TUI through a pty
python3 tests/pty_suspend.py # checks Ctrl+Z suspend / resume

The first two run in CI. pty_suspend.py is local-only, because POSIX discards SIGTSTP sent to an orphaned process group, so Ctrl+Z cannot stop the process on a CI runner with no interactive session.

Screenshot

The image above is generated from this repository with scripts/screenshot.sh, which drives nimo inside a tmux pane and renders the captured screen with freeze.

Releases

Packages

Contributors

Languages