9 unstable releases (3 breaking)
Uses new Rust 2024
new 0.4.0 | Apr 14, 2025 |
---|---|
0.3.1 | Mar 5, 2025 |
0.2.1 | Nov 12, 2024 |
0.1.3 | Jul 17, 2024 |
0.1.1 | Oct 31, 2023 |
#81 in Text editors
30 downloads per month
1MB
15K
SLoC
duat

Duat is a text editor meant to have as much modularity as
possible, while keeping a sensible default configuration. It is
written and configured in Rust, through the use of a
configuration Rust crate, placed in ~/.config/duat/
(or wherever
$XDG_CONFIG_HOME
is set to).
When installing Duat, this crate will be automatically placed in that spot, and it will have a default example configuration.
When you first run Duat, and whenever you update the configuration, it will be compiled and reloaded automatically, so you can see the changes in almost real time. Initially, building Duat and its configuration crate might take a few minutes. And the first reload might also take a similar amount of time. But whenever you make new changes, the next reloads should take only about a second (for debug profile) and ~3 seconds (for release profile).
Note that this is an alpha project, so there may be some quirks and bugs. So if you have a problem, or something seems confusing, feel free to ask questions or raise an issue, that would be very welcome 🥰.
Getting started
To install Duat, do the following:
cargo install duat
Although, since this is an alpha, I would recommend the git version, since that is kept much more up to date:
git clone https://github.com/AhoyISki/duat
cargo install --path duat --features git-deps
And if you want to nuke your config in order to get the newest default config crate, you can do the following:
rm -rf ~/.config/duat
git clone https://github.com/AhoyISki/duat
cargo install --path duat --features git-deps
Configuration
In the configuration file, there should be a setup_duat!
macro,
which takes in a function with no parameters.
This function is the setup for duat, and it can be empty, which is the equivalent of the default configuration for Duat.
Here’s an example configuration file, which makes use of the
duat-kak
crate, which is a plugin for Duat. This plugin, like
all others, is included without the duat_
prefix, so in the
config it is just kak
.
setup_duat!(setup);
use duat::prelude::*;
use kak::{Insert, Normal};
fn setup() {
plug!(
treesitter::TreeSitter::new(),
kak::Kak::new()
);
map::<Insert>("jk", "<Esc>");
print::wrap_on_width();
hooks::remove("FileWidgets");
hooks::add::<OnFileOpen>(|builder| {
builder.push(VertRule::cfg());
builder.push(LineNumbers::cfg());
});
hooks::remove("WindowWidgets");
hooks::add::<OnWindowOpen>(|builder| {
let upper_mode = mode_name().map(|m| match m.split_once('<') {
Some((no_generics, _)) => no_generics.to_uppercase(),
None => m.to_uppercase(),
});
let status_line = status!(
[Mode] upper_mode Spacer file_fmt " " selections_fmt " " main_fmt
);
builder.push(status_line);
let (child, _) = builder.push(PromptLine::cfg());
builder.push_to(child, Notifier::cfg());
});
hooks::add::<ModeSwitched>(|(_, new)| match new {
"Insert" => cursor::set_main(CursorShape::SteadyBar),
_ => cursor::set_main(CursorShape::SteadyBlock)
});
form::set("Mode", Form::dark_magenta());
}
This configuration does the following things:
- plugs the
Kak
plugin, which changes the default mode, and theTreeSitter
plugin, which adds syntax highlighting and is also used by theKak
plugin; - Maps jk to esc in the
Insert
mode; - Changes the wrapping;
- Removes the hook group “FileWidgets”;
- Pushes a vertical rule and line numbers to every file;
- Removes the hook group “WindowWidgets”;
- Pushes a custom status line (with a Spacer for 2 separate
sides, and a reformatted
mode_name
), a command line, and a notifications widget to the bottom of the screen; - Adds hooks for mode changes in Duat;
- Changes the style of the mode printed on the status line;
These are some of the ways you can configure Duat. You might notice some things that can be done with these simple options:
hooks::add::<OnFileOpen>(|builder| {
builder.push(VertRule::cfg());
builder.push(LineNumbers::cfg());
builder.push(VertRule::cfg().on_the_right());
builder.push(LineNumbers::cfg().on_the_right());
});
Now, every file will open with two lines of numbers, one on each side. Would you ever want to do this? …No, not really, but it shows how configurable Duat can be.
Duat also comes with a fully fledged text creation system, which significantly eases the creation of widgets:
let text = text!([MyForm] "Waow it's my form!" [] " not anymore 😢");
In this example, I’m using the “MyForm” form in order to style the
text, while []
reverts back to the “Default” form. The
status!
macro works similarly.
Duat also has a simple command system, that lets you add commands
with arguments supported by Rust’s type system. As an example,
this command will change the numbering of a LineNumbers
widget, switching between absolute and relative numbering.
let callers = ["toggle-relative", "tr"];
cmd::add_for!(callers, |line_numbers: LineNumbers<Ui>, _: Area| {
let mut cfg = line_numbers.get_cfg();
cfg.num_rel = match cfg.num_rel {
LineNum::Abs => LineNum::RelAbs,
LineNum::Rel | LineNum::RelAbs => LineNum::Abs,
};
line_numbers.reconfigure(cfg);
Ok(None)
})
Default plugins
When you install duat, the default config crate will come with some preinstalled plugins:
duat-kak
is a plugin that changes the default mode of Duat to one inspired by Kakoune’s “Normal”, also bringing with it various other modes from Kakoune.duat-catppuccin
is a just a simple colorscheme plugin, it adds the four flavors from the catppuccin colorscheme. You can pick between the four of them, you can apply its colors to otherForm
s and you can allow or disallow the colorscheme to set the background color.duat-treesitter
brings tree-sitter to Duat in the form of syntax highlighting and indentation calculation, which can be used by Modes (such as those fromduat-kak
) in order to give better feedback when editing files.
You can, of course, unplug these by not calling plug!
, or you
could remove them entirely by taking them out of the
Cargo.toml
’s dependencies section.
Features
Duat provides a lot of features, trying to be as configurable as possible, here are some of the things that Duat is capable of:
- Completely custom modes, with full Vim style remapping
- Completely custom widgets, with user created modes
- Arbitrary concealment of text, and arbitrary ghost text
- Custom hooks, whose activation is up to the creator
- Custom commands, with customizable parameters supported by Rust’s robust type system
- Multi UI adaptability, although for now, only a terminal UI has been made
- And many others still being planned
Additionally, by choosing Rust as its configuration language, Duat also gains the following features:
- Complete type safety
- A very functional programming language, with lots of native features
- Cargo is the plugin manager
Roadmap
These are the goals that have been accomplished or are on their way:
- Implement basic visual functionality (printing, scrolling, etc);
- Implement wrapping;
- Implement editing;
- Create a kak mode;
- Implement the use of multiple cursors;
- Implement a history system;
- Implement colors;
- Implement widgets and designated areas;
- Make all of these things easy to use on a public interface;
- Create a number line and a separator line;
- Create a status line;
- File switching;
- Create a command creation interface and a command line;
- Add the ability to frame areas;
- Implement concealment;
- Implement hot reloading of configuration;
- Create a “normal editing” mode;
- Add the ability to create hooks;
- Create a more generalized plugin system;
- Implement incremental Regex searching;
- Implement tree-sitter;
- Add floating widgets, not tied to the session layout;
- Implement autocompletion lists;
- Create an LSP plugin;
- Create a vim mode;
︙
- Create an Iced frontend;
NOTE: These are not set in stone, and may be done out of order.
Why should I use this?
I don’t know what your personal reasoning would be, but in my case, I really like Kakoune’s editing model, but was frustrated with the lack of some features, like folding, multiple file editing, the general barebonesness of the configuration, etc.
I know that Neovim has all of these features, and Helix supposedly tries to solve some of these issues. But I don’t really like either of their editing styles to be honest.
And so I thought, why not make my own text editor?
I thought, why not make a text editor that is as modular as possible, while still having a sensible default configuration? That I could modify however I wanted, and with a language that I love?
That’s why I decided to create Duat.
Why the name
idk, cool sounding word that I got from Spelunky 2.
Also, just wanted to say that no AI was used in this project, cuz I don’t like it.
Dependencies
~8–22MB
~348K SLoC