Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified assets/dark/create.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/dark/demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/dark/explorer.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/dark/help-modal.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/dark/note-editor.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/dark/outline.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/dark/rename.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/dark/vault-selector.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/light/create.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/light/demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/light/explorer.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/light/help-modal.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/light/note-editor.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/light/outline.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/light/rename.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/light/vault-selector.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 27 additions & 2 deletions basalt/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
# Changelog

## [0.12.6](https://github.com/erikjuhani/basalt/releases/tag/basalt/0.12.6) (Unreleased)
## [0.12.6](https://github.com/erikjuhani/basalt/releases/tag/basalt/0.12.6) (Jun, 07 2026)

### Changed

- [0545dc4](https://github.com/erikjuhani/basalt/commit/0545dc4d35d276036ef4fd2c46e27250b43c4a16) Render edit mode line by line (#486)

> Editing used to flip the whole block to raw on entry, and rendering it
> from the AST during edits drifted from the source, so nested lists and
> structural edits were unreliable.
>
> Render the active block with a line decorator that maps 1:1 to source
> place. This keeps indentation, blank lines and code blocks faithful to
> the source and makes editing predictable.
>
> Read mode and non-active blocks keep the AST renderer; unifying the two
> is tracked in #533.

### Fixed

- [f40bc77](https://github.com/erikjuhani/basalt/commit/f40bc77e49fc7e27aca04cd0936d8f4cd746ad17) Preserve source blank lines in Edit mode by @erikjuhani

> In Edit mode the visual rendering now mirrors the source's blank-line
> structure. Empty lines between loose list items render as empty rows,
> and block spacing matches the source byte gap instead of a fixed "one
> empty line per block". Adjacent blocks with no source empty lines now
> render with no visual gap, so deleting at a block's start merges into
> the previous block without a misleading empty row in between.

### Added

Expand All @@ -25,7 +51,6 @@
> The watcher is rebuilt when the active vault changes and avoids stealing
> focus from the editor.


### Fixed

- [f40bc77](https://github.com/erikjuhani/basalt/commit/f40bc77e49fc7e27aca04cd0936d8f4cd746ad17) Preserve source blank lines in Edit mode by @erikjuhani
Expand Down
15 changes: 13 additions & 2 deletions basalt/src/note_editor/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ pub struct Cursor {
pub virtual_column: usize,
}

/// Display width of a source character. Tabs are one byte but rendered as two
/// columns (see the draw-time expansion), so they must count as two here to
/// keep cursor columns aligned with the displayed text.
fn char_display_width(c: char) -> usize {
if c == '\t' {
2
} else {
c.width().unwrap_or(0)
}
}

pub fn virtual_position_to_source_offset<'a>(
(row, col): (usize, usize),
lines: &'a [VirtualLine<'a>],
Expand All @@ -59,7 +70,7 @@ pub fn virtual_position_to_source_offset<'a>(
return Some(range.start + byte_idx);
}

let char_width = ch.width().unwrap_or(0);
let char_width = char_display_width(ch);
cur_col += char_width;
content_col += char_width;
}
Expand Down Expand Up @@ -116,7 +127,7 @@ pub fn source_offset_to_virtual_column<'a>(offset: usize, line: &VirtualLine<'a>
let n = span
.char_indices()
.map_while(|(byte_idx, c)| {
(byte_idx < byte_offset).then(|| c.width().unwrap_or(0))
(byte_idx < byte_offset).then(|| char_display_width(c))
})
.sum::<usize>();

Expand Down
26 changes: 26 additions & 0 deletions basalt/src/note_editor/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,32 @@ mod tests {
state
}),
),
(
// Only the list item under the cursor should render raw; the
// surrounding items stay rendered. Ref: issue #486.
"edit_mode_list_line_by_line_raw",
Box::new(|area| {
let content = indoc! { r#"## Shopping

- apples
- bananas
- cherries
"#};
let mut state = NoteEditorState::new(
content,
"Test",
Path::new("test.md"),
&Symbols::unicode(),
);
state.resize_viewport(area.as_size());
state.set_view(View::Edit(EditMode::Source));
// Enter the list (lands on the first item), then step down to
// the "bananas" item.
state.cursor_down(1);
state.cursor_down(1);
state
}),
),
];

let mut terminal = Terminal::new(TestBackend::new(80, 20)).unwrap();
Expand Down
Loading