A terminal-based text editor written in Rust

Overview

Iota Build Status

Gitter

Iota is a terminal-based text-editor written in Rust.

Here's what it looks like right now, editing itself.

Screenshot

Motivation

Iota was born out of my frustrations with existing text editors. Over the years I've tried combinations of simple text editors, IDEs and everything in between. None of them felt right to me, however. Some were too slow & bulky, others were too difficult to customise and still others were platform specific and I couldn't use them on all my machines.

I started building Iota with the view of combining ideas and features from serveral different editors while designing it to work on modern hardware.

Why Rust? Because its fun and why not!

Goals

The goals for Iota are that it would be:

  • 100% open source
  • highly extensible/customisable/scriptable
  • fast & efficient - designed with modern hardware in mind
  • cross platform - it should work anywhere
  • developer friendly - it should just "get out of the way"
  • Rust tooling integration (see note below)

Iota is still in the very early stages, and is probably not ready for every day use. Right now the focus is on implementing and polishing the basic editing functionality.

Windows support is coming, but it's somewhat slow right now. Help with this would be greatly appreciated!

Note on Rust integration: The aim is to support code editing in all languages (and of course plain text), with a lean towards Rust and integration with Rust tools. I don't intend it to be a "Rust IDE" or "Rust only", however I think it would be cool to experiment with integration with Rust tooling. This could also be applied to other languages too.

Building

Clone the project and run cargo build --release.

NOTE: Iota needs to be built using the nightly toolchain for now, not stable.
Run the following commands - $ rustup install nightly following which run - $ rustup override set nightly .
Rustup is very useful for managing multiple rust versions.

Once you have the source, run:

Usage

To start the editor run ./target/release/iota /path/to/file.txt. Or simply ./target/release/iota to open an empty buffer.

You can also create buffers from stdin.

# open a buffer with the output of `ifconfig`
ifconfig | ./target/release/iota

You can move the cursor around with the arrow keys.

The following keyboard bindings are also available:

  • Ctrl-s save
  • Ctrl-q quit
  • Ctrl-z undo
  • Ctrl-y redo

Iota currently supports both Vi and Emacs style keybindings for simple movement.

You can enable Vi style keybindings by using the --vi flag when starting Iota. The vi-style modes are in the early stages, and not all functionality is there just yet. The following works:

  • while in normal mode:
    • k move up
    • j move down
    • l move forwards
    • h move backwards
    • w move one word forward
    • b move one word backward
    • 0 move to start of line
    • $ move to end of line
    • d delete
    • u undo
    • r redo
    • i insert mode
    • :q quit
    • :w save
  • while in insert mode:
    • ESC normal mode

Alternatively, you can use the following emacs-style keys by using the --emacs flag:

  • Ctrl-p move up
  • Ctrl-n move down
  • Ctrl-b move backwards
  • Ctrl-f move forwards
  • Ctrl-a move to start of line
  • Ctrl-e move to end of line
  • Ctrl-d delete forwards
  • Ctrl-h delete backwards
  • Ctrl-x Ctrl-c quit
  • Ctrl-x Ctrl-s save
  • Ctrl-z undo
  • Ctrl-y redo
