o
is a text editor limited to the VT100 standard.
It might be a good fit for:
- Editing git commit messages (using
EDITOR=o git commit
). - Editing
README.md
andTODO.md
files. - Write Markdown files and then export to PDF.
- Learning "up and coming" programming languages, like Zig or Rust.
- Editing files deep within larger Go or C++ projects.
- Solving Advent of Code tasks.
- Writing and maintaining to-do lists and project documentation in Markdown.
For a more feature complete editor that is also written in Go, check out micro.
You can install o
with Go 1.10 or later:
go get -u github.com/xyproto/o
To set:
git config --global core.editor o
To unset:
git config --global --unset core.editor
These features are unique to o
, as far as I am aware:
- Smart cursor movement, trying to maintain the X position when moving up and down, across short and long lines.
- Press
ctrl-v
once to paste one line, pressctrl-v
again to paste the rest. - Press
ctrl-c
once to copy one line, pressctrl-c
again to copy the rest (until a blank line). - Open or close a portal with
ctrl-r
. When a portal is open, copy lines across files (or within the same file) withctrl-v
. - Build code with
ctrl-space
and format code withctrl-w
, for a wide range of programming languages. - Press
ctrl-w
to toggle the checkmark in- [ ] TODO item
boxes in Markdown. - Cycle git rebase keywords with
ctrl-r
, when in an interactive git rebase session. - Jump to a line with
ctrl-l
. Either enter a number to jump to a line or just pressreturn
to jump to the top. Pressctrl-l
andreturn
again to jump to the bottom. - All text will be red if the loaded file is read-only.
- If tab completion in the terminal went wrong and you are trying to open a
main.
file that does not exist, butmain.cpp
andmain.o
does exists, thenmain.cpp
will be opened.
- Loads up instantly.
- Configuration-free, for better and for worse.
- Can render text to PDF.
- Compile
"Hello, World"
in many popular programming languages simply by pressingctrl-space
. ctrl-t
can jump between a C++ header and source file.- Provides syntax highlighting for Go, C++, Markdown, Bash and several other languages. There is generic syntax highlighting.
- The syntax highlighting is instant.
- Will jump to the last visited line when opening a recent file.
- Is provided as a single self-contained executable.
- Tested with
alacritty
,st
,urxvt
,konsole
andxfce4-terminal
. - Tested on Arch Linux, Debian and FreeBSD.
- Loads faster than both
vim
andemacs
. - Never asks before saving or quitting. Be careful!
- The
NO_COLOR
environment variable can be set to disable all colors. - Rainbow parentheses makes lines with many parentheses easier to read.
- Limited to the VT100 standard, so hotkeys like
ctrl-a
andctrl-e
must be used instead ofHome
andEnd
. - Compiles with either
go
orgccgo
. - Will strip trailing whitespace whenever it can.
- Must be given a filename at start.
- May provide smart indentation.
- Requires that
/dev/tty
is available. xclip
(for X) orwl-clipboard
(for Wayland) must be installed if the system clipboard should be used.- May take a line number as the second argument, with an optional
+
prefix. - If the filename is
COMMIT_EDITMSG
, the look and feel will be adjusted for git commit messages. - Supports
UTF-8
, but some runes may be displayed incorrectly. - Only UNIX-style line endings are supported (
\n
). - Will convert DOS/Windows line endings (
\r\n
) to UNIX line endings (just\n
), whenever possible. - Will replace non-breaking space (
0xc2 0xa0
) with a regular space (0x20
) whenever possible. - If interactive rebase is launched with
git rebase -i
, then eitherctrl-w
orctrl-r
will cycle the keywords for the current line (fixup
,drop
,edit
etc). - When editing Markdown, checkboxes can be toggled with
ctrl-w
. - If the editor executable renamed to
red
(or have a symlink with that name), the default theme will be red/white/gray. - If the editor executable renamed to
light
(or have a symlink with that name), the default theme will be suitable for light backgrounds. - Want to quickly convert Markdown to PDF and have pandoc installed? Try
o filename.md
, pressctrl-space
twice and quit withctrl-q
. o
is written mostly ino
, with some use of NeoViM at the beginning.
- In some terminal emulators, scrolling quickly up or down with the arrow keys can make the text jump around (it works fine in
alacritty
). Scroll up and down withctrl-n
andctrl-p
instead to avoid this. Pressesc
to repaint the text, if needed. - Some unicode runes may disrupt the text flow. This is generally not a problem for editing code and configuration files, but may be an issue when editing files that contains text in many languages.
- For some terminal emulators, if
o
is busy performing an operation, pressingctrl-s
may lock the terminal. Some terminal emulators, likekonsole
, can be configured to turn off this behavior. Pressctrl-q
to unlock the terminal again (together with the unfortunate risk of quittingo
). You can also use thectrl-o
menu for saving and quitting. o
may have issues with large files (of several MB+). For normal text files or source code files, this is a non-issue.- Middle-click pasting (instead of pasting with
ctrl-v
) may have issues with only pasting the first character. - The smart indentation is not always smart.
ctrl-s
- Save.ctrl-q
- Quit.ctrl-r
- Open or close a portal. Text can be pasted from the portal into another file withctrl-v
. For "git interactive rebase" mode (git rebase -i
), this will cycle the rebase keywords.ctrl-w
- Format the current file (see the table below).ctrl-a
- Go to start of text, then start of line and then to the previous line.ctrl-e
- Go to end of line and then to the next line.ctrl-p
- Scroll up 10 lines, or go to the previous match if a search is active.ctrl-n
- Scroll down 10 lines, or go to the next match if a search is active.ctrl-k
- Delete characters to the end of the line, then delete the line.ctrl-g
- Toggle a status line at the bottom for displaying: filename, line, column, Unicode number and word count.ctrl-d
- Delete a single character.ctrl-t
- Render the current document to a PDF file. For C++, toggle between header and implementation files.ctrl-o
- Open a command menu with actions that can be performed. The first menu item is alwaysSave and quit
.ctrl-x
- Cut the current line. Press twice to cut a block of text (to the next blank line).ctrl-c
- Copy one line. Press twice to copy a block of text.ctrl-v
- Paste one trimmed line. Press twice to paste multiple untrimmed lines.ctrl-space
- Build (see table below)ctrl-j
- Join lines (or jump to the bookmark, if set).ctrl-u
- Undo (ctrl-z
is also possible, but may background the application).ctrl-l
- Jump to a specific line number. Follows byreturn
to jump to the top. If at the top, pressreturn
to jump to the bottom.ctrl-f
- Search for a string. The search wraps around and is case sensitive.esc
- Redraw the screen and clear the last search.ctrl-b
- Toggle a bookmark for the current line, or if set: jump to a bookmark on a different line.ctrl-\
- Comment in or out a block of code.ctrl-~
- Jump to a matching parenthesis.
When editing PKGBUILD
files, it is possible to press ctrl-o
and select Call Guessica
to update the pkgver=
and source=
fields, by a combination of guesswork and online searching.
guessica
must be installed for this feature to work.
- At the press of
ctrl-space
,o
will try to build or export the current file. - At the press of
ctrl-w
,o
will try to format the current file, in an opinionated way.
Programming language | File extensions | Jump to error | Build command | Format command ($filename is a temporary file) |
---|---|---|---|---|
Go | .go |
yes | go build |
goimports -w -- $filename |
C++ | .cpp , .cc , .cxx , .h , .hpp , .c++ , .h++ , .c |
yes | cxx |
clang-format -fallback-style=WebKit -style=file -i -- $filename |
Rust | .rs |
yes | rustc $filename |
rustfmt $filename |
Rust, if Cargo.toml or ../Cargo.toml exists |
.rs |
yes | cargo build |
rustfmt $filename |
Zig | .zig |
yes | zig build-exe -lc $filename |
zig fmt $filename |
V | .v |
yes | v build |
v fmt $filename |
Haskell | .hs |
yes | ghc -dynamic $filename |
brittany --write-mode=inplace $filename |
Python | .py |
yes | python -m py_compile $filename |
autopep8 -i --maxline-length 120 $filename |
Crystal | .cr |
yes | crystal build --no-color $filename |
crystal tool format $filename |
Kotlin | .kt |
yes | kotlinc $filename -include-runtime -d |
ktlint |
Kotlin, if kotlinc-native is installed |
.kt |
yes | kotlinc-native -nowarn -opt -Xallocator=mimalloc -produce program -linker-option '--as-needed' $filename |
ktlint |
Java | .java |
yes | javac + jar , see details below |
google-java-format -i $filename |
Scala | .scala |
yes | scalac + jar , see details below |
WIP |
Lua | .lua |
yes | luac |
lua-format -i --no-keep-simple-function-one-line --column-limit=120 --indent-width=2 --no-use-tab $filename |
Object Pascal | .pas , .pp , .lpr |
yes | fpc |
WIP |
Nim | .nim |
WIP | nim c |
WIP |
Odin | .odin |
yes | odin build |
N/A |
/etc/fstab
files are also supported, and can be formatted with ctrl-w
if fstabfmt
is installed.
| Markup language | File extensions | Jump to error | Format command ($filename is a temporary file) |
| HTML | .htm
, .html
| no | tidy -w 120 -q -i -utf8 --show-errors 0 --show-warnings no --tidy-mark no --force-output yes -ashtml -omit no -xml no -m -c
|
o
will try to jump to the location where the error is and otherwise displaySuccess
.- For regular text files,
ctrl-w
will word wrap the lines to a length of 99. - If
kotlinc-native
is not available, this build command will be used instead:kotlinc $filename -include-runtime -d $name.jar
CXX can be downloaded here: GitHub project page for CXX.
File type | File extensions | Build or export command |
---|---|---|
AsciiDoc | .adoc |
asciidoctor -b manpage (writes to out.1 ) |
scdoc | .scd , .scdoc |
scdoc (writes to out.1 ) |
Markdown | .md |
pandoc -N --toc -V geometry:a4paper (writes to $filename.pdf ) |
If guessica
is installed, PKGBUILD
files will be updated at the press of ctrl-w
. The guessica
utility tries to guess the latest project version, tag and git commit hash for a PKGBUILD
file and may or may not succeed.
On Linux:
git clone https://github.com/xyproto/o
cd o
go build -mod=vendor
sudo install -Dm755 o /usr/bin/o
gzip o.1
sudo install -Dm644 o.1.gz /usr/share/man/man1/o.1.gz
C++
- For building code with
ctrl-space
,cxx
must be installed. - For formatting code with
ctrl-w
,clang-format
must be installed.
Go
- For building code with
ctrl-space
, Thego
compiler must be installed. - For formatting code with
ctrl-w
,goimports
must be installed.
Zig
- For building and formatting Zig code, only the
zig
command is needed.
V
- For building and formatting V code, only the
v
command is needed.
Rust
- For building code with
ctrl-space
,Cargo.toml
must exist andcargo
must be installed. - For formatting code with
ctrl-w
,rustfmt
must be installed.
Haskell
- For building the current file with
ctrl-space
, theghc
compiler must be installed. - For formatting code with
ctrl-w
,brittany
must be installed.
Python
ctrl-space
only checks the syntax, without executing. This only requirespython
to be available.- For formatting the code with
ctrl-w
,autopep8
must be installed.
Crystal
- For building and formatting Crystal code, only the
crystal
command is needed.
Kotlin
- For building code with
ctrl-space
,kotlinc
must be installed. A.jar
file is created if the compilation succeeded. - For formatting code with
ctrl-w
,ktlint
must be installed.
Java
- For building code with
ctrl-space
,javac
andjar
must be installed. A.jar
file is created if the compilation succeeded. - For formatting code with
ctrl-w
,google-java-format
must be installed.
Scala
- For building code with
ctrl-space
,scalac
andjar
must be installed. A.jar
file is created if the compilation succeeded. - The jar file can be executed with
java -jar main.jar
. Usescalac -d main.jar MyFile.scala
if you want to produce a jar that can be executed withscala main.jar
. - For formatting code with
ctrl-w
,scalafmt
must be installed.
JSON
- The JSON formatter is built-in.
fstab
- For formatting
fstab
files (usually/etc/fstab
) withctrl-w
,fstabfmt
must be installed.
Since kotlinc $filename -include-runtime -d
builds to a .jar
, I though I should do the same for Java. The idea is to easily build a single or a small collection of .java
files, where one of the file has a main
function.
If you know an easier way to build a .jar
file from *.java
without using something like gradle, please let me know by submitting a pull request. This is pretty verbose...
javaFiles=$(find . -type f -name '*.java')
for f in $javaFiles; do
grep -q 'static void main' "$f" && mainJavaFile="$f"
done
className=$(grep -oP '(?<=class )[A-Z]+[a-z,A-Z,0-9]*' "$mainJavaFile" | head -1)
packageName=$(grep -oP '(?<=package )[a-z,A-Z,0-9,.]*' "$mainJavaFile" | head -1)
if [[ $packageName != "" ]]; then
packageName="$packageName."
fi
mkdir -p _o_build/META-INF
javac -d _o_build $javaFiles
cd _o_build
echo "Main-Class: $packageName$className" > META-INF/MANIFEST.MF
classFiles=$(find . -type f -name '*.class')
jar cmf META-INF/MANIFEST.MF ../main.jar $classFiles
cd ..
rm -rf _o_build
For Scala, I'm using this code, to produce a main.jar
file that can be run directly with java -jar main.jar
:
#!/bin/sh
scalaFiles=$(find . -type f -name '*.scala')
for f in $scalaFiles; do
grep -q 'def main' "$f" && mainScalaFile="$f"
grep -q ' extends App ' "$f" && mainScalaFile="$f"
done
objectName=$(grep -oP '(?<=object )[A-Z]+[a-z,A-Z,0-9]*' "$mainScalaFile" | head -1);
packageName=$(grep -oP '(?<=package )[a-z,A-Z,0-9,.]*' "$mainScalaFile" | head -1);
if [[ $packageName != "" ]]; then
packageName="$packageName."
fi
mkdir -p _o_build/META-INF
scalac -d _o_build $scalaFiles
cd _o_build
echo -e "Main-Class: $packageName$objectName\nClass-Path: /usr/share/scala/lib/scala-library.jar" > META-INF/MANIFEST.MF
classFiles=$(find . -type f -name '*.class')
jar cmf META-INF/MANIFEST.MF ../main.jar $classFiles
cd ..
rm -rf _o_build
If /usr/share/scala/lib/scala-library.jar
is not found scalac -d run_with_scala.jar
is used instead. This file can only be run with the scala
command.
go
/golang
goimports
cxx
g++
/base-devel
clang-format
rustc
rustfmt
cargo
zig
v
ghc
brittany
python
autopep8
kotlin
ktlint
javac
jar
google-java-format
pandoc
- The
o
executable is only 508k when built with GCC 9.3 (for 64-bit Linux) and compressed withupx
. - This isn't as small as e3, an editor written in assembly (which is 234k), but it's reasonably lean.
One way of building with gccgo
and upx
:
go build -mod=vendor -gccgoflags '-Os -s' && upx o
It's 5.2M when built with Go 1.14 and no particular build flags are given.
These four ways of opening file.txt
at line 7
are supported:
o file.txt 7
o file.txt +7
o file.txt:7
o file.txt+7
This also means that filenames containing +
or :
, and then followed by a number, are not supported.
When loading files that are large or from a slow disk, an animated spinner will appear. The loading operation can be interrupted by pressing esc
, q
or ctrl-q
.
This shell function works in zsh
and bash
and may be useful for both searching for and opening a file at the given line number (works best if there is only one matching file, if not it will open several files in succession):
fo() { find . -type f -wholename "*$1" -exec /usr/bin/o {} $2 \;; }
Example use:
fo somefile.cpp 123
Press ctrl-space
twice to render Markdown files to PDF using pandoc
(ctrl-t
will save the text directly to PDF, without using pandoc
).
If the PAPERSIZE
environment variable is set to ie. a4
or letter
, it will be respected when exporting from Markdown to PDF using pandoc, at the press of ctrl-space
.
The --pdf-engine=xelatex
and --listings
flags are used, so xelatex
and the listings
package needs to be available. A standard installation of LaTeX and Pandoc should provide both.
These should work well together with o
:
- Try the
JetBrains Mono NL
font.
- Try the
Breeze
color scheme (but with a black background). It should work well together witho
. - Untick the
Flow control
option in the profile settings, to ensure thatctrl-s
will never freeze the terminal.
- Version: 2.36.0
- License: 3-clause BSD
- Author: Alexander F. Rødseth <xyproto@archlinux.org>