basalt/v0.11.0
0.11.0 (Nov, 30 2025)
Basalt author and maintainer here! Wanted to write a few words before the regular changelog.
Phew, this took longer than expected, but here we are. The editor feature does not offer feature parity with the tui-textarea that was being used previously, however, it can properly wrap the text while writing, which frankly, I find quite pleasing.
If you encounter any bugs or additional strangeness please open an issue! The editor was made by me and most likely contains errors. Use with caution! :)
I'm taking a small break from basalt for the advent of code puzzles! So expect slower development during December.
This release fixes the following issues: #105, #104, #95
Demo:
Added
- ba8f3a0 Introduce virtual document structure with rendering by @erikjuhani
I decided to implement a virtual document, which is essentially the
virtually rendered version of the markdown document. This virtual
document is a collection of virtual blocks, virtual lines and virtual
spans.Virtual lines and spans are turned into Ratatui variants to render them
in terminal.Virtual spans are separated into two concepts, synthetic and content.
- Synthetic spans are elements that are not calculated as part of the
markdown source.- Content spans on the other hand are elements that are calculated as
part of the markdown source.This separation enables more fluid use cases and easier management
codewise for more rendered content, like text wrapping symbols,
additional emphasize lines or spans, etc.Rendering is a collection of functions that are turned into virtual
blocks. These virtual blocks map directly into top level markdown nodes.All rendered functions wrap the text with the given max width. The text
wrapping is a generalized wrapping function that can be now run for "any"
markdown node that is defined in the ast module.
- 943256b Add Cursor module by @erikjuhani
Cursor module is responsible for keeping up with the cursor state.
Cursor can be switched between two modes, read and edit.Each mode behaves a bit differently, read only considers the virtual
elements, and edit mode considers the source content.For now only the read mode variant is properly implemented.
The rendering is handled with a separate stateful CursorWidget component
that takes the cursor state as an input and draws the cursor
accordingly.In read mode the cursor is drawn as a full-width line cursor.
- b26f0ff Add soft break parsing to markdown parser
Also add empty_line() helper function to TextSegment struct. This
creates a new empty line with "\n" as the content.This empty line can then be split in the render functions, but still
keep the content inside a single markdown node (e.g. paragraph).
- 5222b7e Add text wrapping helper utility
The text wrapper module exposes
wrap_preserve_trailing, which, as name
implies, keeps the trailing whitespace.I'm using the
textwrap::WordSeparatorto find and iterate over the
words in the text, and then determine if the word fits in the current
line by using the passed max width variable. Thetextwrapcrate itself
did not ship with a premade wrapping utility that would have preserved
the whitespace, at least, I did not find such utility.
- bf2c86d Add a simple viewport abstraction
The viewport abstraction wraps the ratatui layout structure Rect and
uses additional layout data structures like Size and Offset.
- 5b83d5f Add
charsandchar_indicesmethods to virtual span
These helper methods will allow easier access to the underlying chars
and their byte indices.
Changed
- ee4976f Replace old editor with new implementation by @erikjuhani
The old note editor variant was hard to maintain and was lacking proper
structure. Adding new ast nodes or elements was a cumbersome process.The new variant uses logical structures like virtual document and
separate rendering functions to achieve a more cohesive end result.The editor now requires to have a viewport in order to render anything
properly. This is a requirement for example to decide the correct
wrapping width for text elements.This change also introduces fix for scrolling. Now scrolling works
properly and cursor is always visible in the viewport. This fixes the
issue #104.The rendering is simplified drastically due to the use of more logical
structures.In this commit, only read mode is enabled and the edit mode support is
missing.
- 88be5fa Return a reference instead of owned RichText
No reason to not return a reference, and we avoid allocation.
- 739704a In virtual span width() returns both content and synthetic width
Previously only content width was taken into account, however, this does
not work as intended as the synthetic width needs to be calculated as
well to find for example the correct offset for cursor column.
- fa59ed5 Remove unused methods from virtual line
Also simplified and improved the existing methods. For example virtual
spans now retuns a slice instead of owned Vec.
- d00f9d4 Implement custom text editor
This custom implementation replaces tui-textarea with proper text
wrapping and better WYSIWYG experience. Also the custom implementation
allows for more granular control over how elements are, rendered and
positioned.I tried to mimic the previous functionality in a way so as little is
lost as possible feature wise, obviously, since this is made from
scratch the feature parity is far off still.Additionally there is some known issues, like cursor positioning is
incorrect with unicode symbols in source content. This can be observed
by wrong end position when moving the cursor to the right most end. The
cursor appears as if it is stuck, but that is due to wrong count
somewhere, which should be fixed, but in a different commit.For now the implementation is very limited and implements only a
restricted set of features: Editing markdown nodes, saving changes to
file, moving by words and scrolling by half pages.This commit has quite many changes, and, unfortunately the nature of how
this refactor was introduced, was difficult to separate the commits
atomically and cleanly to smaller pieces.But the most notable ones are:
Cursor changes, which include the cursor movement by columns and words
and proper cursor positioning from the source offset location.Editor state changes to allow insertion, deletion and saving of files,
and source range shifting, which is related to the editor
functionality, which essentially shifts the end of the source range,
if the source ranges are not shifted properly and if the text buffer
exceeds the range start of next node the text buffer would be
replicated and rendered in-place of the next node.Render changes, which introduce a new consolidated text wrapping and
handling for newline characters in both visual and raw rendering
modes. The new consolidated text wrapping uses the new whitespace
preserving text wrap function. Additionally source offset for rendered
virtual lines were fixed. Also added unicode-width dependency for
accurate unicode character width calculations in render.
Dependencies
- 2985a13 Update Rust crate etcetera to 0.11.0 by @renovate-updater[bot]
datasource package from to crate etcetera 0.10.0 0.11.0
Full Changelog: basalt/v0.10.4...basalt/v0.11.0