Comments
  • Can't run cargo test

    Can't run cargo test

    I get the following error:

    $ cargo test
        Updating git repository `https://github.com/gchp/rustbox`
        Updating registry `https://github.com/rust-lang/crates.io-index`
        Updating git repository `https://github.com/gchp/termbox-sys`
     Downloading docopt v0.6.16
       Compiling termbox-sys v0.0.2 (https://github.com/gchp/termbox-sys#e8352762)
       Compiling docopt v0.6.16
    /Users/ruipacheco/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-0.6.16/src/parse.rs:45:34: 45:40 error: unresolved import `std::collections::hash_map::Vacant`. There is no `Vacant` in `std::collections::hash_map`
    /Users/ruipacheco/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-0.6.16/src/parse.rs:45 use std::collections::hash_map::{Vacant, Occupied};
                                                                                                                                     ^~~~~~
    /Users/ruipacheco/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-0.6.16/src/parse.rs:45:42: 45:50 error: unresolved import `std::collections::hash_map::Occupied`. There is no `Occupied` in `std::collections::hash_map`
    /Users/ruipacheco/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-0.6.16/src/parse.rs:45 use std::collections::hash_map::{Vacant, Occupied};
                                                                                                                                             ^~~~~~~~
    error: aborting due to 2 previous errors
    Build failed, waiting for other jobs to finish...
    Could not compile `docopt`.
    
    To learn more, run the command again with --verbose.
    
    opened by ruipacheco 15
  • Proposal: syntax highlighting

    Proposal: syntax highlighting

    First things first I am not a pro at Rust and its only a proposal and nothing more.

    Iota is a text Editor and I think every text editor needs syntax highlighting. I don't know if termbox/rustbox offers this, but it would be a great journey. And how to do this? Thats the point where I think #51 comes to rescue. Toml, Yaml or JSON, a simple Language Definition would be (yaml example):

    # Go
    extension: *.go
    keywords: func type #... 
    

    Keywords would be readed as array, and will be registered with the colors given. And at opening a new file, Iota would check the file extension, if the file extension known, it will be set.

    Also I think writing this everything in one file (languages.toml or languages.iota) would be nice so its a little bit more hackable.

    What you think about this? I would help implementing, but first then I need to start learning Rust.

    Good Evening.

    enhancement planning discussion 
    opened by torwart 11
  • SIGILL on latest OSX

    SIGILL on latest OSX

    git pull cargo build --release ./target/release/iota

    and then

    fish: Job 1, './target/release/iota ' terminated by signal SIGILL (Illegal instruction)

    (I'm using the fish shell)

    bug 
    opened by ruipacheco 11
  • Word movement & deletion vi commands

    Word movement & deletion vi commands

    Still slightly inconsistent with vim with deleting words at the end of a line/blank lines. Also I'm not very happy about using a boolean in the Direction enum for the different vim word matching types, thinking maybe adding another enum that defines the word edge matching might be the way to go. Would allow for adding in whatever emacs bindings there are for moving by word easily.

    So, with those above caveats this is more of a review/discussion request than a serious pull request, yet.

    opened by Nemo157 10
  • Relicense project under GPL

    Relicense project under GPL

    I'd like to relicense the project under the GPL.

    Obviously, this would mean that code contributed already to this project under the MIT license would need to be relicensed. In order to do this I would like the contributors of said code permission to have their contributions relicensed.

    If you've contributed code to Iota up to this point, can you comment below and let me know if you are happy for your contributions to be relicensed under the GPL. Alternatively, if you're not happy for this, please also comment below or email me (email address in commit log).

    Thanks!

    opened by gchp 9
  • Illegal instruction (core dumped)

    Illegal instruction (core dumped)

    After $cargo build, run & get this error. How deal with it?

    $ ./target/iota
    Illegal instruction (core dumped)
    

    PS. Ubuntu 14.04 LTS x64; Nightly Build's rustc and cargo.

    bug 
    opened by yeahnoob 8
  • Remove use of unsafe code

    Remove use of unsafe code

    Currently there are just two unsafe blocks of code in the project. I'd like to remove them and only use safe code if possible.

    I'm not sure if the current design will work without the unsafe code, though. Might be worth evaluating to see if its worth redesigning just to remove it.

    opened by gchp 8
  • Implementing buffer as a gap buffer

    Implementing buffer as a gap buffer

    Hey, I left a comment on your HN posting about The Craft of Text Editing. I've been thinking about both a) implementing a text editor & b) learning Rust for several months now, and I'd like to contribute. I fiddled with a text editor in Python a while ago, which is when I found that book.

    I notice that buffer.rs implements the buffer as a vector of vectors of chars. This is the obvious way to do it, but as I discovered from The Craft of Text Editing, its much more efficient to implement it as a gap buffer - a resizing array with with a moveable gap (see chapter 6 or Wikipedia for more info). A generic gap buffer seems like a good introduction to Rust, so I've started working on it. Ultimately I'll implement the same API as the current buffer and submit a pull request?

    opened by withoutboats 8
  • Panic with ./target/iota src/main.rs

    Panic with ./target/iota src/main.rs

    Opened by ./target/iota src/main.rs and just did something like Pg-Down, Pg-Down, Enter, Enter, Pg-Down, Pg-Down

    Panick

    task '<main>' panicked at 'index out of bounds: the len is 21 but the index is 21', src/iota/lib.rs:1
    Options:                                                                                             task '<unnamed>' panicked at 'sending on a closed channel', /home/rustbuild/src/rust-buildbot/slave/nightly-linux/build/src/libstd/comm/mod.rs:555
    ";                                                                             
    

    Disclaimer: I'm new into Rust ecosystem, so I don't know what details to provide or how to obtain stacktrace et cetera ... If anything I'm wiling to provide you with more details.

    bug 
    opened by leonardinius 8
  • thread '<main>' panicked at 'index out of bounds: the len is 0 but the index is 0', ../src/libcollections/vec.rs:1134

    thread '
    ' panicked at 'index out of bounds: the len is 0 but the index is 0', ../src/libcollections/vec.rs:1134

    env RUST_BACKTRACE=1 ./target/release/iota --vi
    thread '<main>' panicked at 'index out of bounds: the len is 0 but the index is 0', ../src/libcollections/vec.rs:1134
    stack backtrace:
       1:     0x55e8bfa2d130 - sys::backtrace::tracing::imp::write::hf66cd359dc225f8a0nu
       2:     0x55e8bfa2f75b - panicking::default_handler::_<closure>::closure.42795
       3:     0x55e8bfa2f324 - panicking::default_handler::h74bfdb4a758a82e9EFy
       4:     0x55e8bfa215f6 - sys_common::unwind::begin_unwind_inner::h9d3a2e7a2c681f25ygt
       5:     0x55e8bfa21a78 - sys_common::unwind::begin_unwind_fmt::h4fadd261b35ed9d7Eft
       6:     0x55e8bfa2c771 - rust_begin_unwind
       7:     0x55e8bfa5c37f - panicking::panic_fmt::h596d44ac9aaebe47nYL
       8:     0x55e8bfa5c4f2 - panicking::panic_bounds_check::hb399db976cf4f929tXL
       9:     0x55e8bf9acd24 - buffer::Buffer::get_object_index::hee931b9597f98e70Xqa
      10:     0x55e8bf9b0b46 - view::View::move_mark::h50c3269b4d699f3cXIb
      11:     0x55e8bf9a7192 - main::h07af46f8e193902eeda
      12:     0x55e8bfa2efc4 - sys_common::unwind::try::try_fn::h3732045691669936705
      13:     0x55e8bfa2c708 - __rust_try
      14:     0x55e8bfa2ebfd - rt::lang_start::h2071a016df0a133cKxy
      15:     0x7f998bb4357f - __libc_start_main
      16:     0x55e8bf9a4cb8 - _start
      17:                0x0 - <unknown>
    
    opened by dpc 6
  • Keymap

    Keymap

    This is a rough-around-the-edges take on implementing a general purpose key-sequence => command binding framework. See also #30.

    The KeyMap holds a Trie that maps Key nodes to editor Commands, with a bit of state to keep track of incoming key presses.

    The editor can then feed keystrokes to the KeyMap, and receive either a matching Command, a Continue signaling a partial result that needs more keys to disambiguate, or a None indicating that no match was found and the key should be handled normally.

    I don't really know what I'm doing here, so there's certainly a lot of room for cleanup and improvements.

    opened by crespyl 6
  • Simple page up/down implementation

    Simple page up/down implementation

    Hi,

    This PR adds a simple page up and page down implementation. At the moment forward or backward 12 lines (a half of 24 lines in standard old consoles).

    PD: Maybe a better feature will be moving a Kind::Paragraph? Please let me know.

    opened by fedel 0
  • termbox

    termbox

    cargo build
       Compiling termbox-sys v0.2.10
    error: could not find native static library `termbox`, perhaps an -L flag is missing?
    error: aborting due to previous error
    error: Could not compile `termbox-sys`.
    To learn more, run the command again with --verbose.
    

    i use fedora, how install termbox?

    opened by texrg 1
  • Marks & MarkPosition and how are they kept valid?

    Marks & MarkPosition and how are they kept valid?

    I'm sorry if this is a completely inappropriate place to take up my questions regarding some things in this text editor, but I can't seem to find any description of how the thought process was when designing this text editor (and I can't contact the owner of the repo directly).

    I kind of understand the idea behind the Mark and MarkPosition, but what makes me bewildered is, the Buffer Struct contains a HashMap with marks in it - how is this kept valid at all, when insertion and deletion of characters in the buffer is made? I can't seem to find anything in the source code either, or maybe I am completely missing the purpose of this all together?

    Since it indexes into the GapBuffer (and since GapBuffer is a 1D array, basically) through an absolute index, any insertion or deletion before a mark, will completely invalidate it, if no update is made to that entry in the hashmap, at every insertion and deletion, which (if many marks are saved) could lead to quite the overhead, no?

    Or what is the purpose of this HashMap, at first, I thought I thought it was some container for keeping track of positions in the text, (like a bookmarking feature the end user can use, hence my question on validation of the marks and their purpose). But after looking through the source code, that doesn't seem to be it's purpose neither. Could you be so kind and explain briefly to me the purpose of that HashMap?

    Anyway, awesome project, has me inspired to writing my own rusty project.

    opened by theIDinside 0
  • Add Json support for keybindings, to add own keybindings

    Add Json support for keybindings, to add own keybindings

    I would like to write my own keybindings for iota, for example in Json. Example:

    [
      {
        "keys": [
          {
            "mode": "Ctrl",
            "key": "x"
          },
          {
            "mode": "Ctrl",
            "key": "c"
          }
        ],
        "CommandInfo": {
          "command_name": "editor::quit",
          "args": null
        }
      }
    ]
    
    opened by x7airworker 1
Owner
Greg Chapple
Head of Technology @propylon
Greg Chapple
ReVi is a cross-platform terminal based Vim inspired text editor.

ReVi Table Of Contents: About Usage Install Clone && Installing Development Q&A KeyBindings Roadmap Changelog About ReVi is a cross-platform terminal

null 30 Aug 25, 2022
An independent Rust text editor that runs in your terminal!

Ox editor Ox is a code editor that runs in your terminal. About The Project Ox is a code editor. It was written in Rust using ANSI escape sequences. I

null 2.8k Sep 27, 2022
An experimental next-generation Electron-based text editor

Attention: GitHub has decided not to move forward with any aspect of this project. We'll archive the repository in case anybody finds value here, but

Atom Archive 8.6k Sep 22, 2022
TIF is a terminal_image_format. (theres no TIF editor, so i made TIF images through a hex editor lol)

Colors these are the colors you can use when displaying images on the terminal BYTES: 5A = BLUE 5B = BLACK 5C = RED 5D = GREEN 5E = PURPLE 5F = WHITE

buzz 4 Jun 21, 2022
A text editor in ≤1024 lines of code, written in Rust

Kibi: A text editor in ≤1024 lines of code, written in Rust A configurable text editor with UTF-8 support, incremental search, syntax highlighting, li

Ilaï Deutel 839 Sep 24, 2022
Web base text editor written in rust

Ultron Ultron is a web based monospace text-editor with syntax highlighting, completely written in rust. I wrote this code editor for my very specific

Jovansonlee Cesar 59 Aug 8, 2022
A simple terminal-based editor made in rust!

ELuna Editor The terminal-based editor for europa lang. Goals Be as minimal as possible, but retain conveniences found in other editors. Do not add fe

Junhao 3 May 25, 2022
Ginkgo is a text editor built entirely in Rust

Ginkgo is a text editor built entirely in Rust. It supports cursor movements, CTRL commands, select vim commands, insert vs. normal modes, and more. Ginkgo is based on my text editor JED, which itself was based on the popular online editor Kilo.

James Asbury 11 Mar 21, 2022
Aspiring vim-like text editor

Rim Rim is an aspiring Vim-like text editor written in Rust. Current state Rim is in an early prototype stage. This means that you can load, edit and

Mathias Hällman 547 Sep 24, 2022
Archeum - a minimalist text editor

Archeum About The Project Archeum is a minimalist text editor that is really usefull if you've been in the vim psychosis for to long. Reject plugins,

null 4 Jul 1, 2022
(An attempt to write) a modal text editor

kaka (An attempt to write) a modal text editor. NOTE: The project is very young and certainly not ready for use. Current project goals keymap and mode

Marcin Pajkowski 4 Aug 15, 2022
An opinionated modal editor to simplify code editing from the terminal

(I'm currently refactoring the platform layer. So we have to first finish this cleanup before we're able to continue adding features) An opinionated m

Matheus Lessa Rodrigues 271 Sep 24, 2022
eBPF terminal editor

TBM - Terminal Blueprint Meddler A TUI application for fooling around inside eBPF files. Installation cargo install tbm Usage Currently, only prints

Rafael Ortiz 1 Jan 18, 2022
Rust-based traffic editor for RMF

Traffic Editor III Welcome to Traffic Editor III. install stuff Unfortunately we need a newer Rust than what comes with Ubuntu 20.04. First make sure

null 1 Nov 26, 2021
Wealthy Rich ported to Rust! This aims to be a crate for rich text and beautiful formatting in the terminal

Wealthy Rich ported to Rust! This aims to be a crate for rich text and beautiful formatting in the terminal

Sourajyoti Basak 12 Sep 10, 2022
A modern editor with a backend written in Rust.

Xi Editor (pronounced "Zigh") A modern editor with a backend written in Rust. Maintenance status: The xi-editor project is not currently under active

null 19.6k Sep 27, 2022
Lightning-fast and Powerful Code Editor written in Rust

Lapce Lightning-fast and Powerful Code Editor written in Rust About Lapce is written in pure Rust, with UI in Druid. It's using Xi-Editor's Rope Scien

Lapce 18k Sep 26, 2022
A collision editor for Guilty Gear -Strive-, written in Rust

ggst_collision_editor_rs A collision editor for Guilty Gear -Strive- and other Team Red Arc System Works games, written in Rust. Uses a customized ver

null 4 May 3, 2022
Helix - A kakoune / neovim inspired editor, written in Rust

A kakoune / neovim inspired editor, written in Rust. The editing model is very heavily based on kakoune; during development I found myself agree

null 13.1k Sep 28, 2022